1use std::collections::HashMap;
2
3use super::{
4 intrinsics::{
5 CtxType, FunctionCache, GlobalCache, Intrinsics, MemoryCache, tbaa_label, type_to_llvm,
6 },
7 state::{ControlFrame, ExtraInfo, IfElseState, State, TagCatchInfo},
9};
10use crate::{compiler::ModuleBasedSymbolRegistry, config::OptimizationStyle};
11use enumset::EnumSet;
12use inkwell::{
13 AddressSpace, AtomicOrdering, AtomicRMWBinOp, DLLStorageClass, FloatPredicate, IntPredicate,
14 attributes::{Attribute, AttributeLoc},
15 builder::Builder,
16 context::Context,
17 module::{Linkage, Module},
18 passes::PassBuilderOptions,
19 targets::{FileType, TargetMachine},
20 types::{BasicType, BasicTypeEnum, FloatMathType, IntType, PointerType, VectorType},
21 values::{
22 BasicMetadataValueEnum, BasicValue, BasicValueEnum, CallSiteValue, FloatValue,
23 FunctionValue, InstructionOpcode, InstructionValue, IntValue, LLVMTailCallKind, PhiValue,
24 PointerValue, VectorValue,
25 },
26};
27use itertools::Itertools;
28use smallvec::SmallVec;
29use target_lexicon::{Architecture, BinaryFormat, OperatingSystem, Triple};
30use wasmer_compiler::WASM_LARGE_FUNCTION_THRESHOLD;
31
32use crate::{
33 abi::{Abi, get_abi},
34 config::LLVM,
35 error::{err, err_nt},
36 object_file::{CompiledFunction, load_object_file},
37};
38use wasmer_compiler::{
39 CANONICAL_NAN_F32, CANONICAL_NAN_F64, FunctionBinaryReader, FunctionBodyData,
40 GEF32_LEQ_I32_MAX, GEF32_LEQ_I64_MAX, GEF32_LEQ_U32_MAX, GEF32_LEQ_U64_MAX, GEF64_LEQ_I32_MAX,
41 GEF64_LEQ_I64_MAX, GEF64_LEQ_U32_MAX, GEF64_LEQ_U64_MAX, LEF32_GEQ_I32_MIN, LEF32_GEQ_I64_MIN,
42 LEF32_GEQ_U32_MIN, LEF32_GEQ_U64_MIN, LEF64_GEQ_I32_MIN, LEF64_GEQ_I64_MIN, LEF64_GEQ_U32_MIN,
43 LEF64_GEQ_U64_MIN, MiddlewareBinaryReader, ModuleMiddlewareChain, ModuleTranslationState,
44 from_binaryreadererror_wasmerror,
45 misc::CompiledKind,
46 types::{
47 relocation::RelocationTarget,
48 symbols::{Symbol, SymbolRegistry},
49 },
50 wasmparser::{Catch, MemArg, Operator},
51 wpheaptype_to_type, wptype_to_type,
52};
53use wasmer_types::{
54 CompileError, FunctionIndex, FunctionType, GlobalIndex, LocalFunctionIndex, MemoryIndex,
55 ModuleInfo, SignatureHash, SignatureIndex, TableIndex, Type, target::CpuFeature,
56};
57use wasmer_types::{TagIndex, entity::PrimaryMap};
58use wasmer_vm::{MemoryStyle, TableStyle, VMOffsets};
59
60const FUNCTION_SECTION_ELF: &str = "__TEXT,wasmer_function";
61const FUNCTION_SECTION_MACHO: &str = "__TEXT";
62const FUNCTION_SEGMENT_MACHO: &str = "wasmer_function";
63
64const CATCH_ALL_TAG_VALUE: i32 = i32::MAX;
70
71pub struct FuncTranslator {
72 ctx: Context,
73 target_triple: Triple,
74 target_machines: HashMap<OptimizationStyle, TargetMachine>,
75 abi: Box<dyn Abi>,
76 binary_fmt: BinaryFormat,
77 func_section: String,
78 pointer_width: u8,
79 cpu_features: EnumSet<CpuFeature>,
80 non_volatile_memory_ops: bool,
81 wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
82}
83
84impl wasmer_compiler::FuncTranslator for FuncTranslator {}
85
86impl FuncTranslator {
87 pub fn new(
88 target_triple: Triple,
89 target_machines: HashMap<OptimizationStyle, TargetMachine>,
90 binary_fmt: BinaryFormat,
91 pointer_width: u8,
92 cpu_features: EnumSet<CpuFeature>,
93 non_volatile_memory_ops: bool,
94 wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
95 ) -> Result<Self, CompileError> {
96 let abi_source_tm = target_machines
97 .get(&OptimizationStyle::ForSpeed)
98 .expect("target_machines must contain OptimizationStyle::ForSpeed");
99 let abi = get_abi(abi_source_tm);
100 Ok(Self {
101 ctx: Context::create(),
102 target_triple,
103 target_machines,
104 abi,
105 func_section: match binary_fmt {
106 BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
107 BinaryFormat::Macho => FUNCTION_SEGMENT_MACHO.to_string(),
108 _ => {
109 return Err(CompileError::UnsupportedTarget(format!(
110 "Unsupported binary format: {binary_fmt:?}"
111 )));
112 }
113 },
114 binary_fmt,
115 pointer_width,
116 cpu_features,
117 non_volatile_memory_ops,
118 wasm_apply_data_relocs_fn_index,
119 })
120 }
121
122 #[allow(clippy::too_many_arguments)]
123 pub fn translate_to_module(
124 &self,
125 wasm_module: &ModuleInfo,
126 module_translation: &ModuleTranslationState,
127 signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
128 local_func_index: &LocalFunctionIndex,
129 function_body: &FunctionBodyData,
130 config: &LLVM,
131 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
132 _table_styles: &PrimaryMap<TableIndex, TableStyle>,
133 symbol_registry: &dyn SymbolRegistry,
134 target: &Triple,
135 opt_style: OptimizationStyle,
136 ) -> Result<Module<'_>, CompileError> {
137 let func_index = wasm_module.func_index(*local_func_index);
139 let function =
140 CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
141 let function_name =
142 symbol_registry.symbol_to_name(Symbol::LocalFunction(*local_func_index));
143
144 let m0_is_enabled = memory_styles
147 .get(MemoryIndex::from_u32(0))
148 .is_some_and(|memory| matches!(memory, MemoryStyle::Static { .. }));
149
150 let module_name = match wasm_module.name.as_ref() {
151 None => format!("<anonymous module> function {function_name}"),
152 Some(module_name) => format!("module {module_name} function {function_name}"),
153 };
154 let module = self.ctx.create_module(module_name.as_str());
155
156 let target_machine = &self.target_machines.values().next().unwrap();
157 let target_triple = target_machine.get_triple();
158 let target_data = target_machine.get_target_data();
159 module.set_triple(&target_triple);
160 module.set_data_layout(&target_data.get_data_layout());
161 let wasm_fn_type = wasm_module
162 .signatures
163 .get(wasm_module.functions[func_index])
164 .unwrap();
165
166 let offsets = VMOffsets::new(self.pointer_width, wasm_module);
167 let intrinsics = Intrinsics::declare(
168 &module,
169 &self.ctx,
170 &target_data,
171 &self.target_triple,
172 &self.binary_fmt,
173 );
174 let (func_type, func_attrs) = self.abi.func_type_to_llvm(
175 &self.ctx,
176 &intrinsics,
177 Some(&offsets),
178 wasm_fn_type,
179 m0_is_enabled,
180 )?;
181
182 let func = module.add_function(&function_name, func_type, Some(Linkage::External));
183 for (attr, attr_loc) in &func_attrs {
184 func.add_attribute(*attr_loc, *attr);
185 }
186
187 if !matches!(target.operating_system, OperatingSystem::Windows) {
188 func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe);
189 }
190
191 func.add_attribute(AttributeLoc::Function, intrinsics.uwtable);
192 func.add_attribute(AttributeLoc::Function, intrinsics.frame_pointer);
193
194 let section = match self.binary_fmt {
195 BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
196 BinaryFormat::Macho => {
197 format!("{FUNCTION_SECTION_MACHO},{FUNCTION_SEGMENT_MACHO}")
198 }
199 _ => {
200 return Err(CompileError::UnsupportedTarget(format!(
201 "Unsupported binary format: {:?}",
202 self.binary_fmt
203 )));
204 }
205 };
206
207 func.set_personality_function(intrinsics.personality);
208 func.as_global_value().set_section(Some(§ion));
209
210 func.set_linkage(Linkage::DLLExport);
211 func.as_global_value()
212 .set_dll_storage_class(DLLStorageClass::Export);
213
214 let entry = self.ctx.append_basic_block(func, "entry");
215 let start_of_code = self.ctx.append_basic_block(func, "start_of_code");
216 let return_ = self.ctx.append_basic_block(func, "return");
217 let alloca_builder = self.ctx.create_builder();
218 let cache_builder = self.ctx.create_builder();
219 let builder = self.ctx.create_builder();
220 cache_builder.position_at_end(entry);
221 let br = err!(cache_builder.build_unconditional_branch(start_of_code));
222 alloca_builder.position_before(&br);
223 cache_builder.position_before(&br);
224 builder.position_at_end(start_of_code);
225
226 let mut state = State::new();
227 builder.position_at_end(return_);
228 let phis: SmallVec<[PhiValue; 1]> = wasm_fn_type
229 .results()
230 .iter()
231 .map(|&wasm_ty| {
232 type_to_llvm(&intrinsics, wasm_ty).map(|ty| builder.build_phi(ty, "").unwrap())
233 })
234 .collect::<Result<_, _>>()?;
235 state.push_block(return_, phis, 0);
236 builder.position_at_end(start_of_code);
237
238 let mut reader = MiddlewareBinaryReader::new_with_offset(
239 function_body.data,
240 function_body.module_offset,
241 );
242 reader.set_middleware_chain(
243 config
244 .middlewares
245 .generate_function_middleware_chain(*local_func_index),
246 );
247
248 let mut params = vec![];
249 let first_param =
250 if func_type.get_return_type().is_none() && wasm_fn_type.results().len() > 1 {
251 if m0_is_enabled { 3 } else { 2 }
252 } else if m0_is_enabled {
253 2
254 } else {
255 1
256 };
257 let mut is_first_alloca = true;
258 let mut insert_alloca = |ty, name: String| -> Result<PointerValue, CompileError> {
259 let alloca = err!(alloca_builder.build_alloca(ty, &name));
260 if is_first_alloca {
261 alloca_builder.position_at(entry, &alloca.as_instruction_value().unwrap());
262 is_first_alloca = false;
263 }
264 Ok(alloca)
265 };
266
267 for idx in 0..wasm_fn_type.params().len() {
285 let ty = wasm_fn_type.params()[idx];
286 let ty = type_to_llvm(&intrinsics, ty)?;
287 let value = func
288 .get_nth_param((idx as u32).checked_add(first_param).unwrap())
289 .unwrap();
290 let alloca = insert_alloca(ty, format!("param_{idx}"))?;
291 err!(cache_builder.build_store(alloca, value));
292 params.push((ty, alloca));
293 }
294
295 let mut locals = vec![];
296 let num_locals = reader.read_local_count()?;
297 for idx in 0..num_locals {
298 let (count, ty) = reader.read_local_decl()?;
299 let ty = err!(wptype_to_type(ty));
300 let ty = type_to_llvm(&intrinsics, ty)?;
301 for _ in 0..count {
302 let alloca = insert_alloca(ty, format!("local_{idx}"))?;
303 err!(cache_builder.build_store(alloca, ty.const_zero()));
304 locals.push((ty, alloca));
305 }
306 }
307
308 let mut params_locals = params.clone();
309 params_locals.extend(locals.iter().cloned());
310
311 let mut m0_param = None;
312
313 if m0_is_enabled {
314 let m0 = self.abi.get_m0_ptr_param(&func);
315 m0.set_name("m0_base_ptr");
316 m0_param = Some(m0);
317 }
318
319 let mut fcg = LLVMFunctionCodeGenerator {
320 m0_param,
321 context: &self.ctx,
322 builder,
323 alloca_builder,
324 intrinsics: &intrinsics,
325 state,
326 function: func,
327 locals: params_locals,
328 ctx: CtxType::new(
329 wasm_module,
330 &func,
331 &cache_builder,
332 &*self.abi,
333 self.pointer_width,
334 m0_param,
335 ),
336 unreachable_depth: 0,
337 memory_styles,
338 _table_styles,
339 module: &module,
340 module_translation,
341 signature_hashes,
342 wasm_module,
343 symbol_registry,
344 abi: &*self.abi,
345 config,
346 target_triple: self.target_triple.clone(),
347 tags_cache: HashMap::new(),
348 binary_fmt: self.binary_fmt,
349 cpu_features: self.cpu_features,
350 non_volatile_memory_ops: self.non_volatile_memory_ops,
351 };
352
353 fcg.ctx.add_func(
354 func_index,
355 func.as_global_value().as_pointer_value(),
356 func_type,
357 fcg.ctx.basic(),
358 &func_attrs,
359 );
360
361 while fcg.state.has_control_frames() {
362 let pos = reader.current_position() as u32;
363 let op = reader.read_operator()?;
364 fcg.translate_operator(op, pos)?;
365 }
366
367 fcg.finalize(wasm_fn_type)?;
368
369 if let Some(ref callbacks) = config.callbacks {
370 callbacks.preopt_ir(&function, &wasm_module.hash_string(), &module);
371 }
372
373 let mut passes = vec![];
374 if config.enable_verifier {
375 passes.push("verify");
376 }
377
378 match opt_style {
379 OptimizationStyle::Disabled => {
380 passes.push("default<O0>");
381 }
382 OptimizationStyle::ForSize => {
383 passes.push("default<O1>");
385 }
386 OptimizationStyle::ForSpeed => {
387 passes.push("sccp");
388 passes.push("early-cse");
389 passes.push("adce");
391 passes.push("sroa");
392 passes.push("aggressive-instcombine");
393 passes.push("jump-threading");
394 passes.push("simplifycfg");
396 passes.push("reassociate");
397 passes.push("loop-rotate");
398 passes.push("indvars");
399 passes.push("sccp");
403 passes.push("reassociate");
404 passes.push("simplifycfg");
405 passes.push("gvn");
406 passes.push("memcpyopt");
407 passes.push("dse");
408 passes.push("dce");
409 passes.push("reassociate");
411 passes.push("simplifycfg");
412 passes.push("mem2reg");
413 }
414 }
415
416 module
417 .run_passes(
418 &passes.join(","),
419 target_machine,
420 PassBuilderOptions::create(),
421 )
422 .unwrap();
423
424 if let Some(ref callbacks) = config.callbacks {
425 callbacks.postopt_ir(&function, &wasm_module.hash_string(), &module);
426 }
427
428 Ok(module)
429 }
430
431 #[allow(clippy::too_many_arguments)]
432 pub fn translate(
433 &self,
434 wasm_module: &ModuleInfo,
435 module_translation: &ModuleTranslationState,
436 signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
437 local_func_index: &LocalFunctionIndex,
438 function_body: &FunctionBodyData,
439 config: &LLVM,
440 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
441 table_styles: &PrimaryMap<TableIndex, TableStyle>,
442 symbol_registry: &ModuleBasedSymbolRegistry,
443 target: &Triple,
444 ) -> Result<CompiledFunction, CompileError> {
445 let func_index = wasm_module.func_index(*local_func_index);
446 let opt_style = if Some(func_index) == self.wasm_apply_data_relocs_fn_index {
447 OptimizationStyle::Disabled
451 } else if function_body.data.len() as u64 > WASM_LARGE_FUNCTION_THRESHOLD {
452 OptimizationStyle::ForSize
453 } else {
454 OptimizationStyle::ForSpeed
455 };
456 let module = self.translate_to_module(
457 wasm_module,
458 module_translation,
459 signature_hashes,
460 local_func_index,
461 function_body,
462 config,
463 memory_styles,
464 table_styles,
465 symbol_registry,
466 target,
467 opt_style,
468 )?;
469 let function =
470 CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
471
472 let target_machine = self.target_machines.get(&opt_style).unwrap();
473 let memory_buffer = target_machine
474 .write_to_memory_buffer(&module, FileType::Object)
475 .unwrap();
476
477 if let Some(ref callbacks) = config.callbacks {
478 let module_hash = wasm_module.hash().map(|m| m.to_string());
479 callbacks.obj_memory_buffer(&function, &module_hash, &memory_buffer);
480 let asm_buffer = target_machine
481 .write_to_memory_buffer(&module, FileType::Assembly)
482 .unwrap();
483 callbacks.asm_memory_buffer(&function, &module_hash, &asm_buffer)
484 }
485
486 let mem_buf_slice = memory_buffer.as_slice();
487
488 load_object_file(
489 mem_buf_slice,
490 &self.func_section,
491 RelocationTarget::LocalFunc(*local_func_index),
492 |name: &str| {
493 Ok({
494 let name = if matches!(self.binary_fmt, BinaryFormat::Macho) {
495 name.strip_prefix("_").unwrap_or(name)
496 } else {
497 name
498 }
499 .to_string();
500 if let Some(Symbol::LocalFunction(local_func_index)) =
501 symbol_registry.name_to_symbol(&name)
502 {
503 Some(RelocationTarget::LocalFunc(local_func_index))
504 } else {
505 None
506 }
507 })
508 },
509 self.binary_fmt,
510 )
511 }
512}
513
514impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
515 fn splat_vector(
517 &self,
518 value: BasicValueEnum<'ctx>,
519 vec_ty: VectorType<'ctx>,
520 ) -> Result<VectorValue<'ctx>, CompileError> {
521 err_nt!(
524 self.builder.build_shuffle_vector(
525 err!(self.builder.build_insert_element(
526 vec_ty.get_undef(),
527 value,
528 self.intrinsics.i32_zero,
529 "",
530 )),
531 vec_ty.get_undef(),
532 self.intrinsics
533 .i32_ty
534 .vec_type(vec_ty.get_size())
535 .const_zero(),
536 "",
537 )
538 )
539 }
540
541 #[allow(clippy::too_many_arguments)]
544 fn trunc_sat<T: FloatMathType<'ctx>>(
545 &self,
546 fvec_ty: T,
547 ivec_ty: T::MathConvType,
548 lower_bound: u64, upper_bound: u64, int_min_value: u64,
551 int_max_value: u64,
552 value: IntValue<'ctx>,
553 ) -> Result<VectorValue<'ctx>, CompileError> {
554 let fvec_ty = fvec_ty.as_basic_type_enum().into_vector_type();
568 let ivec_ty = ivec_ty.as_basic_type_enum().into_vector_type();
569 let fvec_element_ty = fvec_ty.get_element_type().into_float_type();
570 let ivec_element_ty = ivec_ty.get_element_type().into_int_type();
571
572 let is_signed = int_min_value != 0;
573 let int_min_value = self.splat_vector(
574 ivec_element_ty
575 .const_int(int_min_value, is_signed)
576 .as_basic_value_enum(),
577 ivec_ty,
578 )?;
579 let int_max_value = self.splat_vector(
580 ivec_element_ty
581 .const_int(int_max_value, is_signed)
582 .as_basic_value_enum(),
583 ivec_ty,
584 )?;
585 let lower_bound = if is_signed {
586 err!(self.builder.build_signed_int_to_float(
587 ivec_element_ty.const_int(lower_bound, is_signed),
588 fvec_element_ty,
589 "",
590 ))
591 } else {
592 err!(self.builder.build_unsigned_int_to_float(
593 ivec_element_ty.const_int(lower_bound, is_signed),
594 fvec_element_ty,
595 "",
596 ))
597 };
598 let upper_bound = if is_signed {
599 err!(self.builder.build_signed_int_to_float(
600 ivec_element_ty.const_int(upper_bound, is_signed),
601 fvec_element_ty,
602 "",
603 ))
604 } else {
605 err!(self.builder.build_unsigned_int_to_float(
606 ivec_element_ty.const_int(upper_bound, is_signed),
607 fvec_element_ty,
608 "",
609 ))
610 };
611
612 let value = err!(self.builder.build_bit_cast(value, fvec_ty, "")).into_vector_value();
613 let zero = fvec_ty.const_zero();
614 let lower_bound = self.splat_vector(lower_bound.as_basic_value_enum(), fvec_ty)?;
615 let upper_bound = self.splat_vector(upper_bound.as_basic_value_enum(), fvec_ty)?;
616 let nan_cmp =
617 err!(
618 self.builder
619 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
620 );
621 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
622 FloatPredicate::OGT,
623 value,
624 upper_bound,
625 "above_upper_bound",
626 ));
627 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
628 FloatPredicate::OLT,
629 value,
630 lower_bound,
631 "below_lower_bound",
632 ));
633 let not_representable = err!(self.builder.build_or(
634 err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
635 below_lower_bound_cmp,
636 "not_representable_as_int",
637 ));
638 let value =
639 err!(
640 self.builder
641 .build_select(not_representable, zero, value, "safe_to_convert")
642 )
643 .into_vector_value();
644 let value = if is_signed {
645 self.builder
646 .build_float_to_signed_int(value, ivec_ty, "as_int")
647 } else {
648 self.builder
649 .build_float_to_unsigned_int(value, ivec_ty, "as_int")
650 };
651
652 let value = err!(value);
653 let value =
654 err!(
655 self.builder
656 .build_select(above_upper_bound_cmp, int_max_value, value, "")
657 )
658 .into_vector_value();
659 err_nt!(
660 self.builder
661 .build_select(below_lower_bound_cmp, int_min_value, value, "")
662 .map(|v| v.into_vector_value())
663 )
664 }
665
666 #[allow(clippy::too_many_arguments)]
669 fn trunc_sat_into_int<T: FloatMathType<'ctx>>(
670 &self,
671 fvec_ty: T,
672 ivec_ty: T::MathConvType,
673 lower_bound: u64, upper_bound: u64, int_min_value: u64,
676 int_max_value: u64,
677 value: IntValue<'ctx>,
678 ) -> Result<IntValue<'ctx>, CompileError> {
679 let res = self.trunc_sat(
680 fvec_ty,
681 ivec_ty,
682 lower_bound,
683 upper_bound,
684 int_min_value,
685 int_max_value,
686 value,
687 )?;
688 err_nt!(
689 self.builder
690 .build_bit_cast(res, self.intrinsics.i128_ty, "")
691 .map(|v| v.into_int_value())
692 )
693 }
694
695 fn trunc_sat_scalar(
698 &self,
699 int_ty: IntType<'ctx>,
700 lower_bound: u64, upper_bound: u64, int_min_value: u64,
703 int_max_value: u64,
704 value: FloatValue<'ctx>,
705 ) -> Result<IntValue<'ctx>, CompileError> {
706 let is_signed = int_min_value != 0;
722 let int_min_value = int_ty.const_int(int_min_value, is_signed);
723 let int_max_value = int_ty.const_int(int_max_value, is_signed);
724
725 let lower_bound = if is_signed {
726 err!(self.builder.build_signed_int_to_float(
727 int_ty.const_int(lower_bound, is_signed),
728 value.get_type(),
729 "",
730 ))
731 } else {
732 err!(self.builder.build_unsigned_int_to_float(
733 int_ty.const_int(lower_bound, is_signed),
734 value.get_type(),
735 "",
736 ))
737 };
738 let upper_bound = if is_signed {
739 err!(self.builder.build_signed_int_to_float(
740 int_ty.const_int(upper_bound, is_signed),
741 value.get_type(),
742 "",
743 ))
744 } else {
745 err!(self.builder.build_unsigned_int_to_float(
746 int_ty.const_int(upper_bound, is_signed),
747 value.get_type(),
748 "",
749 ))
750 };
751
752 let zero = value.get_type().const_zero();
753
754 let nan_cmp =
755 err!(
756 self.builder
757 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
758 );
759 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
760 FloatPredicate::OGT,
761 value,
762 upper_bound,
763 "above_upper_bound",
764 ));
765 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
766 FloatPredicate::OLT,
767 value,
768 lower_bound,
769 "below_lower_bound",
770 ));
771 let not_representable = err!(self.builder.build_or(
772 err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
773 below_lower_bound_cmp,
774 "not_representable_as_int",
775 ));
776 let value =
777 err!(
778 self.builder
779 .build_select(not_representable, zero, value, "safe_to_convert")
780 )
781 .into_float_value();
782 let value = if is_signed {
783 err!(
784 self.builder
785 .build_float_to_signed_int(value, int_ty, "as_int")
786 )
787 } else {
788 err!(
789 self.builder
790 .build_float_to_unsigned_int(value, int_ty, "as_int")
791 )
792 };
793 let value =
794 err!(
795 self.builder
796 .build_select(above_upper_bound_cmp, int_max_value, value, "")
797 )
798 .into_int_value();
799 let value =
800 err!(
801 self.builder
802 .build_select(below_lower_bound_cmp, int_min_value, value, "")
803 )
804 .into_int_value();
805
806 err_nt!(
807 self.builder
808 .build_bit_cast(value, int_ty, "")
809 .map(|v| v.into_int_value())
810 )
811 }
812
813 fn trap_if_not_representable_as_int(
814 &self,
815 lower_bound: u64, upper_bound: u64, value: FloatValue<'ctx>,
818 ) -> Result<(), CompileError> {
819 let float_ty = value.get_type();
820 let int_ty = if float_ty == self.intrinsics.f32_ty {
821 self.intrinsics.i32_ty
822 } else {
823 self.intrinsics.i64_ty
824 };
825
826 let lower_bound = err!(self.builder.build_bit_cast(
827 int_ty.const_int(lower_bound, false),
828 float_ty,
829 ""
830 ))
831 .into_float_value();
832 let upper_bound = err!(self.builder.build_bit_cast(
833 int_ty.const_int(upper_bound, false),
834 float_ty,
835 ""
836 ))
837 .into_float_value();
838
839 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
843 FloatPredicate::UGT,
844 value,
845 upper_bound,
846 "above_upper_bound",
847 ));
848 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
849 FloatPredicate::ULT,
850 value,
851 lower_bound,
852 "below_lower_bound",
853 ));
854 let out_of_bounds = err!(self.builder.build_or(
855 above_upper_bound_cmp,
856 below_lower_bound_cmp,
857 "out_of_bounds",
858 ));
859
860 let failure_block = self
861 .context
862 .append_basic_block(self.function, "conversion_failure_block");
863 let continue_block = self
864 .context
865 .append_basic_block(self.function, "conversion_success_block");
866
867 err!(
868 self.builder
869 .build_conditional_branch(out_of_bounds, failure_block, continue_block)
870 );
871 self.builder.position_at_end(failure_block);
872 let is_nan =
873 err!(
874 self.builder
875 .build_float_compare(FloatPredicate::UNO, value, value, "is_nan")
876 );
877 let trap_code = err!(self.builder.build_select(
878 is_nan,
879 self.intrinsics.trap_bad_conversion_to_integer,
880 self.intrinsics.trap_illegal_arithmetic,
881 "",
882 ));
883 self.build_call_with_param_attributes(
884 self.intrinsics.throw_trap,
885 &[trap_code.into()],
886 "throw",
887 )?;
888 err!(self.builder.build_unreachable());
889 self.builder.position_at_end(continue_block);
890
891 Ok(())
892 }
893
894 fn trap_if_zero_or_overflow(
895 &self,
896 left: IntValue<'ctx>,
897 right: IntValue<'ctx>,
898 ) -> Result<(), CompileError> {
899 let int_type = left.get_type();
900
901 let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
902 let min_value = int_type.const_int(i32::MIN as u64, false);
903 let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
904 (min_value, neg_one_value)
905 } else if int_type == self.intrinsics.i64_ty {
906 let min_value = int_type.const_int(i64::MIN as u64, false);
907 let neg_one_value = int_type.const_int(-1i64 as u64, false);
908 (min_value, neg_one_value)
909 } else {
910 unreachable!()
911 };
912
913 let divisor_is_zero = err!(self.builder.build_int_compare(
914 IntPredicate::EQ,
915 right,
916 int_type.const_zero(),
917 "divisor_is_zero",
918 ));
919 let should_trap = err!(self.builder.build_or(
920 divisor_is_zero,
921 err!(self.builder.build_and(
922 err!(self.builder.build_int_compare(
923 IntPredicate::EQ,
924 left,
925 min_value,
926 "left_is_min"
927 )),
928 err!(self.builder.build_int_compare(
929 IntPredicate::EQ,
930 right,
931 neg_one_value,
932 "right_is_neg_one",
933 )),
934 "div_will_overflow",
935 )),
936 "div_should_trap",
937 ));
938
939 let should_trap = self
940 .build_call_with_param_attributes(
941 self.intrinsics.expect_i1,
942 &[
943 should_trap.into(),
944 self.intrinsics.i1_ty.const_zero().into(),
945 ],
946 "should_trap_expect",
947 )?
948 .try_as_basic_value()
949 .unwrap_basic()
950 .into_int_value();
951
952 let shouldnt_trap_block = self
953 .context
954 .append_basic_block(self.function, "shouldnt_trap_block");
955 let should_trap_block = self
956 .context
957 .append_basic_block(self.function, "should_trap_block");
958 err!(self.builder.build_conditional_branch(
959 should_trap,
960 should_trap_block,
961 shouldnt_trap_block
962 ));
963 self.builder.position_at_end(should_trap_block);
964 let trap_code = err!(self.builder.build_select(
965 divisor_is_zero,
966 self.intrinsics.trap_integer_division_by_zero,
967 self.intrinsics.trap_illegal_arithmetic,
968 "",
969 ));
970 err!(
971 self.builder
972 .build_call(self.intrinsics.throw_trap, &[trap_code.into()], "throw")
973 );
974 err!(self.builder.build_unreachable());
975 self.builder.position_at_end(shouldnt_trap_block);
976
977 Ok(())
978 }
979
980 fn trap_if_zero(&self, value: IntValue<'ctx>) -> Result<(), CompileError> {
981 let int_type = value.get_type();
982 let should_trap = err!(self.builder.build_int_compare(
983 IntPredicate::EQ,
984 value,
985 int_type.const_zero(),
986 "divisor_is_zero",
987 ));
988
989 let should_trap = self
990 .build_call_with_param_attributes(
991 self.intrinsics.expect_i1,
992 &[
993 should_trap.into(),
994 self.intrinsics.i1_ty.const_zero().into(),
995 ],
996 "should_trap_expect",
997 )?
998 .try_as_basic_value()
999 .unwrap_basic()
1000 .into_int_value();
1001
1002 let shouldnt_trap_block = self
1003 .context
1004 .append_basic_block(self.function, "shouldnt_trap_block");
1005 let should_trap_block = self
1006 .context
1007 .append_basic_block(self.function, "should_trap_block");
1008 err!(self.builder.build_conditional_branch(
1009 should_trap,
1010 should_trap_block,
1011 shouldnt_trap_block
1012 ));
1013 self.builder.position_at_end(should_trap_block);
1014 self.build_call_with_param_attributes(
1015 self.intrinsics.throw_trap,
1016 &[self.intrinsics.trap_integer_division_by_zero.into()],
1017 "throw",
1018 )?;
1019 err!(self.builder.build_unreachable());
1020 self.builder.position_at_end(shouldnt_trap_block);
1021
1022 Ok(())
1023 }
1024
1025 fn v128_into_int_vec(
1026 &self,
1027 value: BasicValueEnum<'ctx>,
1028 info: ExtraInfo,
1029 int_vec_ty: VectorType<'ctx>,
1030 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1031 let (value, info) = if self.config.enable_nan_canonicalization {
1032 if info.has_pending_f32_nan() {
1033 let value = err!(
1034 self.builder
1035 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1036 );
1037 (self.canonicalize_nans(value)?, info.strip_pending())
1038 } else if info.has_pending_f64_nan() {
1039 let value = err!(
1040 self.builder
1041 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1042 );
1043 (self.canonicalize_nans(value)?, info.strip_pending())
1044 } else {
1045 (value, info)
1046 }
1047 } else {
1048 (value, info)
1049 };
1050 Ok((
1051 err!(self.builder.build_bit_cast(value, int_vec_ty, "")).into_vector_value(),
1052 info,
1053 ))
1054 }
1055
1056 fn v128_into_i8x16(
1057 &self,
1058 value: BasicValueEnum<'ctx>,
1059 info: ExtraInfo,
1060 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1061 self.v128_into_int_vec(value, info, self.intrinsics.i8x16_ty)
1062 }
1063
1064 fn v128_into_i16x8(
1065 &self,
1066 value: BasicValueEnum<'ctx>,
1067 info: ExtraInfo,
1068 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1069 self.v128_into_int_vec(value, info, self.intrinsics.i16x8_ty)
1070 }
1071
1072 fn v128_into_i32x4(
1073 &self,
1074 value: BasicValueEnum<'ctx>,
1075 info: ExtraInfo,
1076 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1077 self.v128_into_int_vec(value, info, self.intrinsics.i32x4_ty)
1078 }
1079
1080 fn v128_into_i64x2(
1081 &self,
1082 value: BasicValueEnum<'ctx>,
1083 info: ExtraInfo,
1084 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1085 self.v128_into_int_vec(value, info, self.intrinsics.i64x2_ty)
1086 }
1087
1088 fn v128_into_f32x4(
1091 &self,
1092 value: BasicValueEnum<'ctx>,
1093 info: ExtraInfo,
1094 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1095 let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f64_nan()
1096 {
1097 let value = err!(
1098 self.builder
1099 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1100 );
1101 (self.canonicalize_nans(value)?, info.strip_pending())
1102 } else {
1103 (value, info)
1104 };
1105 Ok((
1106 err!(
1107 self.builder
1108 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1109 )
1110 .into_vector_value(),
1111 info,
1112 ))
1113 }
1114
1115 fn v128_into_f64x2(
1118 &self,
1119 value: BasicValueEnum<'ctx>,
1120 info: ExtraInfo,
1121 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1122 let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f32_nan()
1123 {
1124 let value = err!(
1125 self.builder
1126 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1127 );
1128 (self.canonicalize_nans(value)?, info.strip_pending())
1129 } else {
1130 (value, info)
1131 };
1132 Ok((
1133 err!(
1134 self.builder
1135 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1136 )
1137 .into_vector_value(),
1138 info,
1139 ))
1140 }
1141
1142 fn apply_pending_canonicalization(
1143 &self,
1144 value: BasicValueEnum<'ctx>,
1145 info: ExtraInfo,
1146 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1147 if !self.config.enable_nan_canonicalization {
1148 return Ok(value);
1149 }
1150
1151 if info.has_pending_f32_nan() {
1152 if value.get_type().is_vector_type()
1153 || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1154 {
1155 let ty = value.get_type();
1156 let value = err!(
1157 self.builder
1158 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1159 );
1160 let value = self.canonicalize_nans(value)?;
1161 err_nt!(self.builder.build_bit_cast(value, ty, ""))
1162 } else {
1163 self.canonicalize_nans(value)
1164 }
1165 } else if info.has_pending_f64_nan() {
1166 if value.get_type().is_vector_type()
1167 || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1168 {
1169 let ty = value.get_type();
1170 let value = err!(
1171 self.builder
1172 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1173 );
1174 let value = self.canonicalize_nans(value)?;
1175 err_nt!(self.builder.build_bit_cast(value, ty, ""))
1176 } else {
1177 self.canonicalize_nans(value)
1178 }
1179 } else {
1180 Ok(value)
1181 }
1182 }
1183
1184 fn canonicalize_nans(
1186 &self,
1187 value: BasicValueEnum<'ctx>,
1188 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1189 if !self.config.enable_nan_canonicalization {
1190 return Ok(value);
1191 }
1192
1193 let f_ty = value.get_type();
1194 if f_ty.is_vector_type() {
1195 let value = value.into_vector_value();
1196 let f_ty = f_ty.into_vector_type();
1197 let zero = f_ty.const_zero();
1198 let nan_cmp =
1199 err!(
1200 self.builder
1201 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1202 );
1203 let canonical_qnan = f_ty
1204 .get_element_type()
1205 .into_float_type()
1206 .const_float(f64::NAN);
1207 let canonical_qnan = self.splat_vector(canonical_qnan.as_basic_value_enum(), f_ty)?;
1208 err_nt!(
1209 self.builder
1210 .build_select(nan_cmp, canonical_qnan, value, "")
1211 .map(|v| v.as_basic_value_enum())
1212 )
1213 } else {
1214 let value = value.into_float_value();
1215 let f_ty = f_ty.into_float_type();
1216 let zero = f_ty.const_zero();
1217 let nan_cmp =
1218 err!(
1219 self.builder
1220 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1221 );
1222 let canonical_qnan = f_ty.const_float(f64::NAN);
1223 err_nt!(
1224 self.builder
1225 .build_select(nan_cmp, canonical_qnan, value, "")
1226 .map(|v| v.as_basic_value_enum())
1227 )
1228 }
1229 }
1230
1231 fn mark_memaccess_nodelete(
1235 &mut self,
1236 memory_index: MemoryIndex,
1237 memaccess: InstructionValue<'ctx>,
1238 ) -> Result<(), CompileError> {
1239 if let MemoryCache::Static { base_ptr: _ } = self.ctx.memory(
1240 memory_index,
1241 self.intrinsics,
1242 self.module,
1243 self.memory_styles,
1244 )? {
1245 memaccess.set_volatile(true).map_err(|err| {
1247 CompileError::Codegen(format!("could not set volatile on memory operation: {err}"))
1248 })
1249 } else {
1250 Ok(())
1251 }
1252 }
1253
1254 fn annotate_user_memaccess(
1255 &mut self,
1256 memory_index: MemoryIndex,
1257 _memarg: &MemArg,
1258 alignment: u32,
1259 memaccess: InstructionValue<'ctx>,
1260 ) -> Result<(), CompileError> {
1261 match memaccess.get_opcode() {
1262 InstructionOpcode::Load | InstructionOpcode::Store => {
1263 memaccess.set_alignment(alignment).unwrap();
1264 }
1265 _ => {}
1266 };
1267 if !self.non_volatile_memory_ops {
1268 self.mark_memaccess_nodelete(memory_index, memaccess)?;
1269 }
1270 tbaa_label(
1271 self.module,
1272 self.intrinsics,
1273 format!("memory {}", memory_index.as_u32()),
1274 memaccess,
1275 );
1276 Ok(())
1277 }
1278
1279 fn resolve_memory_ptr(
1280 &mut self,
1281 memory_index: MemoryIndex,
1282 memarg: &MemArg,
1283 ptr_ty: PointerType<'ctx>,
1284 var_offset: IntValue<'ctx>,
1285 value_size: usize,
1286 ) -> Result<PointerValue<'ctx>, CompileError> {
1287 let builder = &self.builder;
1288 let intrinsics = &self.intrinsics;
1289 let context = &self.context;
1290 let function = &self.function;
1291
1292 let imm_offset = intrinsics.i64_ty.const_int(memarg.offset, false);
1294 let var_offset = err!(builder.build_int_z_extend(var_offset, intrinsics.i64_ty, ""));
1295 let offset = err!(builder.build_int_add(var_offset, imm_offset, ""));
1296
1297 let base_ptr = if let Some(m0) = self.m0_param {
1299 m0
1300 } else {
1301 match self
1302 .ctx
1303 .memory(memory_index, intrinsics, self.module, self.memory_styles)?
1304 {
1305 MemoryCache::Dynamic {
1306 ptr_to_base_ptr,
1307 ptr_to_current_length,
1308 } => {
1309 let minimum = self.wasm_module.memories[memory_index].minimum;
1311 let value_size_v = intrinsics.i64_ty.const_int(value_size as u64, false);
1312 let ptr_in_bounds = if offset.is_const() {
1313 let load_offset_end =
1316 offset.const_add(value_size_v).get_zero_extended_constant();
1317 if load_offset_end.is_some_and(|load_offset_end| {
1318 load_offset_end <= minimum.bytes().0 as u64
1319 }) {
1320 Some(intrinsics.i64_ty.const_int(1, false))
1321 } else {
1322 None
1323 }
1324 } else {
1325 None
1326 };
1327
1328 let ptr_in_bounds = match ptr_in_bounds {
1329 Some(ptr) => ptr,
1330 None => {
1331 let load_offset_end = err!(builder.build_int_add(
1332 offset,
1333 value_size_v,
1334 "load_offset_end"
1335 ));
1336
1337 let current_length = err!(builder.build_load(
1338 self.intrinsics.i32_ty,
1339 ptr_to_current_length,
1340 "current_length"
1341 ))
1342 .into_int_value();
1343 tbaa_label(
1344 self.module,
1345 self.intrinsics,
1346 format!("memory {} length", memory_index.as_u32()),
1347 current_length.as_instruction_value().unwrap(),
1348 );
1349 let current_length = err!(builder.build_int_z_extend(
1350 current_length,
1351 intrinsics.i64_ty,
1352 "current_length_zextd"
1353 ));
1354
1355 err!(builder.build_int_compare(
1356 IntPredicate::ULE,
1357 load_offset_end,
1358 current_length,
1359 "ptr_in_bounds",
1360 ))
1361 }
1362 };
1363
1364 if !ptr_in_bounds.is_constant_int()
1365 || ptr_in_bounds.get_zero_extended_constant().unwrap() != 1
1366 {
1367 let ptr_in_bounds = err!(self.build_call_with_param_attributes(
1373 intrinsics.expect_i1,
1374 &[
1375 ptr_in_bounds.into(),
1376 intrinsics.i1_ty.const_int(1, true).into(),
1377 ],
1378 "ptr_in_bounds_expect",
1379 ))
1380 .try_as_basic_value()
1381 .unwrap_basic()
1382 .into_int_value();
1383
1384 let in_bounds_continue_block =
1385 context.append_basic_block(*function, "in_bounds_continue_block");
1386 let not_in_bounds_block =
1387 context.append_basic_block(*function, "not_in_bounds_block");
1388 err!(builder.build_conditional_branch(
1389 ptr_in_bounds,
1390 in_bounds_continue_block,
1391 not_in_bounds_block,
1392 ));
1393 builder.position_at_end(not_in_bounds_block);
1394 err!(self.build_call_with_param_attributes(
1395 intrinsics.throw_trap,
1396 &[intrinsics.trap_memory_oob.into()],
1397 "throw",
1398 ));
1399 err!(builder.build_unreachable());
1400 builder.position_at_end(in_bounds_continue_block);
1401 }
1402 let ptr_to_base =
1403 err!(builder.build_load(intrinsics.ptr_ty, ptr_to_base_ptr, "ptr_to_base"))
1404 .into_pointer_value();
1405 tbaa_label(
1406 self.module,
1407 self.intrinsics,
1408 format!("memory base_ptr {}", memory_index.as_u32()),
1409 ptr_to_base.as_instruction_value().unwrap(),
1410 );
1411 ptr_to_base
1412 }
1413 MemoryCache::Static { base_ptr } => base_ptr,
1414 }
1415 };
1416 let value_ptr = unsafe {
1417 err!(builder.build_gep(self.intrinsics.i8_ty, base_ptr, &[offset], "mem_value_ptr"))
1418 };
1419 err_nt!(
1420 builder
1421 .build_bit_cast(value_ptr, ptr_ty, "mem_value")
1422 .map(|v| v.into_pointer_value())
1423 )
1424 }
1425
1426 fn trap_if_misaligned(
1427 &self,
1428 _memarg: &MemArg,
1429 ptr: PointerValue<'ctx>,
1430 align: u8,
1431 ) -> Result<(), CompileError> {
1432 if align <= 1 {
1433 return Ok(());
1434 }
1435 let value = err!(self.builder.build_ptr_to_int(
1436 ptr,
1437 self.intrinsics.i64_ty,
1438 "mischeck_value"
1439 ));
1440 let and = err!(self.builder.build_and(
1441 value,
1442 self.intrinsics.i64_ty.const_int((align - 1).into(), false),
1443 "misaligncheck",
1444 ));
1445 let aligned = err!(self.builder.build_int_compare(
1446 IntPredicate::EQ,
1447 and,
1448 self.intrinsics.i64_zero,
1449 "is_aligned"
1450 ));
1451 let aligned = self
1452 .build_call_with_param_attributes(
1453 self.intrinsics.expect_i1,
1454 &[
1455 aligned.into(),
1456 self.intrinsics.i1_ty.const_int(1, false).into(),
1457 ],
1458 "is_aligned_expect",
1459 )?
1460 .try_as_basic_value()
1461 .unwrap_basic()
1462 .into_int_value();
1463
1464 let continue_block = self
1465 .context
1466 .append_basic_block(self.function, "aligned_access_continue_block");
1467 let not_aligned_block = self
1468 .context
1469 .append_basic_block(self.function, "misaligned_trap_block");
1470 err!(
1471 self.builder
1472 .build_conditional_branch(aligned, continue_block, not_aligned_block)
1473 );
1474
1475 self.builder.position_at_end(not_aligned_block);
1476 self.build_call_with_param_attributes(
1477 self.intrinsics.throw_trap,
1478 &[self.intrinsics.trap_unaligned_atomic.into()],
1479 "throw",
1480 )?;
1481 err!(self.builder.build_unreachable());
1482
1483 self.builder.position_at_end(continue_block);
1484 Ok(())
1485 }
1486
1487 fn finalize(&mut self, wasm_fn_type: &FunctionType) -> Result<(), CompileError> {
1488 let func_type = self.function.get_type();
1489
1490 let results = self.state.popn_save_extra(wasm_fn_type.results().len())?;
1491 let results = err!(
1492 results
1493 .into_iter()
1494 .map(|(v, i)| self.apply_pending_canonicalization(v, i))
1495 .collect::<Result<Vec<_>, _>>()
1496 );
1497
1498 if wasm_fn_type.results().is_empty() {
1499 err!(self.builder.build_return(None));
1500 } else if self.abi.is_sret(wasm_fn_type)? {
1501 let sret = self
1502 .function
1503 .get_first_param()
1504 .unwrap()
1505 .into_pointer_value();
1506 let llvm_params: Vec<_> = wasm_fn_type
1507 .results()
1508 .iter()
1509 .map(|x| type_to_llvm(self.intrinsics, *x).unwrap())
1510 .collect();
1511 let mut struct_value = self
1512 .context
1513 .struct_type(llvm_params.as_slice(), false)
1514 .get_undef();
1515 for (idx, value) in results.into_iter().enumerate() {
1516 let value = err!(self.builder.build_bit_cast(
1517 value,
1518 type_to_llvm(self.intrinsics, wasm_fn_type.results()[idx])?,
1519 "",
1520 ));
1521 struct_value =
1522 err!(
1523 self.builder
1524 .build_insert_value(struct_value, value, idx as u32, "")
1525 )
1526 .into_struct_value();
1527 }
1528 err!(self.builder.build_store(sret, struct_value));
1529 err!(self.builder.build_return(None));
1530 } else {
1531 err!(
1532 self.builder
1533 .build_return(Some(&self.abi.pack_values_for_register_return(
1534 self.intrinsics,
1535 &self.builder,
1536 &results,
1537 &func_type,
1538 )?))
1539 );
1540 }
1541 Ok(())
1542 }
1543
1544 fn get_or_insert_tag_type_info_global(&mut self, tag: i32) -> BasicValueEnum<'ctx> {
1547 if let Some(tag) = self.tags_cache.get(&tag) {
1548 return *tag;
1549 }
1550
1551 let tag_ty = self
1552 .context
1553 .struct_type(&[self.intrinsics.i32_ty.into()], false);
1554 let tag_glbl = self.module.add_global(
1555 tag_ty,
1556 Some(AddressSpace::default()),
1557 &format!("__wasmer_eh_type_info_{tag}"),
1558 );
1559 tag_glbl.set_initializer(
1560 &tag_ty
1561 .const_named_struct(&[self.intrinsics.i32_ty.const_int(tag as _, false).into()])
1562 .as_basic_value_enum(),
1563 );
1564
1565 tag_glbl.set_linkage(Linkage::External);
1566 tag_glbl.set_constant(true);
1567 if matches!(self.binary_fmt, target_lexicon::BinaryFormat::Macho) {
1575 tag_glbl.set_section(Some(&format!("{FUNCTION_SECTION_MACHO},_eh_ti_{tag}")));
1576 }
1577
1578 let tag_glbl = tag_glbl.as_basic_value_enum();
1579
1580 self.tags_cache.insert(tag, tag_glbl);
1581 tag_glbl
1582 }
1583
1584 fn emit_return_call(
1585 &mut self,
1586 call_site: CallSiteValue<'ctx>,
1587 callee_llvm_func_type: inkwell::types::FunctionType<'ctx>,
1588 ) -> Result<(), CompileError> {
1589 let tail_call_kind = if self.function.get_type() == callee_llvm_func_type {
1596 LLVMTailCallKind::LLVMTailCallKindMustTail
1597 } else {
1598 LLVMTailCallKind::LLVMTailCallKindTail
1599 };
1600 call_site.set_tail_call_kind(tail_call_kind);
1601
1602 if self.function.get_type().get_return_type().is_none() {
1603 err!(self.builder.build_return(None));
1604 } else {
1605 let ret = call_site.try_as_basic_value();
1606 if ret.is_instruction() {
1607 return Err(CompileError::Codegen(
1608 "return_call expected a non-void call result".to_string(),
1609 ));
1610 }
1611 err!(self.builder.build_return(Some(&ret.unwrap_basic())));
1612 }
1613 Ok(())
1614 }
1615
1616 fn current_sret_ptr(&self, func_type: &FunctionType) -> Option<PointerValue<'ctx>> {
1618 self.abi.is_sret(func_type).ok().map(|_| {
1619 self.function
1620 .get_first_param()
1621 .unwrap()
1622 .into_pointer_value()
1623 })
1624 }
1625
1626 fn build_m0_indirect_call(
1627 &mut self,
1628 table_index: u32,
1629 ctx_ptr: PointerValue<'ctx>,
1630 func_type: &FunctionType,
1631 func_ptr: PointerValue<'ctx>,
1632 func_index: IntValue<'ctx>,
1633 is_return_call: bool,
1634 ) -> Result<(), CompileError> {
1635 let Some(m0) = self.m0_param else {
1636 return Err(CompileError::Codegen(
1637 "Call to build_m0_indirect_call without m0 parameter!".to_string(),
1638 ));
1639 };
1640
1641 let params = self.state.popn_save_extra(func_type.params().len())?;
1642
1643 let mut local_func_indices = vec![];
1644 let mut foreign_func_indices = vec![];
1645
1646 for t in &self.wasm_module.table_initializers {
1647 if t.table_index.as_u32() == table_index {
1648 for (func_in_table_idx, func_idx) in t.elements.iter().enumerate() {
1649 if self.wasm_module.local_func_index(*func_idx).is_some() {
1650 local_func_indices.push(func_in_table_idx)
1651 } else {
1652 foreign_func_indices.push(func_in_table_idx)
1653 }
1654 }
1655 break;
1656 }
1657 }
1658
1659 let needs_switch = self.m0_param.is_some()
1660 && !local_func_indices.is_empty()
1661 && !foreign_func_indices.is_empty();
1662
1663 if needs_switch {
1664 let foreign_idx_block = self
1665 .context
1666 .append_basic_block(self.function, "foreign_call_block");
1667 let local_idx_block = self
1668 .context
1669 .append_basic_block(self.function, "local_call_block");
1670 let unreachable_indirect_call_branch_block = self
1671 .context
1672 .append_basic_block(self.function, "unreachable_indirect_call_branch");
1673
1674 let cont =
1675 (!is_return_call).then(|| self.context.append_basic_block(self.function, "cont"));
1676
1677 err!(
1678 self.builder.build_switch(
1679 func_index,
1680 unreachable_indirect_call_branch_block,
1681 &local_func_indices
1682 .into_iter()
1683 .map(|v| (
1684 self.intrinsics.i32_ty.const_int(v as _, false),
1685 local_idx_block
1686 ))
1687 .chain(foreign_func_indices.into_iter().map(|v| (
1688 self.intrinsics.i32_ty.const_int(v as _, false),
1689 foreign_idx_block
1690 )))
1691 .collect::<Vec<_>>()
1692 )
1693 );
1694
1695 self.builder
1696 .position_at_end(unreachable_indirect_call_branch_block);
1697 err!(self.builder.build_unreachable());
1698
1699 self.builder.position_at_end(local_idx_block);
1701 let (local_call_site, local_llvm_func_type) = self.build_indirect_call_with_params(
1702 ctx_ptr,
1703 func_type,
1704 func_ptr,
1705 Some(m0),
1706 is_return_call,
1707 ¶ms,
1708 )?;
1709
1710 let local_rets = if is_return_call {
1711 self.emit_return_call(local_call_site, local_llvm_func_type)?;
1712 Vec::new()
1713 } else {
1714 let rets = self.abi.rets_from_call(
1715 &self.builder,
1716 self.intrinsics,
1717 local_call_site,
1718 func_type,
1719 )?;
1720 err!(
1721 self.builder
1722 .build_unconditional_branch(cont.expect("non-return call requires cont"))
1723 );
1724 rets
1725 };
1726
1727 self.builder.position_at_end(foreign_idx_block);
1728 let (foreign_call_site, foreign_llvm_func_type) = self
1729 .build_indirect_call_with_params(
1730 ctx_ptr,
1731 func_type,
1732 func_ptr,
1733 None,
1734 is_return_call,
1735 ¶ms,
1736 )?;
1737
1738 let foreign_rets = if is_return_call {
1739 self.emit_return_call(foreign_call_site, foreign_llvm_func_type)?;
1740 Vec::new()
1741 } else {
1742 let rets = self.abi.rets_from_call(
1743 &self.builder,
1744 self.intrinsics,
1745 foreign_call_site,
1746 func_type,
1747 )?;
1748 err!(
1749 self.builder
1750 .build_unconditional_branch(cont.expect("non-return call requires cont"))
1751 );
1752 rets
1753 };
1754
1755 if is_return_call {
1756 return Ok(());
1757 }
1758
1759 self.builder
1760 .position_at_end(cont.expect("non-return call requires cont"));
1761
1762 for i in 0..foreign_rets.len() {
1763 let f_i = foreign_rets[i];
1764 let l_i = local_rets[i];
1765 let ty = f_i.get_type();
1766 let v = err!(self.builder.build_phi(ty, ""));
1767 v.add_incoming(&[(&f_i, foreign_idx_block), (&l_i, local_idx_block)]);
1768 self.state.push1(v.as_basic_value());
1769 }
1770 } else if foreign_func_indices.is_empty() {
1771 let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
1772 ctx_ptr,
1773 func_type,
1774 func_ptr,
1775 Some(m0),
1776 is_return_call,
1777 ¶ms,
1778 )?;
1779
1780 if is_return_call {
1781 self.emit_return_call(call_site, llvm_func_type)?;
1782 } else {
1783 self.abi
1784 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
1785 .iter()
1786 .for_each(|ret| self.state.push1(*ret));
1787 }
1788 } else {
1789 let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
1790 ctx_ptr,
1791 func_type,
1792 func_ptr,
1793 None,
1794 is_return_call,
1795 ¶ms,
1796 )?;
1797 if is_return_call {
1798 self.emit_return_call(call_site, llvm_func_type)?;
1799 } else {
1800 self.abi
1801 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
1802 .iter()
1803 .for_each(|ret| self.state.push1(*ret));
1804 }
1805 }
1806
1807 Ok(())
1808 }
1809
1810 fn build_indirect_call(
1811 &mut self,
1812 ctx_ptr: PointerValue<'ctx>,
1813 func_type: &FunctionType,
1814 func_ptr: PointerValue<'ctx>,
1815 m0_param: Option<PointerValue<'ctx>>,
1816 is_return_call: bool,
1817 ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
1818 let params = self.state.popn_save_extra(func_type.params().len())?;
1819 self.build_indirect_call_with_params(
1820 ctx_ptr,
1821 func_type,
1822 func_ptr,
1823 m0_param,
1824 is_return_call,
1825 ¶ms,
1826 )
1827 }
1828
1829 fn build_indirect_call_with_params(
1830 &mut self,
1831 ctx_ptr: PointerValue<'ctx>,
1832 func_type: &FunctionType,
1833 func_ptr: PointerValue<'ctx>,
1834 m0_param: Option<PointerValue<'ctx>>,
1835 is_return_call: bool,
1836 params: &[(BasicValueEnum<'ctx>, ExtraInfo)],
1837 ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
1838 let (llvm_func_type, llvm_func_attrs) = self.abi.func_type_to_llvm(
1839 self.context,
1840 self.intrinsics,
1841 Some(self.ctx.get_offsets()),
1842 func_type,
1843 m0_param.is_some(),
1844 )?;
1845
1846 let params = params
1848 .iter()
1849 .zip(func_type.params().iter())
1850 .map(|((v, info), wasm_ty)| match wasm_ty {
1851 Type::F32 => err_nt!(self.builder.build_bit_cast(
1852 self.apply_pending_canonicalization(*v, *info)?,
1853 self.intrinsics.f32_ty,
1854 "",
1855 )),
1856 Type::F64 => err_nt!(self.builder.build_bit_cast(
1857 self.apply_pending_canonicalization(*v, *info)?,
1858 self.intrinsics.f64_ty,
1859 "",
1860 )),
1861 Type::V128 => self.apply_pending_canonicalization(*v, *info),
1862 _ => Ok(*v),
1863 })
1864 .collect::<Result<Vec<_>, _>>()?;
1865
1866 let params = self.abi.args_to_call(
1867 &self.alloca_builder,
1868 func_type,
1869 &llvm_func_type,
1870 ctx_ptr,
1871 params.as_slice(),
1872 self.intrinsics,
1873 m0_param,
1874 is_return_call
1875 .then(|| self.current_sret_ptr(func_type))
1876 .flatten(),
1877 )?;
1878
1879 let typed_func_ptr = err!(self.builder.build_pointer_cast(
1880 func_ptr,
1881 self.context.ptr_type(AddressSpace::default()),
1882 "typed_func_ptr",
1883 ));
1884
1885 let call_site_local = self.build_indirect_call_or_invoke(
1886 llvm_func_type,
1887 typed_func_ptr,
1888 params.as_slice(),
1889 "then_block",
1890 is_return_call,
1891 )?;
1892 for (attr, attr_loc) in llvm_func_attrs {
1893 call_site_local.add_attribute(attr_loc, attr);
1894 }
1895
1896 Ok((call_site_local, llvm_func_type))
1897 }
1898
1899 fn build_indirect_call_or_invoke(
1900 &mut self,
1901 llvm_func_type: inkwell::types::FunctionType<'ctx>,
1902 func_ptr: PointerValue<'ctx>,
1903 params: &[BasicValueEnum<'ctx>],
1904 then_block_name: &str,
1905 is_return_call: bool,
1906 ) -> Result<CallSiteValue<'ctx>, CompileError> {
1907 if let Some(lpad) = self.state.get_innermost_landingpad()
1910 && !is_return_call
1911 {
1912 let then_block = self
1913 .context
1914 .append_basic_block(self.function, then_block_name);
1915
1916 let ret = err!(self.builder.build_indirect_invoke(
1917 llvm_func_type,
1918 func_ptr,
1919 params,
1920 then_block,
1921 lpad,
1922 "",
1923 ));
1924
1925 self.builder.position_at_end(then_block);
1926 Ok(ret)
1927 } else {
1928 let call_params = params
1929 .iter()
1930 .copied()
1931 .map(Into::into)
1932 .collect::<Vec<BasicMetadataValueEnum>>();
1933 Ok(err!(self.builder.build_indirect_call(
1934 llvm_func_type,
1935 func_ptr,
1936 call_params.as_slice(),
1937 ""
1938 )))
1939 }
1940 }
1941}
1942
1943pub struct LLVMFunctionCodeGenerator<'ctx, 'a> {
1944 m0_param: Option<PointerValue<'ctx>>,
1945 context: &'ctx Context,
1946 builder: Builder<'ctx>,
1947 alloca_builder: Builder<'ctx>,
1948 intrinsics: &'a Intrinsics<'ctx>,
1949 state: State<'ctx>,
1950 function: FunctionValue<'ctx>,
1951 locals: Vec<(BasicTypeEnum<'ctx>, PointerValue<'ctx>)>, ctx: CtxType<'ctx, 'a>,
1953 unreachable_depth: usize,
1954 memory_styles: &'a PrimaryMap<MemoryIndex, MemoryStyle>,
1955 _table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
1956 module: &'a Module<'ctx>,
1957 module_translation: &'a ModuleTranslationState,
1958 signature_hashes: &'a PrimaryMap<SignatureIndex, SignatureHash>,
1959 wasm_module: &'a ModuleInfo,
1960 symbol_registry: &'a dyn SymbolRegistry,
1961 abi: &'a dyn Abi,
1962 config: &'a LLVM,
1963 target_triple: Triple,
1964 tags_cache: HashMap<i32, BasicValueEnum<'ctx>>,
1965 binary_fmt: target_lexicon::BinaryFormat,
1966 cpu_features: EnumSet<CpuFeature>,
1967 non_volatile_memory_ops: bool,
1968}
1969
1970impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
1971 fn quiet_nan(&self, value: BasicValueEnum<'ctx>) -> Result<BasicValueEnum<'ctx>, CompileError> {
1972 let intrinsic = if value
1973 .get_type()
1974 .eq(&self.intrinsics.f32_ty.as_basic_type_enum())
1975 {
1976 Some(self.intrinsics.add_f32)
1977 } else if value
1978 .get_type()
1979 .eq(&self.intrinsics.f64_ty.as_basic_type_enum())
1980 {
1981 Some(self.intrinsics.add_f64)
1982 } else if value
1983 .get_type()
1984 .eq(&self.intrinsics.f32x4_ty.as_basic_type_enum())
1985 {
1986 Some(self.intrinsics.add_f32x4)
1987 } else if value
1988 .get_type()
1989 .eq(&self.intrinsics.f64x2_ty.as_basic_type_enum())
1990 {
1991 Some(self.intrinsics.add_f64x2)
1992 } else {
1993 None
1994 };
1995
1996 match intrinsic {
1997 Some(intrinsic) => err_nt!(
1998 self.builder
1999 .build_call(
2000 intrinsic,
2001 &[
2002 value.into(),
2003 value.get_type().const_zero().into(),
2004 self.intrinsics.fp_rounding_md,
2005 self.intrinsics.fp_exception_md,
2006 ],
2007 "",
2008 )
2009 .map(|v| v.try_as_basic_value().unwrap_basic())
2010 ),
2011 None => Ok(value),
2012 }
2013 }
2014
2015 fn finalize_minmax_result(
2016 &self,
2017 value: BasicValueEnum<'ctx>,
2018 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
2019 let ty = value.get_type();
2020 if ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2021 || ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2022 {
2023 let value = value.into_float_value();
2024 let is_nan = err!(self.builder.build_float_compare(
2025 FloatPredicate::UNO,
2026 value,
2027 value,
2028 "res_is_nan"
2029 ));
2030 let quiet = self.quiet_nan(value.as_basic_value_enum())?;
2031 let result =
2032 err!(
2033 self.builder
2034 .build_select(is_nan, quiet, value.as_basic_value_enum(), "")
2035 );
2036 Ok(result.as_basic_value_enum())
2037 } else if ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum()) {
2038 let value = value.into_vector_value();
2039 let is_nan = self
2040 .build_call_with_param_attributes(
2041 self.intrinsics.cmp_f32x4,
2042 &[
2043 value.into(),
2044 value.into(),
2045 self.intrinsics.fp_uno_md,
2046 self.intrinsics.fp_exception_md,
2047 ],
2048 "",
2049 )?
2050 .try_as_basic_value()
2051 .unwrap_basic()
2052 .into_vector_value();
2053 let quiet = self
2054 .quiet_nan(value.as_basic_value_enum())?
2055 .into_vector_value();
2056 let result = err!(self.builder.build_select(
2057 is_nan,
2058 quiet.as_basic_value_enum(),
2059 value.as_basic_value_enum(),
2060 "",
2061 ));
2062 Ok(result.as_basic_value_enum())
2063 } else if ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum()) {
2064 let value = value.into_vector_value();
2065 let is_nan = self
2066 .build_call_with_param_attributes(
2067 self.intrinsics.cmp_f64x2,
2068 &[
2069 value.into(),
2070 value.into(),
2071 self.intrinsics.fp_uno_md,
2072 self.intrinsics.fp_exception_md,
2073 ],
2074 "",
2075 )?
2076 .try_as_basic_value()
2077 .unwrap_basic()
2078 .into_vector_value();
2079 let quiet = self
2080 .quiet_nan(value.as_basic_value_enum())?
2081 .into_vector_value();
2082 let result = err!(self.builder.build_select(
2083 is_nan,
2084 quiet.as_basic_value_enum(),
2085 value.as_basic_value_enum(),
2086 "",
2087 ));
2088 Ok(result.as_basic_value_enum())
2089 } else {
2090 Ok(value)
2091 }
2092 }
2093
2094 fn finalize_rounding_result(
2095 &self,
2096 value: BasicValueEnum<'ctx>,
2097 info: ExtraInfo,
2098 ) -> Result<(BasicValueEnum<'ctx>, ExtraInfo), CompileError> {
2099 let ty = value.get_type();
2100 let is_f32 = ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum());
2101 let is_f64 = ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum());
2102 let is_f32x4 = ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum());
2103 let is_f64x2 = ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum());
2104 debug_assert!(is_f32 || is_f64 || is_f32x4 || is_f64x2);
2105
2106 if matches!(
2107 self.target_triple.architecture,
2108 Architecture::Riscv32(..) | Architecture::Riscv64(..)
2109 ) {
2110 if is_f32 || is_f64 {
2111 let input = value.into_float_value();
2112 let is_nan = err!(self.builder.build_float_compare(
2113 FloatPredicate::UNO,
2114 input,
2115 input,
2116 "res_is_nan",
2117 ));
2118 let canonical_nan_bits = if is_f32 {
2119 self.intrinsics
2120 .i32_ty
2121 .const_int(CANONICAL_NAN_F32 as _, false)
2122 } else {
2123 self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false)
2124 };
2125 let canonical_nan = err!(self.builder.build_bit_cast(
2126 canonical_nan_bits,
2127 ty,
2128 "canonical_nan",
2129 ));
2130 let res =
2131 err!(
2132 self.builder
2133 .build_select(is_nan, canonical_nan, value, "canonical_nan",)
2134 );
2135 Ok((res, info))
2136 } else if is_f32x4 {
2137 let value = value.into_vector_value();
2138 let is_nan = err!(self.builder.build_call(
2139 self.intrinsics.cmp_f32x4,
2140 &[
2141 value.into(),
2142 value.into(),
2143 self.intrinsics.fp_uno_md,
2144 self.intrinsics.fp_exception_md,
2145 ],
2146 "",
2147 ))
2148 .try_as_basic_value()
2149 .unwrap_basic()
2150 .into_vector_value();
2151 let canonical_nan_bits = self
2152 .intrinsics
2153 .i32_ty
2154 .const_int(CANONICAL_NAN_F32 as _, false);
2155 let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 4]);
2156 let canonical_nan = err!(self.builder.build_bit_cast(
2157 canonical_nan_bits,
2158 self.intrinsics.f32x4_ty,
2159 "canonical_nan",
2160 ));
2161 let res = err!(self.builder.build_select(
2162 is_nan,
2163 canonical_nan.as_basic_value_enum(),
2164 value.as_basic_value_enum(),
2165 "canonical_nan",
2166 ));
2167 Ok((res, info))
2168 } else {
2169 let value = value.into_vector_value();
2170 let is_nan = err!(self.builder.build_call(
2171 self.intrinsics.cmp_f64x2,
2172 &[
2173 value.into(),
2174 value.into(),
2175 self.intrinsics.fp_uno_md,
2176 self.intrinsics.fp_exception_md,
2177 ],
2178 "",
2179 ))
2180 .try_as_basic_value()
2181 .unwrap_basic()
2182 .into_vector_value();
2183 let canonical_nan_bits = self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false);
2184 let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 2]);
2185 let canonical_nan = err!(self.builder.build_bit_cast(
2186 canonical_nan_bits,
2187 self.intrinsics.f64x2_ty,
2188 "canonical_nan",
2189 ));
2190 let res = err!(self.builder.build_select(
2191 is_nan,
2192 canonical_nan.as_basic_value_enum(),
2193 value.as_basic_value_enum(),
2194 "canonical_nan",
2195 ));
2196 Ok((res, info))
2197 }
2198 } else {
2199 Ok((
2200 value,
2201 (info
2202 | if is_f32 || is_f32x4 {
2203 ExtraInfo::pending_f32_nan()
2204 } else {
2205 ExtraInfo::pending_f64_nan()
2206 })?,
2207 ))
2208 }
2209 }
2210
2211 fn translate_operator(&mut self, op: Operator, _source_loc: u32) -> Result<(), CompileError> {
2212 let vmctx = &self.ctx.basic().into_pointer_value();
2215
2216 if !self.state.reachable {
2219 match op {
2220 Operator::Block { blockty: _ }
2221 | Operator::Loop { blockty: _ }
2222 | Operator::If { blockty: _ }
2223 | Operator::TryTable { .. } => {
2224 self.unreachable_depth += 1;
2225 return Ok(());
2226 }
2227 Operator::Else => {
2228 if self.unreachable_depth != 0 {
2229 return Ok(());
2230 }
2231 }
2232 Operator::End => {
2233 if self.unreachable_depth != 0 {
2234 self.unreachable_depth -= 1;
2235 return Ok(());
2236 }
2237 }
2238 _ => {
2239 return Ok(());
2240 }
2241 }
2242 }
2243
2244 match op {
2245 Operator::Block { blockty } => {
2250 let current_block = self
2251 .builder
2252 .get_insert_block()
2253 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2254
2255 let end_block = self.context.append_basic_block(self.function, "end");
2256 self.builder.position_at_end(end_block);
2257
2258 let phis: SmallVec<[PhiValue<'ctx>; 1]> = self
2259 .module_translation
2260 .blocktype_params_results(&blockty)?
2261 .1
2262 .iter()
2263 .map(|&wp_ty| {
2264 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2265 type_to_llvm(self.intrinsics, wasm_ty)
2266 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2267 })
2268 })
2269 .collect::<Result<_, _>>()?;
2270
2271 self.state.push_block(
2272 end_block,
2273 phis,
2274 self.module_translation
2275 .blocktype_params_results(&blockty)?
2276 .0
2277 .len(),
2278 );
2279 self.builder.position_at_end(current_block);
2280 }
2281 Operator::Loop { blockty } => {
2282 let loop_body = self.context.append_basic_block(self.function, "loop_body");
2283 let loop_next = self.context.append_basic_block(self.function, "loop_outer");
2284 let pre_loop_block = self.builder.get_insert_block().unwrap();
2285
2286 err!(self.builder.build_unconditional_branch(loop_body));
2287
2288 self.builder.position_at_end(loop_next);
2289 let blocktypes = self.module_translation.blocktype_params_results(&blockty)?;
2290 let phis = blocktypes
2291 .1
2292 .iter()
2293 .map(|&wp_ty| {
2294 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2295 type_to_llvm(self.intrinsics, wasm_ty)
2296 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2297 })
2298 })
2299 .collect::<Result<_, _>>()?;
2300 self.builder.position_at_end(loop_body);
2301 let loop_phis: SmallVec<[PhiValue<'ctx>; 1]> = blocktypes
2302 .0
2303 .iter()
2304 .map(|&wp_ty| {
2305 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2306 type_to_llvm(self.intrinsics, wasm_ty)
2307 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2308 })
2309 })
2310 .collect::<Result<_, _>>()?;
2311 for phi in loop_phis.iter().rev() {
2312 let (value, info) = self.state.pop1_extra()?;
2313 let value = self.apply_pending_canonicalization(value, info)?;
2314 phi.add_incoming(&[(&value, pre_loop_block)]);
2315 }
2316 for phi in &loop_phis {
2317 self.state.push1(phi.as_basic_value());
2318 }
2319
2320 let num_inputs = loop_phis.len();
2321 self.state
2322 .push_loop(loop_body, loop_next, loop_phis, phis, num_inputs);
2323 }
2324 Operator::Br { relative_depth } => {
2325 let frame = self.state.frame_at_depth(relative_depth)?;
2326
2327 let current_block = self
2328 .builder
2329 .get_insert_block()
2330 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2331
2332 let phis = if frame.is_loop() {
2333 frame.loop_body_phis()
2334 } else {
2335 frame.phis()
2336 };
2337
2338 let len = phis.len();
2339 let values = self.state.peekn_extra(len)?;
2340 let values = values
2341 .iter()
2342 .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2343 .collect::<Result<Vec<_>, _>>()?;
2344
2345 for (phi, value) in phis.iter().zip(values) {
2349 phi.add_incoming(&[(&value, current_block)]);
2350 }
2351
2352 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2353
2354 self.state.popn(len)?;
2355 self.state.reachable = false;
2356 }
2357 Operator::BrIf { relative_depth } => {
2358 let cond = self.state.pop1()?;
2359 let frame = self.state.frame_at_depth(relative_depth)?;
2360
2361 let current_block = self
2362 .builder
2363 .get_insert_block()
2364 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2365
2366 let phis = if frame.is_loop() {
2367 frame.loop_body_phis()
2368 } else {
2369 frame.phis()
2370 };
2371
2372 let param_stack = self.state.peekn_extra(phis.len())?;
2373 let param_stack = param_stack
2374 .iter()
2375 .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2376 .collect::<Result<Vec<_>, _>>()?;
2377
2378 for (phi, value) in phis.iter().zip(param_stack) {
2379 phi.add_incoming(&[(&value, current_block)]);
2380 }
2381
2382 let else_block = self.context.append_basic_block(self.function, "else");
2383
2384 let cond_value = err!(self.builder.build_int_compare(
2385 IntPredicate::NE,
2386 cond.into_int_value(),
2387 self.intrinsics.i32_zero,
2388 "",
2389 ));
2390 err!(self.builder.build_conditional_branch(
2391 cond_value,
2392 *frame.br_dest(),
2393 else_block
2394 ));
2395 self.builder.position_at_end(else_block);
2396 }
2397 Operator::BrTable { ref targets } => {
2398 let current_block = self
2399 .builder
2400 .get_insert_block()
2401 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2402
2403 let index = self.state.pop1()?;
2404
2405 let default_frame = self.state.frame_at_depth(targets.default())?;
2406
2407 let phis = if default_frame.is_loop() {
2408 default_frame.loop_body_phis()
2409 } else {
2410 default_frame.phis()
2411 };
2412 let args = self.state.peekn(phis.len())?;
2413
2414 for (phi, value) in phis.iter().zip(args.iter()) {
2415 phi.add_incoming(&[(value, current_block)]);
2416 }
2417
2418 let cases: Vec<_> = targets
2419 .targets()
2420 .enumerate()
2421 .map(|(case_index, depth)| {
2422 let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
2423 let frame_result: Result<&ControlFrame, CompileError> =
2424 self.state.frame_at_depth(depth);
2425 let frame = match frame_result {
2426 Ok(v) => v,
2427 Err(e) => return Err(e),
2428 };
2429 let case_index_literal =
2430 self.context.i32_type().const_int(case_index as u64, false);
2431 let phis = if frame.is_loop() {
2432 frame.loop_body_phis()
2433 } else {
2434 frame.phis()
2435 };
2436 for (phi, value) in phis.iter().zip(args.iter()) {
2437 phi.add_incoming(&[(value, current_block)]);
2438 }
2439
2440 Ok((case_index_literal, *frame.br_dest()))
2441 })
2442 .collect::<Result<_, _>>()?;
2443
2444 err!(self.builder.build_switch(
2445 index.into_int_value(),
2446 *default_frame.br_dest(),
2447 &cases[..],
2448 ));
2449
2450 let args_len = args.len();
2451 self.state.popn(args_len)?;
2452 self.state.reachable = false;
2453 }
2454 Operator::If { blockty } => {
2455 let current_block = self
2456 .builder
2457 .get_insert_block()
2458 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2459 let if_then_block = self.context.append_basic_block(self.function, "if_then");
2460 let if_else_block = self.context.append_basic_block(self.function, "if_else");
2461 let end_block = self.context.append_basic_block(self.function, "if_end");
2462
2463 let end_phis = {
2464 self.builder.position_at_end(end_block);
2465
2466 let phis = self
2467 .module_translation
2468 .blocktype_params_results(&blockty)?
2469 .1
2470 .iter()
2471 .map(|&wp_ty| {
2472 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2473 type_to_llvm(self.intrinsics, wasm_ty)
2474 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2475 })
2476 })
2477 .collect::<Result<_, _>>()?;
2478
2479 self.builder.position_at_end(current_block);
2480 phis
2481 };
2482
2483 let cond = self.state.pop1()?;
2484
2485 let cond_value = err!(self.builder.build_int_compare(
2486 IntPredicate::NE,
2487 cond.into_int_value(),
2488 self.intrinsics.i32_zero,
2489 "",
2490 ));
2491
2492 err!(self.builder.build_conditional_branch(
2493 cond_value,
2494 if_then_block,
2495 if_else_block
2496 ));
2497 self.builder.position_at_end(if_else_block);
2498 let block_param_types = self
2499 .module_translation
2500 .blocktype_params_results(&blockty)?
2501 .0
2502 .iter()
2503 .map(|&wp_ty| {
2504 err_nt!(wptype_to_type(wp_ty))
2505 .and_then(|wasm_ty| type_to_llvm(self.intrinsics, wasm_ty))
2506 })
2507 .collect::<Result<Vec<_>, _>>()?;
2508 let else_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2509 .iter()
2510 .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2511 .collect::<Result<SmallVec<_>, _>>()?;
2512 self.builder.position_at_end(if_then_block);
2513 let then_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2514 .iter()
2515 .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2516 .collect::<Result<SmallVec<_>, _>>()?;
2517 for (else_phi, then_phi) in else_phis.iter().rev().zip(then_phis.iter().rev()) {
2518 let (value, info) = self.state.pop1_extra()?;
2519 let value = self.apply_pending_canonicalization(value, info)?;
2520 else_phi.add_incoming(&[(&value, current_block)]);
2521 then_phi.add_incoming(&[(&value, current_block)]);
2522 }
2523 for phi in then_phis.iter() {
2524 self.state.push1(phi.as_basic_value());
2525 }
2526
2527 self.state.push_if(
2528 if_then_block,
2529 if_else_block,
2530 end_block,
2531 then_phis,
2532 else_phis,
2533 end_phis,
2534 block_param_types.len(),
2535 );
2536 }
2537 Operator::Else => {
2538 if self.state.reachable {
2539 let frame = self.state.frame_at_depth(0)?;
2540 let current_block = self.builder.get_insert_block().ok_or_else(|| {
2541 CompileError::Codegen("not currently in a block".to_string())
2542 })?;
2543
2544 for phi in frame.phis().to_vec().iter().rev() {
2545 let (value, info) = self.state.pop1_extra()?;
2546 let value = self.apply_pending_canonicalization(value, info)?;
2547 phi.add_incoming(&[(&value, current_block)])
2548 }
2549
2550 let frame = self.state.frame_at_depth(0)?;
2551 err!(self.builder.build_unconditional_branch(*frame.code_after()));
2552 }
2553
2554 let (if_else_block, if_else_state) = if let ControlFrame::IfElse {
2555 if_else,
2556 if_else_state,
2557 ..
2558 } = self.state.frame_at_depth_mut(0)?
2559 {
2560 (if_else, if_else_state)
2561 } else {
2562 unreachable!()
2563 };
2564
2565 *if_else_state = IfElseState::Else;
2566
2567 self.builder.position_at_end(*if_else_block);
2568 self.state.reachable = true;
2569
2570 if let ControlFrame::IfElse { else_phis, .. } = self.state.frame_at_depth(0)? {
2571 for phi in else_phis.clone().iter() {
2573 self.state.push1(phi.as_basic_value());
2574 }
2575 };
2576 }
2577
2578 Operator::End => {
2579 let frame = self.state.pop_frame()?;
2580 let current_block = self
2581 .builder
2582 .get_insert_block()
2583 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2584
2585 if self.state.reachable {
2586 for phi in frame.phis().iter().rev() {
2587 let (value, info) = self.state.pop1_extra()?;
2588 let value = self.apply_pending_canonicalization(value, info)?;
2589 phi.add_incoming(&[(&value, current_block)]);
2590 }
2591
2592 err!(self.builder.build_unconditional_branch(*frame.code_after()));
2593 }
2594
2595 if let ControlFrame::IfElse {
2596 if_else,
2597 next,
2598 if_else_state: IfElseState::If,
2599 else_phis,
2600 ..
2601 } = &frame
2602 {
2603 for (phi, else_phi) in frame.phis().iter().zip(else_phis.iter()) {
2604 phi.add_incoming(&[(&else_phi.as_basic_value(), *if_else)]);
2605 }
2606 self.builder.position_at_end(*if_else);
2607 err!(self.builder.build_unconditional_branch(*next));
2608 } else if let ControlFrame::Landingpad { .. } = &frame {
2609 self.state.pop_landingpad();
2610 };
2611
2612 self.builder.position_at_end(*frame.code_after());
2613 self.state.reset_stack(&frame);
2614
2615 self.state.reachable = true;
2616
2617 for phi in frame.phis() {
2619 if phi.count_incoming() != 0 {
2620 self.state.push1(phi.as_basic_value());
2621 } else {
2622 let basic_ty = phi.as_basic_value().get_type();
2629 let placeholder_value = basic_ty.const_zero();
2630 self.state.push1(placeholder_value);
2631 phi.as_instruction().erase_from_basic_block();
2632 }
2633 }
2634 }
2635 Operator::Return => {
2636 let current_block = self
2637 .builder
2638 .get_insert_block()
2639 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2640
2641 let frame = self.state.outermost_frame()?;
2642 for phi in frame.phis().to_vec().iter().rev() {
2643 let (arg, info) = self.state.pop1_extra()?;
2644 let arg = self.apply_pending_canonicalization(arg, info)?;
2645 phi.add_incoming(&[(&arg, current_block)]);
2646 }
2647 let frame = self.state.outermost_frame()?;
2648 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2649
2650 self.state.reachable = false;
2651 }
2652
2653 Operator::Unreachable => {
2654 self.build_call_with_param_attributes(
2655 self.intrinsics.throw_trap,
2656 &[self.intrinsics.trap_unreachable.into()],
2657 "throw",
2658 )?;
2659 err!(self.builder.build_unreachable());
2660
2661 self.state.reachable = false;
2662 }
2663
2664 Operator::Nop => {
2669 }
2671 Operator::Drop => {
2672 self.state.pop1()?;
2673 }
2674
2675 Operator::I32Const { value } => {
2677 let i = self.intrinsics.i32_ty.const_int(value as u64, false);
2678 let info = if is_f32_arithmetic(value as u32) {
2679 ExtraInfo::arithmetic_f32()
2680 } else {
2681 Default::default()
2682 };
2683 self.state.push1_extra(i, info);
2684 }
2685 Operator::I64Const { value } => {
2686 let i = self.intrinsics.i64_ty.const_int(value as u64, false);
2687 let info = if is_f64_arithmetic(value as u64) {
2688 ExtraInfo::arithmetic_f64()
2689 } else {
2690 Default::default()
2691 };
2692 self.state.push1_extra(i, info);
2693 }
2694 Operator::F32Const { value } => {
2695 let bits = self.intrinsics.i32_ty.const_int(value.bits() as u64, false);
2696 let info = if is_f32_arithmetic(value.bits()) {
2697 ExtraInfo::arithmetic_f32()
2698 } else {
2699 Default::default()
2700 };
2701 let f = err!(
2702 self.builder
2703 .build_bit_cast(bits, self.intrinsics.f32_ty, "f")
2704 );
2705 self.state.push1_extra(f, info);
2706 }
2707 Operator::F64Const { value } => {
2708 let bits = self.intrinsics.i64_ty.const_int(value.bits(), false);
2709 let info = if is_f64_arithmetic(value.bits()) {
2710 ExtraInfo::arithmetic_f64()
2711 } else {
2712 Default::default()
2713 };
2714 let f = err!(
2715 self.builder
2716 .build_bit_cast(bits, self.intrinsics.f64_ty, "f")
2717 );
2718 self.state.push1_extra(f, info);
2719 }
2720 Operator::V128Const { value } => {
2721 let mut hi: [u8; 8] = Default::default();
2722 let mut lo: [u8; 8] = Default::default();
2723 hi.copy_from_slice(&value.bytes()[0..8]);
2724 lo.copy_from_slice(&value.bytes()[8..16]);
2725 let packed = [u64::from_le_bytes(hi), u64::from_le_bytes(lo)];
2726 let i = self
2727 .intrinsics
2728 .i128_ty
2729 .const_int_arbitrary_precision(&packed);
2730 let mut quad1: [u8; 4] = Default::default();
2731 let mut quad2: [u8; 4] = Default::default();
2732 let mut quad3: [u8; 4] = Default::default();
2733 let mut quad4: [u8; 4] = Default::default();
2734 quad1.copy_from_slice(&value.bytes()[0..4]);
2735 quad2.copy_from_slice(&value.bytes()[4..8]);
2736 quad3.copy_from_slice(&value.bytes()[8..12]);
2737 quad4.copy_from_slice(&value.bytes()[12..16]);
2738 let mut info: ExtraInfo = Default::default();
2739 if is_f32_arithmetic(u32::from_le_bytes(quad1))
2740 && is_f32_arithmetic(u32::from_le_bytes(quad2))
2741 && is_f32_arithmetic(u32::from_le_bytes(quad3))
2742 && is_f32_arithmetic(u32::from_le_bytes(quad4))
2743 {
2744 info |= ExtraInfo::arithmetic_f32();
2745 }
2746 if is_f64_arithmetic(packed[0]) && is_f64_arithmetic(packed[1]) {
2747 info |= ExtraInfo::arithmetic_f64();
2748 }
2749 self.state.push1_extra(i, info);
2750 }
2751
2752 Operator::I8x16Splat => {
2753 let (v, i) = self.state.pop1_extra()?;
2754 let v = v.into_int_value();
2755 let v = err!(
2756 self.builder
2757 .build_int_truncate(v, self.intrinsics.i8_ty, "")
2758 );
2759 let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
2760 let res = err!(
2761 self.builder
2762 .build_bit_cast(res, self.intrinsics.i128_ty, "")
2763 );
2764 self.state.push1_extra(res, i);
2765 }
2766 Operator::I16x8Splat => {
2767 let (v, i) = self.state.pop1_extra()?;
2768 let v = v.into_int_value();
2769 let v = err!(
2770 self.builder
2771 .build_int_truncate(v, self.intrinsics.i16_ty, "")
2772 );
2773 let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
2774 let res = err!(
2775 self.builder
2776 .build_bit_cast(res, self.intrinsics.i128_ty, "")
2777 );
2778 self.state.push1_extra(res, i);
2779 }
2780 Operator::I32x4Splat => {
2781 let (v, i) = self.state.pop1_extra()?;
2782 let res = self.splat_vector(v, self.intrinsics.i32x4_ty)?;
2783 let res = err!(
2784 self.builder
2785 .build_bit_cast(res, self.intrinsics.i128_ty, "")
2786 );
2787 self.state.push1_extra(res, i);
2788 }
2789 Operator::I64x2Splat => {
2790 let (v, i) = self.state.pop1_extra()?;
2791 let res = self.splat_vector(v, self.intrinsics.i64x2_ty)?;
2792 let res = err!(
2793 self.builder
2794 .build_bit_cast(res, self.intrinsics.i128_ty, "")
2795 );
2796 self.state.push1_extra(res, i);
2797 }
2798 Operator::F32x4Splat => {
2799 let (v, i) = self.state.pop1_extra()?;
2800 let res = self.splat_vector(v, self.intrinsics.f32x4_ty)?;
2801 let res = err!(
2802 self.builder
2803 .build_bit_cast(res, self.intrinsics.i128_ty, "")
2804 );
2805 self.state.push1_extra(res, i);
2808 }
2809 Operator::F64x2Splat => {
2810 let (v, i) = self.state.pop1_extra()?;
2811 let res = self.splat_vector(v, self.intrinsics.f64x2_ty)?;
2812 let res = err!(
2813 self.builder
2814 .build_bit_cast(res, self.intrinsics.i128_ty, "")
2815 );
2816 self.state.push1_extra(res, i);
2819 }
2820
2821 Operator::LocalGet { local_index } => {
2823 let (type_value, pointer_value) = self.locals[local_index as usize];
2824 let v = err!(self.builder.build_load(
2825 type_value,
2826 pointer_value,
2827 &format!("local_{local_index}_get")
2828 ));
2829 tbaa_label(
2830 self.module,
2831 self.intrinsics,
2832 format!("local {local_index}"),
2833 v.as_instruction_value().unwrap(),
2834 );
2835 self.state.push1(v);
2836 }
2837 Operator::LocalSet { local_index } => {
2838 let pointer_value = self.locals[local_index as usize].1;
2839 let (v, i) = self.state.pop1_extra()?;
2840 let v = self.apply_pending_canonicalization(v, i)?;
2841 let store = err!(self.builder.build_store(pointer_value, v));
2842 tbaa_label(
2843 self.module,
2844 self.intrinsics,
2845 format!("local {local_index}"),
2846 store,
2847 );
2848 }
2849 Operator::LocalTee { local_index } => {
2850 let pointer_value = self.locals[local_index as usize].1;
2851 let (v, i) = self.state.peek1_extra()?;
2852 let v = self.apply_pending_canonicalization(v, i)?;
2853 let store = err!(self.builder.build_store(pointer_value, v));
2854 tbaa_label(
2855 self.module,
2856 self.intrinsics,
2857 format!("local {local_index}"),
2858 store,
2859 );
2860 }
2861
2862 Operator::GlobalGet { global_index } => {
2863 let global_index = GlobalIndex::from_u32(global_index);
2864 match self
2865 .ctx
2866 .global(global_index, self.intrinsics, self.module)?
2867 {
2868 GlobalCache::Const { value } => {
2869 self.state.push1(*value);
2870 }
2871 GlobalCache::Mut {
2872 ptr_to_value,
2873 value_type,
2874 } => {
2875 let value = err!(self.builder.build_load(*value_type, *ptr_to_value, ""));
2876 tbaa_label(
2877 self.module,
2878 self.intrinsics,
2879 format!("global {}", global_index.as_u32()),
2880 value.as_instruction_value().unwrap(),
2881 );
2882 self.state.push1(value);
2883 }
2884 }
2885 }
2886 Operator::GlobalSet { global_index } => {
2887 let global_index = GlobalIndex::from_u32(global_index);
2888 match self
2889 .ctx
2890 .global(global_index, self.intrinsics, self.module)?
2891 {
2892 GlobalCache::Const { value: _ } => {
2893 return Err(CompileError::Codegen(format!(
2894 "global.set on immutable global index {}",
2895 global_index.as_u32()
2896 )));
2897 }
2898 GlobalCache::Mut { ptr_to_value, .. } => {
2899 let ptr_to_value = *ptr_to_value;
2900 let (value, info) = self.state.pop1_extra()?;
2901 let value = self.apply_pending_canonicalization(value, info)?;
2902 let store = err!(self.builder.build_store(ptr_to_value, value));
2903 tbaa_label(
2904 self.module,
2905 self.intrinsics,
2906 format!("global {}", global_index.as_u32()),
2907 store,
2908 );
2909 }
2910 }
2911 }
2912
2913 Operator::TypedSelect { .. } | Operator::Select => {
2916 let ((v1, i1), (v2, i2), (cond, _)) = self.state.pop3_extra()?;
2917 let (v1, i1, v2, i2) = if i1.has_pending_f32_nan() != i2.has_pending_f32_nan()
2925 || i1.has_pending_f64_nan() != i2.has_pending_f64_nan()
2926 {
2927 (
2928 self.apply_pending_canonicalization(v1, i1)?,
2929 i1.strip_pending(),
2930 self.apply_pending_canonicalization(v2, i2)?,
2931 i2.strip_pending(),
2932 )
2933 } else {
2934 (v1, i1, v2, i2)
2935 };
2936 let cond_value = err!(self.builder.build_int_compare(
2937 IntPredicate::NE,
2938 cond.into_int_value(),
2939 self.intrinsics.i32_zero,
2940 "",
2941 ));
2942 let res = err!(self.builder.build_select(cond_value, v1, v2, ""));
2943 let info = {
2944 let mut info = (i1.strip_pending() & i2.strip_pending())?;
2945 if i1.has_pending_f32_nan() {
2946 debug_assert!(i2.has_pending_f32_nan());
2947 info = (info | ExtraInfo::pending_f32_nan())?;
2948 }
2949 if i1.has_pending_f64_nan() {
2950 debug_assert!(i2.has_pending_f64_nan());
2951 info = (info | ExtraInfo::pending_f64_nan())?;
2952 }
2953 info
2954 };
2955 self.state.push1_extra(res, info);
2956 }
2957 Operator::Call { function_index } | Operator::ReturnCall { function_index } => {
2958 let is_return_call = matches!(op, Operator::ReturnCall { .. });
2959 let func_index = FunctionIndex::from_u32(function_index);
2960 let sigindex = &self.wasm_module.functions[func_index];
2961 let func_type = &self.wasm_module.signatures[*sigindex];
2962
2963 let FunctionCache {
2964 func,
2965 llvm_func_type,
2966 vmctx: callee_vmctx,
2967 imported_include_m0_param,
2968 attrs,
2969 } = if let Some(local_func_index) = self.wasm_module.local_func_index(func_index) {
2970 let function_name = self
2971 .symbol_registry
2972 .symbol_to_name(Symbol::LocalFunction(local_func_index));
2973
2974 self.ctx.local_func(
2975 local_func_index,
2976 func_index,
2977 self.intrinsics,
2978 self.module,
2979 self.context,
2980 func_type,
2981 &function_name,
2982 )?
2983 } else {
2984 self.ctx
2985 .imported_func(func_index, self.intrinsics, self.context, func_type)?
2986 };
2987 let llvm_func_type = *llvm_func_type;
2988 let func = *func;
2989 let callee_vmctx = *callee_vmctx;
2990 let imported_include_m0_param = *imported_include_m0_param;
2991 let attrs = attrs.clone();
2992
2993 let params = self.state.popn_save_extra(func_type.params().len())?;
2999
3000 let params = params
3002 .iter()
3003 .zip(func_type.params().iter())
3004 .map(|((v, info), wasm_ty)| match wasm_ty {
3005 Type::F32 => err_nt!(self.builder.build_bit_cast(
3006 self.apply_pending_canonicalization(*v, *info)?,
3007 self.intrinsics.f32_ty,
3008 "",
3009 )),
3010 Type::F64 => err_nt!(self.builder.build_bit_cast(
3011 self.apply_pending_canonicalization(*v, *info)?,
3012 self.intrinsics.f64_ty,
3013 "",
3014 )),
3015 Type::V128 => self.apply_pending_canonicalization(*v, *info),
3016 _ => Ok(*v),
3017 })
3018 .collect::<Result<Vec<_>, _>>()?;
3019
3020 if let (Some(m0_param), Some(include_m0_param)) =
3021 (self.m0_param, imported_include_m0_param)
3022 {
3023 let (llvm_func_type_no_m0, llvm_func_attrs_no_m0) =
3027 self.abi.func_type_to_llvm(
3028 self.context,
3029 self.intrinsics,
3030 Some(self.ctx.get_offsets()),
3031 func_type,
3032 false,
3033 )?;
3034 let params_with_m0 = self.abi.args_to_call(
3035 &self.alloca_builder,
3036 func_type,
3037 &llvm_func_type,
3038 callee_vmctx.into_pointer_value(),
3039 params.as_slice(),
3040 self.intrinsics,
3041 Some(m0_param),
3042 is_return_call
3043 .then(|| self.current_sret_ptr(func_type))
3044 .flatten(),
3045 )?;
3046 let params_no_m0 = self.abi.args_to_call(
3047 &self.alloca_builder,
3048 func_type,
3049 &llvm_func_type_no_m0,
3050 callee_vmctx.into_pointer_value(),
3051 params.as_slice(),
3052 self.intrinsics,
3053 None,
3054 is_return_call
3055 .then(|| self.current_sret_ptr(func_type))
3056 .flatten(),
3057 )?;
3058
3059 let include_m0_call_block = self
3060 .context
3061 .append_basic_block(self.function, "call_block_with_m0");
3062 let skip_m0_call_block =
3063 self.context.append_basic_block(self.function, "call_block");
3064 let call_cont = self.context.append_basic_block(self.function, "call_cont");
3065 err!(self.builder.build_conditional_branch(
3066 include_m0_param,
3067 include_m0_call_block,
3068 skip_m0_call_block,
3069 ));
3070
3071 self.builder.position_at_end(include_m0_call_block);
3072 let call_site_with_m0 = self.build_indirect_call_or_invoke(
3073 llvm_func_type,
3074 func,
3075 params_with_m0.as_slice(),
3076 "then_block_with_m0",
3077 is_return_call,
3078 )?;
3079 for (attr, attr_loc) in &attrs {
3080 call_site_with_m0.add_attribute(*attr_loc, *attr);
3081 }
3082 let rets_with_m0 = self.abi.rets_from_call(
3083 &self.builder,
3084 self.intrinsics,
3085 call_site_with_m0,
3086 func_type,
3087 )?;
3088 let with_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3089 CompileError::Codegen(
3090 "missing insertion block after call with m0".to_string(),
3091 )
3092 })?;
3093 err!(self.builder.build_unconditional_branch(call_cont));
3094
3095 self.builder.position_at_end(skip_m0_call_block);
3096 let call_site_no_m0 = self.build_indirect_call_or_invoke(
3097 llvm_func_type_no_m0,
3098 func,
3099 params_no_m0.as_slice(),
3100 "then_block",
3101 is_return_call,
3102 )?;
3103 for (attr, attr_loc) in &llvm_func_attrs_no_m0 {
3104 call_site_no_m0.add_attribute(*attr_loc, *attr);
3105 }
3106 let rets_no_m0 = self.abi.rets_from_call(
3107 &self.builder,
3108 self.intrinsics,
3109 call_site_no_m0,
3110 func_type,
3111 )?;
3112 let no_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3113 CompileError::Codegen(
3114 "missing insertion block after call without m0".to_string(),
3115 )
3116 })?;
3117 err!(self.builder.build_unconditional_branch(call_cont));
3118
3119 self.builder.position_at_end(call_cont);
3120 for i in 0..rets_with_m0.len() {
3121 let with_m0 = rets_with_m0[i];
3122 let no_m0 = rets_no_m0[i];
3123 let phi = err!(self.builder.build_phi(with_m0.get_type(), ""));
3124 phi.add_incoming(&[(&with_m0, with_m0_pred), (&no_m0, no_m0_pred)]);
3125 self.state.push1(phi.as_basic_value());
3126 }
3127 } else {
3128 let params = self.abi.args_to_call(
3129 &self.alloca_builder,
3130 func_type,
3131 &llvm_func_type,
3132 callee_vmctx.into_pointer_value(),
3133 params.as_slice(),
3134 self.intrinsics,
3135 self.m0_param,
3136 if is_return_call {
3137 self.current_sret_ptr(func_type)
3138 } else {
3139 None
3140 },
3141 )?;
3142
3143 let call_site = self.build_indirect_call_or_invoke(
3144 llvm_func_type,
3145 func,
3146 params.as_slice(),
3147 "then_block",
3148 is_return_call,
3149 )?;
3150 for (attr, attr_loc) in attrs {
3151 call_site.add_attribute(attr_loc, attr);
3152 }
3153
3154 if is_return_call {
3155 self.emit_return_call(call_site, llvm_func_type)?;
3156 self.state.reachable = false;
3157 } else {
3158 self.abi
3159 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3160 .iter()
3161 .for_each(|ret| self.state.push1(*ret));
3162 }
3163 }
3164 }
3165 Operator::CallIndirect {
3166 type_index,
3167 table_index,
3168 }
3169 | Operator::ReturnCallIndirect {
3170 type_index,
3171 table_index,
3172 } => {
3173 let is_return_call = matches!(op, Operator::ReturnCallIndirect { .. });
3174 let sigindex = SignatureIndex::from_u32(type_index);
3175 let table_index = TableIndex::from_u32(table_index);
3176 let func_type = &self.wasm_module.signatures[sigindex];
3177 let table = self.wasm_module.tables.get(table_index).unwrap();
3178 let local_fixed_funcref_table = self
3179 .wasm_module
3180 .local_table_index(table_index)
3181 .filter(|_| table.is_fixed_funcref_table());
3182 let expected_signature_hash = self
3183 .intrinsics
3184 .i32_ty
3185 .const_int(u64::from(self.signature_hashes[sigindex].as_u32()), false);
3186
3187 let func_index = self.state.pop1()?.into_int_value();
3188 let generic_table = if local_fixed_funcref_table.is_none() {
3189 Some(self.ctx.table(
3190 table_index,
3191 self.intrinsics,
3192 self.module,
3193 &self.builder,
3194 )?)
3195 } else {
3196 None
3197 };
3198
3199 let table_bound = if local_fixed_funcref_table.is_some() {
3200 self.intrinsics
3201 .i32_ty
3202 .const_int(table.minimum.into(), false)
3203 } else {
3204 let (_, table_bound) = *generic_table.as_ref().unwrap();
3205 err!(self.builder.build_int_truncate(
3206 table_bound,
3207 self.intrinsics.i32_ty,
3208 "truncated_table_bounds",
3209 ))
3210 };
3211
3212 let index_in_bounds = err!(self.builder.build_int_compare(
3214 IntPredicate::ULT,
3215 func_index,
3216 table_bound,
3217 "index_in_bounds",
3218 ));
3219
3220 let index_in_bounds = self
3221 .build_call_with_param_attributes(
3222 self.intrinsics.expect_i1,
3223 &[
3224 index_in_bounds.into(),
3225 self.intrinsics.i1_ty.const_int(1, false).into(),
3226 ],
3227 "index_in_bounds_expect",
3228 )?
3229 .try_as_basic_value()
3230 .unwrap_basic()
3231 .into_int_value();
3232
3233 let in_bounds_continue_block = self
3234 .context
3235 .append_basic_block(self.function, "in_bounds_continue_block");
3236 let not_in_bounds_block = self
3237 .context
3238 .append_basic_block(self.function, "not_in_bounds_block");
3239 err!(self.builder.build_conditional_branch(
3240 index_in_bounds,
3241 in_bounds_continue_block,
3242 not_in_bounds_block,
3243 ));
3244 self.builder.position_at_end(not_in_bounds_block);
3245 self.build_call_with_param_attributes(
3246 self.intrinsics.throw_trap,
3247 &[self.intrinsics.trap_table_access_oob.into()],
3248 "throw",
3249 )?;
3250 err!(self.builder.build_unreachable());
3251 self.builder.position_at_end(in_bounds_continue_block);
3252
3253 let anyfunc_struct_ptr = if let Some(local_table_index) = local_fixed_funcref_table
3254 {
3255 let anyfuncs = self.ctx.fixed_funcref_table_anyfuncs(
3256 local_table_index,
3257 self.intrinsics,
3258 &self.builder,
3259 )?;
3260 unsafe {
3261 err!(self.builder.build_in_bounds_gep(
3262 self.intrinsics.anyfunc_ty,
3263 anyfuncs,
3264 &[func_index],
3265 "anyfunc_struct_ptr",
3266 ))
3267 }
3268 } else {
3269 let (table_base, _) = *generic_table.as_ref().unwrap();
3270
3271 let casted_table_base = err!(self.builder.build_pointer_cast(
3274 table_base,
3275 self.context.ptr_type(AddressSpace::default()),
3276 "casted_table_base",
3277 ));
3278
3279 let funcref_ptr = unsafe {
3280 err!(self.builder.build_in_bounds_gep(
3281 self.intrinsics.ptr_ty,
3282 casted_table_base,
3283 &[func_index],
3284 "funcref_ptr",
3285 ))
3286 };
3287
3288 let anyfunc_struct_ptr = err!(self.builder.build_load(
3290 self.intrinsics.ptr_ty,
3291 funcref_ptr,
3292 "anyfunc_struct_ptr",
3293 ))
3294 .into_pointer_value();
3295
3296 if !table.readonly {
3297 let funcref_not_null = err!(
3299 self.builder
3300 .build_is_not_null(anyfunc_struct_ptr, "null_funcref_check")
3301 );
3302
3303 let funcref_continue_deref_block = self
3304 .context
3305 .append_basic_block(self.function, "funcref_continue_deref_block");
3306
3307 let funcref_is_null_block = self
3308 .context
3309 .append_basic_block(self.function, "funcref_is_null_block");
3310 err!(self.builder.build_conditional_branch(
3311 funcref_not_null,
3312 funcref_continue_deref_block,
3313 funcref_is_null_block,
3314 ));
3315 self.builder.position_at_end(funcref_is_null_block);
3316 self.build_call_with_param_attributes(
3317 self.intrinsics.throw_trap,
3318 &[self.intrinsics.trap_call_indirect_null.into()],
3319 "throw",
3320 )?;
3321 err!(self.builder.build_unreachable());
3322 self.builder.position_at_end(funcref_continue_deref_block);
3323 }
3324
3325 anyfunc_struct_ptr
3326 };
3327
3328 let sig_hash_ptr = self
3330 .builder
3331 .build_struct_gep(
3332 self.intrinsics.anyfunc_ty,
3333 anyfunc_struct_ptr,
3334 1,
3335 "sig_hash_ptr",
3336 )
3337 .unwrap();
3338 let func_ptr_ptr = self
3339 .builder
3340 .build_struct_gep(
3341 self.intrinsics.anyfunc_ty,
3342 anyfunc_struct_ptr,
3343 0,
3344 "func_ptr_ptr",
3345 )
3346 .unwrap();
3347 let (func_ptr, found_signature_hash) = (
3348 err!(
3349 self.builder
3350 .build_load(self.intrinsics.ptr_ty, func_ptr_ptr, "func_ptr")
3351 )
3352 .into_pointer_value(),
3353 err!(
3354 self.builder
3355 .build_load(self.intrinsics.i32_ty, sig_hash_ptr, "sig_hash")
3356 )
3357 .into_int_value(),
3358 );
3359
3360 let elem_initialized = err!(self.builder.build_is_not_null(func_ptr, ""));
3364
3365 let sig_hashes_equal = err!(self.builder.build_int_compare(
3368 IntPredicate::EQ,
3369 expected_signature_hash,
3370 found_signature_hash,
3371 "sig_hashes_equal",
3372 ));
3373
3374 let initialized_and_sig_hashes_match = err!(self.builder.build_and(
3375 elem_initialized,
3376 sig_hashes_equal,
3377 ""
3378 ));
3379
3380 let initialized_and_sig_hashes_match = self
3382 .build_call_with_param_attributes(
3383 self.intrinsics.expect_i1,
3384 &[
3385 initialized_and_sig_hashes_match.into(),
3386 self.intrinsics.i1_ty.const_int(1, false).into(),
3387 ],
3388 "initialized_and_sig_hashes_match_expect",
3389 )?
3390 .try_as_basic_value()
3391 .unwrap_basic()
3392 .into_int_value();
3393
3394 let continue_block = self
3395 .context
3396 .append_basic_block(self.function, "continue_block");
3397 let sighashes_notequal_block = self
3398 .context
3399 .append_basic_block(self.function, "sighashes_notequal_block");
3400 err!(self.builder.build_conditional_branch(
3401 initialized_and_sig_hashes_match,
3402 continue_block,
3403 sighashes_notequal_block,
3404 ));
3405
3406 self.builder.position_at_end(sighashes_notequal_block);
3407 let trap_code = err!(self.builder.build_select(
3408 elem_initialized,
3409 self.intrinsics.trap_call_indirect_sig,
3410 self.intrinsics.trap_call_indirect_null,
3411 "",
3412 ));
3413 self.build_call_with_param_attributes(
3414 self.intrinsics.throw_trap,
3415 &[trap_code.into()],
3416 "throw",
3417 )?;
3418 err!(self.builder.build_unreachable());
3419 self.builder.position_at_end(continue_block);
3420
3421 let callee_vmctx = if table.readonly {
3422 *vmctx
3423 } else {
3424 let ctx_ptr_ptr = self
3425 .builder
3426 .build_struct_gep(
3427 self.intrinsics.anyfunc_ty,
3428 anyfunc_struct_ptr,
3429 2,
3430 "ctx_ptr_ptr",
3431 )
3432 .unwrap();
3433 err!(
3434 self.builder
3435 .build_load(self.intrinsics.ptr_ty, ctx_ptr_ptr, "ctx_ptr")
3436 )
3437 .into_pointer_value()
3438 };
3439
3440 if self.m0_param.is_some() {
3441 self.build_m0_indirect_call(
3442 table_index.as_u32(),
3443 callee_vmctx,
3444 func_type,
3445 func_ptr,
3446 func_index,
3447 is_return_call,
3448 )?;
3449 } else {
3450 let (call_site, llvm_func_type) = self.build_indirect_call(
3451 callee_vmctx,
3452 func_type,
3453 func_ptr,
3454 None,
3455 is_return_call,
3456 )?;
3457
3458 if is_return_call {
3459 self.emit_return_call(call_site, llvm_func_type)?;
3460 } else {
3461 self.abi
3462 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3463 .iter()
3464 .for_each(|ret| self.state.push1(*ret));
3465 }
3466 }
3467
3468 if is_return_call {
3469 self.state.reachable = false;
3470 }
3471 }
3472
3473 Operator::I32Add | Operator::I64Add => {
3478 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3479 let v1 = self.apply_pending_canonicalization(v1, i1)?;
3480 let v2 = self.apply_pending_canonicalization(v2, i2)?;
3481 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3482 let res = err!(self.builder.build_int_add(v1, v2, ""));
3483 self.state.push1(res);
3484 }
3485 Operator::I8x16Add => {
3486 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3487 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3488 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3489 let res = err!(self.builder.build_int_add(v1, v2, ""));
3490 let res = err!(
3491 self.builder
3492 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3493 );
3494 self.state.push1(res);
3495 }
3496 Operator::I16x8Add => {
3497 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3498 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3499 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3500 let res = err!(self.builder.build_int_add(v1, v2, ""));
3501 let res = err!(
3502 self.builder
3503 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3504 );
3505 self.state.push1(res);
3506 }
3507 Operator::I16x8ExtAddPairwiseI8x16S | Operator::I16x8ExtAddPairwiseI8x16U => {
3508 let extend_op = match op {
3509 Operator::I16x8ExtAddPairwiseI8x16S => {
3510 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, "")
3511 }
3512 Operator::I16x8ExtAddPairwiseI8x16U => {
3513 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, "")
3514 }
3515 _ => unreachable!("Unhandled internal variant"),
3516 };
3517 let (v, i) = self.state.pop1_extra()?;
3518 let (v, _) = self.v128_into_i8x16(v, i)?;
3519
3520 let left = err!(self.builder.build_shuffle_vector(
3521 v,
3522 v.get_type().get_undef(),
3523 VectorType::const_vector(&[
3524 self.intrinsics.i32_consts[0],
3525 self.intrinsics.i32_consts[2],
3526 self.intrinsics.i32_consts[4],
3527 self.intrinsics.i32_consts[6],
3528 self.intrinsics.i32_consts[8],
3529 self.intrinsics.i32_consts[10],
3530 self.intrinsics.i32_consts[12],
3531 self.intrinsics.i32_consts[14],
3532 ]),
3533 "",
3534 ));
3535 let left = err!(extend_op(self, left));
3536 let right = err!(self.builder.build_shuffle_vector(
3537 v,
3538 v.get_type().get_undef(),
3539 VectorType::const_vector(&[
3540 self.intrinsics.i32_consts[1],
3541 self.intrinsics.i32_consts[3],
3542 self.intrinsics.i32_consts[5],
3543 self.intrinsics.i32_consts[7],
3544 self.intrinsics.i32_consts[9],
3545 self.intrinsics.i32_consts[11],
3546 self.intrinsics.i32_consts[13],
3547 self.intrinsics.i32_consts[15],
3548 ]),
3549 "",
3550 ));
3551 let right = err!(extend_op(self, right));
3552
3553 let res = err!(self.builder.build_int_add(left, right, ""));
3554 let res = err!(
3555 self.builder
3556 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3557 );
3558 self.state.push1(res);
3559 }
3560 Operator::I32x4Add => {
3561 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3562 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3563 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3564 let res = err!(self.builder.build_int_add(v1, v2, ""));
3565 let res = err!(
3566 self.builder
3567 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3568 );
3569 self.state.push1(res);
3570 }
3571 Operator::I32x4ExtAddPairwiseI16x8S | Operator::I32x4ExtAddPairwiseI16x8U => {
3572 let extend_op = match op {
3573 Operator::I32x4ExtAddPairwiseI16x8S => {
3574 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
3575 }
3576 Operator::I32x4ExtAddPairwiseI16x8U => {
3577 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
3578 }
3579 _ => unreachable!("Unhandled internal variant"),
3580 };
3581 let (v, i) = self.state.pop1_extra()?;
3582 let (v, _) = self.v128_into_i16x8(v, i)?;
3583
3584 let left = err!(self.builder.build_shuffle_vector(
3585 v,
3586 v.get_type().get_undef(),
3587 VectorType::const_vector(&[
3588 self.intrinsics.i32_consts[0],
3589 self.intrinsics.i32_consts[2],
3590 self.intrinsics.i32_consts[4],
3591 self.intrinsics.i32_consts[6],
3592 ]),
3593 "",
3594 ));
3595 let left = err!(extend_op(self, left));
3596 let right = err!(self.builder.build_shuffle_vector(
3597 v,
3598 v.get_type().get_undef(),
3599 VectorType::const_vector(&[
3600 self.intrinsics.i32_consts[1],
3601 self.intrinsics.i32_consts[3],
3602 self.intrinsics.i32_consts[5],
3603 self.intrinsics.i32_consts[7],
3604 ]),
3605 "",
3606 ));
3607 let right = err!(extend_op(self, right));
3608
3609 let res = err!(self.builder.build_int_add(left, right, ""));
3610 let res = err!(
3611 self.builder
3612 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3613 );
3614 self.state.push1(res);
3615 }
3616 Operator::I64x2Add => {
3617 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3618 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3619 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3620 let res = err!(self.builder.build_int_add(v1, v2, ""));
3621 let res = err!(
3622 self.builder
3623 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3624 );
3625 self.state.push1(res);
3626 }
3627 Operator::I8x16AddSatS => {
3628 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3629 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3630 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3631 let res = self
3632 .build_call_with_param_attributes(
3633 self.intrinsics.sadd_sat_i8x16,
3634 &[v1.into(), v2.into()],
3635 "",
3636 )?
3637 .try_as_basic_value()
3638 .unwrap_basic();
3639 let res = err!(
3640 self.builder
3641 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3642 );
3643 self.state.push1(res);
3644 }
3645 Operator::I16x8AddSatS => {
3646 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3647 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3648 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3649 let res = self
3650 .build_call_with_param_attributes(
3651 self.intrinsics.sadd_sat_i16x8,
3652 &[v1.into(), v2.into()],
3653 "",
3654 )?
3655 .try_as_basic_value()
3656 .unwrap_basic();
3657 let res = err!(
3658 self.builder
3659 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3660 );
3661 self.state.push1(res);
3662 }
3663 Operator::I8x16AddSatU => {
3664 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3665 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3666 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3667 let res = self
3668 .build_call_with_param_attributes(
3669 self.intrinsics.uadd_sat_i8x16,
3670 &[v1.into(), v2.into()],
3671 "",
3672 )?
3673 .try_as_basic_value()
3674 .unwrap_basic();
3675 let res = err!(
3676 self.builder
3677 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3678 );
3679 self.state.push1(res);
3680 }
3681 Operator::I16x8AddSatU => {
3682 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3683 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3684 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3685 let res = self
3686 .build_call_with_param_attributes(
3687 self.intrinsics.uadd_sat_i16x8,
3688 &[v1.into(), v2.into()],
3689 "",
3690 )?
3691 .try_as_basic_value()
3692 .unwrap_basic();
3693 let res = err!(
3694 self.builder
3695 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3696 );
3697 self.state.push1(res);
3698 }
3699 Operator::I32Sub | Operator::I64Sub => {
3700 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3701 let v1 = self.apply_pending_canonicalization(v1, i1)?;
3702 let v2 = self.apply_pending_canonicalization(v2, i2)?;
3703 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3704 let res = err!(self.builder.build_int_sub(v1, v2, ""));
3705 self.state.push1(res);
3706 }
3707 Operator::I8x16Sub => {
3708 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3709 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3710 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3711 let res = err!(self.builder.build_int_sub(v1, v2, ""));
3712 let res = err!(
3713 self.builder
3714 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3715 );
3716 self.state.push1(res);
3717 }
3718 Operator::I16x8Sub => {
3719 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3720 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3721 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3722 let res = err!(self.builder.build_int_sub(v1, v2, ""));
3723 let res = err!(
3724 self.builder
3725 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3726 );
3727 self.state.push1(res);
3728 }
3729 Operator::I32x4Sub => {
3730 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3731 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3732 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3733 let res = err!(self.builder.build_int_sub(v1, v2, ""));
3734 let res = err!(
3735 self.builder
3736 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3737 );
3738 self.state.push1(res);
3739 }
3740 Operator::I64x2Sub => {
3741 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3742 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3743 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3744 let res = err!(self.builder.build_int_sub(v1, v2, ""));
3745 let res = err!(
3746 self.builder
3747 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3748 );
3749 self.state.push1(res);
3750 }
3751 Operator::I8x16SubSatS => {
3752 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3753 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3754 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3755 let res = self
3756 .build_call_with_param_attributes(
3757 self.intrinsics.ssub_sat_i8x16,
3758 &[v1.into(), v2.into()],
3759 "",
3760 )?
3761 .try_as_basic_value()
3762 .unwrap_basic();
3763 let res = err!(
3764 self.builder
3765 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3766 );
3767 self.state.push1(res);
3768 }
3769 Operator::I16x8SubSatS => {
3770 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3771 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3772 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3773 let res = self
3774 .build_call_with_param_attributes(
3775 self.intrinsics.ssub_sat_i16x8,
3776 &[v1.into(), v2.into()],
3777 "",
3778 )?
3779 .try_as_basic_value()
3780 .unwrap_basic();
3781 let res = err!(
3782 self.builder
3783 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3784 );
3785 self.state.push1(res);
3786 }
3787 Operator::I8x16SubSatU => {
3788 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3789 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3790 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3791 let res = self
3792 .build_call_with_param_attributes(
3793 self.intrinsics.usub_sat_i8x16,
3794 &[v1.into(), v2.into()],
3795 "",
3796 )?
3797 .try_as_basic_value()
3798 .unwrap_basic();
3799 let res = err!(
3800 self.builder
3801 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3802 );
3803 self.state.push1(res);
3804 }
3805 Operator::I16x8SubSatU => {
3806 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3807 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3808 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3809 let res = self
3810 .build_call_with_param_attributes(
3811 self.intrinsics.usub_sat_i16x8,
3812 &[v1.into(), v2.into()],
3813 "",
3814 )?
3815 .try_as_basic_value()
3816 .unwrap_basic();
3817 let res = err!(
3818 self.builder
3819 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3820 );
3821 self.state.push1(res);
3822 }
3823 Operator::I32Mul | Operator::I64Mul => {
3824 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3825 let v1 = self.apply_pending_canonicalization(v1, i1)?;
3826 let v2 = self.apply_pending_canonicalization(v2, i2)?;
3827 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3828 let res = err!(self.builder.build_int_mul(v1, v2, ""));
3829 self.state.push1(res);
3830 }
3831 Operator::I16x8Mul => {
3832 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3833 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3834 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3835 let res = err!(self.builder.build_int_mul(v1, v2, ""));
3836 let res = err!(
3837 self.builder
3838 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3839 );
3840 self.state.push1(res);
3841 }
3842 Operator::I32x4Mul => {
3843 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3844 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3845 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3846 let res = err!(self.builder.build_int_mul(v1, v2, ""));
3847 let res = err!(
3848 self.builder
3849 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3850 );
3851 self.state.push1(res);
3852 }
3853 Operator::I64x2Mul => {
3854 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3855 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3856 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3857 let res = err!(self.builder.build_int_mul(v1, v2, ""));
3858 let res = err!(
3859 self.builder
3860 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3861 );
3862 self.state.push1(res);
3863 }
3864 Operator::I16x8RelaxedQ15mulrS if self.cpu_features.contains(CpuFeature::SSSE3) => {
3865 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3866 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3867 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3868 let res = self
3869 .build_call_with_param_attributes(
3870 self.intrinsics.x86_64.pmulhrsw128,
3871 &[v1.into(), v2.into()],
3872 "",
3873 )?
3874 .try_as_basic_value()
3875 .unwrap_basic();
3876 let res = err!(
3877 self.builder
3878 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3879 );
3880 self.state.push1(res);
3881 }
3882 Operator::I16x8Q15MulrSatS | Operator::I16x8RelaxedQ15mulrS => {
3883 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3884 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3885 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3886
3887 let max_value = self.intrinsics.i16_ty.const_int(i16::MAX as u64, false);
3888 let max_values = VectorType::const_vector(&[max_value; 8]);
3889
3890 let v1 = err!(
3891 self.builder
3892 .build_int_s_extend(v1, self.intrinsics.i32x8_ty, "")
3893 );
3894 let v2 = err!(
3895 self.builder
3896 .build_int_s_extend(v2, self.intrinsics.i32x8_ty, "")
3897 );
3898 let res = err!(self.builder.build_int_mul(v1, v2, ""));
3899
3900 let bit = self.intrinsics.i32_ty.const_int(0x4000, false);
3902 let bits = VectorType::const_vector(&[bit; 8]);
3903
3904 let res = err!(self.builder.build_int_add(res, bits, ""));
3905
3906 let fifteen = self.intrinsics.i32_consts[15];
3907 let fifteens = VectorType::const_vector(&[fifteen; 8]);
3908
3909 let res = err!(self.builder.build_right_shift(res, fifteens, true, ""));
3910 let saturate_up = {
3911 let max_values = err!(self.builder.build_int_s_extend(
3912 max_values,
3913 self.intrinsics.i32x8_ty,
3914 ""
3915 ));
3916 err!(
3917 self.builder
3918 .build_int_compare(IntPredicate::SGT, res, max_values, "")
3919 )
3920 };
3921
3922 let res = err!(
3923 self.builder
3924 .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
3925 );
3926
3927 let res = err!(self.builder.build_select(saturate_up, max_values, res, ""))
3928 .into_vector_value();
3929 let res = err!(
3930 self.builder
3931 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3932 );
3933 self.state.push1(res);
3934 }
3935 Operator::I16x8ExtMulLowI8x16S
3936 | Operator::I16x8ExtMulLowI8x16U
3937 | Operator::I16x8ExtMulHighI8x16S
3938 | Operator::I16x8ExtMulHighI8x16U => {
3939 let extend_op = match op {
3940 Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulHighI8x16S => {
3941 |s: &Self, v| -> Result<VectorValue, CompileError> {
3942 err_nt!(s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, ""))
3943 }
3944 }
3945 Operator::I16x8ExtMulLowI8x16U | Operator::I16x8ExtMulHighI8x16U => {
3946 |s: &Self, v| -> Result<VectorValue, CompileError> {
3947 err_nt!(s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, ""))
3948 }
3949 }
3950 _ => unreachable!("Unhandled internal variant"),
3951 };
3952 let shuffle_array = match op {
3953 Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulLowI8x16U => [
3954 self.intrinsics.i32_consts[0],
3955 self.intrinsics.i32_consts[1],
3956 self.intrinsics.i32_consts[2],
3957 self.intrinsics.i32_consts[3],
3958 self.intrinsics.i32_consts[4],
3959 self.intrinsics.i32_consts[5],
3960 self.intrinsics.i32_consts[6],
3961 self.intrinsics.i32_consts[7],
3962 ],
3963 Operator::I16x8ExtMulHighI8x16S | Operator::I16x8ExtMulHighI8x16U => [
3964 self.intrinsics.i32_consts[8],
3965 self.intrinsics.i32_consts[9],
3966 self.intrinsics.i32_consts[10],
3967 self.intrinsics.i32_consts[11],
3968 self.intrinsics.i32_consts[12],
3969 self.intrinsics.i32_consts[13],
3970 self.intrinsics.i32_consts[14],
3971 self.intrinsics.i32_consts[15],
3972 ],
3973 _ => unreachable!("Unhandled internal variant"),
3974 };
3975 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3976 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3977 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3978 let val1 = err!(self.builder.build_shuffle_vector(
3979 v1,
3980 v1.get_type().get_undef(),
3981 VectorType::const_vector(&shuffle_array),
3982 "",
3983 ));
3984 let val1 = err!(extend_op(self, val1));
3985 let val2 = err!(self.builder.build_shuffle_vector(
3986 v2,
3987 v2.get_type().get_undef(),
3988 VectorType::const_vector(&shuffle_array),
3989 "",
3990 ));
3991 let val2 = err!(extend_op(self, val2));
3992 let res = err!(self.builder.build_int_mul(val1, val2, ""));
3993 let res = err!(
3994 self.builder
3995 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3996 );
3997 self.state.push1(res);
3998 }
3999 Operator::I32x4ExtMulLowI16x8S
4000 | Operator::I32x4ExtMulLowI16x8U
4001 | Operator::I32x4ExtMulHighI16x8S
4002 | Operator::I32x4ExtMulHighI16x8U => {
4003 let extend_op = match op {
4004 Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulHighI16x8S => {
4005 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
4006 }
4007 Operator::I32x4ExtMulLowI16x8U | Operator::I32x4ExtMulHighI16x8U => {
4008 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
4009 }
4010 _ => unreachable!("Unhandled internal variant"),
4011 };
4012 let shuffle_array = match op {
4013 Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulLowI16x8U => [
4014 self.intrinsics.i32_consts[0],
4015 self.intrinsics.i32_consts[1],
4016 self.intrinsics.i32_consts[2],
4017 self.intrinsics.i32_consts[3],
4018 ],
4019 Operator::I32x4ExtMulHighI16x8S | Operator::I32x4ExtMulHighI16x8U => [
4020 self.intrinsics.i32_consts[4],
4021 self.intrinsics.i32_consts[5],
4022 self.intrinsics.i32_consts[6],
4023 self.intrinsics.i32_consts[7],
4024 ],
4025 _ => unreachable!("Unhandled internal variant"),
4026 };
4027 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4028 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4029 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4030 let val1 = err!(self.builder.build_shuffle_vector(
4031 v1,
4032 v1.get_type().get_undef(),
4033 VectorType::const_vector(&shuffle_array),
4034 "",
4035 ));
4036 let val1 = err!(extend_op(self, val1));
4037 let val2 = err!(self.builder.build_shuffle_vector(
4038 v2,
4039 v2.get_type().get_undef(),
4040 VectorType::const_vector(&shuffle_array),
4041 "",
4042 ));
4043 let val2 = err!(extend_op(self, val2));
4044 let res = err!(self.builder.build_int_mul(val1, val2, ""));
4045 let res = err!(
4046 self.builder
4047 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4048 );
4049 self.state.push1(res);
4050 }
4051 Operator::I64x2ExtMulLowI32x4S
4052 | Operator::I64x2ExtMulLowI32x4U
4053 | Operator::I64x2ExtMulHighI32x4S
4054 | Operator::I64x2ExtMulHighI32x4U => {
4055 let extend_op = match op {
4056 Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulHighI32x4S => {
4057 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
4058 }
4059 Operator::I64x2ExtMulLowI32x4U | Operator::I64x2ExtMulHighI32x4U => {
4060 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
4061 }
4062 _ => unreachable!("Unhandled internal variant"),
4063 };
4064 let shuffle_array = match op {
4065 Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulLowI32x4U => {
4066 [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
4067 }
4068 Operator::I64x2ExtMulHighI32x4S | Operator::I64x2ExtMulHighI32x4U => {
4069 [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
4070 }
4071 _ => unreachable!("Unhandled internal variant"),
4072 };
4073 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4074 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4075 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4076 let val1 = err!(self.builder.build_shuffle_vector(
4077 v1,
4078 v1.get_type().get_undef(),
4079 VectorType::const_vector(&shuffle_array),
4080 "",
4081 ));
4082 let val1 = err!(extend_op(self, val1));
4083 let val2 = err!(self.builder.build_shuffle_vector(
4084 v2,
4085 v2.get_type().get_undef(),
4086 VectorType::const_vector(&shuffle_array),
4087 "",
4088 ));
4089 let val2 = err!(extend_op(self, val2));
4090 let res = err!(self.builder.build_int_mul(val1, val2, ""));
4091 let res = err!(
4092 self.builder
4093 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4094 );
4095 self.state.push1(res);
4096 }
4097 Operator::I32x4DotI16x8S => {
4098 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4099 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4100 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4101 let low_i16 = [
4102 self.intrinsics.i32_consts[0],
4103 self.intrinsics.i32_consts[2],
4104 self.intrinsics.i32_consts[4],
4105 self.intrinsics.i32_consts[6],
4106 ];
4107 let high_i16 = [
4108 self.intrinsics.i32_consts[1],
4109 self.intrinsics.i32_consts[3],
4110 self.intrinsics.i32_consts[5],
4111 self.intrinsics.i32_consts[7],
4112 ];
4113 let v1_low = err!(self.builder.build_shuffle_vector(
4114 v1,
4115 v1.get_type().get_undef(),
4116 VectorType::const_vector(&low_i16),
4117 "",
4118 ));
4119 let v1_low = err!(self.builder.build_int_s_extend(
4120 v1_low,
4121 self.intrinsics.i32x4_ty,
4122 ""
4123 ));
4124 let v1_high = err!(self.builder.build_shuffle_vector(
4125 v1,
4126 v1.get_type().get_undef(),
4127 VectorType::const_vector(&high_i16),
4128 "",
4129 ));
4130 let v1_high = err!(self.builder.build_int_s_extend(
4131 v1_high,
4132 self.intrinsics.i32x4_ty,
4133 ""
4134 ));
4135 let v2_low = err!(self.builder.build_shuffle_vector(
4136 v2,
4137 v2.get_type().get_undef(),
4138 VectorType::const_vector(&low_i16),
4139 "",
4140 ));
4141 let v2_low = err!(self.builder.build_int_s_extend(
4142 v2_low,
4143 self.intrinsics.i32x4_ty,
4144 ""
4145 ));
4146 let v2_high = err!(self.builder.build_shuffle_vector(
4147 v2,
4148 v2.get_type().get_undef(),
4149 VectorType::const_vector(&high_i16),
4150 "",
4151 ));
4152 let v2_high = err!(self.builder.build_int_s_extend(
4153 v2_high,
4154 self.intrinsics.i32x4_ty,
4155 ""
4156 ));
4157 let low_product = err!(self.builder.build_int_mul(v1_low, v2_low, ""));
4158 let high_product = err!(self.builder.build_int_mul(v1_high, v2_high, ""));
4159
4160 let res = err!(self.builder.build_int_add(low_product, high_product, ""));
4161 let res = err!(
4162 self.builder
4163 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4164 );
4165 self.state.push1(res);
4166 }
4167 Operator::I16x8RelaxedDotI8x16I7x16S
4168 if self.cpu_features.contains(CpuFeature::SSSE3) =>
4169 {
4170 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4171 let (a, _) = self.v128_into_i8x16(v1, i1)?;
4172 let (b, _) = self.v128_into_i8x16(v2, i2)?;
4173
4174 let res = self
4175 .build_call_with_param_attributes(
4176 self.intrinsics.x86_64.pmaddubsw128,
4177 &[b.into(), a.into()],
4178 "",
4179 )?
4180 .try_as_basic_value()
4181 .unwrap_basic()
4182 .into_vector_value();
4183 let res = err!(
4184 self.builder
4185 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4186 );
4187 self.state.push1(res);
4188 }
4189 Operator::I16x8RelaxedDotI8x16I7x16S => {
4190 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4191 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4192 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4193
4194 let left_indices = [
4195 self.intrinsics.i32_consts[0],
4196 self.intrinsics.i32_consts[2],
4197 self.intrinsics.i32_consts[4],
4198 self.intrinsics.i32_consts[6],
4199 self.intrinsics.i32_consts[8],
4200 self.intrinsics.i32_consts[10],
4201 self.intrinsics.i32_consts[12],
4202 self.intrinsics.i32_consts[14],
4203 ];
4204 let right_indices = [
4205 self.intrinsics.i32_consts[1],
4206 self.intrinsics.i32_consts[3],
4207 self.intrinsics.i32_consts[5],
4208 self.intrinsics.i32_consts[7],
4209 self.intrinsics.i32_consts[9],
4210 self.intrinsics.i32_consts[11],
4211 self.intrinsics.i32_consts[13],
4212 self.intrinsics.i32_consts[15],
4213 ];
4214
4215 let v1_left = err!(self.builder.build_shuffle_vector(
4216 v1,
4217 v1.get_type().get_undef(),
4218 VectorType::const_vector(&left_indices),
4219 "",
4220 ));
4221 let v1_left = err!(self.builder.build_int_s_extend(
4222 v1_left,
4223 self.intrinsics.i16x8_ty,
4224 ""
4225 ));
4226 let v1_right = err!(self.builder.build_shuffle_vector(
4227 v1,
4228 v1.get_type().get_undef(),
4229 VectorType::const_vector(&right_indices),
4230 "",
4231 ));
4232 let v1_right = err!(self.builder.build_int_s_extend(
4233 v1_right,
4234 self.intrinsics.i16x8_ty,
4235 ""
4236 ));
4237
4238 let v2_left = err!(self.builder.build_shuffle_vector(
4239 v2,
4240 v2.get_type().get_undef(),
4241 VectorType::const_vector(&left_indices),
4242 "",
4243 ));
4244 let v2_left = err!(self.builder.build_int_s_extend(
4245 v2_left,
4246 self.intrinsics.i16x8_ty,
4247 ""
4248 ));
4249 let v2_right = err!(self.builder.build_shuffle_vector(
4250 v2,
4251 v2.get_type().get_undef(),
4252 VectorType::const_vector(&right_indices),
4253 "",
4254 ));
4255 let v2_right = err!(self.builder.build_int_s_extend(
4256 v2_right,
4257 self.intrinsics.i16x8_ty,
4258 ""
4259 ));
4260
4261 let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4262 let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4263 let res = err!(self.builder.build_int_add(prod_left, prod_right, ""));
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::I32x4RelaxedDotI8x16I7x16AddS
4271 if self.cpu_features.contains(CpuFeature::SSSE3) =>
4272 {
4273 let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4274 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4275 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4276 let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4277
4278 let dot16 = self
4281 .build_call_with_param_attributes(
4282 self.intrinsics.x86_64.pmaddubsw128,
4283 &[v2.into(), v1.into()],
4284 "",
4285 )?
4286 .try_as_basic_value()
4287 .unwrap_basic()
4288 .into_vector_value();
4289 let ones =
4290 VectorType::const_vector(&[self.intrinsics.i16_ty.const_int(1, false); 8]);
4291 let dot32 = self
4292 .build_call_with_param_attributes(
4293 self.intrinsics.x86_64.pmaddwd128,
4294 &[dot16.into(), ones.into()],
4295 "",
4296 )?
4297 .try_as_basic_value()
4298 .unwrap_basic()
4299 .into_vector_value();
4300 let res = err!(self.builder.build_int_add(dot32, acc, ""));
4301 let res = err!(
4302 self.builder
4303 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4304 );
4305 self.state.push1(res);
4306 }
4307 Operator::I32x4RelaxedDotI8x16I7x16AddS => {
4308 let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4309 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4310 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4311 let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4312
4313 let left_indices = [
4314 self.intrinsics.i32_consts[0],
4315 self.intrinsics.i32_consts[2],
4316 self.intrinsics.i32_consts[4],
4317 self.intrinsics.i32_consts[6],
4318 self.intrinsics.i32_consts[8],
4319 self.intrinsics.i32_consts[10],
4320 self.intrinsics.i32_consts[12],
4321 self.intrinsics.i32_consts[14],
4322 ];
4323 let right_indices = [
4324 self.intrinsics.i32_consts[1],
4325 self.intrinsics.i32_consts[3],
4326 self.intrinsics.i32_consts[5],
4327 self.intrinsics.i32_consts[7],
4328 self.intrinsics.i32_consts[9],
4329 self.intrinsics.i32_consts[11],
4330 self.intrinsics.i32_consts[13],
4331 self.intrinsics.i32_consts[15],
4332 ];
4333
4334 let v1_left = err!(self.builder.build_shuffle_vector(
4335 v1,
4336 v1.get_type().get_undef(),
4337 VectorType::const_vector(&left_indices),
4338 "",
4339 ));
4340 let v1_left = err!(self.builder.build_int_s_extend(
4341 v1_left,
4342 self.intrinsics.i16x8_ty,
4343 ""
4344 ));
4345 let v1_right = err!(self.builder.build_shuffle_vector(
4346 v1,
4347 v1.get_type().get_undef(),
4348 VectorType::const_vector(&right_indices),
4349 "",
4350 ));
4351 let v1_right = err!(self.builder.build_int_s_extend(
4352 v1_right,
4353 self.intrinsics.i16x8_ty,
4354 ""
4355 ));
4356
4357 let v2_left = err!(self.builder.build_shuffle_vector(
4358 v2,
4359 v2.get_type().get_undef(),
4360 VectorType::const_vector(&left_indices),
4361 "",
4362 ));
4363 let v2_left = err!(self.builder.build_int_s_extend(
4364 v2_left,
4365 self.intrinsics.i16x8_ty,
4366 ""
4367 ));
4368 let v2_right = err!(self.builder.build_shuffle_vector(
4369 v2,
4370 v2.get_type().get_undef(),
4371 VectorType::const_vector(&right_indices),
4372 "",
4373 ));
4374 let v2_right = err!(self.builder.build_int_s_extend(
4375 v2_right,
4376 self.intrinsics.i16x8_ty,
4377 ""
4378 ));
4379
4380 let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4381 let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4382 let dot16 = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4383
4384 let pair_left = err!(self.builder.build_shuffle_vector(
4385 dot16,
4386 dot16.get_type().get_undef(),
4387 VectorType::const_vector(&[
4388 self.intrinsics.i32_consts[0],
4389 self.intrinsics.i32_consts[2],
4390 self.intrinsics.i32_consts[4],
4391 self.intrinsics.i32_consts[6],
4392 ]),
4393 "",
4394 ));
4395 let pair_left = err!(self.builder.build_int_s_extend(
4396 pair_left,
4397 self.intrinsics.i32x4_ty,
4398 ""
4399 ));
4400 let pair_right = err!(self.builder.build_shuffle_vector(
4401 dot16,
4402 dot16.get_type().get_undef(),
4403 VectorType::const_vector(&[
4404 self.intrinsics.i32_consts[1],
4405 self.intrinsics.i32_consts[3],
4406 self.intrinsics.i32_consts[5],
4407 self.intrinsics.i32_consts[7],
4408 ]),
4409 "",
4410 ));
4411 let pair_right = err!(self.builder.build_int_s_extend(
4412 pair_right,
4413 self.intrinsics.i32x4_ty,
4414 ""
4415 ));
4416 let dot32 = err!(self.builder.build_int_add(pair_left, pair_right, ""));
4417 let res = err!(self.builder.build_int_add(dot32, acc, ""));
4418 let res = err!(
4419 self.builder
4420 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4421 );
4422 self.state.push1(res);
4423 }
4424 Operator::I32DivS | Operator::I64DivS => {
4425 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4426 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4427 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4428 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4429
4430 self.trap_if_zero_or_overflow(v1, v2)?;
4431
4432 let res = err!(self.builder.build_int_signed_div(v1, v2, ""));
4433 self.state.push1(res);
4434 }
4435 Operator::I32DivU | Operator::I64DivU => {
4436 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4437 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4438 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4439 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4440
4441 self.trap_if_zero(v2)?;
4442
4443 let res = err!(self.builder.build_int_unsigned_div(v1, v2, ""));
4444 self.state.push1(res);
4445 }
4446 Operator::I32RemS | Operator::I64RemS => {
4447 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4448 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4449 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4450 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4451 let int_type = v1.get_type();
4452 let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
4453 let min_value = int_type.const_int(i32::MIN as u64, false);
4454 let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
4455 (min_value, neg_one_value)
4456 } else if int_type == self.intrinsics.i64_ty {
4457 let min_value = int_type.const_int(i64::MIN as u64, false);
4458 let neg_one_value = int_type.const_int(-1i64 as u64, false);
4459 (min_value, neg_one_value)
4460 } else {
4461 unreachable!()
4462 };
4463
4464 self.trap_if_zero(v2)?;
4465
4466 let will_overflow = err!(self.builder.build_and(
4478 err!(self.builder.build_int_compare(
4479 IntPredicate::EQ,
4480 v1,
4481 min_value,
4482 "left_is_min"
4483 )),
4484 err!(self.builder.build_int_compare(
4485 IntPredicate::EQ,
4486 v2,
4487 neg_one_value,
4488 "right_is_neg_one",
4489 )),
4490 "srem_will_overflow",
4491 ));
4492 let v1 =
4493 err!(
4494 self.builder
4495 .build_select(will_overflow, int_type.const_zero(), v1, "")
4496 )
4497 .into_int_value();
4498 let res = err!(self.builder.build_int_signed_rem(v1, v2, ""));
4499 self.state.push1(res);
4500 }
4501 Operator::I32RemU | Operator::I64RemU => {
4502 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4503 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4504 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4505 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4506
4507 self.trap_if_zero(v2)?;
4508
4509 let res = err!(self.builder.build_int_unsigned_rem(v1, v2, ""));
4510 self.state.push1(res);
4511 }
4512 Operator::I32And | Operator::I64And | Operator::V128And => {
4513 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4514 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4515 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4516 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4517 let res = err!(self.builder.build_and(v1, v2, ""));
4518 self.state.push1(res);
4519 }
4520 Operator::I32Or | Operator::I64Or | Operator::V128Or => {
4521 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4522 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4523 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4524 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4525 let res = err!(self.builder.build_or(v1, v2, ""));
4526 self.state.push1(res);
4527 }
4528 Operator::I32Xor | Operator::I64Xor | Operator::V128Xor => {
4529 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4530 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4531 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4532 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4533 let res = err!(self.builder.build_xor(v1, v2, ""));
4534 self.state.push1(res);
4535 }
4536 Operator::V128AndNot => {
4537 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4538 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4539 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4540 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4541 let v2 = err!(self.builder.build_not(v2, ""));
4542 let res = err!(self.builder.build_and(v1, v2, ""));
4543 self.state.push1(res);
4544 }
4545 Operator::I8x16RelaxedLaneselect
4546 | Operator::I16x8RelaxedLaneselect
4547 | Operator::I32x4RelaxedLaneselect
4548 | Operator::I64x2RelaxedLaneselect
4549 if self.cpu_features.contains(CpuFeature::SSE41) =>
4550 {
4551 let ((v1, i1), (v2, i2), (mask, mask_info)) = self.state.pop3_extra()?;
4552 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4553 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4554 let mask = self.apply_pending_canonicalization(mask, mask_info)?;
4555
4556 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4557 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4558 let (mask, _) = self.v128_into_i8x16(mask, mask_info)?;
4559 let res = self
4560 .build_call_with_param_attributes(
4561 self.intrinsics.x86_64.pblendvb,
4562 &[v2.into(), v1.into(), mask.into()],
4563 "",
4564 )?
4565 .try_as_basic_value()
4566 .unwrap_basic();
4567 let res = err!(
4568 self.builder
4569 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4570 );
4571 self.state.push1(res);
4572 }
4573 Operator::I8x16RelaxedLaneselect
4574 | Operator::I16x8RelaxedLaneselect
4575 | Operator::I32x4RelaxedLaneselect
4576 | Operator::I64x2RelaxedLaneselect
4577 | Operator::V128Bitselect => {
4578 let ((v1, i1), (v2, i2), (cond, cond_info)) = self.state.pop3_extra()?;
4579 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4580 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4581 let cond = self.apply_pending_canonicalization(cond, cond_info)?;
4582 let v1 = err!(
4583 self.builder
4584 .build_bit_cast(v1, self.intrinsics.i1x128_ty, "")
4585 )
4586 .into_vector_value();
4587 let v2 = err!(
4588 self.builder
4589 .build_bit_cast(v2, self.intrinsics.i1x128_ty, "")
4590 )
4591 .into_vector_value();
4592 let cond = err!(
4593 self.builder
4594 .build_bit_cast(cond, self.intrinsics.i1x128_ty, "")
4595 )
4596 .into_vector_value();
4597 let res = err!(self.builder.build_select(cond, v1, v2, ""));
4598 let res = err!(
4599 self.builder
4600 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4601 );
4602 self.state.push1(res);
4603 }
4604 Operator::I8x16Bitmask => {
4605 let (v, i) = self.state.pop1_extra()?;
4606 let (v, _) = self.v128_into_i8x16(v, i)?;
4607
4608 let zeros = self.intrinsics.i8x16_ty.const_zero();
4609 let res = err!(
4610 self.builder
4611 .build_int_compare(IntPredicate::SLT, v, zeros, "")
4612 );
4613 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i16_ty, ""))
4614 .into_int_value();
4615 let res = err!(
4616 self.builder
4617 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4618 );
4619 self.state.push1(res);
4620 }
4621 Operator::I16x8Bitmask => {
4622 let (v, i) = self.state.pop1_extra()?;
4623 let (v, _) = self.v128_into_i16x8(v, i)?;
4624
4625 let zeros = self.intrinsics.i16x8_ty.const_zero();
4626 let res = err!(
4627 self.builder
4628 .build_int_compare(IntPredicate::SLT, v, zeros, "")
4629 );
4630 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i8_ty, ""))
4631 .into_int_value();
4632 let res = err!(
4633 self.builder
4634 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4635 );
4636 self.state.push1(res);
4637 }
4638 Operator::I32x4Bitmask => {
4639 let (v, i) = self.state.pop1_extra()?;
4640 let (v, _) = self.v128_into_i32x4(v, i)?;
4641
4642 let zeros = self.intrinsics.i32x4_ty.const_zero();
4643 let res = err!(
4644 self.builder
4645 .build_int_compare(IntPredicate::SLT, v, zeros, "")
4646 );
4647 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i4_ty, ""))
4648 .into_int_value();
4649 let res = err!(
4650 self.builder
4651 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4652 );
4653 self.state.push1(res);
4654 }
4655 Operator::I64x2Bitmask => {
4656 let (v, i) = self.state.pop1_extra()?;
4657 let (v, _) = self.v128_into_i64x2(v, i)?;
4658
4659 let zeros = self.intrinsics.i64x2_ty.const_zero();
4660 let res = err!(
4661 self.builder
4662 .build_int_compare(IntPredicate::SLT, v, zeros, "")
4663 );
4664 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i2_ty, ""))
4665 .into_int_value();
4666 let res = err!(
4667 self.builder
4668 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4669 );
4670 self.state.push1(res);
4671 }
4672 Operator::I32Shl => {
4673 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4674 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4675 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4676 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4677 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4678 let v2 = err!(self.builder.build_and(v2, mask, ""));
4679 let res = err!(self.builder.build_left_shift(v1, v2, ""));
4680 self.state.push1(res);
4681 }
4682 Operator::I64Shl => {
4683 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4684 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4685 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4686 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4687 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4688 let v2 = err!(self.builder.build_and(v2, mask, ""));
4689 let res = err!(self.builder.build_left_shift(v1, v2, ""));
4690 self.state.push1(res);
4691 }
4692 Operator::I8x16Shl => {
4693 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4694 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4695 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4696 let v2 = v2.into_int_value();
4697 let v2 = err!(
4698 self.builder
4699 .build_and(v2, self.intrinsics.i32_consts[7], "")
4700 );
4701 let v2 = err!(
4702 self.builder
4703 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
4704 );
4705 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
4706 let res = err!(self.builder.build_left_shift(v1, v2, ""));
4707 let res = err!(
4708 self.builder
4709 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4710 );
4711 self.state.push1(res);
4712 }
4713 Operator::I16x8Shl => {
4714 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4715 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4716 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4717 let v2 = v2.into_int_value();
4718 let v2 = err!(
4719 self.builder
4720 .build_and(v2, self.intrinsics.i32_consts[15], "")
4721 );
4722 let v2 = err!(
4723 self.builder
4724 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
4725 );
4726 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
4727 let res = err!(self.builder.build_left_shift(v1, v2, ""));
4728 let res = err!(
4729 self.builder
4730 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4731 );
4732 self.state.push1(res);
4733 }
4734 Operator::I32x4Shl => {
4735 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4736 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4737 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4738 let v2 = v2.into_int_value();
4739 let v2 = err!(self.builder.build_and(
4740 v2,
4741 self.intrinsics.i32_ty.const_int(31, false),
4742 ""
4743 ));
4744 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
4745 let res = err!(self.builder.build_left_shift(v1, v2, ""));
4746 let res = err!(
4747 self.builder
4748 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4749 );
4750 self.state.push1(res);
4751 }
4752 Operator::I64x2Shl => {
4753 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4754 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4755 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4756 let v2 = v2.into_int_value();
4757 let v2 = err!(self.builder.build_and(
4758 v2,
4759 self.intrinsics.i32_ty.const_int(63, false),
4760 ""
4761 ));
4762 let v2 = err!(
4763 self.builder
4764 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
4765 );
4766 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
4767 let res = err!(self.builder.build_left_shift(v1, v2, ""));
4768 let res = err!(
4769 self.builder
4770 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4771 );
4772 self.state.push1(res);
4773 }
4774 Operator::I32ShrS => {
4775 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4776 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4777 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4778 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4779 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4780 let v2 = err!(self.builder.build_and(v2, mask, ""));
4781 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4782 self.state.push1(res);
4783 }
4784 Operator::I64ShrS => {
4785 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4786 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4787 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4788 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4789 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4790 let v2 = err!(self.builder.build_and(v2, mask, ""));
4791 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4792 self.state.push1(res);
4793 }
4794 Operator::I8x16ShrS => {
4795 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4796 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4797 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4798 let v2 = v2.into_int_value();
4799 let v2 = err!(
4800 self.builder
4801 .build_and(v2, self.intrinsics.i32_consts[7], "")
4802 );
4803 let v2 = err!(
4804 self.builder
4805 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
4806 );
4807 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
4808 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4809 let res = err!(
4810 self.builder
4811 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4812 );
4813 self.state.push1(res);
4814 }
4815 Operator::I16x8ShrS => {
4816 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4817 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4818 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4819 let v2 = v2.into_int_value();
4820 let v2 = err!(
4821 self.builder
4822 .build_and(v2, self.intrinsics.i32_consts[15], "")
4823 );
4824 let v2 = err!(
4825 self.builder
4826 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
4827 );
4828 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
4829 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4830 let res = err!(
4831 self.builder
4832 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4833 );
4834 self.state.push1(res);
4835 }
4836 Operator::I32x4ShrS => {
4837 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4838 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4839 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4840 let v2 = v2.into_int_value();
4841 let v2 = err!(self.builder.build_and(
4842 v2,
4843 self.intrinsics.i32_ty.const_int(31, false),
4844 ""
4845 ));
4846 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
4847 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4848 let res = err!(
4849 self.builder
4850 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4851 );
4852 self.state.push1(res);
4853 }
4854 Operator::I64x2ShrS => {
4855 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4856 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4857 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4858 let v2 = v2.into_int_value();
4859 let v2 = err!(self.builder.build_and(
4860 v2,
4861 self.intrinsics.i32_ty.const_int(63, false),
4862 ""
4863 ));
4864 let v2 = err!(
4865 self.builder
4866 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
4867 );
4868 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
4869 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4870 let res = err!(
4871 self.builder
4872 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4873 );
4874 self.state.push1(res);
4875 }
4876 Operator::I32ShrU => {
4877 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4878 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4879 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4880 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4881 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4882 let v2 = err!(self.builder.build_and(v2, mask, ""));
4883 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4884 self.state.push1(res);
4885 }
4886 Operator::I64ShrU => {
4887 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4888 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4889 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4890 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4891 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4892 let v2 = err!(self.builder.build_and(v2, mask, ""));
4893 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4894 self.state.push1(res);
4895 }
4896 Operator::I8x16ShrU => {
4897 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4898 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4899 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4900 let v2 = v2.into_int_value();
4901 let v2 = err!(
4902 self.builder
4903 .build_and(v2, self.intrinsics.i32_consts[7], "")
4904 );
4905 let v2 = err!(
4906 self.builder
4907 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
4908 );
4909 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
4910 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4911 let res = err!(
4912 self.builder
4913 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4914 );
4915 self.state.push1(res);
4916 }
4917 Operator::I16x8ShrU => {
4918 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4919 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4920 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4921 let v2 = v2.into_int_value();
4922 let v2 = err!(
4923 self.builder
4924 .build_and(v2, self.intrinsics.i32_consts[15], "")
4925 );
4926 let v2 = err!(
4927 self.builder
4928 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
4929 );
4930 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
4931 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4932 let res = err!(
4933 self.builder
4934 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4935 );
4936 self.state.push1(res);
4937 }
4938 Operator::I32x4ShrU => {
4939 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4940 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4941 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4942 let v2 = v2.into_int_value();
4943 let v2 = err!(self.builder.build_and(
4944 v2,
4945 self.intrinsics.i32_ty.const_int(31, false),
4946 ""
4947 ));
4948 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
4949 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4950 let res = err!(
4951 self.builder
4952 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4953 );
4954 self.state.push1(res);
4955 }
4956 Operator::I64x2ShrU => {
4957 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4958 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4959 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4960 let v2 = v2.into_int_value();
4961 let v2 = err!(self.builder.build_and(
4962 v2,
4963 self.intrinsics.i32_ty.const_int(63, false),
4964 ""
4965 ));
4966 let v2 = err!(
4967 self.builder
4968 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
4969 );
4970 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
4971 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4972 let res = err!(
4973 self.builder
4974 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4975 );
4976 self.state.push1(res);
4977 }
4978 Operator::I32Rotl => {
4979 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4980 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4981 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4982 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4983 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4984 let v2 = err!(self.builder.build_and(v2, mask, ""));
4985 let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
4986 let rhs = {
4987 let negv2 = err!(self.builder.build_int_neg(v2, ""));
4988 let rhs = err!(self.builder.build_and(negv2, mask, ""));
4989 err!(self.builder.build_right_shift(v1, rhs, false, ""))
4990 };
4991 let res = err!(self.builder.build_or(lhs, rhs, ""));
4992 self.state.push1(res);
4993 }
4994 Operator::I64Rotl => {
4995 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4996 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4997 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4998 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4999 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5000 let v2 = err!(self.builder.build_and(v2, mask, ""));
5001 let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5002 let rhs = {
5003 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5004 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5005 err!(self.builder.build_right_shift(v1, rhs, false, ""))
5006 };
5007 let res = err!(self.builder.build_or(lhs, rhs, ""));
5008 self.state.push1(res);
5009 }
5010 Operator::I32Rotr => {
5011 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5012 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5013 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5014 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5015 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5016 let v2 = err!(self.builder.build_and(v2, mask, ""));
5017 let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5018 let rhs = {
5019 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5020 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5021 err!(self.builder.build_left_shift(v1, rhs, ""))
5022 };
5023 let res = err!(self.builder.build_or(lhs, rhs, ""));
5024 self.state.push1(res);
5025 }
5026 Operator::I64Rotr => {
5027 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5028 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5029 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5030 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5031 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5032 let v2 = err!(self.builder.build_and(v2, mask, ""));
5033 let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5034 let rhs = {
5035 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5036 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5037 err!(self.builder.build_left_shift(v1, rhs, ""))
5038 };
5039 let res = err!(self.builder.build_or(lhs, rhs, ""));
5040 self.state.push1(res);
5041 }
5042 Operator::I32Clz => {
5043 let (input, info) = self.state.pop1_extra()?;
5044 let input = self.apply_pending_canonicalization(input, info)?;
5045 let is_zero_undef = self.intrinsics.i1_zero;
5046 let res = self
5047 .build_call_with_param_attributes(
5048 self.intrinsics.ctlz_i32,
5049 &[input.into(), is_zero_undef.into()],
5050 "",
5051 )?
5052 .try_as_basic_value()
5053 .unwrap_basic();
5054 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5055 }
5056 Operator::I64Clz => {
5057 let (input, info) = self.state.pop1_extra()?;
5058 let input = self.apply_pending_canonicalization(input, info)?;
5059 let is_zero_undef = self.intrinsics.i1_zero;
5060 let res = self
5061 .build_call_with_param_attributes(
5062 self.intrinsics.ctlz_i64,
5063 &[input.into(), is_zero_undef.into()],
5064 "",
5065 )?
5066 .try_as_basic_value()
5067 .unwrap_basic();
5068 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5069 }
5070 Operator::I32Ctz => {
5071 let (input, info) = self.state.pop1_extra()?;
5072 let input = self.apply_pending_canonicalization(input, info)?;
5073 let is_zero_undef = self.intrinsics.i1_zero;
5074 let res = self
5075 .build_call_with_param_attributes(
5076 self.intrinsics.cttz_i32,
5077 &[input.into(), is_zero_undef.into()],
5078 "",
5079 )?
5080 .try_as_basic_value()
5081 .unwrap_basic();
5082 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5083 }
5084 Operator::I64Ctz => {
5085 let (input, info) = self.state.pop1_extra()?;
5086 let input = self.apply_pending_canonicalization(input, info)?;
5087 let is_zero_undef = self.intrinsics.i1_zero;
5088 let res = self
5089 .build_call_with_param_attributes(
5090 self.intrinsics.cttz_i64,
5091 &[input.into(), is_zero_undef.into()],
5092 "",
5093 )?
5094 .try_as_basic_value()
5095 .unwrap_basic();
5096 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5097 }
5098 Operator::I8x16Popcnt => {
5099 let (v, i) = self.state.pop1_extra()?;
5100 let (v, _) = self.v128_into_i8x16(v, i)?;
5101 let res = self
5102 .build_call_with_param_attributes(self.intrinsics.ctpop_i8x16, &[v.into()], "")?
5103 .try_as_basic_value()
5104 .unwrap_basic();
5105 let res = err!(
5106 self.builder
5107 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5108 );
5109 self.state.push1(res);
5110 }
5111 Operator::I32Popcnt => {
5112 let (input, info) = self.state.pop1_extra()?;
5113 let input = self.apply_pending_canonicalization(input, info)?;
5114 let res = self
5115 .build_call_with_param_attributes(
5116 self.intrinsics.ctpop_i32,
5117 &[input.into()],
5118 "",
5119 )?
5120 .try_as_basic_value()
5121 .unwrap_basic();
5122 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5123 }
5124 Operator::I64Popcnt => {
5125 let (input, info) = self.state.pop1_extra()?;
5126 let input = self.apply_pending_canonicalization(input, info)?;
5127 let res = self
5128 .build_call_with_param_attributes(
5129 self.intrinsics.ctpop_i64,
5130 &[input.into()],
5131 "",
5132 )?
5133 .try_as_basic_value()
5134 .unwrap_basic();
5135 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5136 }
5137 Operator::I32Eqz => {
5138 let input = self.state.pop1()?.into_int_value();
5139 let cond = err!(self.builder.build_int_compare(
5140 IntPredicate::EQ,
5141 input,
5142 self.intrinsics.i32_zero,
5143 "",
5144 ));
5145 let res = err!(
5146 self.builder
5147 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5148 );
5149 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5150 }
5151 Operator::I64Eqz => {
5152 let input = self.state.pop1()?.into_int_value();
5153 let cond = err!(self.builder.build_int_compare(
5154 IntPredicate::EQ,
5155 input,
5156 self.intrinsics.i64_zero,
5157 "",
5158 ));
5159 let res = err!(
5160 self.builder
5161 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5162 );
5163 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5164 }
5165 Operator::I8x16Abs => {
5166 let (v, i) = self.state.pop1_extra()?;
5167 let (v, _) = self.v128_into_i8x16(v, i)?;
5168
5169 let seven = self.intrinsics.i8_ty.const_int(7, false);
5170 let seven = VectorType::const_vector(&[seven; 16]);
5171 let all_sign_bits = err!(self.builder.build_right_shift(v, seven, true, ""));
5172 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5173 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5174 let res = err!(
5175 self.builder
5176 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5177 );
5178 self.state.push1(res);
5179 }
5180 Operator::I16x8Abs => {
5181 let (v, i) = self.state.pop1_extra()?;
5182 let (v, _) = self.v128_into_i16x8(v, i)?;
5183
5184 let fifteen = self.intrinsics.i16_ty.const_int(15, false);
5185 let fifteen = VectorType::const_vector(&[fifteen; 8]);
5186 let all_sign_bits = err!(self.builder.build_right_shift(v, fifteen, true, ""));
5187 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5188 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5189 let res = err!(
5190 self.builder
5191 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5192 );
5193 self.state.push1(res);
5194 }
5195 Operator::I32x4Abs => {
5196 let (v, i) = self.state.pop1_extra()?;
5197 let (v, _) = self.v128_into_i32x4(v, i)?;
5198
5199 let thirtyone = self.intrinsics.i32_ty.const_int(31, false);
5200 let thirtyone = VectorType::const_vector(&[thirtyone; 4]);
5201 let all_sign_bits = err!(self.builder.build_right_shift(v, thirtyone, true, ""));
5202 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5203 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5204 let res = err!(
5205 self.builder
5206 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5207 );
5208 self.state.push1(res);
5209 }
5210 Operator::I64x2Abs => {
5211 let (v, i) = self.state.pop1_extra()?;
5212 let (v, _) = self.v128_into_i64x2(v, i)?;
5213
5214 let sixtythree = self.intrinsics.i64_ty.const_int(63, false);
5215 let sixtythree = VectorType::const_vector(&[sixtythree; 2]);
5216 let all_sign_bits = err!(self.builder.build_right_shift(v, sixtythree, true, ""));
5217 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5218 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5219 let res = err!(
5220 self.builder
5221 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5222 );
5223 self.state.push1(res);
5224 }
5225 Operator::I8x16MinS => {
5226 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5227 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5228 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5229 let cmp = err!(
5230 self.builder
5231 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5232 );
5233 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5234 let res = err!(
5235 self.builder
5236 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5237 );
5238 self.state.push1(res);
5239 }
5240 Operator::I8x16MinU => {
5241 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5242 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5243 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5244 let cmp = err!(
5245 self.builder
5246 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5247 );
5248 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5249 let res = err!(
5250 self.builder
5251 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5252 );
5253 self.state.push1(res);
5254 }
5255 Operator::I8x16MaxS => {
5256 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5257 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5258 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5259 let cmp = err!(
5260 self.builder
5261 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5262 );
5263 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5264 let res = err!(
5265 self.builder
5266 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5267 );
5268 self.state.push1(res);
5269 }
5270 Operator::I8x16MaxU => {
5271 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5272 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5273 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5274 let cmp = err!(
5275 self.builder
5276 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5277 );
5278 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5279 let res = err!(
5280 self.builder
5281 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5282 );
5283 self.state.push1(res);
5284 }
5285 Operator::I16x8MinS => {
5286 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5287 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5288 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5289 let cmp = err!(
5290 self.builder
5291 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5292 );
5293 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5294 let res = err!(
5295 self.builder
5296 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5297 );
5298 self.state.push1(res);
5299 }
5300 Operator::I16x8MinU => {
5301 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5302 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5303 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5304 let cmp = err!(
5305 self.builder
5306 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5307 );
5308 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5309 let res = err!(
5310 self.builder
5311 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5312 );
5313 self.state.push1(res);
5314 }
5315 Operator::I16x8MaxS => {
5316 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5317 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5318 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5319 let cmp = err!(
5320 self.builder
5321 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5322 );
5323 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5324 let res = err!(
5325 self.builder
5326 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5327 );
5328 self.state.push1(res);
5329 }
5330 Operator::I16x8MaxU => {
5331 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5332 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5333 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5334 let cmp = err!(
5335 self.builder
5336 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5337 );
5338 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5339 let res = err!(
5340 self.builder
5341 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5342 );
5343 self.state.push1(res);
5344 }
5345 Operator::I32x4MinS => {
5346 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5347 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5348 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5349 let cmp = err!(
5350 self.builder
5351 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5352 );
5353 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5354 let res = err!(
5355 self.builder
5356 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5357 );
5358 self.state.push1(res);
5359 }
5360 Operator::I32x4MinU => {
5361 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5362 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5363 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5364 let cmp = err!(
5365 self.builder
5366 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5367 );
5368 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5369 let res = err!(
5370 self.builder
5371 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5372 );
5373 self.state.push1(res);
5374 }
5375 Operator::I32x4MaxS => {
5376 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5377 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5378 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5379 let cmp = err!(
5380 self.builder
5381 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5382 );
5383 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5384 let res = err!(
5385 self.builder
5386 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5387 );
5388 self.state.push1(res);
5389 }
5390 Operator::I32x4MaxU => {
5391 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5392 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5393 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5394 let cmp = err!(
5395 self.builder
5396 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5397 );
5398 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5399 let res = err!(
5400 self.builder
5401 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5402 );
5403 self.state.push1(res);
5404 }
5405 Operator::I8x16AvgrU => {
5406 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5407 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5408 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5409
5410 let ext_ty = self.intrinsics.i16_ty.vec_type(16);
5421 let one = self.intrinsics.i16_ty.const_int(1, false);
5422 let one = VectorType::const_vector(&[one; 16]);
5423
5424 let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5425 let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5426 let res = err!(self.builder.build_int_add(
5427 err!(self.builder.build_int_add(one, v1, "")),
5428 v2,
5429 ""
5430 ));
5431 let res = err!(self.builder.build_right_shift(res, one, false, ""));
5432 let res = err!(
5433 self.builder
5434 .build_int_truncate(res, self.intrinsics.i8x16_ty, "")
5435 );
5436 let res = err!(
5437 self.builder
5438 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5439 );
5440 self.state.push1(res);
5441 }
5442 Operator::I16x8AvgrU => {
5443 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5444 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5445 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5446
5447 let ext_ty = self.intrinsics.i32_ty.vec_type(8);
5458 let one = self.intrinsics.i32_consts[1];
5459 let one = VectorType::const_vector(&[one; 8]);
5460
5461 let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5462 let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5463 let res = err!(self.builder.build_int_add(
5464 err!(self.builder.build_int_add(one, v1, "")),
5465 v2,
5466 ""
5467 ));
5468 let res = err!(self.builder.build_right_shift(res, one, false, ""));
5469 let res = err!(
5470 self.builder
5471 .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
5472 );
5473 let res = err!(
5474 self.builder
5475 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5476 );
5477 self.state.push1(res);
5478 }
5479
5480 Operator::F32Add => {
5485 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5486 let res = self
5487 .build_call_with_param_attributes(
5488 self.intrinsics.add_f32,
5489 &[
5490 v1.into(),
5491 v2.into(),
5492 self.intrinsics.fp_rounding_md,
5493 self.intrinsics.fp_exception_md,
5494 ],
5495 "",
5496 )?
5497 .try_as_basic_value()
5498 .unwrap_basic();
5499 self.state.push1_extra(
5500 res,
5501 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5502 );
5503 }
5504 Operator::F64Add => {
5505 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5506 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5507 let res = self
5508 .build_call_with_param_attributes(
5509 self.intrinsics.add_f64,
5510 &[
5511 v1.into(),
5512 v2.into(),
5513 self.intrinsics.fp_rounding_md,
5514 self.intrinsics.fp_exception_md,
5515 ],
5516 "",
5517 )?
5518 .try_as_basic_value()
5519 .unwrap_basic();
5520 self.state.push1_extra(
5521 res,
5522 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5523 );
5524 }
5525 Operator::F32x4Add => {
5526 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5527 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5528 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5529 let res = self
5530 .build_call_with_param_attributes(
5531 self.intrinsics.add_f32x4,
5532 &[
5533 v1.into(),
5534 v2.into(),
5535 self.intrinsics.fp_rounding_md,
5536 self.intrinsics.fp_exception_md,
5537 ],
5538 "",
5539 )?
5540 .try_as_basic_value()
5541 .unwrap_basic();
5542 let res = err!(
5543 self.builder
5544 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5545 );
5546 self.state.push1_extra(
5547 res,
5548 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5549 );
5550 }
5551 Operator::F64x2Add => {
5552 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5553 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5554 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5555 let res = self
5556 .build_call_with_param_attributes(
5557 self.intrinsics.add_f64x2,
5558 &[
5559 v1.into(),
5560 v2.into(),
5561 self.intrinsics.fp_rounding_md,
5562 self.intrinsics.fp_exception_md,
5563 ],
5564 "",
5565 )?
5566 .try_as_basic_value()
5567 .unwrap_basic();
5568 let res = err!(
5569 self.builder
5570 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5571 );
5572 self.state.push1_extra(
5573 res,
5574 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5575 );
5576 }
5577 Operator::F32Sub => {
5578 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5579 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5580 let res = self
5581 .build_call_with_param_attributes(
5582 self.intrinsics.sub_f32,
5583 &[
5584 v1.into(),
5585 v2.into(),
5586 self.intrinsics.fp_rounding_md,
5587 self.intrinsics.fp_exception_md,
5588 ],
5589 "",
5590 )?
5591 .try_as_basic_value()
5592 .unwrap_basic();
5593 self.state.push1_extra(
5594 res,
5595 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5596 );
5597 }
5598 Operator::F64Sub => {
5599 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5600 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5601 let res = self
5602 .build_call_with_param_attributes(
5603 self.intrinsics.sub_f64,
5604 &[
5605 v1.into(),
5606 v2.into(),
5607 self.intrinsics.fp_rounding_md,
5608 self.intrinsics.fp_exception_md,
5609 ],
5610 "",
5611 )?
5612 .try_as_basic_value()
5613 .unwrap_basic();
5614 self.state.push1_extra(
5615 res,
5616 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5617 );
5618 }
5619 Operator::F32x4Sub => {
5620 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5621 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5622 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5623 let res = self
5624 .build_call_with_param_attributes(
5625 self.intrinsics.sub_f32x4,
5626 &[
5627 v1.into(),
5628 v2.into(),
5629 self.intrinsics.fp_rounding_md,
5630 self.intrinsics.fp_exception_md,
5631 ],
5632 "",
5633 )?
5634 .try_as_basic_value()
5635 .unwrap_basic();
5636 let res = err!(
5637 self.builder
5638 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5639 );
5640 self.state.push1_extra(
5641 res,
5642 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5643 );
5644 }
5645 Operator::F64x2Sub => {
5646 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5647 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5648 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5649 let res = self
5650 .build_call_with_param_attributes(
5651 self.intrinsics.sub_f64x2,
5652 &[
5653 v1.into(),
5654 v2.into(),
5655 self.intrinsics.fp_rounding_md,
5656 self.intrinsics.fp_exception_md,
5657 ],
5658 "",
5659 )?
5660 .try_as_basic_value()
5661 .unwrap_basic();
5662 let res = err!(
5663 self.builder
5664 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5665 );
5666 self.state.push1_extra(
5667 res,
5668 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5669 );
5670 }
5671 Operator::F32Mul => {
5672 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5673 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5674 let res = self
5675 .build_call_with_param_attributes(
5676 self.intrinsics.mul_f32,
5677 &[
5678 v1.into(),
5679 v2.into(),
5680 self.intrinsics.fp_rounding_md,
5681 self.intrinsics.fp_exception_md,
5682 ],
5683 "",
5684 )?
5685 .try_as_basic_value()
5686 .unwrap_basic();
5687 self.state.push1_extra(
5688 res,
5689 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5690 );
5691 }
5692 Operator::F64Mul => {
5693 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5694 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5695 let res = self
5696 .build_call_with_param_attributes(
5697 self.intrinsics.mul_f64,
5698 &[
5699 v1.into(),
5700 v2.into(),
5701 self.intrinsics.fp_rounding_md,
5702 self.intrinsics.fp_exception_md,
5703 ],
5704 "",
5705 )?
5706 .try_as_basic_value()
5707 .unwrap_basic();
5708 self.state.push1_extra(
5709 res,
5710 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5711 );
5712 }
5713 Operator::F32x4Mul => {
5714 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5715 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5716 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5717 let res = self
5718 .build_call_with_param_attributes(
5719 self.intrinsics.mul_f32x4,
5720 &[
5721 v1.into(),
5722 v2.into(),
5723 self.intrinsics.fp_rounding_md,
5724 self.intrinsics.fp_exception_md,
5725 ],
5726 "",
5727 )?
5728 .try_as_basic_value()
5729 .unwrap_basic();
5730 let res = err!(
5731 self.builder
5732 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5733 );
5734 self.state.push1_extra(
5735 res,
5736 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5737 );
5738 }
5739 Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd
5740 if self.cpu_features.contains(CpuFeature::FMA) =>
5741 {
5742 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5743 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5744 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5745 let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
5746
5747 let v1 = match op {
5748 Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5749 _ => v1,
5750 };
5751 let res = self
5752 .build_call_with_param_attributes(
5753 self.intrinsics.muladd_f32x4,
5754 &[
5755 v1.into(),
5756 v2.into(),
5757 v3.into(),
5758 self.intrinsics.fp_rounding_md,
5759 self.intrinsics.fp_exception_md,
5760 ],
5761 "",
5762 )?
5763 .try_as_basic_value()
5764 .unwrap_basic();
5765 let res = err!(
5766 self.builder
5767 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5768 );
5769 let info = (i1.strip_pending() & i2.strip_pending())?;
5770 let info = (info & i3.strip_pending())?;
5771 let info = (info | ExtraInfo::pending_f32_nan())?;
5772 self.state.push1_extra(res, info);
5773 }
5774 Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd => {
5775 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5776 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5777 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5778 let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
5779
5780 let v1 = match op {
5781 Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5782 _ => v1,
5783 };
5784 let mul = self
5785 .build_call_with_param_attributes(
5786 self.intrinsics.mul_f32x4,
5787 &[
5788 v1.into(),
5789 v2.into(),
5790 self.intrinsics.fp_rounding_md,
5791 self.intrinsics.fp_exception_md,
5792 ],
5793 "",
5794 )?
5795 .try_as_basic_value()
5796 .unwrap_basic();
5797 let mul = mul.into_vector_value();
5798 let res = self
5799 .build_call_with_param_attributes(
5800 self.intrinsics.add_f32x4,
5801 &[
5802 mul.into(),
5803 v3.into(),
5804 self.intrinsics.fp_rounding_md,
5805 self.intrinsics.fp_exception_md,
5806 ],
5807 "",
5808 )?
5809 .try_as_basic_value()
5810 .unwrap_basic();
5811 let res = err!(
5812 self.builder
5813 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5814 );
5815 let info = (i1.strip_pending() & i2.strip_pending())?;
5816 let info = (info & i3.strip_pending())?;
5817 let info = (info | ExtraInfo::pending_f32_nan())?;
5818 self.state.push1_extra(res, info);
5819 }
5820 Operator::F64x2Mul => {
5821 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5822 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5823 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5824 let res = self
5825 .build_call_with_param_attributes(
5826 self.intrinsics.mul_f64x2,
5827 &[
5828 v1.into(),
5829 v2.into(),
5830 self.intrinsics.fp_rounding_md,
5831 self.intrinsics.fp_exception_md,
5832 ],
5833 "",
5834 )?
5835 .try_as_basic_value()
5836 .unwrap_basic();
5837 let res = err!(
5838 self.builder
5839 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5840 );
5841 self.state.push1_extra(
5842 res,
5843 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5844 );
5845 }
5846 Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd
5847 if self.cpu_features.contains(CpuFeature::FMA) =>
5848 {
5849 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5850 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5851 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5852 let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
5853
5854 let v1 = match op {
5855 Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5856 _ => v1,
5857 };
5858 let res = self
5859 .build_call_with_param_attributes(
5860 self.intrinsics.muladd_f64x2,
5861 &[
5862 v1.into(),
5863 v2.into(),
5864 v3.into(),
5865 self.intrinsics.fp_rounding_md,
5866 self.intrinsics.fp_exception_md,
5867 ],
5868 "",
5869 )?
5870 .try_as_basic_value()
5871 .unwrap_basic();
5872 let res = err!(
5873 self.builder
5874 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5875 );
5876 let info = (i1.strip_pending() & i2.strip_pending())?;
5877 let info = (info & i3.strip_pending())?;
5878 let info = (info | ExtraInfo::pending_f64_nan())?;
5879 self.state.push1_extra(res, info);
5880 }
5881 Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd => {
5882 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5883 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5884 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5885 let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
5886
5887 let v1 = match op {
5888 Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5889 _ => v1,
5890 };
5891 let mul = self
5892 .build_call_with_param_attributes(
5893 self.intrinsics.mul_f64x2,
5894 &[
5895 v1.into(),
5896 v2.into(),
5897 self.intrinsics.fp_rounding_md,
5898 self.intrinsics.fp_exception_md,
5899 ],
5900 "",
5901 )?
5902 .try_as_basic_value()
5903 .unwrap_basic();
5904 let mul = mul.into_vector_value();
5905 let res = self
5906 .build_call_with_param_attributes(
5907 self.intrinsics.add_f64x2,
5908 &[
5909 mul.into(),
5910 v3.into(),
5911 self.intrinsics.fp_rounding_md,
5912 self.intrinsics.fp_exception_md,
5913 ],
5914 "",
5915 )?
5916 .try_as_basic_value()
5917 .unwrap_basic();
5918 let res = err!(
5919 self.builder
5920 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5921 );
5922 let info = (i1.strip_pending() & i2.strip_pending())?;
5923 let info = (info & i3.strip_pending())?;
5924 let info = (info | ExtraInfo::pending_f64_nan())?;
5925 self.state.push1_extra(res, info);
5926 }
5927 Operator::F32Div => {
5928 let (v1, v2) = self.state.pop2()?;
5929 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5930 let res = self
5931 .build_call_with_param_attributes(
5932 self.intrinsics.div_f32,
5933 &[
5934 v1.into(),
5935 v2.into(),
5936 self.intrinsics.fp_rounding_md,
5937 self.intrinsics.fp_exception_md,
5938 ],
5939 "",
5940 )?
5941 .try_as_basic_value()
5942 .unwrap_basic();
5943 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
5944 }
5945 Operator::F64Div => {
5946 let (v1, v2) = self.state.pop2()?;
5947 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5948 let res = self
5949 .build_call_with_param_attributes(
5950 self.intrinsics.div_f64,
5951 &[
5952 v1.into(),
5953 v2.into(),
5954 self.intrinsics.fp_rounding_md,
5955 self.intrinsics.fp_exception_md,
5956 ],
5957 "",
5958 )?
5959 .try_as_basic_value()
5960 .unwrap_basic();
5961 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
5962 }
5963 Operator::F32x4Div => {
5964 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5965 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
5966 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
5967 let res = self
5968 .build_call_with_param_attributes(
5969 self.intrinsics.div_f32x4,
5970 &[
5971 v1.into(),
5972 v2.into(),
5973 self.intrinsics.fp_rounding_md,
5974 self.intrinsics.fp_exception_md,
5975 ],
5976 "",
5977 )?
5978 .try_as_basic_value()
5979 .unwrap_basic();
5980 let res = err!(
5981 self.builder
5982 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5983 );
5984 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
5985 }
5986 Operator::F64x2Div => {
5987 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5988 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
5989 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
5990 let res = self
5991 .build_call_with_param_attributes(
5992 self.intrinsics.div_f64x2,
5993 &[
5994 v1.into(),
5995 v2.into(),
5996 self.intrinsics.fp_rounding_md,
5997 self.intrinsics.fp_exception_md,
5998 ],
5999 "",
6000 )?
6001 .try_as_basic_value()
6002 .unwrap_basic();
6003 let res = err!(
6004 self.builder
6005 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6006 );
6007 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6008 }
6009 Operator::F32Sqrt => {
6010 let input = self.state.pop1()?;
6011 let res = self
6012 .build_call_with_param_attributes(
6013 self.intrinsics.sqrt_f32,
6014 &[input.into()],
6015 "",
6016 )?
6017 .try_as_basic_value()
6018 .unwrap_basic();
6019 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6020 }
6021 Operator::F64Sqrt => {
6022 let input = self.state.pop1()?;
6023 let res = self
6024 .build_call_with_param_attributes(
6025 self.intrinsics.sqrt_f64,
6026 &[input.into()],
6027 "",
6028 )?
6029 .try_as_basic_value()
6030 .unwrap_basic();
6031 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6032 }
6033 Operator::F32x4Sqrt => {
6034 let (v, i) = self.state.pop1_extra()?;
6035 let (v, _) = self.v128_into_f32x4(v, i)?;
6036 let res = self
6037 .build_call_with_param_attributes(self.intrinsics.sqrt_f32x4, &[v.into()], "")?
6038 .try_as_basic_value()
6039 .unwrap_basic();
6040 let bits = err!(
6041 self.builder
6042 .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6043 );
6044 self.state.push1_extra(bits, ExtraInfo::pending_f32_nan());
6045 }
6046 Operator::F64x2Sqrt => {
6047 let (v, i) = self.state.pop1_extra()?;
6048 let (v, _) = self.v128_into_f64x2(v, i)?;
6049 let res = self
6050 .build_call_with_param_attributes(self.intrinsics.sqrt_f64x2, &[v.into()], "")?
6051 .try_as_basic_value()
6052 .unwrap_basic();
6053 let bits = err!(
6054 self.builder
6055 .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6056 );
6057 self.state.push1(bits);
6058 }
6059 Operator::F32Min => {
6060 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6061 let lhs = self
6062 .apply_pending_canonicalization(lhs, lhs_info)?
6063 .into_float_value();
6064 let rhs = self
6065 .apply_pending_canonicalization(rhs, rhs_info)?
6066 .into_float_value();
6067
6068 let res = self
6069 .build_call_with_param_attributes(
6070 self.intrinsics.minimum_f32,
6071 &[lhs.into(), rhs.into()],
6072 "",
6073 )?
6074 .try_as_basic_value()
6075 .unwrap_basic();
6076
6077 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6078 let res = res.into_float_value();
6079
6080 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6081 }
6082 Operator::F64Min => {
6083 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6084 let lhs = self
6085 .apply_pending_canonicalization(lhs, lhs_info)?
6086 .into_float_value();
6087 let rhs = self
6088 .apply_pending_canonicalization(rhs, rhs_info)?
6089 .into_float_value();
6090
6091 let res = self
6092 .build_call_with_param_attributes(
6093 self.intrinsics.minimum_f64,
6094 &[lhs.into(), rhs.into()],
6095 "",
6096 )?
6097 .try_as_basic_value()
6098 .unwrap_basic();
6099
6100 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6101 let res = res.into_float_value();
6102
6103 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6104 }
6105 Operator::F32x4RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6106 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6107 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6108 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6109 let res = self
6110 .build_call_with_param_attributes(
6111 self.intrinsics.x86_64.min_ps,
6112 &[v1.into(), v2.into()],
6113 "",
6114 )?
6115 .try_as_basic_value()
6116 .unwrap_basic();
6117 let res = err!(
6118 self.builder
6119 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6120 );
6121 self.state.push1_extra(
6122 res,
6123 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6124 );
6125 }
6126 Operator::F32x4Min | Operator::F32x4RelaxedMin => {
6127 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6128 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6129 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6130 let res = self
6131 .build_call_with_param_attributes(
6132 self.intrinsics.minimum_f32x4,
6133 &[v1.into(), v2.into()],
6134 "",
6135 )?
6136 .try_as_basic_value()
6137 .unwrap_basic();
6138
6139 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6140 let res = res.into_vector_value();
6141
6142 let res = err!(
6143 self.builder
6144 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6145 );
6146 self.state.push1_extra(
6147 res,
6148 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6149 );
6150 }
6151 Operator::F32x4PMin => {
6152 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6154 let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6155 let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6156 let cmp = err!(
6157 self.builder
6158 .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6159 );
6160 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6161 let res = err!(
6162 self.builder
6163 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6164 );
6165 self.state.push1(res);
6166 }
6167 Operator::F64x2RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6168 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6169 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6170 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6171 let res = self
6172 .build_call_with_param_attributes(
6173 self.intrinsics.x86_64.min_pd,
6174 &[v1.into(), v2.into()],
6175 "",
6176 )?
6177 .try_as_basic_value()
6178 .unwrap_basic();
6179 let res = err!(
6180 self.builder
6181 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6182 );
6183 self.state.push1_extra(
6184 res,
6185 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6186 );
6187 }
6188 Operator::F64x2Min | Operator::F64x2RelaxedMin => {
6189 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6190 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6191 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6192 let res = self
6193 .build_call_with_param_attributes(
6194 self.intrinsics.minimum_f64x2,
6195 &[v1.into(), v2.into()],
6196 "",
6197 )?
6198 .try_as_basic_value()
6199 .unwrap_basic();
6200
6201 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6202 let res = res.into_vector_value();
6203
6204 let res = err!(
6205 self.builder
6206 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6207 );
6208 self.state.push1_extra(
6209 res,
6210 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6211 );
6212 }
6213 Operator::F64x2PMin => {
6214 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6216 let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6217 let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6218 let cmp = err!(
6219 self.builder
6220 .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6221 );
6222 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6223 let res = err!(
6224 self.builder
6225 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6226 );
6227 self.state.push1(res);
6228 }
6229 Operator::F32Max => {
6230 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6231 let lhs = self
6232 .apply_pending_canonicalization(lhs, lhs_info)?
6233 .into_float_value();
6234 let rhs = self
6235 .apply_pending_canonicalization(rhs, rhs_info)?
6236 .into_float_value();
6237
6238 let res = self
6239 .build_call_with_param_attributes(
6240 self.intrinsics.maximum_f32,
6241 &[lhs.into(), rhs.into()],
6242 "",
6243 )?
6244 .try_as_basic_value()
6245 .unwrap_basic();
6246
6247 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6248 let res = res.into_float_value();
6249
6250 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6251 }
6252 Operator::F64Max => {
6253 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6254 let lhs = self
6255 .apply_pending_canonicalization(lhs, lhs_info)?
6256 .into_float_value();
6257 let rhs = self
6258 .apply_pending_canonicalization(rhs, rhs_info)?
6259 .into_float_value();
6260
6261 let res = self
6262 .build_call_with_param_attributes(
6263 self.intrinsics.maximum_f64,
6264 &[lhs.into(), rhs.into()],
6265 "",
6266 )?
6267 .try_as_basic_value()
6268 .unwrap_basic();
6269
6270 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6271 let res = res.into_float_value();
6272
6273 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6274 }
6275 Operator::F32x4RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6276 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6277 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6278 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6279 let res = self
6280 .build_call_with_param_attributes(
6281 self.intrinsics.x86_64.max_ps,
6282 &[v1.into(), v2.into()],
6283 "",
6284 )?
6285 .try_as_basic_value()
6286 .unwrap_basic();
6287 let res = err!(
6288 self.builder
6289 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6290 );
6291 self.state.push1_extra(
6292 res,
6293 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6294 );
6295 }
6296 Operator::F32x4Max | Operator::F32x4RelaxedMax => {
6297 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6298 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6299 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6300 let res = self
6301 .build_call_with_param_attributes(
6302 self.intrinsics.maximum_f32x4,
6303 &[v1.into(), v2.into()],
6304 "",
6305 )?
6306 .try_as_basic_value()
6307 .unwrap_basic();
6308
6309 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6310 let res = res.into_vector_value();
6311
6312 let res = err!(
6313 self.builder
6314 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6315 );
6316 self.state.push1_extra(
6317 res,
6318 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6319 );
6320 }
6321 Operator::F32x4PMax => {
6322 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6324 let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6325 let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6326 let cmp = err!(
6327 self.builder
6328 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6329 );
6330 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6331
6332 let res = err!(
6333 self.builder
6334 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6335 );
6336 self.state.push1(res);
6337 }
6338 Operator::F64x2RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6339 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6340 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6341 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6342 let res = self
6343 .build_call_with_param_attributes(
6344 self.intrinsics.x86_64.max_pd,
6345 &[v1.into(), v2.into()],
6346 "",
6347 )?
6348 .try_as_basic_value()
6349 .unwrap_basic();
6350 let res = err!(
6351 self.builder
6352 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6353 );
6354 self.state.push1_extra(
6355 res,
6356 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6357 );
6358 }
6359 Operator::F64x2Max | Operator::F64x2RelaxedMax => {
6360 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6361 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6362 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6363 let res = self
6364 .build_call_with_param_attributes(
6365 self.intrinsics.maximum_f64x2,
6366 &[v1.into(), v2.into()],
6367 "",
6368 )?
6369 .try_as_basic_value()
6370 .unwrap_basic();
6371
6372 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6373 let res = res.into_vector_value();
6374
6375 let res = err!(
6376 self.builder
6377 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6378 );
6379 self.state.push1_extra(
6380 res,
6381 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6382 );
6383 }
6384 Operator::F64x2PMax => {
6385 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6387 let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6388 let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6389 let cmp = err!(
6390 self.builder
6391 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6392 );
6393 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6394 let res = err!(
6395 self.builder
6396 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6397 );
6398 self.state.push1(res);
6399 }
6400 Operator::F32Ceil => {
6401 let (input, info) = self.state.pop1_extra()?;
6402 let res = err!(self.build_call_with_param_attributes(
6403 self.intrinsics.ceil_f32,
6404 &[input.into()],
6405 ""
6406 ))
6407 .try_as_basic_value()
6408 .unwrap_basic();
6409 let (res, info) = self.finalize_rounding_result(res, info)?;
6410 self.state.push1_extra(res, info);
6411 }
6412 Operator::F32x4Ceil => {
6413 let (v, i) = self.state.pop1_extra()?;
6414 let (v, _) = self.v128_into_f32x4(v, i)?;
6415 let res = err!(self.build_call_with_param_attributes(
6416 self.intrinsics.ceil_f32x4,
6417 &[v.into()],
6418 ""
6419 ))
6420 .try_as_basic_value()
6421 .unwrap_basic();
6422 let (res, info) = self.finalize_rounding_result(res, i)?;
6423 let res = err!(
6424 self.builder
6425 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6426 );
6427 self.state.push1_extra(res, info);
6428 }
6429 Operator::F64Ceil => {
6430 let (input, info) = self.state.pop1_extra()?;
6431 let res = err!(self.build_call_with_param_attributes(
6432 self.intrinsics.ceil_f64,
6433 &[input.into()],
6434 ""
6435 ))
6436 .try_as_basic_value()
6437 .unwrap_basic();
6438 let (res, info) = self.finalize_rounding_result(res, info)?;
6439 self.state.push1_extra(res, info);
6440 }
6441 Operator::F64x2Ceil => {
6442 let (v, i) = self.state.pop1_extra()?;
6443 let (v, _) = self.v128_into_f64x2(v, i)?;
6444 let res = err!(self.build_call_with_param_attributes(
6445 self.intrinsics.ceil_f64x2,
6446 &[v.into()],
6447 ""
6448 ))
6449 .try_as_basic_value()
6450 .unwrap_basic();
6451 let (res, info) = self.finalize_rounding_result(res, i)?;
6452 let res = err!(
6453 self.builder
6454 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6455 );
6456 self.state.push1_extra(res, info);
6457 }
6458 Operator::F32Floor => {
6459 let (input, info) = self.state.pop1_extra()?;
6460 let res = err!(self.build_call_with_param_attributes(
6461 self.intrinsics.floor_f32,
6462 &[input.into()],
6463 ""
6464 ))
6465 .try_as_basic_value()
6466 .unwrap_basic();
6467 let (res, info) = self.finalize_rounding_result(res, info)?;
6468 self.state.push1_extra(res, info);
6469 }
6470 Operator::F32x4Floor => {
6471 let (v, i) = self.state.pop1_extra()?;
6472 let (v, _) = self.v128_into_f32x4(v, i)?;
6473 let res = err!(self.build_call_with_param_attributes(
6474 self.intrinsics.floor_f32x4,
6475 &[v.into()],
6476 ""
6477 ))
6478 .try_as_basic_value()
6479 .unwrap_basic();
6480 let (res, info) = self.finalize_rounding_result(res, i)?;
6481 let res = err!(
6482 self.builder
6483 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6484 );
6485 self.state.push1_extra(res, info);
6486 }
6487 Operator::F64Floor => {
6488 let (input, info) = self.state.pop1_extra()?;
6489 let res = err!(self.build_call_with_param_attributes(
6490 self.intrinsics.floor_f64,
6491 &[input.into()],
6492 ""
6493 ))
6494 .try_as_basic_value()
6495 .unwrap_basic();
6496 let (res, info) = self.finalize_rounding_result(res, info)?;
6497 self.state.push1_extra(res, info);
6498 }
6499 Operator::F64x2Floor => {
6500 let (v, i) = self.state.pop1_extra()?;
6501 let (v, _) = self.v128_into_f64x2(v, i)?;
6502 let res = err!(self.build_call_with_param_attributes(
6503 self.intrinsics.floor_f64x2,
6504 &[v.into()],
6505 ""
6506 ))
6507 .try_as_basic_value()
6508 .unwrap_basic();
6509 let (res, info) = self.finalize_rounding_result(res, i)?;
6510 let res = err!(
6511 self.builder
6512 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6513 );
6514 self.state.push1_extra(res, info);
6515 }
6516 Operator::F32Trunc => {
6517 let (v, info) = self.state.pop1_extra()?;
6518 let res = err!(
6519 self.builder
6520 .build_call(self.intrinsics.trunc_f32, &[v.into()], "")
6521 )
6522 .try_as_basic_value()
6523 .unwrap_basic();
6524 let (res, info) = self.finalize_rounding_result(res, info)?;
6525 self.state.push1_extra(res, info);
6526 }
6527 Operator::F32x4Trunc => {
6528 let (v, i) = self.state.pop1_extra()?;
6529 let (v, _) = self.v128_into_f32x4(v, i)?;
6530 let res = err!(self.build_call_with_param_attributes(
6531 self.intrinsics.trunc_f32x4,
6532 &[v.into()],
6533 ""
6534 ))
6535 .try_as_basic_value()
6536 .unwrap_basic();
6537 let (res, info) = self.finalize_rounding_result(res, i)?;
6538 let res = err!(
6539 self.builder
6540 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6541 );
6542 self.state.push1_extra(res, info);
6543 }
6544 Operator::F64Trunc => {
6545 let (v, info) = self.state.pop1_extra()?;
6546 let res = err!(
6547 self.builder
6548 .build_call(self.intrinsics.trunc_f64, &[v.into()], "")
6549 )
6550 .try_as_basic_value()
6551 .unwrap_basic();
6552 let (res, info) = self.finalize_rounding_result(res, info)?;
6553 self.state.push1_extra(res, info);
6554 }
6555 Operator::F64x2Trunc => {
6556 let (v, i) = self.state.pop1_extra()?;
6557 let (v, _) = self.v128_into_f64x2(v, i)?;
6558 let res = err!(self.build_call_with_param_attributes(
6559 self.intrinsics.trunc_f64x2,
6560 &[v.into()],
6561 ""
6562 ))
6563 .try_as_basic_value()
6564 .unwrap_basic();
6565 let (res, info) = self.finalize_rounding_result(res, i)?;
6566 let res = err!(
6567 self.builder
6568 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6569 );
6570 self.state.push1_extra(res, info);
6571 }
6572 Operator::F32Nearest => {
6573 let (v, info) = self.state.pop1_extra()?;
6574 let res = err!(self.build_call_with_param_attributes(
6575 self.intrinsics.nearbyint_f32,
6576 &[v.into()],
6577 ""
6578 ))
6579 .try_as_basic_value()
6580 .unwrap_basic();
6581 let (res, info) = self.finalize_rounding_result(res, info)?;
6582 self.state.push1_extra(res, info);
6583 }
6584 Operator::F32x4Nearest => {
6585 let (v, i) = self.state.pop1_extra()?;
6586 let (v, _) = self.v128_into_f32x4(v, i)?;
6587 let res = err!(self.build_call_with_param_attributes(
6588 self.intrinsics.nearbyint_f32x4,
6589 &[v.into()],
6590 ""
6591 ))
6592 .try_as_basic_value()
6593 .unwrap_basic();
6594 let (res, info) = self.finalize_rounding_result(res, i)?;
6595 let res = err!(
6596 self.builder
6597 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6598 );
6599 self.state.push1_extra(res, info);
6600 }
6601 Operator::F64Nearest => {
6602 let (v, info) = self.state.pop1_extra()?;
6603 let res = err!(self.build_call_with_param_attributes(
6604 self.intrinsics.nearbyint_f64,
6605 &[v.into()],
6606 ""
6607 ))
6608 .try_as_basic_value()
6609 .unwrap_basic();
6610 let (res, info) = self.finalize_rounding_result(res, info)?;
6611 self.state.push1_extra(res, info);
6612 }
6613 Operator::F64x2Nearest => {
6614 let (v, i) = self.state.pop1_extra()?;
6615 let (v, _) = self.v128_into_f64x2(v, i)?;
6616 let res = err!(self.build_call_with_param_attributes(
6617 self.intrinsics.nearbyint_f64x2,
6618 &[v.into()],
6619 ""
6620 ))
6621 .try_as_basic_value()
6622 .unwrap_basic();
6623 let (res, info) = self.finalize_rounding_result(res, i)?;
6624 let res = err!(
6625 self.builder
6626 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6627 );
6628 self.state.push1_extra(res, info);
6629 }
6630 Operator::F32Abs => {
6631 let (v, i) = self.state.pop1_extra()?;
6632 let v = self.apply_pending_canonicalization(v, i)?;
6633 let res = err!(
6634 self.builder
6635 .build_call(self.intrinsics.fabs_f32, &[v.into()], "")
6636 )
6637 .try_as_basic_value()
6638 .unwrap_basic();
6639 self.state.push1_extra(res, i.strip_pending());
6642 }
6643 Operator::F64Abs => {
6644 let (v, i) = self.state.pop1_extra()?;
6645 let v = self.apply_pending_canonicalization(v, i)?;
6646 let res = err!(
6647 self.builder
6648 .build_call(self.intrinsics.fabs_f64, &[v.into()], "")
6649 )
6650 .try_as_basic_value()
6651 .unwrap_basic();
6652 self.state.push1_extra(res, i.strip_pending());
6655 }
6656 Operator::F32x4Abs => {
6657 let (v, i) = self.state.pop1_extra()?;
6658 let v = err!(self.builder.build_bit_cast(
6659 v.into_int_value(),
6660 self.intrinsics.f32x4_ty,
6661 ""
6662 ));
6663 let v = self.apply_pending_canonicalization(v, i)?;
6664 let res = self
6665 .build_call_with_param_attributes(self.intrinsics.fabs_f32x4, &[v.into()], "")?
6666 .try_as_basic_value()
6667 .unwrap_basic();
6668 let res = err!(
6669 self.builder
6670 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6671 );
6672 self.state.push1_extra(res, i.strip_pending());
6675 }
6676 Operator::F64x2Abs => {
6677 let (v, i) = self.state.pop1_extra()?;
6678 let v = err!(self.builder.build_bit_cast(
6679 v.into_int_value(),
6680 self.intrinsics.f64x2_ty,
6681 ""
6682 ));
6683 let v = self.apply_pending_canonicalization(v, i)?;
6684 let res = self
6685 .build_call_with_param_attributes(self.intrinsics.fabs_f64x2, &[v.into()], "")?
6686 .try_as_basic_value()
6687 .unwrap_basic();
6688 let res = err!(
6689 self.builder
6690 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6691 );
6692 self.state.push1_extra(res, i.strip_pending());
6695 }
6696 Operator::F32x4Neg => {
6697 let (v, i) = self.state.pop1_extra()?;
6698 let v = err!(self.builder.build_bit_cast(
6699 v.into_int_value(),
6700 self.intrinsics.f32x4_ty,
6701 ""
6702 ));
6703 let v = self
6704 .apply_pending_canonicalization(v, i)?
6705 .into_vector_value();
6706 let res = err!(self.builder.build_float_neg(v, ""));
6707 let res = err!(
6708 self.builder
6709 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6710 );
6711 self.state.push1_extra(res, i.strip_pending());
6714 }
6715 Operator::F64x2Neg => {
6716 let (v, i) = self.state.pop1_extra()?;
6717 let v = err!(self.builder.build_bit_cast(
6718 v.into_int_value(),
6719 self.intrinsics.f64x2_ty,
6720 ""
6721 ));
6722 let v = self
6723 .apply_pending_canonicalization(v, i)?
6724 .into_vector_value();
6725 let res = err!(self.builder.build_float_neg(v, ""));
6726 let res = err!(
6727 self.builder
6728 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6729 );
6730 self.state.push1_extra(res, i.strip_pending());
6733 }
6734 Operator::F32Neg | Operator::F64Neg => {
6735 let (v, i) = self.state.pop1_extra()?;
6736 let v = self
6737 .apply_pending_canonicalization(v, i)?
6738 .into_float_value();
6739 let res = err!(self.builder.build_float_neg(v, ""));
6740 self.state.push1_extra(res, i.strip_pending());
6743 }
6744 Operator::F32Copysign => {
6745 let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
6746 let mag = self.apply_pending_canonicalization(mag, mag_info)?;
6747 let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
6748 let res = self
6749 .build_call_with_param_attributes(
6750 self.intrinsics.copysign_f32,
6751 &[mag.into(), sgn.into()],
6752 "",
6753 )?
6754 .try_as_basic_value()
6755 .unwrap_basic();
6756 self.state.push1_extra(res, mag_info.strip_pending());
6759 }
6760 Operator::F64Copysign => {
6761 let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
6762 let mag = self.apply_pending_canonicalization(mag, mag_info)?;
6763 let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
6764 let res = self
6765 .build_call_with_param_attributes(
6766 self.intrinsics.copysign_f64,
6767 &[mag.into(), sgn.into()],
6768 "",
6769 )?
6770 .try_as_basic_value()
6771 .unwrap_basic();
6772 self.state.push1_extra(res, mag_info.strip_pending());
6775 }
6776
6777 Operator::I32Eq | Operator::I64Eq => {
6782 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6783 let v1 = self.apply_pending_canonicalization(v1, i1)?;
6784 let v2 = self.apply_pending_canonicalization(v2, i2)?;
6785 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6786 let cond = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6787 let res = err!(
6788 self.builder
6789 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6790 );
6791 self.state.push1_extra(
6792 res,
6793 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6794 );
6795 }
6796 Operator::I8x16Eq => {
6797 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6798 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6799 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6800 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6801 let res = err!(
6802 self.builder
6803 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6804 );
6805 let res = err!(
6806 self.builder
6807 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6808 );
6809 self.state.push1(res);
6810 }
6811 Operator::I16x8Eq => {
6812 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6813 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6814 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6815 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6816 let res = err!(
6817 self.builder
6818 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6819 );
6820 let res = err!(
6821 self.builder
6822 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6823 );
6824 self.state.push1(res);
6825 }
6826 Operator::I32x4Eq => {
6827 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6828 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6829 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6830 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6831 let res = err!(
6832 self.builder
6833 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6834 );
6835 let res = err!(
6836 self.builder
6837 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6838 );
6839 self.state.push1(res);
6840 }
6841 Operator::I64x2Eq => {
6842 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6843 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
6844 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
6845 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6846 let res = err!(
6847 self.builder
6848 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
6849 );
6850 let res = err!(
6851 self.builder
6852 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6853 );
6854 self.state.push1(res);
6855 }
6856 Operator::I32Ne | Operator::I64Ne => {
6857 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6858 let v1 = self.apply_pending_canonicalization(v1, i1)?;
6859 let v2 = self.apply_pending_canonicalization(v2, i2)?;
6860 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6861 let cond = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6862 let res = err!(
6863 self.builder
6864 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6865 );
6866 self.state.push1_extra(
6867 res,
6868 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6869 );
6870 }
6871 Operator::I8x16Ne => {
6872 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6873 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6874 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6875 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6876 let res = err!(
6877 self.builder
6878 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6879 );
6880 let res = err!(
6881 self.builder
6882 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6883 );
6884 self.state.push1(res);
6885 }
6886 Operator::I16x8Ne => {
6887 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6888 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6889 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6890 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6891 let res = err!(
6892 self.builder
6893 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6894 );
6895 let res = err!(
6896 self.builder
6897 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6898 );
6899 self.state.push1(res);
6900 }
6901 Operator::I32x4Ne => {
6902 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6903 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6904 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6905 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6906 let res = err!(
6907 self.builder
6908 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6909 );
6910 let res = err!(
6911 self.builder
6912 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6913 );
6914 self.state.push1(res);
6915 }
6916 Operator::I64x2Ne => {
6917 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6918 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
6919 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
6920 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6921 let res = err!(
6922 self.builder
6923 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
6924 );
6925 let res = err!(
6926 self.builder
6927 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6928 );
6929 self.state.push1(res);
6930 }
6931 Operator::I32LtS | Operator::I64LtS => {
6932 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6933 let v1 = self.apply_pending_canonicalization(v1, i1)?;
6934 let v2 = self.apply_pending_canonicalization(v2, i2)?;
6935 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6936 let cond = err!(
6937 self.builder
6938 .build_int_compare(IntPredicate::SLT, v1, v2, "")
6939 );
6940 let res = err!(
6941 self.builder
6942 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6943 );
6944 self.state.push1_extra(
6945 res,
6946 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6947 );
6948 }
6949 Operator::I8x16LtS => {
6950 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6951 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6952 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6953 let res = err!(
6954 self.builder
6955 .build_int_compare(IntPredicate::SLT, v1, v2, "")
6956 );
6957 let res = err!(
6958 self.builder
6959 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6960 );
6961 let res = err!(
6962 self.builder
6963 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6964 );
6965 self.state.push1(res);
6966 }
6967 Operator::I16x8LtS => {
6968 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6969 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6970 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6971 let res = err!(
6972 self.builder
6973 .build_int_compare(IntPredicate::SLT, v1, v2, "")
6974 );
6975 let res = err!(
6976 self.builder
6977 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6978 );
6979 let res = err!(
6980 self.builder
6981 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6982 );
6983 self.state.push1(res);
6984 }
6985 Operator::I32x4LtS => {
6986 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6987 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6988 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6989 let res = err!(
6990 self.builder
6991 .build_int_compare(IntPredicate::SLT, v1, v2, "")
6992 );
6993 let res = err!(
6994 self.builder
6995 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6996 );
6997 let res = err!(
6998 self.builder
6999 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7000 );
7001 self.state.push1(res);
7002 }
7003 Operator::I64x2LtS => {
7004 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7005 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7006 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7007 let res = err!(
7008 self.builder
7009 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7010 );
7011 let res = err!(
7012 self.builder
7013 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7014 );
7015 let res = err!(
7016 self.builder
7017 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7018 );
7019 self.state.push1(res);
7020 }
7021 Operator::I32LtU | Operator::I64LtU => {
7022 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7023 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7024 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7025 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7026 let cond = err!(
7027 self.builder
7028 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7029 );
7030 let res = err!(
7031 self.builder
7032 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7033 );
7034 self.state.push1(res);
7035 }
7036 Operator::I8x16LtU => {
7037 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7038 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7039 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7040 let res = err!(
7041 self.builder
7042 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7043 );
7044 let res = err!(
7045 self.builder
7046 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7047 );
7048 let res = err!(
7049 self.builder
7050 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7051 );
7052 self.state.push1(res);
7053 }
7054 Operator::I16x8LtU => {
7055 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7056 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7057 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7058 let res = err!(
7059 self.builder
7060 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7061 );
7062 let res = err!(
7063 self.builder
7064 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7065 );
7066 let res = err!(
7067 self.builder
7068 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7069 );
7070 self.state.push1(res);
7071 }
7072 Operator::I32x4LtU => {
7073 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7074 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7075 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7076 let res = err!(
7077 self.builder
7078 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7079 );
7080 let res = err!(
7081 self.builder
7082 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7083 );
7084 let res = err!(
7085 self.builder
7086 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7087 );
7088 self.state.push1(res);
7089 }
7090 Operator::I32LeS | Operator::I64LeS => {
7091 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7092 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7093 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7094 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7095 let cond = err!(
7096 self.builder
7097 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7098 );
7099 let res = err!(
7100 self.builder
7101 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7102 );
7103 self.state.push1_extra(
7104 res,
7105 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7106 );
7107 }
7108 Operator::I8x16LeS => {
7109 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7110 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7111 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7112 let res = err!(
7113 self.builder
7114 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7115 );
7116 let res = err!(
7117 self.builder
7118 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7119 );
7120 let res = err!(
7121 self.builder
7122 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7123 );
7124 self.state.push1(res);
7125 }
7126 Operator::I16x8LeS => {
7127 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7128 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7129 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7130 let res = err!(
7131 self.builder
7132 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7133 );
7134 let res = err!(
7135 self.builder
7136 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7137 );
7138 let res = err!(
7139 self.builder
7140 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7141 );
7142 self.state.push1(res);
7143 }
7144 Operator::I32x4LeS => {
7145 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7146 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7147 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7148 let res = err!(
7149 self.builder
7150 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7151 );
7152 let res = err!(
7153 self.builder
7154 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7155 );
7156 let res = err!(
7157 self.builder
7158 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7159 );
7160 self.state.push1(res);
7161 }
7162 Operator::I64x2LeS => {
7163 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7164 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7165 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7166 let res = err!(
7167 self.builder
7168 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7169 );
7170 let res = err!(
7171 self.builder
7172 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7173 );
7174 let res = err!(
7175 self.builder
7176 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7177 );
7178 self.state.push1(res);
7179 }
7180 Operator::I32LeU | Operator::I64LeU => {
7181 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7182 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7183 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7184 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7185 let cond = err!(
7186 self.builder
7187 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7188 );
7189 let res = err!(
7190 self.builder
7191 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7192 );
7193 self.state.push1_extra(
7194 res,
7195 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7196 );
7197 }
7198 Operator::I8x16LeU => {
7199 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7200 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7201 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7202 let res = err!(
7203 self.builder
7204 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7205 );
7206 let res = err!(
7207 self.builder
7208 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7209 );
7210 let res = err!(
7211 self.builder
7212 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7213 );
7214 self.state.push1(res);
7215 }
7216 Operator::I16x8LeU => {
7217 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7218 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7219 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7220 let res = err!(
7221 self.builder
7222 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7223 );
7224 let res = err!(
7225 self.builder
7226 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7227 );
7228 let res = err!(
7229 self.builder
7230 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7231 );
7232 self.state.push1(res);
7233 }
7234 Operator::I32x4LeU => {
7235 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7236 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7237 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7238 let res = err!(
7239 self.builder
7240 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7241 );
7242 let res = err!(
7243 self.builder
7244 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7245 );
7246 let res = err!(
7247 self.builder
7248 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7249 );
7250 self.state.push1(res);
7251 }
7252 Operator::I32GtS | Operator::I64GtS => {
7253 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7254 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7255 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7256 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7257 let cond = err!(
7258 self.builder
7259 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7260 );
7261 let res = err!(
7262 self.builder
7263 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7264 );
7265 self.state.push1_extra(
7266 res,
7267 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7268 );
7269 }
7270 Operator::I8x16GtS => {
7271 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7272 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7273 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7274 let res = err!(
7275 self.builder
7276 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7277 );
7278 let res = err!(
7279 self.builder
7280 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7281 );
7282 let res = err!(
7283 self.builder
7284 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7285 );
7286 self.state.push1(res);
7287 }
7288 Operator::I16x8GtS => {
7289 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7290 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7291 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7292 let res = err!(
7293 self.builder
7294 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7295 );
7296 let res = err!(
7297 self.builder
7298 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7299 );
7300 let res = err!(
7301 self.builder
7302 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7303 );
7304 self.state.push1(res);
7305 }
7306 Operator::I32x4GtS => {
7307 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7308 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7309 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7310 let res = err!(
7311 self.builder
7312 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7313 );
7314 let res = err!(
7315 self.builder
7316 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7317 );
7318 let res = err!(
7319 self.builder
7320 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7321 );
7322 self.state.push1(res);
7323 }
7324 Operator::I64x2GtS => {
7325 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7326 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7327 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7328 let res = err!(
7329 self.builder
7330 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7331 );
7332 let res = err!(
7333 self.builder
7334 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7335 );
7336 let res = err!(
7337 self.builder
7338 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7339 );
7340 self.state.push1(res);
7341 }
7342 Operator::I32GtU | Operator::I64GtU => {
7343 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7344 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7345 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7346 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7347 let cond = err!(
7348 self.builder
7349 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7350 );
7351 let res = err!(
7352 self.builder
7353 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7354 );
7355 self.state.push1_extra(
7356 res,
7357 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7358 );
7359 }
7360 Operator::I8x16GtU => {
7361 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7362 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7363 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7364 let res = err!(
7365 self.builder
7366 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7367 );
7368 let res = err!(
7369 self.builder
7370 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7371 );
7372 let res = err!(
7373 self.builder
7374 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7375 );
7376 self.state.push1(res);
7377 }
7378 Operator::I16x8GtU => {
7379 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7380 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7381 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7382 let res = err!(
7383 self.builder
7384 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7385 );
7386 let res = err!(
7387 self.builder
7388 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7389 );
7390 let res = err!(
7391 self.builder
7392 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7393 );
7394 self.state.push1(res);
7395 }
7396 Operator::I32x4GtU => {
7397 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7398 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7399 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7400 let res = err!(
7401 self.builder
7402 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7403 );
7404 let res = err!(
7405 self.builder
7406 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7407 );
7408 let res = err!(
7409 self.builder
7410 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7411 );
7412 self.state.push1(res);
7413 }
7414 Operator::I32GeS | Operator::I64GeS => {
7415 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7416 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7417 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7418 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7419 let cond = err!(
7420 self.builder
7421 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7422 );
7423 let res = err!(
7424 self.builder
7425 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7426 );
7427 self.state.push1(res);
7428 }
7429 Operator::I8x16GeS => {
7430 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7431 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7432 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7433 let res = err!(
7434 self.builder
7435 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7436 );
7437 let res = err!(
7438 self.builder
7439 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7440 );
7441 let res = err!(
7442 self.builder
7443 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7444 );
7445 self.state.push1(res);
7446 }
7447 Operator::I16x8GeS => {
7448 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7449 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7450 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7451 let res = err!(
7452 self.builder
7453 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7454 );
7455 let res = err!(
7456 self.builder
7457 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7458 );
7459 let res = err!(
7460 self.builder
7461 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7462 );
7463 self.state.push1(res);
7464 }
7465 Operator::I32x4GeS => {
7466 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7467 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7468 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7469 let res = err!(
7470 self.builder
7471 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7472 );
7473 let res = err!(
7474 self.builder
7475 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7476 );
7477 let res = err!(
7478 self.builder
7479 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7480 );
7481 self.state.push1(res);
7482 }
7483 Operator::I64x2GeS => {
7484 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7485 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7486 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7487 let res = err!(
7488 self.builder
7489 .build_int_compare(IntPredicate::SGE, v1, v2, "")
7490 );
7491 let res = err!(
7492 self.builder
7493 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7494 );
7495 let res = err!(
7496 self.builder
7497 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7498 );
7499 self.state.push1(res);
7500 }
7501 Operator::I32GeU | Operator::I64GeU => {
7502 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7503 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7504 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7505 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7506 let cond = err!(
7507 self.builder
7508 .build_int_compare(IntPredicate::UGE, v1, v2, "")
7509 );
7510 let res = err!(
7511 self.builder
7512 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7513 );
7514 self.state.push1_extra(
7515 res,
7516 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7517 );
7518 }
7519 Operator::I8x16GeU => {
7520 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7521 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7522 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7523 let res = err!(
7524 self.builder
7525 .build_int_compare(IntPredicate::UGE, v1, v2, "")
7526 );
7527 let res = err!(
7528 self.builder
7529 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7530 );
7531 let res = err!(
7532 self.builder
7533 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7534 );
7535 self.state.push1(res);
7536 }
7537 Operator::I16x8GeU => {
7538 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7539 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7540 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7541 let res = err!(
7542 self.builder
7543 .build_int_compare(IntPredicate::UGE, v1, v2, "")
7544 );
7545 let res = err!(
7546 self.builder
7547 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7548 );
7549 let res = err!(
7550 self.builder
7551 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7552 );
7553 self.state.push1(res);
7554 }
7555 Operator::I32x4GeU => {
7556 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7557 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7558 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7559 let res = err!(
7560 self.builder
7561 .build_int_compare(IntPredicate::UGE, v1, v2, "")
7562 );
7563 let res = err!(
7564 self.builder
7565 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7566 );
7567 let res = err!(
7568 self.builder
7569 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7570 );
7571 self.state.push1(res);
7572 }
7573
7574 Operator::F32Eq | Operator::F64Eq => {
7579 let (v1, v2) = self.state.pop2()?;
7580 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7581 let cond = err!(
7582 self.builder
7583 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
7584 );
7585 let res = err!(
7586 self.builder
7587 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7588 );
7589 self.state.push1_extra(
7590 res,
7591 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7592 );
7593 }
7594 Operator::F32x4Eq => {
7595 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7596 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7597 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7598 let res = err!(
7599 self.builder
7600 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
7601 );
7602 let res = err!(
7603 self.builder
7604 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7605 );
7606 let res = err!(
7607 self.builder
7608 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7609 );
7610 self.state.push1(res);
7611 }
7612 Operator::F64x2Eq => {
7613 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7614 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7615 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7616 let res = err!(
7617 self.builder
7618 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
7619 );
7620 let res = err!(
7621 self.builder
7622 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7623 );
7624 let res = err!(
7625 self.builder
7626 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7627 );
7628 self.state.push1(res);
7629 }
7630 Operator::F32Ne | Operator::F64Ne => {
7631 let (v1, v2) = self.state.pop2()?;
7632 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7633 let cond = err!(
7634 self.builder
7635 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
7636 );
7637 let res = err!(
7638 self.builder
7639 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7640 );
7641 self.state.push1_extra(
7642 res,
7643 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7644 );
7645 }
7646 Operator::F32x4Ne => {
7647 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7648 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7649 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7650 let res = err!(
7651 self.builder
7652 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
7653 );
7654 let res = err!(
7655 self.builder
7656 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7657 );
7658 let res = err!(
7659 self.builder
7660 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7661 );
7662 self.state.push1(res);
7663 }
7664 Operator::F64x2Ne => {
7665 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7666 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7667 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7668 let res = err!(
7669 self.builder
7670 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
7671 );
7672 let res = err!(
7673 self.builder
7674 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7675 );
7676 let res = err!(
7677 self.builder
7678 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7679 );
7680 self.state.push1(res);
7681 }
7682 Operator::F32Lt | Operator::F64Lt => {
7683 let (v1, v2) = self.state.pop2()?;
7684 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7685 let cond = err!(
7686 self.builder
7687 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7688 );
7689 let res = err!(
7690 self.builder
7691 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7692 );
7693 self.state.push1_extra(
7694 res,
7695 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7696 );
7697 }
7698 Operator::F32x4Lt => {
7699 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7700 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7701 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7702 let res = err!(
7703 self.builder
7704 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7705 );
7706 let res = err!(
7707 self.builder
7708 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7709 );
7710 let res = err!(
7711 self.builder
7712 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7713 );
7714 self.state.push1(res);
7715 }
7716 Operator::F64x2Lt => {
7717 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7718 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7719 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7720 let res = err!(
7721 self.builder
7722 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7723 );
7724 let res = err!(
7725 self.builder
7726 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7727 );
7728 let res = err!(
7729 self.builder
7730 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7731 );
7732 self.state.push1(res);
7733 }
7734 Operator::F32Le | Operator::F64Le => {
7735 let (v1, v2) = self.state.pop2()?;
7736 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7737 let cond = err!(
7738 self.builder
7739 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
7740 );
7741 let res = err!(
7742 self.builder
7743 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7744 );
7745 self.state.push1_extra(
7746 res,
7747 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7748 );
7749 }
7750 Operator::F32x4Le => {
7751 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7752 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7753 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7754 let res = err!(
7755 self.builder
7756 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
7757 );
7758 let res = err!(
7759 self.builder
7760 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7761 );
7762 let res = err!(
7763 self.builder
7764 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7765 );
7766 self.state.push1(res);
7767 }
7768 Operator::F64x2Le => {
7769 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7770 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7771 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7772 let res = err!(
7773 self.builder
7774 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
7775 );
7776 let res = err!(
7777 self.builder
7778 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7779 );
7780 let res = err!(
7781 self.builder
7782 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7783 );
7784 self.state.push1(res);
7785 }
7786 Operator::F32Gt | Operator::F64Gt => {
7787 let (v1, v2) = self.state.pop2()?;
7788 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7789 let cond = err!(
7790 self.builder
7791 .build_float_compare(FloatPredicate::OGT, 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::F32x4Gt => {
7803 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7804 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7805 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7806 let res = err!(
7807 self.builder
7808 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
7809 );
7810 let res = err!(
7811 self.builder
7812 .build_int_s_extend(res, self.intrinsics.i32x4_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::F64x2Gt => {
7821 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7822 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7823 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7824 let res = err!(
7825 self.builder
7826 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
7827 );
7828 let res = err!(
7829 self.builder
7830 .build_int_s_extend(res, self.intrinsics.i64x2_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::F32Ge | Operator::F64Ge => {
7839 let (v1, v2) = self.state.pop2()?;
7840 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7841 let cond = err!(
7842 self.builder
7843 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
7844 );
7845 let res = err!(
7846 self.builder
7847 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7848 );
7849 self.state.push1_extra(
7850 res,
7851 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7852 );
7853 }
7854 Operator::F32x4Ge => {
7855 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7856 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7857 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7858 let res = err!(
7859 self.builder
7860 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
7861 );
7862 let res = err!(
7863 self.builder
7864 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7865 );
7866 let res = err!(
7867 self.builder
7868 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7869 );
7870 self.state.push1(res);
7871 }
7872 Operator::F64x2Ge => {
7873 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7874 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7875 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7876 let res = err!(
7877 self.builder
7878 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
7879 );
7880 let res = err!(
7881 self.builder
7882 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7883 );
7884 let res = err!(
7885 self.builder
7886 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7887 );
7888 self.state.push1(res);
7889 }
7890
7891 Operator::I32WrapI64 => {
7896 let (v, i) = self.state.pop1_extra()?;
7897 let v = self.apply_pending_canonicalization(v, i)?;
7898 let v = v.into_int_value();
7899 let res = err!(
7900 self.builder
7901 .build_int_truncate(v, self.intrinsics.i32_ty, "")
7902 );
7903 self.state.push1(res);
7904 }
7905 Operator::I64ExtendI32S => {
7906 let (v, i) = self.state.pop1_extra()?;
7907 let v = self.apply_pending_canonicalization(v, i)?;
7908 let v = v.into_int_value();
7909 let res = err!(
7910 self.builder
7911 .build_int_s_extend(v, self.intrinsics.i64_ty, "")
7912 );
7913 self.state.push1(res);
7914 }
7915 Operator::I64ExtendI32U => {
7916 let (v, i) = self.state.pop1_extra()?;
7917 let v = self.apply_pending_canonicalization(v, i)?;
7918 let v = v.into_int_value();
7919 let res = err!(
7920 self.builder
7921 .build_int_z_extend(v, self.intrinsics.i64_ty, "")
7922 );
7923 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
7924 }
7925 Operator::I16x8ExtendLowI8x16S => {
7926 let (v, i) = self.state.pop1_extra()?;
7927 let (v, _) = self.v128_into_i8x16(v, i)?;
7928 let low = err!(self.builder.build_shuffle_vector(
7929 v,
7930 v.get_type().get_undef(),
7931 VectorType::const_vector(&[
7932 self.intrinsics.i32_consts[0],
7933 self.intrinsics.i32_consts[1],
7934 self.intrinsics.i32_consts[2],
7935 self.intrinsics.i32_consts[3],
7936 self.intrinsics.i32_consts[4],
7937 self.intrinsics.i32_consts[5],
7938 self.intrinsics.i32_consts[6],
7939 self.intrinsics.i32_consts[7],
7940 ]),
7941 "",
7942 ));
7943 let res = err!(
7944 self.builder
7945 .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
7946 );
7947 let res = err!(
7948 self.builder
7949 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7950 );
7951 self.state.push1(res);
7952 }
7953 Operator::I16x8ExtendHighI8x16S => {
7954 let (v, i) = self.state.pop1_extra()?;
7955 let (v, _) = self.v128_into_i8x16(v, i)?;
7956 let low = err!(self.builder.build_shuffle_vector(
7957 v,
7958 v.get_type().get_undef(),
7959 VectorType::const_vector(&[
7960 self.intrinsics.i32_consts[8],
7961 self.intrinsics.i32_consts[9],
7962 self.intrinsics.i32_consts[10],
7963 self.intrinsics.i32_consts[11],
7964 self.intrinsics.i32_consts[12],
7965 self.intrinsics.i32_consts[13],
7966 self.intrinsics.i32_consts[14],
7967 self.intrinsics.i32_consts[15],
7968 ]),
7969 "",
7970 ));
7971 let res = err!(
7972 self.builder
7973 .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
7974 );
7975 let res = err!(
7976 self.builder
7977 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7978 );
7979 self.state.push1(res);
7980 }
7981 Operator::I16x8ExtendLowI8x16U => {
7982 let (v, i) = self.state.pop1_extra()?;
7983 let (v, _) = self.v128_into_i8x16(v, i)?;
7984 let low = err!(self.builder.build_shuffle_vector(
7985 v,
7986 v.get_type().get_undef(),
7987 VectorType::const_vector(&[
7988 self.intrinsics.i32_consts[0],
7989 self.intrinsics.i32_consts[1],
7990 self.intrinsics.i32_consts[2],
7991 self.intrinsics.i32_consts[3],
7992 self.intrinsics.i32_consts[4],
7993 self.intrinsics.i32_consts[5],
7994 self.intrinsics.i32_consts[6],
7995 self.intrinsics.i32_consts[7],
7996 ]),
7997 "",
7998 ));
7999 let res = err!(
8000 self.builder
8001 .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8002 );
8003 let res = err!(
8004 self.builder
8005 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8006 );
8007 self.state.push1(res);
8008 }
8009 Operator::I16x8ExtendHighI8x16U => {
8010 let (v, i) = self.state.pop1_extra()?;
8011 let (v, _) = self.v128_into_i8x16(v, i)?;
8012 let low = err!(self.builder.build_shuffle_vector(
8013 v,
8014 v.get_type().get_undef(),
8015 VectorType::const_vector(&[
8016 self.intrinsics.i32_consts[8],
8017 self.intrinsics.i32_consts[9],
8018 self.intrinsics.i32_consts[10],
8019 self.intrinsics.i32_consts[11],
8020 self.intrinsics.i32_consts[12],
8021 self.intrinsics.i32_consts[13],
8022 self.intrinsics.i32_consts[14],
8023 self.intrinsics.i32_consts[15],
8024 ]),
8025 "",
8026 ));
8027 let res = err!(
8028 self.builder
8029 .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8030 );
8031 let res = err!(
8032 self.builder
8033 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8034 );
8035 self.state.push1(res);
8036 }
8037 Operator::I32x4ExtendLowI16x8S => {
8038 let (v, i) = self.state.pop1_extra()?;
8039 let (v, _) = self.v128_into_i16x8(v, i)?;
8040 let low = err!(self.builder.build_shuffle_vector(
8041 v,
8042 v.get_type().get_undef(),
8043 VectorType::const_vector(&[
8044 self.intrinsics.i32_consts[0],
8045 self.intrinsics.i32_consts[1],
8046 self.intrinsics.i32_consts[2],
8047 self.intrinsics.i32_consts[3],
8048 ]),
8049 "",
8050 ));
8051 let res = err!(
8052 self.builder
8053 .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8054 );
8055 let res = err!(
8056 self.builder
8057 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8058 );
8059 self.state.push1(res);
8060 }
8061 Operator::I32x4ExtendHighI16x8S => {
8062 let (v, i) = self.state.pop1_extra()?;
8063 let (v, _) = self.v128_into_i16x8(v, i)?;
8064 let low = err!(self.builder.build_shuffle_vector(
8065 v,
8066 v.get_type().get_undef(),
8067 VectorType::const_vector(&[
8068 self.intrinsics.i32_consts[4],
8069 self.intrinsics.i32_consts[5],
8070 self.intrinsics.i32_consts[6],
8071 self.intrinsics.i32_consts[7],
8072 ]),
8073 "",
8074 ));
8075 let res = err!(
8076 self.builder
8077 .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8078 );
8079 let res = err!(
8080 self.builder
8081 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8082 );
8083 self.state.push1(res);
8084 }
8085 Operator::I32x4ExtendLowI16x8U => {
8086 let (v, i) = self.state.pop1_extra()?;
8087 let (v, _) = self.v128_into_i16x8(v, i)?;
8088 let low = err!(self.builder.build_shuffle_vector(
8089 v,
8090 v.get_type().get_undef(),
8091 VectorType::const_vector(&[
8092 self.intrinsics.i32_consts[0],
8093 self.intrinsics.i32_consts[1],
8094 self.intrinsics.i32_consts[2],
8095 self.intrinsics.i32_consts[3],
8096 ]),
8097 "",
8098 ));
8099 let res = err!(
8100 self.builder
8101 .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8102 );
8103 let res = err!(
8104 self.builder
8105 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8106 );
8107 self.state.push1(res);
8108 }
8109 Operator::I32x4ExtendHighI16x8U => {
8110 let (v, i) = self.state.pop1_extra()?;
8111 let (v, _) = self.v128_into_i16x8(v, i)?;
8112 let low = err!(self.builder.build_shuffle_vector(
8113 v,
8114 v.get_type().get_undef(),
8115 VectorType::const_vector(&[
8116 self.intrinsics.i32_consts[4],
8117 self.intrinsics.i32_consts[5],
8118 self.intrinsics.i32_consts[6],
8119 self.intrinsics.i32_consts[7],
8120 ]),
8121 "",
8122 ));
8123 let res = err!(
8124 self.builder
8125 .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8126 );
8127 let res = err!(
8128 self.builder
8129 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8130 );
8131 self.state.push1(res);
8132 }
8133 Operator::I64x2ExtendLowI32x4U
8134 | Operator::I64x2ExtendLowI32x4S
8135 | Operator::I64x2ExtendHighI32x4U
8136 | Operator::I64x2ExtendHighI32x4S => {
8137 let extend = match op {
8138 Operator::I64x2ExtendLowI32x4U | Operator::I64x2ExtendHighI32x4U => {
8139 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
8140 }
8141 Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendHighI32x4S => {
8142 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
8143 }
8144 _ => unreachable!("Unhandled inner case"),
8145 };
8146 let indices = match op {
8147 Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendLowI32x4U => {
8148 [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
8149 }
8150 Operator::I64x2ExtendHighI32x4S | Operator::I64x2ExtendHighI32x4U => {
8151 [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
8152 }
8153 _ => unreachable!("Unhandled inner case"),
8154 };
8155 let (v, i) = self.state.pop1_extra()?;
8156 let (v, _) = self.v128_into_i32x4(v, i)?;
8157 let low = err!(self.builder.build_shuffle_vector(
8158 v,
8159 v.get_type().get_undef(),
8160 VectorType::const_vector(&indices),
8161 "",
8162 ));
8163 let res = err!(extend(self, low));
8164 let res = err!(
8165 self.builder
8166 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8167 );
8168 self.state.push1(res);
8169 }
8170 Operator::I8x16NarrowI16x8S => {
8171 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8172 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8173 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8174 let min = self.intrinsics.i16_ty.const_int(0xff80, false);
8175 let max = self.intrinsics.i16_ty.const_int(0x007f, false);
8176 let min = VectorType::const_vector(&[min; 8]);
8177 let max = VectorType::const_vector(&[max; 8]);
8178 let apply_min_clamp_v1 =
8179 err!(
8180 self.builder
8181 .build_int_compare(IntPredicate::SLT, v1, min, "")
8182 );
8183 let apply_max_clamp_v1 =
8184 err!(
8185 self.builder
8186 .build_int_compare(IntPredicate::SGT, v1, max, "")
8187 );
8188 let apply_min_clamp_v2 =
8189 err!(
8190 self.builder
8191 .build_int_compare(IntPredicate::SLT, v2, min, "")
8192 );
8193 let apply_max_clamp_v2 =
8194 err!(
8195 self.builder
8196 .build_int_compare(IntPredicate::SGT, v2, max, "")
8197 );
8198 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8199 .into_vector_value();
8200 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8201 .into_vector_value();
8202 let v1 = err!(self.builder.build_int_truncate(
8203 v1,
8204 self.intrinsics.i8_ty.vec_type(8),
8205 ""
8206 ));
8207 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8208 .into_vector_value();
8209 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8210 .into_vector_value();
8211 let v2 = err!(self.builder.build_int_truncate(
8212 v2,
8213 self.intrinsics.i8_ty.vec_type(8),
8214 ""
8215 ));
8216 let res = err!(self.builder.build_shuffle_vector(
8217 v1,
8218 v2,
8219 VectorType::const_vector(&[
8220 self.intrinsics.i32_consts[0],
8221 self.intrinsics.i32_consts[1],
8222 self.intrinsics.i32_consts[2],
8223 self.intrinsics.i32_consts[3],
8224 self.intrinsics.i32_consts[4],
8225 self.intrinsics.i32_consts[5],
8226 self.intrinsics.i32_consts[6],
8227 self.intrinsics.i32_consts[7],
8228 self.intrinsics.i32_consts[8],
8229 self.intrinsics.i32_consts[9],
8230 self.intrinsics.i32_consts[10],
8231 self.intrinsics.i32_consts[11],
8232 self.intrinsics.i32_consts[12],
8233 self.intrinsics.i32_consts[13],
8234 self.intrinsics.i32_consts[14],
8235 self.intrinsics.i32_consts[15],
8236 ]),
8237 "",
8238 ));
8239 let res = err!(
8240 self.builder
8241 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8242 );
8243 self.state.push1(res);
8244 }
8245 Operator::I8x16NarrowI16x8U => {
8246 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8247 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8248 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8249 let min = self.intrinsics.i16x8_ty.const_zero();
8250 let max = self.intrinsics.i16_ty.const_int(0x00ff, false);
8251 let max = VectorType::const_vector(&[max; 8]);
8252 let apply_min_clamp_v1 =
8253 err!(
8254 self.builder
8255 .build_int_compare(IntPredicate::SLT, v1, min, "")
8256 );
8257 let apply_max_clamp_v1 =
8258 err!(
8259 self.builder
8260 .build_int_compare(IntPredicate::SGT, v1, max, "")
8261 );
8262 let apply_min_clamp_v2 =
8263 err!(
8264 self.builder
8265 .build_int_compare(IntPredicate::SLT, v2, min, "")
8266 );
8267 let apply_max_clamp_v2 =
8268 err!(
8269 self.builder
8270 .build_int_compare(IntPredicate::SGT, v2, max, "")
8271 );
8272 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8273 .into_vector_value();
8274 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8275 .into_vector_value();
8276 let v1 = err!(self.builder.build_int_truncate(
8277 v1,
8278 self.intrinsics.i8_ty.vec_type(8),
8279 ""
8280 ));
8281 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8282 .into_vector_value();
8283 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8284 .into_vector_value();
8285 let v2 = err!(self.builder.build_int_truncate(
8286 v2,
8287 self.intrinsics.i8_ty.vec_type(8),
8288 ""
8289 ));
8290 let res = err!(self.builder.build_shuffle_vector(
8291 v1,
8292 v2,
8293 VectorType::const_vector(&[
8294 self.intrinsics.i32_consts[0],
8295 self.intrinsics.i32_consts[1],
8296 self.intrinsics.i32_consts[2],
8297 self.intrinsics.i32_consts[3],
8298 self.intrinsics.i32_consts[4],
8299 self.intrinsics.i32_consts[5],
8300 self.intrinsics.i32_consts[6],
8301 self.intrinsics.i32_consts[7],
8302 self.intrinsics.i32_consts[8],
8303 self.intrinsics.i32_consts[9],
8304 self.intrinsics.i32_consts[10],
8305 self.intrinsics.i32_consts[11],
8306 self.intrinsics.i32_consts[12],
8307 self.intrinsics.i32_consts[13],
8308 self.intrinsics.i32_consts[14],
8309 self.intrinsics.i32_consts[15],
8310 ]),
8311 "",
8312 ));
8313 let res = err!(
8314 self.builder
8315 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8316 );
8317 self.state.push1(res);
8318 }
8319 Operator::I16x8NarrowI32x4S => {
8320 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8321 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8322 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8323 let min = self.intrinsics.i32_ty.const_int(0xffff8000, false);
8324 let max = self.intrinsics.i32_ty.const_int(0x00007fff, false);
8325 let min = VectorType::const_vector(&[min; 4]);
8326 let max = VectorType::const_vector(&[max; 4]);
8327 let apply_min_clamp_v1 =
8328 err!(
8329 self.builder
8330 .build_int_compare(IntPredicate::SLT, v1, min, "")
8331 );
8332 let apply_max_clamp_v1 =
8333 err!(
8334 self.builder
8335 .build_int_compare(IntPredicate::SGT, v1, max, "")
8336 );
8337 let apply_min_clamp_v2 =
8338 err!(
8339 self.builder
8340 .build_int_compare(IntPredicate::SLT, v2, min, "")
8341 );
8342 let apply_max_clamp_v2 =
8343 err!(
8344 self.builder
8345 .build_int_compare(IntPredicate::SGT, v2, max, "")
8346 );
8347 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8348 .into_vector_value();
8349 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8350 .into_vector_value();
8351 let v1 = err!(self.builder.build_int_truncate(
8352 v1,
8353 self.intrinsics.i16_ty.vec_type(4),
8354 ""
8355 ));
8356 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8357 .into_vector_value();
8358 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8359 .into_vector_value();
8360 let v2 = err!(self.builder.build_int_truncate(
8361 v2,
8362 self.intrinsics.i16_ty.vec_type(4),
8363 ""
8364 ));
8365 let res = err!(self.builder.build_shuffle_vector(
8366 v1,
8367 v2,
8368 VectorType::const_vector(&[
8369 self.intrinsics.i32_consts[0],
8370 self.intrinsics.i32_consts[1],
8371 self.intrinsics.i32_consts[2],
8372 self.intrinsics.i32_consts[3],
8373 self.intrinsics.i32_consts[4],
8374 self.intrinsics.i32_consts[5],
8375 self.intrinsics.i32_consts[6],
8376 self.intrinsics.i32_consts[7],
8377 ]),
8378 "",
8379 ));
8380 let res = err!(
8381 self.builder
8382 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8383 );
8384 self.state.push1(res);
8385 }
8386 Operator::I16x8NarrowI32x4U => {
8387 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8388 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8389 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8390 let min = self.intrinsics.i32x4_ty.const_zero();
8391 let max = self.intrinsics.i32_ty.const_int(0xffff, false);
8392 let max = VectorType::const_vector(&[max; 4]);
8393 let apply_min_clamp_v1 =
8394 err!(
8395 self.builder
8396 .build_int_compare(IntPredicate::SLT, v1, min, "")
8397 );
8398 let apply_max_clamp_v1 =
8399 err!(
8400 self.builder
8401 .build_int_compare(IntPredicate::SGT, v1, max, "")
8402 );
8403 let apply_min_clamp_v2 =
8404 err!(
8405 self.builder
8406 .build_int_compare(IntPredicate::SLT, v2, min, "")
8407 );
8408 let apply_max_clamp_v2 =
8409 err!(
8410 self.builder
8411 .build_int_compare(IntPredicate::SGT, v2, max, "")
8412 );
8413 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8414 .into_vector_value();
8415 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8416 .into_vector_value();
8417 let v1 = err!(self.builder.build_int_truncate(
8418 v1,
8419 self.intrinsics.i16_ty.vec_type(4),
8420 ""
8421 ));
8422 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8423 .into_vector_value();
8424 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8425 .into_vector_value();
8426 let v2 = err!(self.builder.build_int_truncate(
8427 v2,
8428 self.intrinsics.i16_ty.vec_type(4),
8429 ""
8430 ));
8431 let res = err!(self.builder.build_shuffle_vector(
8432 v1,
8433 v2,
8434 VectorType::const_vector(&[
8435 self.intrinsics.i32_consts[0],
8436 self.intrinsics.i32_consts[1],
8437 self.intrinsics.i32_consts[2],
8438 self.intrinsics.i32_consts[3],
8439 self.intrinsics.i32_consts[4],
8440 self.intrinsics.i32_consts[5],
8441 self.intrinsics.i32_consts[6],
8442 self.intrinsics.i32_consts[7],
8443 ]),
8444 "",
8445 ));
8446 let res = err!(
8447 self.builder
8448 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8449 );
8450 self.state.push1(res);
8451 }
8452 Operator::I32x4RelaxedTruncF32x4S if self.cpu_features.contains(CpuFeature::SSE2) => {
8453 let (v, i) = self.state.pop1_extra()?;
8454 let (v, _) = self.v128_into_f32x4(v, i)?;
8455 let res = self
8456 .build_call_with_param_attributes(
8457 self.intrinsics.x86_64.cvttps2dq,
8458 &[v.into()],
8459 "",
8460 )?
8461 .try_as_basic_value()
8462 .unwrap_basic();
8463 let res = err!(
8464 self.builder
8465 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8466 );
8467 self.state.push1(res);
8468 }
8469 Operator::I32x4TruncSatF32x4S | Operator::I32x4RelaxedTruncF32x4S => {
8470 let (v, i) = self.state.pop1_extra()?;
8471 let v = self.apply_pending_canonicalization(v, i)?;
8472 let v = v.into_int_value();
8473 let res = self.trunc_sat_into_int(
8474 self.intrinsics.f32x4_ty,
8475 self.intrinsics.i32x4_ty,
8476 LEF32_GEQ_I32_MIN,
8477 GEF32_LEQ_I32_MAX,
8478 i32::MIN as u64,
8479 i32::MAX as u64,
8480 v,
8481 )?;
8482 self.state.push1(res);
8483 }
8484 Operator::I32x4RelaxedTruncF32x4U
8485 if self.cpu_features.contains(CpuFeature::AVX512F)
8486 && self.cpu_features.contains(CpuFeature::AVX512VL) =>
8487 {
8488 let (v, i) = self.state.pop1_extra()?;
8489 let (v, _) = self.v128_into_f32x4(v, i)?;
8490 let res = self
8491 .build_call_with_param_attributes(
8492 self.intrinsics.x86_64.cvtps2udq128,
8493 &[
8494 v.into(),
8495 self.intrinsics.i32x4_ty.const_zero().into(),
8496 self.intrinsics.i8_ty.const_int(0xff, false).into(),
8497 ],
8498 "",
8499 )?
8500 .try_as_basic_value()
8501 .unwrap_basic();
8502 let res = err!(
8503 self.builder
8504 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8505 );
8506 self.state.push1(res);
8507 }
8508 Operator::I32x4TruncSatF32x4U | Operator::I32x4RelaxedTruncF32x4U => {
8509 let (v, i) = self.state.pop1_extra()?;
8510 let v = self.apply_pending_canonicalization(v, i)?;
8511 let v = v.into_int_value();
8512 let res = self.trunc_sat_into_int(
8513 self.intrinsics.f32x4_ty,
8514 self.intrinsics.i32x4_ty,
8515 LEF32_GEQ_U32_MIN,
8516 GEF32_LEQ_U32_MAX,
8517 u32::MIN as u64,
8518 u32::MAX as u64,
8519 v,
8520 )?;
8521 self.state.push1(res);
8522 }
8523 Operator::I32x4RelaxedTruncF64x2SZero
8524 if self.cpu_features.contains(CpuFeature::SSE2) =>
8525 {
8526 let (v, i) = self.state.pop1_extra()?;
8527 let (v, _) = self.v128_into_f64x2(v, i)?;
8528 let res = self
8529 .build_call_with_param_attributes(
8530 self.intrinsics.x86_64.cvtpd2dq,
8531 &[v.into()],
8532 "",
8533 )?
8534 .try_as_basic_value()
8535 .unwrap_basic();
8536 let res = err!(
8537 self.builder
8538 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8539 );
8540 self.state.push1(res);
8541 }
8542 Operator::I32x4RelaxedTruncF64x2UZero
8543 if self.cpu_features.contains(CpuFeature::AVX512F)
8544 && self.cpu_features.contains(CpuFeature::AVX512VL) =>
8545 {
8546 let (v, i) = self.state.pop1_extra()?;
8547 let (v, _) = self.v128_into_f64x2(v, i)?;
8548 let res = self
8549 .build_call_with_param_attributes(
8550 self.intrinsics.x86_64.cvtpd2udq128,
8551 &[
8552 v.into(),
8553 self.intrinsics.i32x4_ty.const_zero().into(),
8554 self.intrinsics.i8_ty.const_int(0xff, false).into(),
8555 ],
8556 "",
8557 )?
8558 .try_as_basic_value()
8559 .unwrap_basic();
8560 let res = err!(
8561 self.builder
8562 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8563 );
8564 self.state.push1(res);
8565 }
8566 Operator::I32x4TruncSatF64x2SZero
8567 | Operator::I32x4TruncSatF64x2UZero
8568 | Operator::I32x4RelaxedTruncF64x2SZero
8569 | Operator::I32x4RelaxedTruncF64x2UZero => {
8570 let ((min, max), (cmp_min, cmp_max)) = match op {
8571 Operator::I32x4TruncSatF64x2SZero => (
8572 (i32::MIN as u64, i32::MAX as u64),
8573 (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
8574 ),
8575 Operator::I32x4TruncSatF64x2UZero => (
8576 (u32::MIN as u64, u32::MAX as u64),
8577 (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
8578 ),
8579 Operator::I32x4RelaxedTruncF64x2SZero => (
8580 (i32::MIN as u64, i32::MAX as u64),
8581 (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
8582 ),
8583 Operator::I32x4RelaxedTruncF64x2UZero => (
8584 (u32::MIN as u64, u32::MAX as u64),
8585 (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
8586 ),
8587 _ => unreachable!("Unhandled internal variant"),
8588 };
8589 let (v, i) = self.state.pop1_extra()?;
8590 let v = self.apply_pending_canonicalization(v, i)?;
8591 let v = v.into_int_value();
8592 let res = self.trunc_sat(
8593 self.intrinsics.f64x2_ty,
8594 self.intrinsics.i32_ty.vec_type(2),
8595 cmp_min,
8596 cmp_max,
8597 min,
8598 max,
8599 v,
8600 )?;
8601
8602 let zero = self.intrinsics.i32_consts[0];
8603 let zeros = VectorType::const_vector(&[zero; 2]);
8604 let res = err!(self.builder.build_shuffle_vector(
8605 res,
8606 zeros,
8607 VectorType::const_vector(&[
8608 self.intrinsics.i32_consts[0],
8609 self.intrinsics.i32_consts[1],
8610 self.intrinsics.i32_consts[2],
8611 self.intrinsics.i32_consts[3],
8612 ]),
8613 "",
8614 ));
8615 let res = err!(
8616 self.builder
8617 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8618 );
8619 self.state.push1(res);
8620 }
8621 Operator::I32TruncF32S => {
8652 let v1 = self.state.pop1()?.into_float_value();
8653 self.trap_if_not_representable_as_int(
8654 0xcf000000, 0x4effffff, v1,
8657 )?;
8658 let res = err!(self.builder.build_float_to_signed_int(
8659 v1,
8660 self.intrinsics.i32_ty,
8661 ""
8662 ));
8663 self.state.push1(res);
8664 }
8665 Operator::I32TruncF64S => {
8666 let v1 = self.state.pop1()?.into_float_value();
8667 self.trap_if_not_representable_as_int(
8668 0xc1e00000001fffff, 0x41dfffffffffffff, v1,
8671 )?;
8672 let res = err!(self.builder.build_float_to_signed_int(
8673 v1,
8674 self.intrinsics.i32_ty,
8675 ""
8676 ));
8677 self.state.push1(res);
8678 }
8679 Operator::I32TruncSatF32S => {
8680 let (v, i) = self.state.pop1_extra()?;
8681 let v = self.apply_pending_canonicalization(v, i)?;
8682 let v = v.into_float_value();
8683 let res = self.trunc_sat_scalar(
8684 self.intrinsics.i32_ty,
8685 LEF32_GEQ_I32_MIN,
8686 GEF32_LEQ_I32_MAX,
8687 i32::MIN as u32 as u64,
8688 i32::MAX as u32 as u64,
8689 v,
8690 )?;
8691 self.state.push1(res);
8692 }
8693 Operator::I32TruncSatF64S => {
8694 let (v, i) = self.state.pop1_extra()?;
8695 let v = self.apply_pending_canonicalization(v, i)?;
8696 let v = v.into_float_value();
8697 let res = self.trunc_sat_scalar(
8698 self.intrinsics.i32_ty,
8699 LEF64_GEQ_I32_MIN,
8700 GEF64_LEQ_I32_MAX,
8701 i32::MIN as u64,
8702 i32::MAX as u64,
8703 v,
8704 )?;
8705 self.state.push1(res);
8706 }
8707 Operator::I64TruncF32S => {
8708 let v1 = self.state.pop1()?.into_float_value();
8709 self.trap_if_not_representable_as_int(
8710 0xdf000000, 0x5effffff, v1,
8713 )?;
8714 let res = err!(self.builder.build_float_to_signed_int(
8715 v1,
8716 self.intrinsics.i64_ty,
8717 ""
8718 ));
8719 self.state.push1(res);
8720 }
8721 Operator::I64TruncF64S => {
8722 let v1 = self.state.pop1()?.into_float_value();
8723 self.trap_if_not_representable_as_int(
8724 0xc3e0000000000000, 0x43dfffffffffffff, v1,
8727 )?;
8728 let res = err!(self.builder.build_float_to_signed_int(
8729 v1,
8730 self.intrinsics.i64_ty,
8731 ""
8732 ));
8733 self.state.push1(res);
8734 }
8735 Operator::I64TruncSatF32S => {
8736 let (v, i) = self.state.pop1_extra()?;
8737 let v = self.apply_pending_canonicalization(v, i)?;
8738 let v = v.into_float_value();
8739 let res = self.trunc_sat_scalar(
8740 self.intrinsics.i64_ty,
8741 LEF32_GEQ_I64_MIN,
8742 GEF32_LEQ_I64_MAX,
8743 i64::MIN as u64,
8744 i64::MAX as u64,
8745 v,
8746 )?;
8747 self.state.push1(res);
8748 }
8749 Operator::I64TruncSatF64S => {
8750 let (v, i) = self.state.pop1_extra()?;
8751 let v = self.apply_pending_canonicalization(v, i)?;
8752 let v = v.into_float_value();
8753 let res = self.trunc_sat_scalar(
8754 self.intrinsics.i64_ty,
8755 LEF64_GEQ_I64_MIN,
8756 GEF64_LEQ_I64_MAX,
8757 i64::MIN as u64,
8758 i64::MAX as u64,
8759 v,
8760 )?;
8761 self.state.push1(res);
8762 }
8763 Operator::I32TruncF32U => {
8764 let v1 = self.state.pop1()?.into_float_value();
8765 self.trap_if_not_representable_as_int(
8766 0xbf7fffff, 0x4f7fffff, v1,
8769 )?;
8770 let res = err!(self.builder.build_float_to_unsigned_int(
8771 v1,
8772 self.intrinsics.i32_ty,
8773 ""
8774 ));
8775 self.state.push1(res);
8776 }
8777 Operator::I32TruncF64U => {
8778 let v1 = self.state.pop1()?.into_float_value();
8779 self.trap_if_not_representable_as_int(
8780 0xbfefffffffffffff, 0x41efffffffffffff, v1,
8783 )?;
8784 let res = err!(self.builder.build_float_to_unsigned_int(
8785 v1,
8786 self.intrinsics.i32_ty,
8787 ""
8788 ));
8789 self.state.push1(res);
8790 }
8791 Operator::I32TruncSatF32U => {
8792 let (v, i) = self.state.pop1_extra()?;
8793 let v = self.apply_pending_canonicalization(v, i)?;
8794 let v = v.into_float_value();
8795 let res = self.trunc_sat_scalar(
8796 self.intrinsics.i32_ty,
8797 LEF32_GEQ_U32_MIN,
8798 GEF32_LEQ_U32_MAX,
8799 u32::MIN as u64,
8800 u32::MAX as u64,
8801 v,
8802 )?;
8803 self.state.push1(res);
8804 }
8805 Operator::I32TruncSatF64U => {
8806 let (v, i) = self.state.pop1_extra()?;
8807 let v = self.apply_pending_canonicalization(v, i)?;
8808 let v = v.into_float_value();
8809 let res = self.trunc_sat_scalar(
8810 self.intrinsics.i32_ty,
8811 LEF64_GEQ_U32_MIN,
8812 GEF64_LEQ_U32_MAX,
8813 u32::MIN as u64,
8814 u32::MAX as u64,
8815 v,
8816 )?;
8817 self.state.push1(res);
8818 }
8819 Operator::I64TruncF32U => {
8820 let v1 = self.state.pop1()?.into_float_value();
8821 self.trap_if_not_representable_as_int(
8822 0xbf7fffff, 0x5f7fffff, v1,
8825 )?;
8826 let res = err!(self.builder.build_float_to_unsigned_int(
8827 v1,
8828 self.intrinsics.i64_ty,
8829 ""
8830 ));
8831 self.state.push1(res);
8832 }
8833 Operator::I64TruncF64U => {
8834 let v1 = self.state.pop1()?.into_float_value();
8835 self.trap_if_not_representable_as_int(
8836 0xbfefffffffffffff, 0x43efffffffffffff, v1,
8839 )?;
8840 let res = err!(self.builder.build_float_to_unsigned_int(
8841 v1,
8842 self.intrinsics.i64_ty,
8843 ""
8844 ));
8845 self.state.push1(res);
8846 }
8847 Operator::I64TruncSatF32U => {
8848 let (v, i) = self.state.pop1_extra()?;
8849 let v = self.apply_pending_canonicalization(v, i)?;
8850 let v = v.into_float_value();
8851 let res = self.trunc_sat_scalar(
8852 self.intrinsics.i64_ty,
8853 LEF32_GEQ_U64_MIN,
8854 GEF32_LEQ_U64_MAX,
8855 u64::MIN,
8856 u64::MAX,
8857 v,
8858 )?;
8859 self.state.push1(res);
8860 }
8861 Operator::I64TruncSatF64U => {
8862 let (v, i) = self.state.pop1_extra()?;
8863 let v = self.apply_pending_canonicalization(v, i)?;
8864 let v = v.into_float_value();
8865 let res = self.trunc_sat_scalar(
8866 self.intrinsics.i64_ty,
8867 LEF64_GEQ_U64_MIN,
8868 GEF64_LEQ_U64_MAX,
8869 u64::MIN,
8870 u64::MAX,
8871 v,
8872 )?;
8873 self.state.push1(res);
8874 }
8875 Operator::F32DemoteF64 => {
8876 let v = self.state.pop1()?;
8877 let v = v.into_float_value();
8878 let res = self
8879 .build_call_with_param_attributes(
8880 self.intrinsics.fptrunc_f64,
8881 &[
8882 v.into(),
8883 self.intrinsics.fp_rounding_md,
8884 self.intrinsics.fp_exception_md,
8885 ],
8886 "",
8887 )?
8888 .try_as_basic_value()
8889 .unwrap_basic();
8890 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
8891 }
8892 Operator::F64PromoteF32 => {
8893 let v = self.state.pop1()?;
8894 let v = v.into_float_value();
8895 let res = self
8896 .build_call_with_param_attributes(
8897 self.intrinsics.fpext_f32,
8898 &[v.into(), self.intrinsics.fp_exception_md],
8899 "",
8900 )?
8901 .try_as_basic_value()
8902 .unwrap_basic();
8903 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
8904 }
8905 Operator::F32ConvertI32S | Operator::F32ConvertI64S => {
8906 let (v, i) = self.state.pop1_extra()?;
8907 let v = self.apply_pending_canonicalization(v, i)?;
8908 let v = v.into_int_value();
8909 let res = err!(self.builder.build_signed_int_to_float(
8910 v,
8911 self.intrinsics.f32_ty,
8912 ""
8913 ));
8914 self.state.push1(res);
8915 }
8916 Operator::F64ConvertI32S | Operator::F64ConvertI64S => {
8917 let (v, i) = self.state.pop1_extra()?;
8918 let v = self.apply_pending_canonicalization(v, i)?;
8919 let v = v.into_int_value();
8920 let res = err!(self.builder.build_signed_int_to_float(
8921 v,
8922 self.intrinsics.f64_ty,
8923 ""
8924 ));
8925 self.state.push1(res);
8926 }
8927 Operator::F32ConvertI32U | Operator::F32ConvertI64U => {
8928 let (v, i) = self.state.pop1_extra()?;
8929 let v = self.apply_pending_canonicalization(v, i)?;
8930 let v = v.into_int_value();
8931 let res = err!(self.builder.build_unsigned_int_to_float(
8932 v,
8933 self.intrinsics.f32_ty,
8934 ""
8935 ));
8936 self.state.push1(res);
8937 }
8938 Operator::F64ConvertI32U | Operator::F64ConvertI64U => {
8939 let (v, i) = self.state.pop1_extra()?;
8940 let v = self.apply_pending_canonicalization(v, i)?;
8941 let v = v.into_int_value();
8942 let res = err!(self.builder.build_unsigned_int_to_float(
8943 v,
8944 self.intrinsics.f64_ty,
8945 ""
8946 ));
8947 self.state.push1(res);
8948 }
8949 Operator::F32x4ConvertI32x4S => {
8950 let v = self.state.pop1()?;
8951 let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
8952 .into_vector_value();
8953 let res = err!(self.builder.build_signed_int_to_float(
8954 v,
8955 self.intrinsics.f32x4_ty,
8956 ""
8957 ));
8958 let res = err!(
8959 self.builder
8960 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8961 );
8962 self.state.push1(res);
8963 }
8964 Operator::F32x4ConvertI32x4U => {
8965 let v = self.state.pop1()?;
8966 let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
8967 .into_vector_value();
8968 let res = err!(self.builder.build_unsigned_int_to_float(
8969 v,
8970 self.intrinsics.f32x4_ty,
8971 ""
8972 ));
8973 let res = err!(
8974 self.builder
8975 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8976 );
8977 self.state.push1(res);
8978 }
8979 Operator::F64x2ConvertLowI32x4S | Operator::F64x2ConvertLowI32x4U => {
8980 let extend = match op {
8981 Operator::F64x2ConvertLowI32x4U => {
8982 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
8983 }
8984 Operator::F64x2ConvertLowI32x4S => {
8985 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
8986 }
8987 _ => unreachable!("Unhandled inner case"),
8988 };
8989 let (v, i) = self.state.pop1_extra()?;
8990 let (v, _) = self.v128_into_i32x4(v, i)?;
8991 let low = err!(self.builder.build_shuffle_vector(
8992 v,
8993 v.get_type().get_undef(),
8994 VectorType::const_vector(&[
8995 self.intrinsics.i32_consts[0],
8996 self.intrinsics.i32_consts[1],
8997 ]),
8998 "",
8999 ));
9000 let res = err!(extend(self, low));
9001 let res = err!(self.builder.build_signed_int_to_float(
9002 res,
9003 self.intrinsics.f64x2_ty,
9004 ""
9005 ));
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::F64x2PromoteLowF32x4 => {
9013 let (v, i) = self.state.pop1_extra()?;
9014 let (v, _) = self.v128_into_f32x4(v, i)?;
9015 let low = err!(self.builder.build_shuffle_vector(
9016 v,
9017 v.get_type().get_undef(),
9018 VectorType::const_vector(&[
9019 self.intrinsics.i32_consts[0],
9020 self.intrinsics.i32_consts[1],
9021 ]),
9022 "",
9023 ));
9024 let res = err!(
9025 self.builder
9026 .build_float_ext(low, self.intrinsics.f64x2_ty, "")
9027 );
9028 let res = err!(
9029 self.builder
9030 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9031 );
9032 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9033 }
9034 Operator::F32x4DemoteF64x2Zero => {
9035 let (v, i) = self.state.pop1_extra()?;
9036 let (v, _) = self.v128_into_f64x2(v, i)?;
9037 let f32x2_ty = self.intrinsics.f32_ty.vec_type(2);
9038 let res = err!(self.builder.build_float_trunc(v, f32x2_ty, ""));
9039 let zeros = f32x2_ty.const_zero();
9040 let res = err!(self.builder.build_shuffle_vector(
9041 res,
9042 zeros,
9043 VectorType::const_vector(&[
9044 self.intrinsics.i32_consts[0],
9045 self.intrinsics.i32_consts[1],
9046 self.intrinsics.i32_consts[2],
9047 self.intrinsics.i32_consts[3],
9048 ]),
9049 "",
9050 ));
9051 let res = err!(
9052 self.builder
9053 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9054 );
9055 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9056 }
9057 Operator::I32ReinterpretF32 => {
9082 let (v, i) = self.state.pop1_extra()?;
9083 let v = self.apply_pending_canonicalization(v, i)?;
9084 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i32_ty, ""));
9085 self.state.push1_extra(ret, ExtraInfo::arithmetic_f32());
9086 }
9087 Operator::I64ReinterpretF64 => {
9088 let (v, i) = self.state.pop1_extra()?;
9089 let v = self.apply_pending_canonicalization(v, i)?;
9090 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i64_ty, ""));
9091 self.state.push1_extra(ret, ExtraInfo::arithmetic_f64());
9092 }
9093 Operator::F32ReinterpretI32 => {
9094 let (v, i) = self.state.pop1_extra()?;
9095 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f32_ty, ""));
9096 self.state.push1_extra(ret, i);
9097 }
9098 Operator::F64ReinterpretI64 => {
9099 let (v, i) = self.state.pop1_extra()?;
9100 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f64_ty, ""));
9101 self.state.push1_extra(ret, i);
9102 }
9103
9104 Operator::I32Extend8S => {
9109 let value = self.state.pop1()?.into_int_value();
9110 let narrow_value = err!(self.builder.build_int_truncate(
9111 value,
9112 self.intrinsics.i8_ty,
9113 ""
9114 ));
9115 let extended_value = err!(self.builder.build_int_s_extend(
9116 narrow_value,
9117 self.intrinsics.i32_ty,
9118 ""
9119 ));
9120 self.state.push1(extended_value);
9121 }
9122 Operator::I32Extend16S => {
9123 let value = self.state.pop1()?.into_int_value();
9124 let narrow_value = err!(self.builder.build_int_truncate(
9125 value,
9126 self.intrinsics.i16_ty,
9127 ""
9128 ));
9129 let extended_value = err!(self.builder.build_int_s_extend(
9130 narrow_value,
9131 self.intrinsics.i32_ty,
9132 ""
9133 ));
9134 self.state.push1(extended_value);
9135 }
9136 Operator::I64Extend8S => {
9137 let value = self.state.pop1()?.into_int_value();
9138 let narrow_value = err!(self.builder.build_int_truncate(
9139 value,
9140 self.intrinsics.i8_ty,
9141 ""
9142 ));
9143 let extended_value = err!(self.builder.build_int_s_extend(
9144 narrow_value,
9145 self.intrinsics.i64_ty,
9146 ""
9147 ));
9148 self.state.push1(extended_value);
9149 }
9150 Operator::I64Extend16S => {
9151 let value = self.state.pop1()?.into_int_value();
9152 let narrow_value = err!(self.builder.build_int_truncate(
9153 value,
9154 self.intrinsics.i16_ty,
9155 ""
9156 ));
9157 let extended_value = err!(self.builder.build_int_s_extend(
9158 narrow_value,
9159 self.intrinsics.i64_ty,
9160 ""
9161 ));
9162 self.state.push1(extended_value);
9163 }
9164 Operator::I64Extend32S => {
9165 let value = self.state.pop1()?.into_int_value();
9166 let narrow_value = err!(self.builder.build_int_truncate(
9167 value,
9168 self.intrinsics.i32_ty,
9169 ""
9170 ));
9171 let extended_value = err!(self.builder.build_int_s_extend(
9172 narrow_value,
9173 self.intrinsics.i64_ty,
9174 ""
9175 ));
9176 self.state.push1(extended_value);
9177 }
9178
9179 Operator::I32Load { ref memarg } => {
9184 let offset = self.state.pop1()?.into_int_value();
9185 let memory_index = MemoryIndex::from_u32(0);
9186 let effective_address = self.resolve_memory_ptr(
9187 memory_index,
9188 memarg,
9189 self.intrinsics.ptr_ty,
9190 offset,
9191 4,
9192 )?;
9193 let result = err!(self.builder.build_load(
9194 self.intrinsics.i32_ty,
9195 effective_address,
9196 ""
9197 ));
9198 self.annotate_user_memaccess(
9199 memory_index,
9200 memarg,
9201 1,
9202 result.as_instruction_value().unwrap(),
9203 )?;
9204 self.state.push1(result);
9205 }
9206 Operator::I64Load { ref memarg } => {
9207 let offset = self.state.pop1()?.into_int_value();
9208 let memory_index = MemoryIndex::from_u32(0);
9209 let effective_address = self.resolve_memory_ptr(
9210 memory_index,
9211 memarg,
9212 self.intrinsics.ptr_ty,
9213 offset,
9214 8,
9215 )?;
9216 let result = err!(self.builder.build_load(
9217 self.intrinsics.i64_ty,
9218 effective_address,
9219 ""
9220 ));
9221 self.annotate_user_memaccess(
9222 memory_index,
9223 memarg,
9224 1,
9225 result.as_instruction_value().unwrap(),
9226 )?;
9227 self.state.push1(result);
9228 }
9229 Operator::F32Load { ref memarg } => {
9230 let offset = self.state.pop1()?.into_int_value();
9231 let memory_index = MemoryIndex::from_u32(0);
9232 let effective_address = self.resolve_memory_ptr(
9233 memory_index,
9234 memarg,
9235 self.intrinsics.ptr_ty,
9236 offset,
9237 4,
9238 )?;
9239 let result = err!(self.builder.build_load(
9240 self.intrinsics.f32_ty,
9241 effective_address,
9242 ""
9243 ));
9244 self.annotate_user_memaccess(
9245 memory_index,
9246 memarg,
9247 1,
9248 result.as_instruction_value().unwrap(),
9249 )?;
9250 self.state.push1(result);
9251 }
9252 Operator::F64Load { ref memarg } => {
9253 let offset = self.state.pop1()?.into_int_value();
9254 let memory_index = MemoryIndex::from_u32(0);
9255 let effective_address = self.resolve_memory_ptr(
9256 memory_index,
9257 memarg,
9258 self.intrinsics.ptr_ty,
9259 offset,
9260 8,
9261 )?;
9262 let result = err!(self.builder.build_load(
9263 self.intrinsics.f64_ty,
9264 effective_address,
9265 ""
9266 ));
9267 self.annotate_user_memaccess(
9268 memory_index,
9269 memarg,
9270 1,
9271 result.as_instruction_value().unwrap(),
9272 )?;
9273 self.state.push1(result);
9274 }
9275 Operator::V128Load { ref memarg } => {
9276 let offset = self.state.pop1()?.into_int_value();
9277 let memory_index = MemoryIndex::from_u32(0);
9278 let effective_address = self.resolve_memory_ptr(
9279 memory_index,
9280 memarg,
9281 self.intrinsics.ptr_ty,
9282 offset,
9283 16,
9284 )?;
9285 let result = err!(self.builder.build_load(
9286 self.intrinsics.i128_ty,
9287 effective_address,
9288 ""
9289 ));
9290 self.annotate_user_memaccess(
9291 memory_index,
9292 memarg,
9293 1,
9294 result.as_instruction_value().unwrap(),
9295 )?;
9296 self.state.push1(result);
9297 }
9298 Operator::V128Load8Lane { ref memarg, lane } => {
9299 let (v, i) = self.state.pop1_extra()?;
9300 let (v, _i) = self.v128_into_i8x16(v, i)?;
9301 let offset = self.state.pop1()?.into_int_value();
9302 let memory_index = MemoryIndex::from_u32(memarg.memory);
9303 let effective_address = self.resolve_memory_ptr(
9304 memory_index,
9305 memarg,
9306 self.intrinsics.ptr_ty,
9307 offset,
9308 1,
9309 )?;
9310 let element = err!(self.builder.build_load(
9311 self.intrinsics.i8_ty,
9312 effective_address,
9313 ""
9314 ));
9315 self.annotate_user_memaccess(
9316 memory_index,
9317 memarg,
9318 1,
9319 element.as_instruction_value().unwrap(),
9320 )?;
9321 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9322 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9323 let res = err!(
9324 self.builder
9325 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9326 );
9327 self.state.push1(res);
9328 }
9329 Operator::V128Load16Lane { ref memarg, lane } => {
9330 let (v, i) = self.state.pop1_extra()?;
9331 let (v, i) = self.v128_into_i16x8(v, i)?;
9332 let offset = self.state.pop1()?.into_int_value();
9333 let memory_index = MemoryIndex::from_u32(memarg.memory);
9334 let effective_address = self.resolve_memory_ptr(
9335 memory_index,
9336 memarg,
9337 self.intrinsics.ptr_ty,
9338 offset,
9339 2,
9340 )?;
9341 let element = err!(self.builder.build_load(
9342 self.intrinsics.i16_ty,
9343 effective_address,
9344 ""
9345 ));
9346 self.annotate_user_memaccess(
9347 memory_index,
9348 memarg,
9349 1,
9350 element.as_instruction_value().unwrap(),
9351 )?;
9352 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9353 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9354 let res = err!(
9355 self.builder
9356 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9357 );
9358 self.state.push1_extra(res, i);
9359 }
9360 Operator::V128Load32Lane { ref memarg, lane } => {
9361 let (v, i) = self.state.pop1_extra()?;
9362 let (v, i) = self.v128_into_i32x4(v, i)?;
9363 let offset = self.state.pop1()?.into_int_value();
9364 let memory_index = MemoryIndex::from_u32(memarg.memory);
9365 let effective_address = self.resolve_memory_ptr(
9366 memory_index,
9367 memarg,
9368 self.intrinsics.ptr_ty,
9369 offset,
9370 4,
9371 )?;
9372 let element = err!(self.builder.build_load(
9373 self.intrinsics.i32_ty,
9374 effective_address,
9375 ""
9376 ));
9377 self.annotate_user_memaccess(
9378 memory_index,
9379 memarg,
9380 1,
9381 element.as_instruction_value().unwrap(),
9382 )?;
9383 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9384 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9385 let res = err!(
9386 self.builder
9387 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9388 );
9389 self.state.push1_extra(res, i);
9390 }
9391 Operator::V128Load64Lane { ref memarg, lane } => {
9392 let (v, i) = self.state.pop1_extra()?;
9393 let (v, i) = self.v128_into_i64x2(v, i)?;
9394 let offset = self.state.pop1()?.into_int_value();
9395 let memory_index = MemoryIndex::from_u32(memarg.memory);
9396 let effective_address = self.resolve_memory_ptr(
9397 memory_index,
9398 memarg,
9399 self.intrinsics.ptr_ty,
9400 offset,
9401 8,
9402 )?;
9403 let element = err!(self.builder.build_load(
9404 self.intrinsics.i64_ty,
9405 effective_address,
9406 ""
9407 ));
9408 self.annotate_user_memaccess(
9409 memory_index,
9410 memarg,
9411 1,
9412 element.as_instruction_value().unwrap(),
9413 )?;
9414 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9415 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9416 let res = err!(
9417 self.builder
9418 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9419 );
9420 self.state.push1_extra(res, i);
9421 }
9422
9423 Operator::I32Store { ref memarg } => {
9424 let value = self.state.pop1()?;
9425 let offset = self.state.pop1()?.into_int_value();
9426 let memory_index = MemoryIndex::from_u32(0);
9427 let effective_address = self.resolve_memory_ptr(
9428 memory_index,
9429 memarg,
9430 self.intrinsics.ptr_ty,
9431 offset,
9432 4,
9433 )?;
9434 let dead_load = err!(self.builder.build_load(
9435 self.intrinsics.i32_ty,
9436 effective_address,
9437 ""
9438 ));
9439 self.annotate_user_memaccess(
9440 memory_index,
9441 memarg,
9442 1,
9443 dead_load.as_instruction_value().unwrap(),
9444 )?;
9445 let store = err!(self.builder.build_store(effective_address, value));
9446 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9447 }
9448 Operator::I64Store { ref memarg } => {
9449 let value = self.state.pop1()?;
9450 let offset = self.state.pop1()?.into_int_value();
9451 let memory_index = MemoryIndex::from_u32(0);
9452 let effective_address = self.resolve_memory_ptr(
9453 memory_index,
9454 memarg,
9455 self.intrinsics.ptr_ty,
9456 offset,
9457 8,
9458 )?;
9459 let dead_load = err!(self.builder.build_load(
9460 self.intrinsics.i64_ty,
9461 effective_address,
9462 ""
9463 ));
9464 self.annotate_user_memaccess(
9465 memory_index,
9466 memarg,
9467 1,
9468 dead_load.as_instruction_value().unwrap(),
9469 )?;
9470 let store = err!(self.builder.build_store(effective_address, value));
9471 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9472 }
9473 Operator::F32Store { ref memarg } => {
9474 let (v, i) = self.state.pop1_extra()?;
9475 let v = self.apply_pending_canonicalization(v, i)?;
9476 let offset = self.state.pop1()?.into_int_value();
9477 let memory_index = MemoryIndex::from_u32(0);
9478 let effective_address = self.resolve_memory_ptr(
9479 memory_index,
9480 memarg,
9481 self.intrinsics.ptr_ty,
9482 offset,
9483 4,
9484 )?;
9485 let dead_load = err!(self.builder.build_load(
9486 self.intrinsics.f32_ty,
9487 effective_address,
9488 ""
9489 ));
9490 self.annotate_user_memaccess(
9491 memory_index,
9492 memarg,
9493 1,
9494 dead_load.as_instruction_value().unwrap(),
9495 )?;
9496 let store = err!(self.builder.build_store(effective_address, v));
9497 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9498 }
9499 Operator::F64Store { ref memarg } => {
9500 let (v, i) = self.state.pop1_extra()?;
9501 let v = self.apply_pending_canonicalization(v, i)?;
9502 let offset = self.state.pop1()?.into_int_value();
9503 let memory_index = MemoryIndex::from_u32(0);
9504 let effective_address = self.resolve_memory_ptr(
9505 memory_index,
9506 memarg,
9507 self.intrinsics.ptr_ty,
9508 offset,
9509 8,
9510 )?;
9511 let dead_load = err!(self.builder.build_load(
9512 self.intrinsics.f64_ty,
9513 effective_address,
9514 ""
9515 ));
9516 self.annotate_user_memaccess(
9517 memory_index,
9518 memarg,
9519 1,
9520 dead_load.as_instruction_value().unwrap(),
9521 )?;
9522 let store = err!(self.builder.build_store(effective_address, v));
9523 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9524 }
9525 Operator::V128Store { ref memarg } => {
9526 let (v, i) = self.state.pop1_extra()?;
9527 let v = self.apply_pending_canonicalization(v, i)?;
9528 let offset = self.state.pop1()?.into_int_value();
9529 let memory_index = MemoryIndex::from_u32(0);
9530 let effective_address = self.resolve_memory_ptr(
9531 memory_index,
9532 memarg,
9533 self.intrinsics.ptr_ty,
9534 offset,
9535 16,
9536 )?;
9537 let dead_load = err!(self.builder.build_load(
9538 self.intrinsics.i128_ty,
9539 effective_address,
9540 ""
9541 ));
9542 self.annotate_user_memaccess(
9543 memory_index,
9544 memarg,
9545 1,
9546 dead_load.as_instruction_value().unwrap(),
9547 )?;
9548 let store = err!(self.builder.build_store(effective_address, v));
9549 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9550 }
9551 Operator::V128Store8Lane { ref memarg, lane } => {
9552 let (v, i) = self.state.pop1_extra()?;
9553 let (v, _i) = self.v128_into_i8x16(v, i)?;
9554 let offset = self.state.pop1()?.into_int_value();
9555 let memory_index = MemoryIndex::from_u32(memarg.memory);
9556
9557 let effective_address = self.resolve_memory_ptr(
9558 memory_index,
9559 memarg,
9560 self.intrinsics.ptr_ty,
9561 offset,
9562 1,
9563 )?;
9564 let dead_load = err!(self.builder.build_load(
9565 self.intrinsics.i8_ty,
9566 effective_address,
9567 ""
9568 ));
9569 self.annotate_user_memaccess(
9570 memory_index,
9571 memarg,
9572 1,
9573 dead_load.as_instruction_value().unwrap(),
9574 )?;
9575 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9576 let val = err!(self.builder.build_extract_element(v, idx, ""));
9577 let store = err!(self.builder.build_store(effective_address, val));
9578 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9579 }
9580 Operator::V128Store16Lane { ref memarg, lane } => {
9581 let (v, i) = self.state.pop1_extra()?;
9582 let (v, _i) = self.v128_into_i16x8(v, i)?;
9583 let offset = self.state.pop1()?.into_int_value();
9584 let memory_index = MemoryIndex::from_u32(memarg.memory);
9585
9586 let effective_address = self.resolve_memory_ptr(
9587 memory_index,
9588 memarg,
9589 self.intrinsics.ptr_ty,
9590 offset,
9591 2,
9592 )?;
9593 let dead_load = err!(self.builder.build_load(
9594 self.intrinsics.i16_ty,
9595 effective_address,
9596 ""
9597 ));
9598 self.annotate_user_memaccess(
9599 memory_index,
9600 memarg,
9601 1,
9602 dead_load.as_instruction_value().unwrap(),
9603 )?;
9604 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9605 let val = err!(self.builder.build_extract_element(v, idx, ""));
9606 let store = err!(self.builder.build_store(effective_address, val));
9607 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9608 }
9609 Operator::V128Store32Lane { ref memarg, lane } => {
9610 let (v, i) = self.state.pop1_extra()?;
9611 let (v, _i) = self.v128_into_i32x4(v, i)?;
9612 let offset = self.state.pop1()?.into_int_value();
9613 let memory_index = MemoryIndex::from_u32(memarg.memory);
9614
9615 let effective_address = self.resolve_memory_ptr(
9616 memory_index,
9617 memarg,
9618 self.intrinsics.ptr_ty,
9619 offset,
9620 4,
9621 )?;
9622 let dead_load = err!(self.builder.build_load(
9623 self.intrinsics.i32_ty,
9624 effective_address,
9625 ""
9626 ));
9627 self.annotate_user_memaccess(
9628 memory_index,
9629 memarg,
9630 1,
9631 dead_load.as_instruction_value().unwrap(),
9632 )?;
9633 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9634 let val = err!(self.builder.build_extract_element(v, idx, ""));
9635 let store = err!(self.builder.build_store(effective_address, val));
9636 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9637 }
9638 Operator::V128Store64Lane { ref memarg, lane } => {
9639 let (v, i) = self.state.pop1_extra()?;
9640 let (v, _i) = self.v128_into_i64x2(v, i)?;
9641 let offset = self.state.pop1()?.into_int_value();
9642 let memory_index = MemoryIndex::from_u32(memarg.memory);
9643
9644 let effective_address = self.resolve_memory_ptr(
9645 memory_index,
9646 memarg,
9647 self.intrinsics.ptr_ty,
9648 offset,
9649 8,
9650 )?;
9651 let dead_load = err!(self.builder.build_load(
9652 self.intrinsics.i64_ty,
9653 effective_address,
9654 ""
9655 ));
9656 self.annotate_user_memaccess(
9657 memory_index,
9658 memarg,
9659 1,
9660 dead_load.as_instruction_value().unwrap(),
9661 )?;
9662 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9663 let val = err!(self.builder.build_extract_element(v, idx, ""));
9664 let store = err!(self.builder.build_store(effective_address, val));
9665 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9666 }
9667 Operator::I32Load8S { ref memarg } => {
9668 let offset = self.state.pop1()?.into_int_value();
9669 let memory_index = MemoryIndex::from_u32(0);
9670 let effective_address = self.resolve_memory_ptr(
9671 memory_index,
9672 memarg,
9673 self.intrinsics.ptr_ty,
9674 offset,
9675 1,
9676 )?;
9677 let narrow_result = err!(self.builder.build_load(
9678 self.intrinsics.i8_ty,
9679 effective_address,
9680 ""
9681 ));
9682 self.annotate_user_memaccess(
9683 memory_index,
9684 memarg,
9685 1,
9686 narrow_result.as_instruction_value().unwrap(),
9687 )?;
9688 let result = err!(self.builder.build_int_s_extend(
9689 narrow_result.into_int_value(),
9690 self.intrinsics.i32_ty,
9691 "",
9692 ));
9693 self.state.push1(result);
9694 }
9695 Operator::I32Load16S { ref memarg } => {
9696 let offset = self.state.pop1()?.into_int_value();
9697 let memory_index = MemoryIndex::from_u32(0);
9698 let effective_address = self.resolve_memory_ptr(
9699 memory_index,
9700 memarg,
9701 self.intrinsics.ptr_ty,
9702 offset,
9703 2,
9704 )?;
9705 let narrow_result = err!(self.builder.build_load(
9706 self.intrinsics.i16_ty,
9707 effective_address,
9708 ""
9709 ));
9710 self.annotate_user_memaccess(
9711 memory_index,
9712 memarg,
9713 1,
9714 narrow_result.as_instruction_value().unwrap(),
9715 )?;
9716 let result = err!(self.builder.build_int_s_extend(
9717 narrow_result.into_int_value(),
9718 self.intrinsics.i32_ty,
9719 "",
9720 ));
9721 self.state.push1(result);
9722 }
9723 Operator::I64Load8S { ref memarg } => {
9724 let offset = self.state.pop1()?.into_int_value();
9725 let memory_index = MemoryIndex::from_u32(0);
9726 let effective_address = self.resolve_memory_ptr(
9727 memory_index,
9728 memarg,
9729 self.intrinsics.ptr_ty,
9730 offset,
9731 1,
9732 )?;
9733 let narrow_result = err!(self.builder.build_load(
9734 self.intrinsics.i8_ty,
9735 effective_address,
9736 ""
9737 ))
9738 .into_int_value();
9739 self.annotate_user_memaccess(
9740 memory_index,
9741 memarg,
9742 1,
9743 narrow_result.as_instruction_value().unwrap(),
9744 )?;
9745 let result = err!(self.builder.build_int_s_extend(
9746 narrow_result,
9747 self.intrinsics.i64_ty,
9748 ""
9749 ));
9750 self.state.push1(result);
9751 }
9752 Operator::I64Load16S { ref memarg } => {
9753 let offset = self.state.pop1()?.into_int_value();
9754 let memory_index = MemoryIndex::from_u32(0);
9755 let effective_address = self.resolve_memory_ptr(
9756 memory_index,
9757 memarg,
9758 self.intrinsics.ptr_ty,
9759 offset,
9760 2,
9761 )?;
9762 let narrow_result = err!(self.builder.build_load(
9763 self.intrinsics.i16_ty,
9764 effective_address,
9765 ""
9766 ))
9767 .into_int_value();
9768 self.annotate_user_memaccess(
9769 memory_index,
9770 memarg,
9771 1,
9772 narrow_result.as_instruction_value().unwrap(),
9773 )?;
9774 let result = err!(self.builder.build_int_s_extend(
9775 narrow_result,
9776 self.intrinsics.i64_ty,
9777 ""
9778 ));
9779 self.state.push1(result);
9780 }
9781 Operator::I64Load32S { ref memarg } => {
9782 let offset = self.state.pop1()?.into_int_value();
9783 let memory_index = MemoryIndex::from_u32(0);
9784 let effective_address = self.resolve_memory_ptr(
9785 memory_index,
9786 memarg,
9787 self.intrinsics.ptr_ty,
9788 offset,
9789 4,
9790 )?;
9791 let narrow_result = err!(self.builder.build_load(
9792 self.intrinsics.i32_ty,
9793 effective_address,
9794 ""
9795 ));
9796 self.annotate_user_memaccess(
9797 memory_index,
9798 memarg,
9799 1,
9800 narrow_result.as_instruction_value().unwrap(),
9801 )?;
9802 let result = err!(self.builder.build_int_s_extend(
9803 narrow_result.into_int_value(),
9804 self.intrinsics.i64_ty,
9805 "",
9806 ));
9807 self.state.push1(result);
9808 }
9809
9810 Operator::I32Load8U { ref memarg } => {
9811 let offset = self.state.pop1()?.into_int_value();
9812 let memory_index = MemoryIndex::from_u32(0);
9813 let effective_address = self.resolve_memory_ptr(
9814 memory_index,
9815 memarg,
9816 self.intrinsics.ptr_ty,
9817 offset,
9818 1,
9819 )?;
9820 let narrow_result = err!(self.builder.build_load(
9821 self.intrinsics.i8_ty,
9822 effective_address,
9823 ""
9824 ));
9825 self.annotate_user_memaccess(
9826 memory_index,
9827 memarg,
9828 1,
9829 narrow_result.as_instruction_value().unwrap(),
9830 )?;
9831 let result = err!(self.builder.build_int_z_extend(
9832 narrow_result.into_int_value(),
9833 self.intrinsics.i32_ty,
9834 "",
9835 ));
9836 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9837 }
9838 Operator::I32Load16U { ref memarg } => {
9839 let offset = self.state.pop1()?.into_int_value();
9840 let memory_index = MemoryIndex::from_u32(0);
9841 let effective_address = self.resolve_memory_ptr(
9842 memory_index,
9843 memarg,
9844 self.intrinsics.ptr_ty,
9845 offset,
9846 2,
9847 )?;
9848 let narrow_result = err!(self.builder.build_load(
9849 self.intrinsics.i16_ty,
9850 effective_address,
9851 ""
9852 ));
9853 self.annotate_user_memaccess(
9854 memory_index,
9855 memarg,
9856 1,
9857 narrow_result.as_instruction_value().unwrap(),
9858 )?;
9859 let result = err!(self.builder.build_int_z_extend(
9860 narrow_result.into_int_value(),
9861 self.intrinsics.i32_ty,
9862 "",
9863 ));
9864 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9865 }
9866 Operator::I64Load8U { ref memarg } => {
9867 let offset = self.state.pop1()?.into_int_value();
9868 let memory_index = MemoryIndex::from_u32(0);
9869 let effective_address = self.resolve_memory_ptr(
9870 memory_index,
9871 memarg,
9872 self.intrinsics.ptr_ty,
9873 offset,
9874 1,
9875 )?;
9876 let narrow_result = err!(self.builder.build_load(
9877 self.intrinsics.i8_ty,
9878 effective_address,
9879 ""
9880 ));
9881 self.annotate_user_memaccess(
9882 memory_index,
9883 memarg,
9884 1,
9885 narrow_result.as_instruction_value().unwrap(),
9886 )?;
9887 let result = err!(self.builder.build_int_z_extend(
9888 narrow_result.into_int_value(),
9889 self.intrinsics.i64_ty,
9890 "",
9891 ));
9892 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9893 }
9894 Operator::I64Load16U { ref memarg } => {
9895 let offset = self.state.pop1()?.into_int_value();
9896 let memory_index = MemoryIndex::from_u32(0);
9897 let effective_address = self.resolve_memory_ptr(
9898 memory_index,
9899 memarg,
9900 self.intrinsics.ptr_ty,
9901 offset,
9902 2,
9903 )?;
9904 let narrow_result = err!(self.builder.build_load(
9905 self.intrinsics.i16_ty,
9906 effective_address,
9907 ""
9908 ));
9909 self.annotate_user_memaccess(
9910 memory_index,
9911 memarg,
9912 1,
9913 narrow_result.as_instruction_value().unwrap(),
9914 )?;
9915 let result = err!(self.builder.build_int_z_extend(
9916 narrow_result.into_int_value(),
9917 self.intrinsics.i64_ty,
9918 "",
9919 ));
9920 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9921 }
9922 Operator::I64Load32U { ref memarg } => {
9923 let offset = self.state.pop1()?.into_int_value();
9924 let memory_index = MemoryIndex::from_u32(0);
9925 let effective_address = self.resolve_memory_ptr(
9926 memory_index,
9927 memarg,
9928 self.intrinsics.ptr_ty,
9929 offset,
9930 4,
9931 )?;
9932 let narrow_result = err!(self.builder.build_load(
9933 self.intrinsics.i32_ty,
9934 effective_address,
9935 ""
9936 ));
9937 self.annotate_user_memaccess(
9938 memory_index,
9939 memarg,
9940 1,
9941 narrow_result.as_instruction_value().unwrap(),
9942 )?;
9943 let result = err!(self.builder.build_int_z_extend(
9944 narrow_result.into_int_value(),
9945 self.intrinsics.i64_ty,
9946 "",
9947 ));
9948 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9949 }
9950
9951 Operator::I32Store8 { ref memarg } | Operator::I64Store8 { ref memarg } => {
9952 let value = self.state.pop1()?.into_int_value();
9953 let offset = self.state.pop1()?.into_int_value();
9954 let memory_index = MemoryIndex::from_u32(0);
9955 let effective_address = self.resolve_memory_ptr(
9956 memory_index,
9957 memarg,
9958 self.intrinsics.ptr_ty,
9959 offset,
9960 1,
9961 )?;
9962 let dead_load = err!(self.builder.build_load(
9963 self.intrinsics.i8_ty,
9964 effective_address,
9965 ""
9966 ));
9967 self.annotate_user_memaccess(
9968 memory_index,
9969 memarg,
9970 1,
9971 dead_load.as_instruction_value().unwrap(),
9972 )?;
9973 let narrow_value = err!(self.builder.build_int_truncate(
9974 value,
9975 self.intrinsics.i8_ty,
9976 ""
9977 ));
9978 let store = err!(self.builder.build_store(effective_address, narrow_value));
9979 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9980 }
9981 Operator::I32Store16 { ref memarg } | Operator::I64Store16 { ref memarg } => {
9982 let value = self.state.pop1()?.into_int_value();
9983 let offset = self.state.pop1()?.into_int_value();
9984 let memory_index = MemoryIndex::from_u32(0);
9985 let effective_address = self.resolve_memory_ptr(
9986 memory_index,
9987 memarg,
9988 self.intrinsics.ptr_ty,
9989 offset,
9990 2,
9991 )?;
9992 let dead_load = err!(self.builder.build_load(
9993 self.intrinsics.i16_ty,
9994 effective_address,
9995 ""
9996 ));
9997 self.annotate_user_memaccess(
9998 memory_index,
9999 memarg,
10000 1,
10001 dead_load.as_instruction_value().unwrap(),
10002 )?;
10003 let narrow_value = err!(self.builder.build_int_truncate(
10004 value,
10005 self.intrinsics.i16_ty,
10006 ""
10007 ));
10008 let store = err!(self.builder.build_store(effective_address, narrow_value));
10009 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
10010 }
10011 Operator::I64Store32 { ref memarg } => {
10012 let value = self.state.pop1()?.into_int_value();
10013 let offset = self.state.pop1()?.into_int_value();
10014 let memory_index = MemoryIndex::from_u32(0);
10015 let effective_address = self.resolve_memory_ptr(
10016 memory_index,
10017 memarg,
10018 self.intrinsics.ptr_ty,
10019 offset,
10020 4,
10021 )?;
10022 let dead_load = err!(self.builder.build_load(
10023 self.intrinsics.i32_ty,
10024 effective_address,
10025 ""
10026 ));
10027 self.annotate_user_memaccess(
10028 memory_index,
10029 memarg,
10030 1,
10031 dead_load.as_instruction_value().unwrap(),
10032 )?;
10033 let narrow_value = err!(self.builder.build_int_truncate(
10034 value,
10035 self.intrinsics.i32_ty,
10036 ""
10037 ));
10038 let store = err!(self.builder.build_store(effective_address, narrow_value));
10039 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
10040 }
10041 Operator::I8x16Neg => {
10042 let (v, i) = self.state.pop1_extra()?;
10043 let (v, _) = self.v128_into_i8x16(v, i)?;
10044 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10045 let res = err!(
10046 self.builder
10047 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10048 );
10049 self.state.push1(res);
10050 }
10051 Operator::I16x8Neg => {
10052 let (v, i) = self.state.pop1_extra()?;
10053 let (v, _) = self.v128_into_i16x8(v, i)?;
10054 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10055 let res = err!(
10056 self.builder
10057 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10058 );
10059 self.state.push1(res);
10060 }
10061 Operator::I32x4Neg => {
10062 let (v, i) = self.state.pop1_extra()?;
10063 let (v, _) = self.v128_into_i32x4(v, i)?;
10064 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10065 let res = err!(
10066 self.builder
10067 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10068 );
10069 self.state.push1(res);
10070 }
10071 Operator::I64x2Neg => {
10072 let (v, i) = self.state.pop1_extra()?;
10073 let (v, _) = self.v128_into_i64x2(v, i)?;
10074 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10075 let res = err!(
10076 self.builder
10077 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10078 );
10079 self.state.push1(res);
10080 }
10081 Operator::V128Not => {
10082 let (v, i) = self.state.pop1_extra()?;
10083 let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10084 let res = err!(self.builder.build_not(v, ""));
10085 self.state.push1(res);
10086 }
10087 Operator::V128AnyTrue => {
10088 let v = self.state.pop1()?.into_int_value();
10091 let res = err!(self.builder.build_int_compare(
10092 IntPredicate::NE,
10093 v,
10094 v.get_type().const_zero(),
10095 "",
10096 ));
10097 let res = err!(
10098 self.builder
10099 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10100 );
10101 self.state.push1_extra(
10102 res,
10103 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10104 );
10105 }
10106 Operator::I8x16AllTrue
10107 | Operator::I16x8AllTrue
10108 | Operator::I32x4AllTrue
10109 | Operator::I64x2AllTrue => {
10110 let vec_ty = match op {
10111 Operator::I8x16AllTrue => self.intrinsics.i8x16_ty,
10112 Operator::I16x8AllTrue => self.intrinsics.i16x8_ty,
10113 Operator::I32x4AllTrue => self.intrinsics.i32x4_ty,
10114 Operator::I64x2AllTrue => self.intrinsics.i64x2_ty,
10115 _ => unreachable!(),
10116 };
10117 let (v, i) = self.state.pop1_extra()?;
10118 let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10119 let lane_int_ty = self.context.custom_width_int_type(vec_ty.get_size());
10120 let vec = err!(self.builder.build_bit_cast(v, vec_ty, "vec")).into_vector_value();
10121 let mask = err!(self.builder.build_int_compare(
10122 IntPredicate::NE,
10123 vec,
10124 vec_ty.const_zero(),
10125 "mask",
10126 ));
10127 let cmask =
10128 err!(self.builder.build_bit_cast(mask, lane_int_ty, "cmask")).into_int_value();
10129 let res = err!(self.builder.build_int_compare(
10130 IntPredicate::EQ,
10131 cmask,
10132 lane_int_ty.const_int(u64::MAX, true),
10133 "",
10134 ));
10135 let res = err!(
10136 self.builder
10137 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10138 );
10139 self.state.push1_extra(
10140 res,
10141 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10142 );
10143 }
10144 Operator::I8x16ExtractLaneS { lane } => {
10145 let (v, i) = self.state.pop1_extra()?;
10146 let (v, _) = self.v128_into_i8x16(v, i)?;
10147 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10148 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10149 let res = err!(
10150 self.builder
10151 .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10152 );
10153 self.state.push1(res);
10154 }
10155 Operator::I8x16ExtractLaneU { lane } => {
10156 let (v, i) = self.state.pop1_extra()?;
10157 let (v, _) = self.v128_into_i8x16(v, i)?;
10158 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10159 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10160 let res = err!(
10161 self.builder
10162 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10163 );
10164 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10165 }
10166 Operator::I16x8ExtractLaneS { lane } => {
10167 let (v, i) = self.state.pop1_extra()?;
10168 let (v, _) = self.v128_into_i16x8(v, i)?;
10169 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10170 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10171 let res = err!(
10172 self.builder
10173 .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10174 );
10175 self.state.push1(res);
10176 }
10177 Operator::I16x8ExtractLaneU { lane } => {
10178 let (v, i) = self.state.pop1_extra()?;
10179 let (v, _) = self.v128_into_i16x8(v, i)?;
10180 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10181 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10182 let res = err!(
10183 self.builder
10184 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10185 );
10186 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10187 }
10188 Operator::I32x4ExtractLane { lane } => {
10189 let (v, i) = self.state.pop1_extra()?;
10190 let (v, i) = self.v128_into_i32x4(v, i)?;
10191 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10192 let res = err!(self.builder.build_extract_element(v, idx, ""));
10193 self.state.push1_extra(res, i);
10194 }
10195 Operator::I64x2ExtractLane { lane } => {
10196 let (v, i) = self.state.pop1_extra()?;
10197 let (v, i) = self.v128_into_i64x2(v, i)?;
10198 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10199 let res = err!(self.builder.build_extract_element(v, idx, ""));
10200 self.state.push1_extra(res, i);
10201 }
10202 Operator::F32x4ExtractLane { lane } => {
10203 let (v, i) = self.state.pop1_extra()?;
10204 let (v, i) = self.v128_into_f32x4(v, i)?;
10205 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10206 let res = err!(self.builder.build_extract_element(v, idx, ""));
10207 self.state.push1_extra(res, i);
10208 }
10209 Operator::F64x2ExtractLane { lane } => {
10210 let (v, i) = self.state.pop1_extra()?;
10211 let (v, i) = self.v128_into_f64x2(v, i)?;
10212 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10213 let res = err!(self.builder.build_extract_element(v, idx, ""));
10214 self.state.push1_extra(res, i);
10215 }
10216 Operator::I8x16ReplaceLane { lane } => {
10217 let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10218 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10219 let v2 = v2.into_int_value();
10220 let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i8_ty, ""));
10221 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10222 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10223 let res = err!(
10224 self.builder
10225 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10226 );
10227 self.state.push1(res);
10228 }
10229 Operator::I16x8ReplaceLane { lane } => {
10230 let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10231 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
10232 let v2 = v2.into_int_value();
10233 let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i16_ty, ""));
10234 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10235 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10236 let res = err!(
10237 self.builder
10238 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10239 );
10240 self.state.push1(res);
10241 }
10242 Operator::I32x4ReplaceLane { lane } => {
10243 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10244 let (v1, i1) = self.v128_into_i32x4(v1, i1)?;
10245 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10246 let v2 = v2.into_int_value();
10247 let i2 = i2.strip_pending();
10248 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10249 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10250 let res = err!(
10251 self.builder
10252 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10253 );
10254 self.state
10255 .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f32())?);
10256 }
10257 Operator::I64x2ReplaceLane { lane } => {
10258 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10259 let (v1, i1) = self.v128_into_i64x2(v1, i1)?;
10260 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10261 let v2 = v2.into_int_value();
10262 let i2 = i2.strip_pending();
10263 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10264 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10265 let res = err!(
10266 self.builder
10267 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10268 );
10269 self.state
10270 .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f64())?);
10271 }
10272 Operator::F32x4ReplaceLane { lane } => {
10273 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10274 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
10275 let push_pending_f32_nan_to_result =
10276 i1.has_pending_f32_nan() && i2.has_pending_f32_nan();
10277 let (v1, v2) = if !push_pending_f32_nan_to_result {
10278 (
10279 self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10280 .into_vector_value(),
10281 self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10282 .into_float_value(),
10283 )
10284 } else {
10285 (v1, v2.into_float_value())
10286 };
10287 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10288 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10289 let res = err!(
10290 self.builder
10291 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10292 );
10293 let info = if push_pending_f32_nan_to_result {
10294 ExtraInfo::pending_f32_nan()
10295 } else {
10296 (i1.strip_pending() & i2.strip_pending())?
10297 };
10298 self.state.push1_extra(res, info);
10299 }
10300 Operator::F64x2ReplaceLane { lane } => {
10301 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10302 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
10303 let push_pending_f64_nan_to_result =
10304 i1.has_pending_f64_nan() && i2.has_pending_f64_nan();
10305 let (v1, v2) = if !push_pending_f64_nan_to_result {
10306 (
10307 self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10308 .into_vector_value(),
10309 self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10310 .into_float_value(),
10311 )
10312 } else {
10313 (v1, v2.into_float_value())
10314 };
10315 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10316 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10317 let res = err!(
10318 self.builder
10319 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10320 );
10321 let info = if push_pending_f64_nan_to_result {
10322 ExtraInfo::pending_f64_nan()
10323 } else {
10324 (i1.strip_pending() & i2.strip_pending())?
10325 };
10326 self.state.push1_extra(res, info);
10327 }
10328 Operator::I8x16RelaxedSwizzle if self.cpu_features.contains(CpuFeature::SSSE3) => {
10329 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10330 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10331 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10332
10333 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10334 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
10335 let res = self
10336 .build_call_with_param_attributes(
10337 self.intrinsics.x86_64.pshufb128,
10338 &[v1.into(), v2.into()],
10339 "",
10340 )?
10341 .try_as_basic_value()
10342 .unwrap_basic();
10343 let res = err!(
10344 self.builder
10345 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10346 );
10347 self.state.push1(res);
10348 }
10349 Operator::I8x16Swizzle | Operator::I8x16RelaxedSwizzle => {
10350 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10351 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10352 let v1 = err!(
10353 self.builder
10354 .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10355 )
10356 .into_vector_value();
10357 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10358 let v2 = err!(
10359 self.builder
10360 .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10361 )
10362 .into_vector_value();
10363 let lanes = self.intrinsics.i8_ty.const_int(16, false);
10364 let lanes =
10365 self.splat_vector(lanes.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
10366 let mut res = self.intrinsics.i8x16_ty.get_undef();
10367 let idx_out_of_range = err!(self.builder.build_int_compare(
10368 IntPredicate::UGE,
10369 v2,
10370 lanes,
10371 "idx_out_of_range",
10372 ));
10373 let idx_clamped = err!(self.builder.build_select(
10374 idx_out_of_range,
10375 self.intrinsics.i8x16_ty.const_zero(),
10376 v2,
10377 "idx_clamped",
10378 ))
10379 .into_vector_value();
10380 for i in 0..16 {
10381 let idx = err!(self.builder.build_extract_element(
10382 idx_clamped,
10383 self.intrinsics.i32_ty.const_int(i, false),
10384 "idx",
10385 ))
10386 .into_int_value();
10387 let replace_with_zero = err!(self.builder.build_extract_element(
10388 idx_out_of_range,
10389 self.intrinsics.i32_ty.const_int(i, false),
10390 "replace_with_zero",
10391 ))
10392 .into_int_value();
10393 let elem =
10394 err!(self.builder.build_extract_element(v1, idx, "elem")).into_int_value();
10395 let elem_or_zero = err!(self.builder.build_select(
10396 replace_with_zero,
10397 self.intrinsics.i8_zero,
10398 elem,
10399 "elem_or_zero",
10400 ));
10401 res = err!(self.builder.build_insert_element(
10402 res,
10403 elem_or_zero,
10404 self.intrinsics.i32_ty.const_int(i, false),
10405 "",
10406 ));
10407 }
10408 let res = err!(
10409 self.builder
10410 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10411 );
10412 self.state.push1(res);
10413 }
10414 Operator::I8x16Shuffle { lanes } => {
10415 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10416 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10417 let v1 = err!(
10418 self.builder
10419 .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10420 )
10421 .into_vector_value();
10422 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10423 let v2 = err!(
10424 self.builder
10425 .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10426 )
10427 .into_vector_value();
10428 let mask = VectorType::const_vector(
10429 lanes
10430 .iter()
10431 .map(|l| self.intrinsics.i32_ty.const_int((*l).into(), false))
10432 .collect::<Vec<IntValue>>()
10433 .as_slice(),
10434 );
10435 let res = err!(self.builder.build_shuffle_vector(v1, v2, mask, ""));
10436 let res = err!(
10437 self.builder
10438 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10439 );
10440 self.state.push1(res);
10441 }
10442 Operator::V128Load8x8S { ref memarg } => {
10443 let offset = self.state.pop1()?.into_int_value();
10444 let memory_index = MemoryIndex::from_u32(0);
10445 let effective_address = self.resolve_memory_ptr(
10446 memory_index,
10447 memarg,
10448 self.intrinsics.ptr_ty,
10449 offset,
10450 8,
10451 )?;
10452 let v = err!(self.builder.build_load(
10453 self.intrinsics.i64_ty,
10454 effective_address,
10455 ""
10456 ));
10457 let v = err!(
10458 self.builder
10459 .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10460 )
10461 .into_vector_value();
10462 let res = err!(
10463 self.builder
10464 .build_int_s_extend(v, self.intrinsics.i16x8_ty, "")
10465 );
10466 let res = err!(
10467 self.builder
10468 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10469 );
10470 self.state.push1(res);
10471 }
10472 Operator::V128Load8x8U { ref memarg } => {
10473 let offset = self.state.pop1()?.into_int_value();
10474 let memory_index = MemoryIndex::from_u32(0);
10475 let effective_address = self.resolve_memory_ptr(
10476 memory_index,
10477 memarg,
10478 self.intrinsics.ptr_ty,
10479 offset,
10480 8,
10481 )?;
10482 let v = err!(self.builder.build_load(
10483 self.intrinsics.i64_ty,
10484 effective_address,
10485 ""
10486 ));
10487 let v = err!(
10488 self.builder
10489 .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10490 )
10491 .into_vector_value();
10492 let res = err!(
10493 self.builder
10494 .build_int_z_extend(v, self.intrinsics.i16x8_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::V128Load16x4S { ref memarg } => {
10503 let offset = self.state.pop1()?.into_int_value();
10504 let memory_index = MemoryIndex::from_u32(0);
10505 let effective_address = self.resolve_memory_ptr(
10506 memory_index,
10507 memarg,
10508 self.intrinsics.ptr_ty,
10509 offset,
10510 8,
10511 )?;
10512 let v = err!(self.builder.build_load(
10513 self.intrinsics.i64_ty,
10514 effective_address,
10515 ""
10516 ));
10517 let v = err!(self.builder.build_bit_cast(
10518 v,
10519 self.intrinsics.i16_ty.vec_type(4),
10520 ""
10521 ))
10522 .into_vector_value();
10523 let res = err!(
10524 self.builder
10525 .build_int_s_extend(v, self.intrinsics.i32x4_ty, "")
10526 );
10527 let res = err!(
10528 self.builder
10529 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10530 );
10531 self.state.push1(res);
10532 }
10533 Operator::V128Load16x4U { ref memarg } => {
10534 let offset = self.state.pop1()?.into_int_value();
10535 let memory_index = MemoryIndex::from_u32(0);
10536 let effective_address = self.resolve_memory_ptr(
10537 memory_index,
10538 memarg,
10539 self.intrinsics.ptr_ty,
10540 offset,
10541 8,
10542 )?;
10543 let v = err!(self.builder.build_load(
10544 self.intrinsics.i64_ty,
10545 effective_address,
10546 ""
10547 ));
10548 let v = err!(self.builder.build_bit_cast(
10549 v,
10550 self.intrinsics.i16_ty.vec_type(4),
10551 ""
10552 ))
10553 .into_vector_value();
10554 let res = err!(
10555 self.builder
10556 .build_int_z_extend(v, self.intrinsics.i32x4_ty, "")
10557 );
10558 let res = err!(
10559 self.builder
10560 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10561 );
10562 self.state.push1(res);
10563 }
10564 Operator::V128Load32x2S { ref memarg } => {
10565 let offset = self.state.pop1()?.into_int_value();
10566 let memory_index = MemoryIndex::from_u32(0);
10567 let effective_address = self.resolve_memory_ptr(
10568 memory_index,
10569 memarg,
10570 self.intrinsics.ptr_ty,
10571 offset,
10572 8,
10573 )?;
10574 let v = err!(self.builder.build_load(
10575 self.intrinsics.i64_ty,
10576 effective_address,
10577 ""
10578 ));
10579 let v = err!(self.builder.build_bit_cast(
10580 v,
10581 self.intrinsics.i32_ty.vec_type(2),
10582 ""
10583 ))
10584 .into_vector_value();
10585 let res = err!(
10586 self.builder
10587 .build_int_s_extend(v, self.intrinsics.i64x2_ty, "")
10588 );
10589 let res = err!(
10590 self.builder
10591 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10592 );
10593 self.state.push1(res);
10594 }
10595 Operator::V128Load32x2U { ref memarg } => {
10596 let offset = self.state.pop1()?.into_int_value();
10597 let memory_index = MemoryIndex::from_u32(0);
10598 let effective_address = self.resolve_memory_ptr(
10599 memory_index,
10600 memarg,
10601 self.intrinsics.ptr_ty,
10602 offset,
10603 8,
10604 )?;
10605 let v = err!(self.builder.build_load(
10606 self.intrinsics.i64_ty,
10607 effective_address,
10608 ""
10609 ));
10610 let v = err!(self.builder.build_bit_cast(
10611 v,
10612 self.intrinsics.i32_ty.vec_type(2),
10613 ""
10614 ))
10615 .into_vector_value();
10616 let res = err!(
10617 self.builder
10618 .build_int_z_extend(v, self.intrinsics.i64x2_ty, "")
10619 );
10620 let res = err!(
10621 self.builder
10622 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10623 );
10624 self.state.push1(res);
10625 }
10626 Operator::V128Load32Zero { ref memarg } => {
10627 let offset = self.state.pop1()?.into_int_value();
10628 let memory_index = MemoryIndex::from_u32(0);
10629 let effective_address = self.resolve_memory_ptr(
10630 memory_index,
10631 memarg,
10632 self.intrinsics.ptr_ty,
10633 offset,
10634 4,
10635 )?;
10636 let elem = err!(self.builder.build_load(
10637 self.intrinsics.i32_ty,
10638 effective_address,
10639 ""
10640 ));
10641 self.annotate_user_memaccess(
10642 memory_index,
10643 memarg,
10644 1,
10645 elem.as_instruction_value().unwrap(),
10646 )?;
10647 let res = err!(self.builder.build_int_z_extend(
10648 elem.into_int_value(),
10649 self.intrinsics.i128_ty,
10650 "",
10651 ));
10652 self.state.push1(res);
10653 }
10654 Operator::V128Load64Zero { ref memarg } => {
10655 let offset = self.state.pop1()?.into_int_value();
10656 let memory_index = MemoryIndex::from_u32(0);
10657 let effective_address = self.resolve_memory_ptr(
10658 memory_index,
10659 memarg,
10660 self.intrinsics.ptr_ty,
10661 offset,
10662 8,
10663 )?;
10664 let elem = err!(self.builder.build_load(
10665 self.intrinsics.i64_ty,
10666 effective_address,
10667 ""
10668 ));
10669 self.annotate_user_memaccess(
10670 memory_index,
10671 memarg,
10672 1,
10673 elem.as_instruction_value().unwrap(),
10674 )?;
10675 let res = err!(self.builder.build_int_z_extend(
10676 elem.into_int_value(),
10677 self.intrinsics.i128_ty,
10678 "",
10679 ));
10680 self.state.push1(res);
10681 }
10682 Operator::V128Load8Splat { ref memarg } => {
10683 let offset = self.state.pop1()?.into_int_value();
10684 let memory_index = MemoryIndex::from_u32(0);
10685 let effective_address = self.resolve_memory_ptr(
10686 memory_index,
10687 memarg,
10688 self.intrinsics.ptr_ty,
10689 offset,
10690 1,
10691 )?;
10692 let elem = err!(self.builder.build_load(
10693 self.intrinsics.i8_ty,
10694 effective_address,
10695 ""
10696 ));
10697 self.annotate_user_memaccess(
10698 memory_index,
10699 memarg,
10700 1,
10701 elem.as_instruction_value().unwrap(),
10702 )?;
10703 let res = self.splat_vector(elem, self.intrinsics.i8x16_ty)?;
10704 let res = err!(
10705 self.builder
10706 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10707 );
10708 self.state.push1(res);
10709 }
10710 Operator::V128Load16Splat { ref memarg } => {
10711 let offset = self.state.pop1()?.into_int_value();
10712 let memory_index = MemoryIndex::from_u32(0);
10713 let effective_address = self.resolve_memory_ptr(
10714 memory_index,
10715 memarg,
10716 self.intrinsics.ptr_ty,
10717 offset,
10718 2,
10719 )?;
10720 let elem = err!(self.builder.build_load(
10721 self.intrinsics.i16_ty,
10722 effective_address,
10723 ""
10724 ));
10725 self.annotate_user_memaccess(
10726 memory_index,
10727 memarg,
10728 1,
10729 elem.as_instruction_value().unwrap(),
10730 )?;
10731 let res = self.splat_vector(elem, self.intrinsics.i16x8_ty)?;
10732 let res = err!(
10733 self.builder
10734 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10735 );
10736 self.state.push1(res);
10737 }
10738 Operator::V128Load32Splat { ref memarg } => {
10739 let offset = self.state.pop1()?.into_int_value();
10740 let memory_index = MemoryIndex::from_u32(0);
10741 let effective_address = self.resolve_memory_ptr(
10742 memory_index,
10743 memarg,
10744 self.intrinsics.ptr_ty,
10745 offset,
10746 4,
10747 )?;
10748 let elem = err!(self.builder.build_load(
10749 self.intrinsics.i32_ty,
10750 effective_address,
10751 ""
10752 ));
10753 self.annotate_user_memaccess(
10754 memory_index,
10755 memarg,
10756 1,
10757 elem.as_instruction_value().unwrap(),
10758 )?;
10759 let res = self.splat_vector(elem, self.intrinsics.i32x4_ty)?;
10760 let res = err!(
10761 self.builder
10762 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10763 );
10764 self.state.push1(res);
10765 }
10766 Operator::V128Load64Splat { ref memarg } => {
10767 let offset = self.state.pop1()?.into_int_value();
10768 let memory_index = MemoryIndex::from_u32(0);
10769 let effective_address = self.resolve_memory_ptr(
10770 memory_index,
10771 memarg,
10772 self.intrinsics.ptr_ty,
10773 offset,
10774 8,
10775 )?;
10776 let elem = err!(self.builder.build_load(
10777 self.intrinsics.i64_ty,
10778 effective_address,
10779 ""
10780 ));
10781 self.annotate_user_memaccess(
10782 memory_index,
10783 memarg,
10784 1,
10785 elem.as_instruction_value().unwrap(),
10786 )?;
10787 let res = self.splat_vector(elem, self.intrinsics.i64x2_ty)?;
10788 let res = err!(
10789 self.builder
10790 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10791 );
10792 self.state.push1(res);
10793 }
10794 Operator::AtomicFence => {
10795 }
10803 Operator::I32AtomicLoad { ref memarg } => {
10804 let offset = self.state.pop1()?.into_int_value();
10805 let memory_index = MemoryIndex::from_u32(0);
10806 let effective_address = self.resolve_memory_ptr(
10807 memory_index,
10808 memarg,
10809 self.intrinsics.ptr_ty,
10810 offset,
10811 4,
10812 )?;
10813 self.trap_if_misaligned(memarg, effective_address, 4)?;
10814 let result = err!(self.builder.build_load(
10815 self.intrinsics.i32_ty,
10816 effective_address,
10817 "atomic_load"
10818 ));
10819 let load = result.as_instruction_value().unwrap();
10820 self.annotate_user_memaccess(memory_index, memarg, 4, load)?;
10821 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10822 .unwrap();
10823 self.state.push1(result);
10824 }
10825 Operator::I64AtomicLoad { ref memarg } => {
10826 let offset = self.state.pop1()?.into_int_value();
10827 let memory_index = MemoryIndex::from_u32(0);
10828 let effective_address = self.resolve_memory_ptr(
10829 memory_index,
10830 memarg,
10831 self.intrinsics.ptr_ty,
10832 offset,
10833 8,
10834 )?;
10835 self.trap_if_misaligned(memarg, effective_address, 8)?;
10836 let result = err!(self.builder.build_load(
10837 self.intrinsics.i64_ty,
10838 effective_address,
10839 ""
10840 ));
10841 let load = result.as_instruction_value().unwrap();
10842 self.annotate_user_memaccess(memory_index, memarg, 8, load)?;
10843 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10844 .unwrap();
10845 self.state.push1(result);
10846 }
10847 Operator::I32AtomicLoad8U { ref memarg } => {
10848 let offset = self.state.pop1()?.into_int_value();
10849 let memory_index = MemoryIndex::from_u32(0);
10850 let effective_address = self.resolve_memory_ptr(
10851 memory_index,
10852 memarg,
10853 self.intrinsics.ptr_ty,
10854 offset,
10855 1,
10856 )?;
10857 self.trap_if_misaligned(memarg, effective_address, 1)?;
10858 let narrow_result = err!(self.builder.build_load(
10859 self.intrinsics.i8_ty,
10860 effective_address,
10861 ""
10862 ))
10863 .into_int_value();
10864 let load = narrow_result.as_instruction_value().unwrap();
10865 self.annotate_user_memaccess(memory_index, memarg, 1, load)?;
10866 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10867 .unwrap();
10868 let result = err!(self.builder.build_int_z_extend(
10869 narrow_result,
10870 self.intrinsics.i32_ty,
10871 ""
10872 ));
10873 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10874 }
10875 Operator::I32AtomicLoad16U { ref memarg } => {
10876 let offset = self.state.pop1()?.into_int_value();
10877 let memory_index = MemoryIndex::from_u32(0);
10878 let effective_address = self.resolve_memory_ptr(
10879 memory_index,
10880 memarg,
10881 self.intrinsics.ptr_ty,
10882 offset,
10883 2,
10884 )?;
10885 self.trap_if_misaligned(memarg, effective_address, 2)?;
10886 let narrow_result = err!(self.builder.build_load(
10887 self.intrinsics.i16_ty,
10888 effective_address,
10889 ""
10890 ))
10891 .into_int_value();
10892 let load = narrow_result.as_instruction_value().unwrap();
10893 self.annotate_user_memaccess(memory_index, memarg, 2, load)?;
10894 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10895 .unwrap();
10896 let result = err!(self.builder.build_int_z_extend(
10897 narrow_result,
10898 self.intrinsics.i32_ty,
10899 ""
10900 ));
10901 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10902 }
10903 Operator::I64AtomicLoad8U { ref memarg } => {
10904 let offset = self.state.pop1()?.into_int_value();
10905 let memory_index = MemoryIndex::from_u32(0);
10906 let effective_address = self.resolve_memory_ptr(
10907 memory_index,
10908 memarg,
10909 self.intrinsics.ptr_ty,
10910 offset,
10911 1,
10912 )?;
10913 self.trap_if_misaligned(memarg, effective_address, 1)?;
10914 let narrow_result = err!(self.builder.build_load(
10915 self.intrinsics.i8_ty,
10916 effective_address,
10917 ""
10918 ))
10919 .into_int_value();
10920 let load = narrow_result.as_instruction_value().unwrap();
10921 self.annotate_user_memaccess(memory_index, memarg, 1, load)?;
10922 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10923 .unwrap();
10924 let result = err!(self.builder.build_int_z_extend(
10925 narrow_result,
10926 self.intrinsics.i64_ty,
10927 ""
10928 ));
10929 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10930 }
10931 Operator::I64AtomicLoad16U { ref memarg } => {
10932 let offset = self.state.pop1()?.into_int_value();
10933 let memory_index = MemoryIndex::from_u32(0);
10934 let effective_address = self.resolve_memory_ptr(
10935 memory_index,
10936 memarg,
10937 self.intrinsics.ptr_ty,
10938 offset,
10939 2,
10940 )?;
10941 self.trap_if_misaligned(memarg, effective_address, 2)?;
10942 let narrow_result = err!(self.builder.build_load(
10943 self.intrinsics.i16_ty,
10944 effective_address,
10945 ""
10946 ))
10947 .into_int_value();
10948 let load = narrow_result.as_instruction_value().unwrap();
10949 self.annotate_user_memaccess(memory_index, memarg, 2, load)?;
10950 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10951 .unwrap();
10952 let result = err!(self.builder.build_int_z_extend(
10953 narrow_result,
10954 self.intrinsics.i64_ty,
10955 ""
10956 ));
10957 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10958 }
10959 Operator::I64AtomicLoad32U { ref memarg } => {
10960 let offset = self.state.pop1()?.into_int_value();
10961 let memory_index = MemoryIndex::from_u32(0);
10962 let effective_address = self.resolve_memory_ptr(
10963 memory_index,
10964 memarg,
10965 self.intrinsics.ptr_ty,
10966 offset,
10967 4,
10968 )?;
10969 self.trap_if_misaligned(memarg, effective_address, 4)?;
10970 let narrow_result = err!(self.builder.build_load(
10971 self.intrinsics.i32_ty,
10972 effective_address,
10973 ""
10974 ))
10975 .into_int_value();
10976 let load = narrow_result.as_instruction_value().unwrap();
10977 self.annotate_user_memaccess(memory_index, memarg, 4, load)?;
10978 load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10979 .unwrap();
10980 let result = err!(self.builder.build_int_z_extend(
10981 narrow_result,
10982 self.intrinsics.i64_ty,
10983 ""
10984 ));
10985 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10986 }
10987 Operator::I32AtomicStore { ref memarg } => {
10988 let value = self.state.pop1()?;
10989 let offset = self.state.pop1()?.into_int_value();
10990 let memory_index = MemoryIndex::from_u32(0);
10991 let effective_address = self.resolve_memory_ptr(
10992 memory_index,
10993 memarg,
10994 self.intrinsics.ptr_ty,
10995 offset,
10996 4,
10997 )?;
10998 self.trap_if_misaligned(memarg, effective_address, 4)?;
10999 let store = err!(self.builder.build_store(effective_address, value));
11000 self.annotate_user_memaccess(memory_index, memarg, 4, store)?;
11001 store
11002 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
11003 .unwrap();
11004 }
11005 Operator::I64AtomicStore { ref memarg } => {
11006 let value = self.state.pop1()?;
11007 let offset = self.state.pop1()?.into_int_value();
11008 let memory_index = MemoryIndex::from_u32(0);
11009 let effective_address = self.resolve_memory_ptr(
11010 memory_index,
11011 memarg,
11012 self.intrinsics.ptr_ty,
11013 offset,
11014 8,
11015 )?;
11016 self.trap_if_misaligned(memarg, effective_address, 8)?;
11017 let store = err!(self.builder.build_store(effective_address, value));
11018 self.annotate_user_memaccess(memory_index, memarg, 8, store)?;
11019 store
11020 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
11021 .unwrap();
11022 }
11023 Operator::I32AtomicStore8 { ref memarg } | Operator::I64AtomicStore8 { ref memarg } => {
11024 let value = self.state.pop1()?.into_int_value();
11025 let offset = self.state.pop1()?.into_int_value();
11026 let memory_index = MemoryIndex::from_u32(0);
11027 let effective_address = self.resolve_memory_ptr(
11028 memory_index,
11029 memarg,
11030 self.intrinsics.ptr_ty,
11031 offset,
11032 1,
11033 )?;
11034 self.trap_if_misaligned(memarg, effective_address, 1)?;
11035 let narrow_value = err!(self.builder.build_int_truncate(
11036 value,
11037 self.intrinsics.i8_ty,
11038 ""
11039 ));
11040 let store = err!(self.builder.build_store(effective_address, narrow_value));
11041 self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
11042 store
11043 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
11044 .unwrap();
11045 }
11046 Operator::I32AtomicStore16 { ref memarg }
11047 | Operator::I64AtomicStore16 { ref memarg } => {
11048 let value = self.state.pop1()?.into_int_value();
11049 let offset = self.state.pop1()?.into_int_value();
11050 let memory_index = MemoryIndex::from_u32(0);
11051 let effective_address = self.resolve_memory_ptr(
11052 memory_index,
11053 memarg,
11054 self.intrinsics.ptr_ty,
11055 offset,
11056 2,
11057 )?;
11058 self.trap_if_misaligned(memarg, effective_address, 2)?;
11059 let narrow_value = err!(self.builder.build_int_truncate(
11060 value,
11061 self.intrinsics.i16_ty,
11062 ""
11063 ));
11064 let store = err!(self.builder.build_store(effective_address, narrow_value));
11065 self.annotate_user_memaccess(memory_index, memarg, 2, store)?;
11066 store
11067 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
11068 .unwrap();
11069 }
11070 Operator::I64AtomicStore32 { ref memarg } => {
11071 let value = self.state.pop1()?.into_int_value();
11072 let offset = self.state.pop1()?.into_int_value();
11073 let memory_index = MemoryIndex::from_u32(0);
11074 let effective_address = self.resolve_memory_ptr(
11075 memory_index,
11076 memarg,
11077 self.intrinsics.ptr_ty,
11078 offset,
11079 4,
11080 )?;
11081 self.trap_if_misaligned(memarg, effective_address, 4)?;
11082 let narrow_value = err!(self.builder.build_int_truncate(
11083 value,
11084 self.intrinsics.i32_ty,
11085 ""
11086 ));
11087 let store = err!(self.builder.build_store(effective_address, narrow_value));
11088 self.annotate_user_memaccess(memory_index, memarg, 4, store)?;
11089 store
11090 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
11091 .unwrap();
11092 }
11093 Operator::I32AtomicRmw8AddU { ref memarg } => {
11094 let value = self.state.pop1()?.into_int_value();
11095 let offset = self.state.pop1()?.into_int_value();
11096 let memory_index = MemoryIndex::from_u32(0);
11097 let effective_address = self.resolve_memory_ptr(
11098 memory_index,
11099 memarg,
11100 self.intrinsics.ptr_ty,
11101 offset,
11102 1,
11103 )?;
11104 self.trap_if_misaligned(memarg, effective_address, 1)?;
11105 let narrow_value = err!(self.builder.build_int_truncate(
11106 value,
11107 self.intrinsics.i8_ty,
11108 ""
11109 ));
11110 let old = self
11111 .builder
11112 .build_atomicrmw(
11113 AtomicRMWBinOp::Add,
11114 effective_address,
11115 narrow_value,
11116 AtomicOrdering::SequentiallyConsistent,
11117 )
11118 .unwrap();
11119 tbaa_label(
11120 self.module,
11121 self.intrinsics,
11122 format!("memory {}", memory_index.as_u32()),
11123 old.as_instruction_value().unwrap(),
11124 );
11125 let old = err!(
11126 self.builder
11127 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11128 );
11129 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11130 }
11131 Operator::I32AtomicRmw16AddU { ref memarg } => {
11132 let value = self.state.pop1()?.into_int_value();
11133 let offset = self.state.pop1()?.into_int_value();
11134 let memory_index = MemoryIndex::from_u32(0);
11135 let effective_address = self.resolve_memory_ptr(
11136 memory_index,
11137 memarg,
11138 self.intrinsics.ptr_ty,
11139 offset,
11140 2,
11141 )?;
11142 self.trap_if_misaligned(memarg, effective_address, 2)?;
11143 let narrow_value = err!(self.builder.build_int_truncate(
11144 value,
11145 self.intrinsics.i16_ty,
11146 ""
11147 ));
11148 let old = self
11149 .builder
11150 .build_atomicrmw(
11151 AtomicRMWBinOp::Add,
11152 effective_address,
11153 narrow_value,
11154 AtomicOrdering::SequentiallyConsistent,
11155 )
11156 .unwrap();
11157 tbaa_label(
11158 self.module,
11159 self.intrinsics,
11160 format!("memory {}", memory_index.as_u32()),
11161 old.as_instruction_value().unwrap(),
11162 );
11163 let old = err!(
11164 self.builder
11165 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11166 );
11167 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11168 }
11169 Operator::I32AtomicRmwAdd { ref memarg } => {
11170 let value = self.state.pop1()?.into_int_value();
11171 let offset = self.state.pop1()?.into_int_value();
11172 let memory_index = MemoryIndex::from_u32(0);
11173 let effective_address = self.resolve_memory_ptr(
11174 memory_index,
11175 memarg,
11176 self.intrinsics.ptr_ty,
11177 offset,
11178 4,
11179 )?;
11180 self.trap_if_misaligned(memarg, effective_address, 4)?;
11181 let old = self
11182 .builder
11183 .build_atomicrmw(
11184 AtomicRMWBinOp::Add,
11185 effective_address,
11186 value,
11187 AtomicOrdering::SequentiallyConsistent,
11188 )
11189 .unwrap();
11190 tbaa_label(
11191 self.module,
11192 self.intrinsics,
11193 format!("memory {}", memory_index.as_u32()),
11194 old.as_instruction_value().unwrap(),
11195 );
11196 self.state.push1(old);
11197 }
11198 Operator::I64AtomicRmw8AddU { ref memarg } => {
11199 let value = self.state.pop1()?.into_int_value();
11200 let offset = self.state.pop1()?.into_int_value();
11201 let memory_index = MemoryIndex::from_u32(0);
11202 let effective_address = self.resolve_memory_ptr(
11203 memory_index,
11204 memarg,
11205 self.intrinsics.ptr_ty,
11206 offset,
11207 1,
11208 )?;
11209 self.trap_if_misaligned(memarg, effective_address, 1)?;
11210 let narrow_value = err!(self.builder.build_int_truncate(
11211 value,
11212 self.intrinsics.i8_ty,
11213 ""
11214 ));
11215 let old = self
11216 .builder
11217 .build_atomicrmw(
11218 AtomicRMWBinOp::Add,
11219 effective_address,
11220 narrow_value,
11221 AtomicOrdering::SequentiallyConsistent,
11222 )
11223 .unwrap();
11224 self.annotate_user_memaccess(
11225 memory_index,
11226 memarg,
11227 0,
11228 old.as_instruction_value().unwrap(),
11229 )?;
11230 let old = err!(
11231 self.builder
11232 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11233 );
11234 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11235 }
11236 Operator::I64AtomicRmw16AddU { ref memarg } => {
11237 let value = self.state.pop1()?.into_int_value();
11238 let offset = self.state.pop1()?.into_int_value();
11239 let memory_index = MemoryIndex::from_u32(0);
11240 let effective_address = self.resolve_memory_ptr(
11241 memory_index,
11242 memarg,
11243 self.intrinsics.ptr_ty,
11244 offset,
11245 2,
11246 )?;
11247 self.trap_if_misaligned(memarg, effective_address, 2)?;
11248 let narrow_value = err!(self.builder.build_int_truncate(
11249 value,
11250 self.intrinsics.i16_ty,
11251 ""
11252 ));
11253 let old = self
11254 .builder
11255 .build_atomicrmw(
11256 AtomicRMWBinOp::Add,
11257 effective_address,
11258 narrow_value,
11259 AtomicOrdering::SequentiallyConsistent,
11260 )
11261 .unwrap();
11262 self.annotate_user_memaccess(
11263 memory_index,
11264 memarg,
11265 0,
11266 old.as_instruction_value().unwrap(),
11267 )?;
11268 let old = err!(
11269 self.builder
11270 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11271 );
11272 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11273 }
11274 Operator::I64AtomicRmw32AddU { ref memarg } => {
11275 let value = self.state.pop1()?.into_int_value();
11276 let offset = self.state.pop1()?.into_int_value();
11277 let memory_index = MemoryIndex::from_u32(0);
11278 let effective_address = self.resolve_memory_ptr(
11279 memory_index,
11280 memarg,
11281 self.intrinsics.ptr_ty,
11282 offset,
11283 4,
11284 )?;
11285 self.trap_if_misaligned(memarg, effective_address, 4)?;
11286 let narrow_value = err!(self.builder.build_int_truncate(
11287 value,
11288 self.intrinsics.i32_ty,
11289 ""
11290 ));
11291 let old = self
11292 .builder
11293 .build_atomicrmw(
11294 AtomicRMWBinOp::Add,
11295 effective_address,
11296 narrow_value,
11297 AtomicOrdering::SequentiallyConsistent,
11298 )
11299 .unwrap();
11300 self.annotate_user_memaccess(
11301 memory_index,
11302 memarg,
11303 0,
11304 old.as_instruction_value().unwrap(),
11305 )?;
11306 let old = err!(
11307 self.builder
11308 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11309 );
11310 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11311 }
11312 Operator::I64AtomicRmwAdd { ref memarg } => {
11313 let value = self.state.pop1()?.into_int_value();
11314 let offset = self.state.pop1()?.into_int_value();
11315 let memory_index = MemoryIndex::from_u32(0);
11316 let effective_address = self.resolve_memory_ptr(
11317 memory_index,
11318 memarg,
11319 self.intrinsics.ptr_ty,
11320 offset,
11321 8,
11322 )?;
11323 self.trap_if_misaligned(memarg, effective_address, 8)?;
11324 let old = self
11325 .builder
11326 .build_atomicrmw(
11327 AtomicRMWBinOp::Add,
11328 effective_address,
11329 value,
11330 AtomicOrdering::SequentiallyConsistent,
11331 )
11332 .unwrap();
11333 self.annotate_user_memaccess(
11334 memory_index,
11335 memarg,
11336 0,
11337 old.as_instruction_value().unwrap(),
11338 )?;
11339 self.state.push1(old);
11340 }
11341 Operator::I32AtomicRmw8SubU { ref memarg } => {
11342 let value = self.state.pop1()?.into_int_value();
11343 let offset = self.state.pop1()?.into_int_value();
11344 let memory_index = MemoryIndex::from_u32(0);
11345 let effective_address = self.resolve_memory_ptr(
11346 memory_index,
11347 memarg,
11348 self.intrinsics.ptr_ty,
11349 offset,
11350 1,
11351 )?;
11352 self.trap_if_misaligned(memarg, effective_address, 1)?;
11353 let narrow_value = err!(self.builder.build_int_truncate(
11354 value,
11355 self.intrinsics.i8_ty,
11356 ""
11357 ));
11358 let old = self
11359 .builder
11360 .build_atomicrmw(
11361 AtomicRMWBinOp::Sub,
11362 effective_address,
11363 narrow_value,
11364 AtomicOrdering::SequentiallyConsistent,
11365 )
11366 .unwrap();
11367 self.annotate_user_memaccess(
11368 memory_index,
11369 memarg,
11370 0,
11371 old.as_instruction_value().unwrap(),
11372 )?;
11373 let old = err!(
11374 self.builder
11375 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11376 );
11377 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11378 }
11379 Operator::I32AtomicRmw16SubU { ref memarg } => {
11380 let value = self.state.pop1()?.into_int_value();
11381 let offset = self.state.pop1()?.into_int_value();
11382 let memory_index = MemoryIndex::from_u32(0);
11383 let effective_address = self.resolve_memory_ptr(
11384 memory_index,
11385 memarg,
11386 self.intrinsics.ptr_ty,
11387 offset,
11388 2,
11389 )?;
11390 self.trap_if_misaligned(memarg, effective_address, 2)?;
11391 let narrow_value = err!(self.builder.build_int_truncate(
11392 value,
11393 self.intrinsics.i16_ty,
11394 ""
11395 ));
11396 let old = self
11397 .builder
11398 .build_atomicrmw(
11399 AtomicRMWBinOp::Sub,
11400 effective_address,
11401 narrow_value,
11402 AtomicOrdering::SequentiallyConsistent,
11403 )
11404 .unwrap();
11405 self.annotate_user_memaccess(
11406 memory_index,
11407 memarg,
11408 0,
11409 old.as_instruction_value().unwrap(),
11410 )?;
11411 let old = err!(
11412 self.builder
11413 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11414 );
11415 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11416 }
11417 Operator::I32AtomicRmwSub { ref memarg } => {
11418 let value = self.state.pop1()?.into_int_value();
11419 let offset = self.state.pop1()?.into_int_value();
11420 let memory_index = MemoryIndex::from_u32(0);
11421 let effective_address = self.resolve_memory_ptr(
11422 memory_index,
11423 memarg,
11424 self.intrinsics.ptr_ty,
11425 offset,
11426 4,
11427 )?;
11428 self.trap_if_misaligned(memarg, effective_address, 4)?;
11429 let old = self
11430 .builder
11431 .build_atomicrmw(
11432 AtomicRMWBinOp::Sub,
11433 effective_address,
11434 value,
11435 AtomicOrdering::SequentiallyConsistent,
11436 )
11437 .unwrap();
11438 self.annotate_user_memaccess(
11439 memory_index,
11440 memarg,
11441 0,
11442 old.as_instruction_value().unwrap(),
11443 )?;
11444 self.state.push1(old);
11445 }
11446 Operator::I64AtomicRmw8SubU { ref memarg } => {
11447 let value = self.state.pop1()?.into_int_value();
11448 let offset = self.state.pop1()?.into_int_value();
11449 let memory_index = MemoryIndex::from_u32(0);
11450 let effective_address = self.resolve_memory_ptr(
11451 memory_index,
11452 memarg,
11453 self.intrinsics.ptr_ty,
11454 offset,
11455 1,
11456 )?;
11457 self.trap_if_misaligned(memarg, effective_address, 1)?;
11458 let narrow_value = err!(self.builder.build_int_truncate(
11459 value,
11460 self.intrinsics.i8_ty,
11461 ""
11462 ));
11463 let old = self
11464 .builder
11465 .build_atomicrmw(
11466 AtomicRMWBinOp::Sub,
11467 effective_address,
11468 narrow_value,
11469 AtomicOrdering::SequentiallyConsistent,
11470 )
11471 .unwrap();
11472 self.annotate_user_memaccess(
11473 memory_index,
11474 memarg,
11475 0,
11476 old.as_instruction_value().unwrap(),
11477 )?;
11478 let old = err!(
11479 self.builder
11480 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11481 );
11482 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11483 }
11484 Operator::I64AtomicRmw16SubU { ref memarg } => {
11485 let value = self.state.pop1()?.into_int_value();
11486 let offset = self.state.pop1()?.into_int_value();
11487 let memory_index = MemoryIndex::from_u32(0);
11488 let effective_address = self.resolve_memory_ptr(
11489 memory_index,
11490 memarg,
11491 self.intrinsics.ptr_ty,
11492 offset,
11493 2,
11494 )?;
11495 self.trap_if_misaligned(memarg, effective_address, 2)?;
11496 let narrow_value = err!(self.builder.build_int_truncate(
11497 value,
11498 self.intrinsics.i16_ty,
11499 ""
11500 ));
11501 let old = self
11502 .builder
11503 .build_atomicrmw(
11504 AtomicRMWBinOp::Sub,
11505 effective_address,
11506 narrow_value,
11507 AtomicOrdering::SequentiallyConsistent,
11508 )
11509 .unwrap();
11510 self.annotate_user_memaccess(
11511 memory_index,
11512 memarg,
11513 0,
11514 old.as_instruction_value().unwrap(),
11515 )?;
11516 let old = err!(
11517 self.builder
11518 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11519 );
11520 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11521 }
11522 Operator::I64AtomicRmw32SubU { ref memarg } => {
11523 let value = self.state.pop1()?.into_int_value();
11524 let offset = self.state.pop1()?.into_int_value();
11525 let memory_index = MemoryIndex::from_u32(0);
11526 let effective_address = self.resolve_memory_ptr(
11527 memory_index,
11528 memarg,
11529 self.intrinsics.ptr_ty,
11530 offset,
11531 4,
11532 )?;
11533 self.trap_if_misaligned(memarg, effective_address, 4)?;
11534 let narrow_value = err!(self.builder.build_int_truncate(
11535 value,
11536 self.intrinsics.i32_ty,
11537 ""
11538 ));
11539 let old = self
11540 .builder
11541 .build_atomicrmw(
11542 AtomicRMWBinOp::Sub,
11543 effective_address,
11544 narrow_value,
11545 AtomicOrdering::SequentiallyConsistent,
11546 )
11547 .unwrap();
11548 self.annotate_user_memaccess(
11549 memory_index,
11550 memarg,
11551 0,
11552 old.as_instruction_value().unwrap(),
11553 )?;
11554 let old = err!(
11555 self.builder
11556 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11557 );
11558 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11559 }
11560 Operator::I64AtomicRmwSub { ref memarg } => {
11561 let value = self.state.pop1()?.into_int_value();
11562 let offset = self.state.pop1()?.into_int_value();
11563 let memory_index = MemoryIndex::from_u32(0);
11564 let effective_address = self.resolve_memory_ptr(
11565 memory_index,
11566 memarg,
11567 self.intrinsics.ptr_ty,
11568 offset,
11569 8,
11570 )?;
11571 self.trap_if_misaligned(memarg, effective_address, 8)?;
11572 let old = self
11573 .builder
11574 .build_atomicrmw(
11575 AtomicRMWBinOp::Sub,
11576 effective_address,
11577 value,
11578 AtomicOrdering::SequentiallyConsistent,
11579 )
11580 .unwrap();
11581 self.annotate_user_memaccess(
11582 memory_index,
11583 memarg,
11584 0,
11585 old.as_instruction_value().unwrap(),
11586 )?;
11587 self.state.push1(old);
11588 }
11589 Operator::I32AtomicRmw8AndU { ref memarg } => {
11590 let value = self.state.pop1()?.into_int_value();
11591 let offset = self.state.pop1()?.into_int_value();
11592 let memory_index = MemoryIndex::from_u32(0);
11593 let effective_address = self.resolve_memory_ptr(
11594 memory_index,
11595 memarg,
11596 self.intrinsics.ptr_ty,
11597 offset,
11598 1,
11599 )?;
11600 self.trap_if_misaligned(memarg, effective_address, 1)?;
11601 let narrow_value = err!(self.builder.build_int_truncate(
11602 value,
11603 self.intrinsics.i8_ty,
11604 ""
11605 ));
11606 let old = self
11607 .builder
11608 .build_atomicrmw(
11609 AtomicRMWBinOp::And,
11610 effective_address,
11611 narrow_value,
11612 AtomicOrdering::SequentiallyConsistent,
11613 )
11614 .unwrap();
11615 self.annotate_user_memaccess(
11616 memory_index,
11617 memarg,
11618 0,
11619 old.as_instruction_value().unwrap(),
11620 )?;
11621 let old = err!(
11622 self.builder
11623 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11624 );
11625 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11626 }
11627 Operator::I32AtomicRmw16AndU { ref memarg } => {
11628 let value = self.state.pop1()?.into_int_value();
11629 let offset = self.state.pop1()?.into_int_value();
11630 let memory_index = MemoryIndex::from_u32(0);
11631 let effective_address = self.resolve_memory_ptr(
11632 memory_index,
11633 memarg,
11634 self.intrinsics.ptr_ty,
11635 offset,
11636 2,
11637 )?;
11638 self.trap_if_misaligned(memarg, effective_address, 2)?;
11639 let narrow_value = err!(self.builder.build_int_truncate(
11640 value,
11641 self.intrinsics.i16_ty,
11642 ""
11643 ));
11644 let old = self
11645 .builder
11646 .build_atomicrmw(
11647 AtomicRMWBinOp::And,
11648 effective_address,
11649 narrow_value,
11650 AtomicOrdering::SequentiallyConsistent,
11651 )
11652 .unwrap();
11653 self.annotate_user_memaccess(
11654 memory_index,
11655 memarg,
11656 0,
11657 old.as_instruction_value().unwrap(),
11658 )?;
11659 let old = err!(
11660 self.builder
11661 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11662 );
11663 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11664 }
11665 Operator::I32AtomicRmwAnd { ref memarg } => {
11666 let value = self.state.pop1()?.into_int_value();
11667 let offset = self.state.pop1()?.into_int_value();
11668 let memory_index = MemoryIndex::from_u32(0);
11669 let effective_address = self.resolve_memory_ptr(
11670 memory_index,
11671 memarg,
11672 self.intrinsics.ptr_ty,
11673 offset,
11674 4,
11675 )?;
11676 self.trap_if_misaligned(memarg, effective_address, 4)?;
11677 let old = self
11678 .builder
11679 .build_atomicrmw(
11680 AtomicRMWBinOp::And,
11681 effective_address,
11682 value,
11683 AtomicOrdering::SequentiallyConsistent,
11684 )
11685 .unwrap();
11686 self.annotate_user_memaccess(
11687 memory_index,
11688 memarg,
11689 0,
11690 old.as_instruction_value().unwrap(),
11691 )?;
11692 self.state.push1(old);
11693 }
11694 Operator::I64AtomicRmw8AndU { ref memarg } => {
11695 let value = self.state.pop1()?.into_int_value();
11696 let offset = self.state.pop1()?.into_int_value();
11697 let memory_index = MemoryIndex::from_u32(0);
11698 let effective_address = self.resolve_memory_ptr(
11699 memory_index,
11700 memarg,
11701 self.intrinsics.ptr_ty,
11702 offset,
11703 1,
11704 )?;
11705 self.trap_if_misaligned(memarg, effective_address, 1)?;
11706 let narrow_value = err!(self.builder.build_int_truncate(
11707 value,
11708 self.intrinsics.i8_ty,
11709 ""
11710 ));
11711 let old = self
11712 .builder
11713 .build_atomicrmw(
11714 AtomicRMWBinOp::And,
11715 effective_address,
11716 narrow_value,
11717 AtomicOrdering::SequentiallyConsistent,
11718 )
11719 .unwrap();
11720 self.annotate_user_memaccess(
11721 memory_index,
11722 memarg,
11723 0,
11724 old.as_instruction_value().unwrap(),
11725 )?;
11726 let old = err!(
11727 self.builder
11728 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11729 );
11730 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11731 }
11732 Operator::I64AtomicRmw16AndU { ref memarg } => {
11733 let value = self.state.pop1()?.into_int_value();
11734 let offset = self.state.pop1()?.into_int_value();
11735 let memory_index = MemoryIndex::from_u32(0);
11736 let effective_address = self.resolve_memory_ptr(
11737 memory_index,
11738 memarg,
11739 self.intrinsics.ptr_ty,
11740 offset,
11741 2,
11742 )?;
11743 self.trap_if_misaligned(memarg, effective_address, 2)?;
11744 let narrow_value = err!(self.builder.build_int_truncate(
11745 value,
11746 self.intrinsics.i16_ty,
11747 ""
11748 ));
11749 let old = self
11750 .builder
11751 .build_atomicrmw(
11752 AtomicRMWBinOp::And,
11753 effective_address,
11754 narrow_value,
11755 AtomicOrdering::SequentiallyConsistent,
11756 )
11757 .unwrap();
11758 self.annotate_user_memaccess(
11759 memory_index,
11760 memarg,
11761 0,
11762 old.as_instruction_value().unwrap(),
11763 )?;
11764 let old = err!(
11765 self.builder
11766 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11767 );
11768 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11769 }
11770 Operator::I64AtomicRmw32AndU { ref memarg } => {
11771 let value = self.state.pop1()?.into_int_value();
11772 let offset = self.state.pop1()?.into_int_value();
11773 let memory_index = MemoryIndex::from_u32(0);
11774 let effective_address = self.resolve_memory_ptr(
11775 memory_index,
11776 memarg,
11777 self.intrinsics.ptr_ty,
11778 offset,
11779 4,
11780 )?;
11781 self.trap_if_misaligned(memarg, effective_address, 4)?;
11782 let narrow_value = err!(self.builder.build_int_truncate(
11783 value,
11784 self.intrinsics.i32_ty,
11785 ""
11786 ));
11787 let old = self
11788 .builder
11789 .build_atomicrmw(
11790 AtomicRMWBinOp::And,
11791 effective_address,
11792 narrow_value,
11793 AtomicOrdering::SequentiallyConsistent,
11794 )
11795 .unwrap();
11796 self.annotate_user_memaccess(
11797 memory_index,
11798 memarg,
11799 0,
11800 old.as_instruction_value().unwrap(),
11801 )?;
11802 let old = err!(
11803 self.builder
11804 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11805 );
11806 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11807 }
11808 Operator::I64AtomicRmwAnd { ref memarg } => {
11809 let value = self.state.pop1()?.into_int_value();
11810 let offset = self.state.pop1()?.into_int_value();
11811 let memory_index = MemoryIndex::from_u32(0);
11812 let effective_address = self.resolve_memory_ptr(
11813 memory_index,
11814 memarg,
11815 self.intrinsics.ptr_ty,
11816 offset,
11817 8,
11818 )?;
11819 self.trap_if_misaligned(memarg, effective_address, 8)?;
11820 let old = self
11821 .builder
11822 .build_atomicrmw(
11823 AtomicRMWBinOp::And,
11824 effective_address,
11825 value,
11826 AtomicOrdering::SequentiallyConsistent,
11827 )
11828 .unwrap();
11829 self.annotate_user_memaccess(
11830 memory_index,
11831 memarg,
11832 0,
11833 old.as_instruction_value().unwrap(),
11834 )?;
11835 self.state.push1(old);
11836 }
11837 Operator::I32AtomicRmw8OrU { ref memarg } => {
11838 let value = self.state.pop1()?.into_int_value();
11839 let offset = self.state.pop1()?.into_int_value();
11840 let memory_index = MemoryIndex::from_u32(0);
11841 let effective_address = self.resolve_memory_ptr(
11842 memory_index,
11843 memarg,
11844 self.intrinsics.ptr_ty,
11845 offset,
11846 1,
11847 )?;
11848 self.trap_if_misaligned(memarg, effective_address, 1)?;
11849 let narrow_value = err!(self.builder.build_int_truncate(
11850 value,
11851 self.intrinsics.i8_ty,
11852 ""
11853 ));
11854 let old = self
11855 .builder
11856 .build_atomicrmw(
11857 AtomicRMWBinOp::Or,
11858 effective_address,
11859 narrow_value,
11860 AtomicOrdering::SequentiallyConsistent,
11861 )
11862 .unwrap();
11863 self.annotate_user_memaccess(
11864 memory_index,
11865 memarg,
11866 0,
11867 old.as_instruction_value().unwrap(),
11868 )?;
11869 let old = err!(
11870 self.builder
11871 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11872 );
11873 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11874 }
11875 Operator::I32AtomicRmw16OrU { ref memarg } => {
11876 let value = self.state.pop1()?.into_int_value();
11877 let offset = self.state.pop1()?.into_int_value();
11878 let memory_index = MemoryIndex::from_u32(0);
11879 let effective_address = self.resolve_memory_ptr(
11880 memory_index,
11881 memarg,
11882 self.intrinsics.ptr_ty,
11883 offset,
11884 2,
11885 )?;
11886 self.trap_if_misaligned(memarg, effective_address, 2)?;
11887 let narrow_value = err!(self.builder.build_int_truncate(
11888 value,
11889 self.intrinsics.i16_ty,
11890 ""
11891 ));
11892 let old = self
11893 .builder
11894 .build_atomicrmw(
11895 AtomicRMWBinOp::Or,
11896 effective_address,
11897 narrow_value,
11898 AtomicOrdering::SequentiallyConsistent,
11899 )
11900 .unwrap();
11901 self.annotate_user_memaccess(
11902 memory_index,
11903 memarg,
11904 0,
11905 old.as_instruction_value().unwrap(),
11906 )?;
11907 let old = err!(
11908 self.builder
11909 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11910 );
11911 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11912 }
11913 Operator::I32AtomicRmwOr { ref memarg } => {
11914 let value = self.state.pop1()?.into_int_value();
11915 let offset = self.state.pop1()?.into_int_value();
11916 let memory_index = MemoryIndex::from_u32(0);
11917 let effective_address = self.resolve_memory_ptr(
11918 memory_index,
11919 memarg,
11920 self.intrinsics.ptr_ty,
11921 offset,
11922 4,
11923 )?;
11924 self.trap_if_misaligned(memarg, effective_address, 4)?;
11925 let old = self
11926 .builder
11927 .build_atomicrmw(
11928 AtomicRMWBinOp::Or,
11929 effective_address,
11930 value,
11931 AtomicOrdering::SequentiallyConsistent,
11932 )
11933 .unwrap();
11934 self.annotate_user_memaccess(
11935 memory_index,
11936 memarg,
11937 0,
11938 old.as_instruction_value().unwrap(),
11939 )?;
11940 let old = err!(
11941 self.builder
11942 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11943 );
11944 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11945 }
11946 Operator::I64AtomicRmw8OrU { ref memarg } => {
11947 let value = self.state.pop1()?.into_int_value();
11948 let offset = self.state.pop1()?.into_int_value();
11949 let memory_index = MemoryIndex::from_u32(0);
11950 let effective_address = self.resolve_memory_ptr(
11951 memory_index,
11952 memarg,
11953 self.intrinsics.ptr_ty,
11954 offset,
11955 1,
11956 )?;
11957 self.trap_if_misaligned(memarg, effective_address, 1)?;
11958 let narrow_value = err!(self.builder.build_int_truncate(
11959 value,
11960 self.intrinsics.i8_ty,
11961 ""
11962 ));
11963 let old = self
11964 .builder
11965 .build_atomicrmw(
11966 AtomicRMWBinOp::Or,
11967 effective_address,
11968 narrow_value,
11969 AtomicOrdering::SequentiallyConsistent,
11970 )
11971 .unwrap();
11972 self.annotate_user_memaccess(
11973 memory_index,
11974 memarg,
11975 0,
11976 old.as_instruction_value().unwrap(),
11977 )?;
11978 let old = err!(
11979 self.builder
11980 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11981 );
11982 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11983 }
11984 Operator::I64AtomicRmw16OrU { ref memarg } => {
11985 let value = self.state.pop1()?.into_int_value();
11986 let offset = self.state.pop1()?.into_int_value();
11987 let memory_index = MemoryIndex::from_u32(0);
11988 let effective_address = self.resolve_memory_ptr(
11989 memory_index,
11990 memarg,
11991 self.intrinsics.ptr_ty,
11992 offset,
11993 2,
11994 )?;
11995 self.trap_if_misaligned(memarg, effective_address, 2)?;
11996 let narrow_value = err!(self.builder.build_int_truncate(
11997 value,
11998 self.intrinsics.i16_ty,
11999 ""
12000 ));
12001 let old = self
12002 .builder
12003 .build_atomicrmw(
12004 AtomicRMWBinOp::Or,
12005 effective_address,
12006 narrow_value,
12007 AtomicOrdering::SequentiallyConsistent,
12008 )
12009 .unwrap();
12010 self.annotate_user_memaccess(
12011 memory_index,
12012 memarg,
12013 0,
12014 old.as_instruction_value().unwrap(),
12015 )?;
12016 let old = err!(
12017 self.builder
12018 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12019 );
12020 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12021 }
12022 Operator::I64AtomicRmw32OrU { ref memarg } => {
12023 let value = self.state.pop1()?.into_int_value();
12024 let offset = self.state.pop1()?.into_int_value();
12025 let memory_index = MemoryIndex::from_u32(0);
12026 let effective_address = self.resolve_memory_ptr(
12027 memory_index,
12028 memarg,
12029 self.intrinsics.ptr_ty,
12030 offset,
12031 4,
12032 )?;
12033 self.trap_if_misaligned(memarg, effective_address, 4)?;
12034 let narrow_value = err!(self.builder.build_int_truncate(
12035 value,
12036 self.intrinsics.i32_ty,
12037 ""
12038 ));
12039 let old = self
12040 .builder
12041 .build_atomicrmw(
12042 AtomicRMWBinOp::Or,
12043 effective_address,
12044 narrow_value,
12045 AtomicOrdering::SequentiallyConsistent,
12046 )
12047 .unwrap();
12048 self.annotate_user_memaccess(
12049 memory_index,
12050 memarg,
12051 0,
12052 old.as_instruction_value().unwrap(),
12053 )?;
12054 let old = err!(
12055 self.builder
12056 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12057 );
12058 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12059 }
12060 Operator::I64AtomicRmwOr { ref memarg } => {
12061 let value = self.state.pop1()?.into_int_value();
12062 let offset = self.state.pop1()?.into_int_value();
12063 let memory_index = MemoryIndex::from_u32(0);
12064 let effective_address = self.resolve_memory_ptr(
12065 memory_index,
12066 memarg,
12067 self.intrinsics.ptr_ty,
12068 offset,
12069 8,
12070 )?;
12071 self.trap_if_misaligned(memarg, effective_address, 8)?;
12072 let old = self
12073 .builder
12074 .build_atomicrmw(
12075 AtomicRMWBinOp::Or,
12076 effective_address,
12077 value,
12078 AtomicOrdering::SequentiallyConsistent,
12079 )
12080 .unwrap();
12081 self.annotate_user_memaccess(
12082 memory_index,
12083 memarg,
12084 0,
12085 old.as_instruction_value().unwrap(),
12086 )?;
12087 self.state.push1(old);
12088 }
12089 Operator::I32AtomicRmw8XorU { ref memarg } => {
12090 let value = self.state.pop1()?.into_int_value();
12091 let offset = self.state.pop1()?.into_int_value();
12092 let memory_index = MemoryIndex::from_u32(0);
12093 let effective_address = self.resolve_memory_ptr(
12094 memory_index,
12095 memarg,
12096 self.intrinsics.ptr_ty,
12097 offset,
12098 1,
12099 )?;
12100 self.trap_if_misaligned(memarg, effective_address, 2)?;
12101 let narrow_value = err!(self.builder.build_int_truncate(
12102 value,
12103 self.intrinsics.i8_ty,
12104 ""
12105 ));
12106 let old = self
12107 .builder
12108 .build_atomicrmw(
12109 AtomicRMWBinOp::Xor,
12110 effective_address,
12111 narrow_value,
12112 AtomicOrdering::SequentiallyConsistent,
12113 )
12114 .unwrap();
12115 self.annotate_user_memaccess(
12116 memory_index,
12117 memarg,
12118 0,
12119 old.as_instruction_value().unwrap(),
12120 )?;
12121 let old = err!(
12122 self.builder
12123 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12124 );
12125 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12126 }
12127 Operator::I32AtomicRmw16XorU { ref memarg } => {
12128 let value = self.state.pop1()?.into_int_value();
12129 let offset = self.state.pop1()?.into_int_value();
12130 let memory_index = MemoryIndex::from_u32(0);
12131 let effective_address = self.resolve_memory_ptr(
12132 memory_index,
12133 memarg,
12134 self.intrinsics.ptr_ty,
12135 offset,
12136 2,
12137 )?;
12138 self.trap_if_misaligned(memarg, effective_address, 2)?;
12139 let narrow_value = err!(self.builder.build_int_truncate(
12140 value,
12141 self.intrinsics.i16_ty,
12142 ""
12143 ));
12144 let old = self
12145 .builder
12146 .build_atomicrmw(
12147 AtomicRMWBinOp::Xor,
12148 effective_address,
12149 narrow_value,
12150 AtomicOrdering::SequentiallyConsistent,
12151 )
12152 .unwrap();
12153 self.annotate_user_memaccess(
12154 memory_index,
12155 memarg,
12156 0,
12157 old.as_instruction_value().unwrap(),
12158 )?;
12159 let old = err!(
12160 self.builder
12161 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12162 );
12163 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12164 }
12165 Operator::I32AtomicRmwXor { ref memarg } => {
12166 let value = self.state.pop1()?.into_int_value();
12167 let offset = self.state.pop1()?.into_int_value();
12168 let memory_index = MemoryIndex::from_u32(0);
12169 let effective_address = self.resolve_memory_ptr(
12170 memory_index,
12171 memarg,
12172 self.intrinsics.ptr_ty,
12173 offset,
12174 4,
12175 )?;
12176 self.trap_if_misaligned(memarg, effective_address, 4)?;
12177 let old = self
12178 .builder
12179 .build_atomicrmw(
12180 AtomicRMWBinOp::Xor,
12181 effective_address,
12182 value,
12183 AtomicOrdering::SequentiallyConsistent,
12184 )
12185 .unwrap();
12186 self.annotate_user_memaccess(
12187 memory_index,
12188 memarg,
12189 0,
12190 old.as_instruction_value().unwrap(),
12191 )?;
12192 self.state.push1(old);
12193 }
12194 Operator::I64AtomicRmw8XorU { ref memarg } => {
12195 let value = self.state.pop1()?.into_int_value();
12196 let offset = self.state.pop1()?.into_int_value();
12197 let memory_index = MemoryIndex::from_u32(0);
12198 let effective_address = self.resolve_memory_ptr(
12199 memory_index,
12200 memarg,
12201 self.intrinsics.ptr_ty,
12202 offset,
12203 1,
12204 )?;
12205 self.trap_if_misaligned(memarg, effective_address, 1)?;
12206 let narrow_value = err!(self.builder.build_int_truncate(
12207 value,
12208 self.intrinsics.i8_ty,
12209 ""
12210 ));
12211 let old = self
12212 .builder
12213 .build_atomicrmw(
12214 AtomicRMWBinOp::Xor,
12215 effective_address,
12216 narrow_value,
12217 AtomicOrdering::SequentiallyConsistent,
12218 )
12219 .unwrap();
12220 self.annotate_user_memaccess(
12221 memory_index,
12222 memarg,
12223 0,
12224 old.as_instruction_value().unwrap(),
12225 )?;
12226 let old = err!(
12227 self.builder
12228 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12229 );
12230 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12231 }
12232 Operator::I64AtomicRmw16XorU { ref memarg } => {
12233 let value = self.state.pop1()?.into_int_value();
12234 let offset = self.state.pop1()?.into_int_value();
12235 let memory_index = MemoryIndex::from_u32(0);
12236 let effective_address = self.resolve_memory_ptr(
12237 memory_index,
12238 memarg,
12239 self.intrinsics.ptr_ty,
12240 offset,
12241 2,
12242 )?;
12243 self.trap_if_misaligned(memarg, effective_address, 2)?;
12244 let narrow_value = err!(self.builder.build_int_truncate(
12245 value,
12246 self.intrinsics.i16_ty,
12247 ""
12248 ));
12249 let old = self
12250 .builder
12251 .build_atomicrmw(
12252 AtomicRMWBinOp::Xor,
12253 effective_address,
12254 narrow_value,
12255 AtomicOrdering::SequentiallyConsistent,
12256 )
12257 .unwrap();
12258 self.annotate_user_memaccess(
12259 memory_index,
12260 memarg,
12261 0,
12262 old.as_instruction_value().unwrap(),
12263 )?;
12264 let old = err!(
12265 self.builder
12266 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12267 );
12268 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12269 }
12270 Operator::I64AtomicRmw32XorU { ref memarg } => {
12271 let value = self.state.pop1()?.into_int_value();
12272 let offset = self.state.pop1()?.into_int_value();
12273 let memory_index = MemoryIndex::from_u32(0);
12274 let effective_address = self.resolve_memory_ptr(
12275 memory_index,
12276 memarg,
12277 self.intrinsics.ptr_ty,
12278 offset,
12279 4,
12280 )?;
12281 self.trap_if_misaligned(memarg, effective_address, 4)?;
12282 let narrow_value = err!(self.builder.build_int_truncate(
12283 value,
12284 self.intrinsics.i32_ty,
12285 ""
12286 ));
12287 let old = self
12288 .builder
12289 .build_atomicrmw(
12290 AtomicRMWBinOp::Xor,
12291 effective_address,
12292 narrow_value,
12293 AtomicOrdering::SequentiallyConsistent,
12294 )
12295 .unwrap();
12296 self.annotate_user_memaccess(
12297 memory_index,
12298 memarg,
12299 0,
12300 old.as_instruction_value().unwrap(),
12301 )?;
12302 let old = err!(
12303 self.builder
12304 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12305 );
12306 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12307 }
12308 Operator::I64AtomicRmwXor { ref memarg } => {
12309 let value = self.state.pop1()?.into_int_value();
12310 let offset = self.state.pop1()?.into_int_value();
12311 let memory_index = MemoryIndex::from_u32(0);
12312 let effective_address = self.resolve_memory_ptr(
12313 memory_index,
12314 memarg,
12315 self.intrinsics.ptr_ty,
12316 offset,
12317 8,
12318 )?;
12319 self.trap_if_misaligned(memarg, effective_address, 8)?;
12320 let old = self
12321 .builder
12322 .build_atomicrmw(
12323 AtomicRMWBinOp::Xor,
12324 effective_address,
12325 value,
12326 AtomicOrdering::SequentiallyConsistent,
12327 )
12328 .unwrap();
12329 self.annotate_user_memaccess(
12330 memory_index,
12331 memarg,
12332 0,
12333 old.as_instruction_value().unwrap(),
12334 )?;
12335 self.state.push1(old);
12336 }
12337 Operator::I32AtomicRmw8XchgU { ref memarg } => {
12338 let value = self.state.pop1()?.into_int_value();
12339 let offset = self.state.pop1()?.into_int_value();
12340 let memory_index = MemoryIndex::from_u32(0);
12341 let effective_address = self.resolve_memory_ptr(
12342 memory_index,
12343 memarg,
12344 self.intrinsics.ptr_ty,
12345 offset,
12346 1,
12347 )?;
12348 self.trap_if_misaligned(memarg, effective_address, 1)?;
12349 let narrow_value = err!(self.builder.build_int_truncate(
12350 value,
12351 self.intrinsics.i8_ty,
12352 ""
12353 ));
12354 let old = self
12355 .builder
12356 .build_atomicrmw(
12357 AtomicRMWBinOp::Xchg,
12358 effective_address,
12359 narrow_value,
12360 AtomicOrdering::SequentiallyConsistent,
12361 )
12362 .unwrap();
12363 self.annotate_user_memaccess(
12364 memory_index,
12365 memarg,
12366 0,
12367 old.as_instruction_value().unwrap(),
12368 )?;
12369 let old = err!(
12370 self.builder
12371 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12372 );
12373 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12374 }
12375 Operator::I32AtomicRmw16XchgU { ref memarg } => {
12376 let value = self.state.pop1()?.into_int_value();
12377 let offset = self.state.pop1()?.into_int_value();
12378 let memory_index = MemoryIndex::from_u32(0);
12379 let effective_address = self.resolve_memory_ptr(
12380 memory_index,
12381 memarg,
12382 self.intrinsics.ptr_ty,
12383 offset,
12384 2,
12385 )?;
12386 self.trap_if_misaligned(memarg, effective_address, 2)?;
12387 let narrow_value = err!(self.builder.build_int_truncate(
12388 value,
12389 self.intrinsics.i16_ty,
12390 ""
12391 ));
12392 let old = self
12393 .builder
12394 .build_atomicrmw(
12395 AtomicRMWBinOp::Xchg,
12396 effective_address,
12397 narrow_value,
12398 AtomicOrdering::SequentiallyConsistent,
12399 )
12400 .unwrap();
12401 self.annotate_user_memaccess(
12402 memory_index,
12403 memarg,
12404 0,
12405 old.as_instruction_value().unwrap(),
12406 )?;
12407 let old = err!(
12408 self.builder
12409 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12410 );
12411 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12412 }
12413 Operator::I32AtomicRmwXchg { ref memarg } => {
12414 let value = self.state.pop1()?.into_int_value();
12415 let offset = self.state.pop1()?.into_int_value();
12416 let memory_index = MemoryIndex::from_u32(0);
12417 let effective_address = self.resolve_memory_ptr(
12418 memory_index,
12419 memarg,
12420 self.intrinsics.ptr_ty,
12421 offset,
12422 4,
12423 )?;
12424 self.trap_if_misaligned(memarg, effective_address, 4)?;
12425 let old = self
12426 .builder
12427 .build_atomicrmw(
12428 AtomicRMWBinOp::Xchg,
12429 effective_address,
12430 value,
12431 AtomicOrdering::SequentiallyConsistent,
12432 )
12433 .unwrap();
12434 self.annotate_user_memaccess(
12435 memory_index,
12436 memarg,
12437 0,
12438 old.as_instruction_value().unwrap(),
12439 )?;
12440 self.state.push1(old);
12441 }
12442 Operator::I64AtomicRmw8XchgU { ref memarg } => {
12443 let value = self.state.pop1()?.into_int_value();
12444 let offset = self.state.pop1()?.into_int_value();
12445 let memory_index = MemoryIndex::from_u32(0);
12446 let effective_address = self.resolve_memory_ptr(
12447 memory_index,
12448 memarg,
12449 self.intrinsics.ptr_ty,
12450 offset,
12451 1,
12452 )?;
12453 self.trap_if_misaligned(memarg, effective_address, 1)?;
12454 let narrow_value = err!(self.builder.build_int_truncate(
12455 value,
12456 self.intrinsics.i8_ty,
12457 ""
12458 ));
12459 let old = self
12460 .builder
12461 .build_atomicrmw(
12462 AtomicRMWBinOp::Xchg,
12463 effective_address,
12464 narrow_value,
12465 AtomicOrdering::SequentiallyConsistent,
12466 )
12467 .unwrap();
12468 self.annotate_user_memaccess(
12469 memory_index,
12470 memarg,
12471 0,
12472 old.as_instruction_value().unwrap(),
12473 )?;
12474 let old = err!(
12475 self.builder
12476 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12477 );
12478 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12479 }
12480 Operator::I64AtomicRmw16XchgU { ref memarg } => {
12481 let value = self.state.pop1()?.into_int_value();
12482 let offset = self.state.pop1()?.into_int_value();
12483 let memory_index = MemoryIndex::from_u32(0);
12484 let effective_address = self.resolve_memory_ptr(
12485 memory_index,
12486 memarg,
12487 self.intrinsics.ptr_ty,
12488 offset,
12489 2,
12490 )?;
12491 self.trap_if_misaligned(memarg, effective_address, 2)?;
12492 let narrow_value = err!(self.builder.build_int_truncate(
12493 value,
12494 self.intrinsics.i16_ty,
12495 ""
12496 ));
12497 let old = self
12498 .builder
12499 .build_atomicrmw(
12500 AtomicRMWBinOp::Xchg,
12501 effective_address,
12502 narrow_value,
12503 AtomicOrdering::SequentiallyConsistent,
12504 )
12505 .unwrap();
12506 self.annotate_user_memaccess(
12507 memory_index,
12508 memarg,
12509 0,
12510 old.as_instruction_value().unwrap(),
12511 )?;
12512 let old = err!(
12513 self.builder
12514 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12515 );
12516 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12517 }
12518 Operator::I64AtomicRmw32XchgU { ref memarg } => {
12519 let value = self.state.pop1()?.into_int_value();
12520 let offset = self.state.pop1()?.into_int_value();
12521 let memory_index = MemoryIndex::from_u32(0);
12522 let effective_address = self.resolve_memory_ptr(
12523 memory_index,
12524 memarg,
12525 self.intrinsics.ptr_ty,
12526 offset,
12527 4,
12528 )?;
12529 self.trap_if_misaligned(memarg, effective_address, 4)?;
12530 let narrow_value = err!(self.builder.build_int_truncate(
12531 value,
12532 self.intrinsics.i32_ty,
12533 ""
12534 ));
12535 let old = self
12536 .builder
12537 .build_atomicrmw(
12538 AtomicRMWBinOp::Xchg,
12539 effective_address,
12540 narrow_value,
12541 AtomicOrdering::SequentiallyConsistent,
12542 )
12543 .unwrap();
12544 self.annotate_user_memaccess(
12545 memory_index,
12546 memarg,
12547 0,
12548 old.as_instruction_value().unwrap(),
12549 )?;
12550 let old = err!(
12551 self.builder
12552 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12553 );
12554 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12555 }
12556 Operator::I64AtomicRmwXchg { ref memarg } => {
12557 let value = self.state.pop1()?.into_int_value();
12558 let offset = self.state.pop1()?.into_int_value();
12559 let memory_index = MemoryIndex::from_u32(0);
12560 let effective_address = self.resolve_memory_ptr(
12561 memory_index,
12562 memarg,
12563 self.intrinsics.ptr_ty,
12564 offset,
12565 8,
12566 )?;
12567 self.trap_if_misaligned(memarg, effective_address, 8)?;
12568 let old = self
12569 .builder
12570 .build_atomicrmw(
12571 AtomicRMWBinOp::Xchg,
12572 effective_address,
12573 value,
12574 AtomicOrdering::SequentiallyConsistent,
12575 )
12576 .unwrap();
12577 self.annotate_user_memaccess(
12578 memory_index,
12579 memarg,
12580 0,
12581 old.as_instruction_value().unwrap(),
12582 )?;
12583 self.state.push1(old);
12584 }
12585 Operator::I32AtomicRmw8CmpxchgU { ref memarg } => {
12586 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12587 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12588 let new = self.apply_pending_canonicalization(new, new_info)?;
12589 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12590 let offset = self.state.pop1()?.into_int_value();
12591 let memory_index = MemoryIndex::from_u32(0);
12592 let effective_address = self.resolve_memory_ptr(
12593 memory_index,
12594 memarg,
12595 self.intrinsics.ptr_ty,
12596 offset,
12597 1,
12598 )?;
12599 self.trap_if_misaligned(memarg, effective_address, 1)?;
12600 let narrow_cmp = err!(self.builder.build_int_truncate(
12601 cmp,
12602 self.intrinsics.i8_ty,
12603 ""
12604 ));
12605 let narrow_new = err!(self.builder.build_int_truncate(
12606 new,
12607 self.intrinsics.i8_ty,
12608 ""
12609 ));
12610 let old = self
12611 .builder
12612 .build_cmpxchg(
12613 effective_address,
12614 narrow_cmp,
12615 narrow_new,
12616 AtomicOrdering::SequentiallyConsistent,
12617 AtomicOrdering::SequentiallyConsistent,
12618 )
12619 .unwrap();
12620 self.annotate_user_memaccess(
12621 memory_index,
12622 memarg,
12623 0,
12624 old.as_instruction_value().unwrap(),
12625 )?;
12626 let old = self
12627 .builder
12628 .build_extract_value(old, 0, "")
12629 .unwrap()
12630 .into_int_value();
12631 let old = err!(
12632 self.builder
12633 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12634 );
12635 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12636 }
12637 Operator::I32AtomicRmw16CmpxchgU { ref memarg } => {
12638 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12639 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12640 let new = self.apply_pending_canonicalization(new, new_info)?;
12641 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12642 let offset = self.state.pop1()?.into_int_value();
12643 let memory_index = MemoryIndex::from_u32(0);
12644 let effective_address = self.resolve_memory_ptr(
12645 memory_index,
12646 memarg,
12647 self.intrinsics.ptr_ty,
12648 offset,
12649 2,
12650 )?;
12651 self.trap_if_misaligned(memarg, effective_address, 2)?;
12652 let narrow_cmp = err!(self.builder.build_int_truncate(
12653 cmp,
12654 self.intrinsics.i16_ty,
12655 ""
12656 ));
12657 let narrow_new = err!(self.builder.build_int_truncate(
12658 new,
12659 self.intrinsics.i16_ty,
12660 ""
12661 ));
12662 let old = self
12663 .builder
12664 .build_cmpxchg(
12665 effective_address,
12666 narrow_cmp,
12667 narrow_new,
12668 AtomicOrdering::SequentiallyConsistent,
12669 AtomicOrdering::SequentiallyConsistent,
12670 )
12671 .unwrap();
12672 self.annotate_user_memaccess(
12673 memory_index,
12674 memarg,
12675 0,
12676 old.as_instruction_value().unwrap(),
12677 )?;
12678 let old = self
12679 .builder
12680 .build_extract_value(old, 0, "")
12681 .unwrap()
12682 .into_int_value();
12683 let old = err!(
12684 self.builder
12685 .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12686 );
12687 self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12688 }
12689 Operator::I32AtomicRmwCmpxchg { ref memarg } => {
12690 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12691 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12692 let new = self.apply_pending_canonicalization(new, new_info)?;
12693 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12694 let offset = self.state.pop1()?.into_int_value();
12695 let memory_index = MemoryIndex::from_u32(0);
12696 let effective_address = self.resolve_memory_ptr(
12697 memory_index,
12698 memarg,
12699 self.intrinsics.ptr_ty,
12700 offset,
12701 4,
12702 )?;
12703 self.trap_if_misaligned(memarg, effective_address, 4)?;
12704 let old = self
12705 .builder
12706 .build_cmpxchg(
12707 effective_address,
12708 cmp,
12709 new,
12710 AtomicOrdering::SequentiallyConsistent,
12711 AtomicOrdering::SequentiallyConsistent,
12712 )
12713 .unwrap();
12714 self.annotate_user_memaccess(
12715 memory_index,
12716 memarg,
12717 0,
12718 old.as_instruction_value().unwrap(),
12719 )?;
12720 let old = err!(self.builder.build_extract_value(old, 0, ""));
12721 self.state.push1(old);
12722 }
12723 Operator::I64AtomicRmw8CmpxchgU { ref memarg } => {
12724 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12725 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12726 let new = self.apply_pending_canonicalization(new, new_info)?;
12727 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12728 let offset = self.state.pop1()?.into_int_value();
12729 let memory_index = MemoryIndex::from_u32(0);
12730 let effective_address = self.resolve_memory_ptr(
12731 memory_index,
12732 memarg,
12733 self.intrinsics.ptr_ty,
12734 offset,
12735 1,
12736 )?;
12737 self.trap_if_misaligned(memarg, effective_address, 1)?;
12738 let narrow_cmp = err!(self.builder.build_int_truncate(
12739 cmp,
12740 self.intrinsics.i8_ty,
12741 ""
12742 ));
12743 let narrow_new = err!(self.builder.build_int_truncate(
12744 new,
12745 self.intrinsics.i8_ty,
12746 ""
12747 ));
12748 let old = self
12749 .builder
12750 .build_cmpxchg(
12751 effective_address,
12752 narrow_cmp,
12753 narrow_new,
12754 AtomicOrdering::SequentiallyConsistent,
12755 AtomicOrdering::SequentiallyConsistent,
12756 )
12757 .unwrap();
12758 self.annotate_user_memaccess(
12759 memory_index,
12760 memarg,
12761 0,
12762 old.as_instruction_value().unwrap(),
12763 )?;
12764 let old = self
12765 .builder
12766 .build_extract_value(old, 0, "")
12767 .unwrap()
12768 .into_int_value();
12769 let old = err!(
12770 self.builder
12771 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12772 );
12773 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12774 }
12775 Operator::I64AtomicRmw16CmpxchgU { ref memarg } => {
12776 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12777 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12778 let new = self.apply_pending_canonicalization(new, new_info)?;
12779 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12780 let offset = self.state.pop1()?.into_int_value();
12781 let memory_index = MemoryIndex::from_u32(0);
12782 let effective_address = self.resolve_memory_ptr(
12783 memory_index,
12784 memarg,
12785 self.intrinsics.ptr_ty,
12786 offset,
12787 2,
12788 )?;
12789 self.trap_if_misaligned(memarg, effective_address, 2)?;
12790 let narrow_cmp = err!(self.builder.build_int_truncate(
12791 cmp,
12792 self.intrinsics.i16_ty,
12793 ""
12794 ));
12795 let narrow_new = err!(self.builder.build_int_truncate(
12796 new,
12797 self.intrinsics.i16_ty,
12798 ""
12799 ));
12800 let old = self
12801 .builder
12802 .build_cmpxchg(
12803 effective_address,
12804 narrow_cmp,
12805 narrow_new,
12806 AtomicOrdering::SequentiallyConsistent,
12807 AtomicOrdering::SequentiallyConsistent,
12808 )
12809 .unwrap();
12810 self.annotate_user_memaccess(
12811 memory_index,
12812 memarg,
12813 0,
12814 old.as_instruction_value().unwrap(),
12815 )?;
12816 let old = self
12817 .builder
12818 .build_extract_value(old, 0, "")
12819 .unwrap()
12820 .into_int_value();
12821 let old = err!(
12822 self.builder
12823 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12824 );
12825 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12826 }
12827 Operator::I64AtomicRmw32CmpxchgU { ref memarg } => {
12828 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12829 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12830 let new = self.apply_pending_canonicalization(new, new_info)?;
12831 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12832 let offset = self.state.pop1()?.into_int_value();
12833 let memory_index = MemoryIndex::from_u32(0);
12834 let effective_address = self.resolve_memory_ptr(
12835 memory_index,
12836 memarg,
12837 self.intrinsics.ptr_ty,
12838 offset,
12839 4,
12840 )?;
12841 self.trap_if_misaligned(memarg, effective_address, 4)?;
12842 let narrow_cmp = err!(self.builder.build_int_truncate(
12843 cmp,
12844 self.intrinsics.i32_ty,
12845 ""
12846 ));
12847 let narrow_new = err!(self.builder.build_int_truncate(
12848 new,
12849 self.intrinsics.i32_ty,
12850 ""
12851 ));
12852 let old = self
12853 .builder
12854 .build_cmpxchg(
12855 effective_address,
12856 narrow_cmp,
12857 narrow_new,
12858 AtomicOrdering::SequentiallyConsistent,
12859 AtomicOrdering::SequentiallyConsistent,
12860 )
12861 .unwrap();
12862 self.annotate_user_memaccess(
12863 memory_index,
12864 memarg,
12865 0,
12866 old.as_instruction_value().unwrap(),
12867 )?;
12868 let old = self
12869 .builder
12870 .build_extract_value(old, 0, "")
12871 .unwrap()
12872 .into_int_value();
12873 let old = err!(
12874 self.builder
12875 .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12876 );
12877 self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12878 }
12879 Operator::I64AtomicRmwCmpxchg { ref memarg } => {
12880 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12881 let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12882 let new = self.apply_pending_canonicalization(new, new_info)?;
12883 let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12884 let offset = self.state.pop1()?.into_int_value();
12885 let memory_index = MemoryIndex::from_u32(0);
12886 let effective_address = self.resolve_memory_ptr(
12887 memory_index,
12888 memarg,
12889 self.intrinsics.ptr_ty,
12890 offset,
12891 8,
12892 )?;
12893 self.trap_if_misaligned(memarg, effective_address, 8)?;
12894 let old = self
12895 .builder
12896 .build_cmpxchg(
12897 effective_address,
12898 cmp,
12899 new,
12900 AtomicOrdering::SequentiallyConsistent,
12901 AtomicOrdering::SequentiallyConsistent,
12902 )
12903 .unwrap();
12904 self.annotate_user_memaccess(
12905 memory_index,
12906 memarg,
12907 0,
12908 old.as_instruction_value().unwrap(),
12909 )?;
12910 let old = err!(self.builder.build_extract_value(old, 0, ""));
12911 self.state.push1(old);
12912 }
12913
12914 Operator::MemoryGrow { mem } => {
12915 let memory_index = MemoryIndex::from_u32(mem);
12916 let delta = self.state.pop1()?;
12917 let grow_fn_ptr = self.ctx.memory_grow(memory_index, self.intrinsics)?;
12918 let grow = err!(self.builder.build_indirect_call(
12919 self.intrinsics.memory_grow_ty,
12920 grow_fn_ptr,
12921 &[
12922 vmctx.as_basic_value_enum().into(),
12923 delta.into(),
12924 self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
12925 ],
12926 "",
12927 ));
12928 self.state.push1(grow.try_as_basic_value().unwrap_basic());
12929 }
12930 Operator::MemorySize { mem } => {
12931 let memory_index = MemoryIndex::from_u32(mem);
12932 let size_fn_ptr = self.ctx.memory_size(memory_index, self.intrinsics)?;
12933 let size = err!(self.builder.build_indirect_call(
12934 self.intrinsics.memory_size_ty,
12935 size_fn_ptr,
12936 &[
12937 vmctx.as_basic_value_enum().into(),
12938 self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
12939 ],
12940 "",
12941 ));
12942 self.state.push1(size.try_as_basic_value().unwrap_basic());
12944 }
12945 Operator::MemoryInit { data_index, mem } => {
12946 let (dest, src, len) = self.state.pop3()?;
12947 let mem = self.intrinsics.i32_ty.const_int(mem.into(), false);
12948 let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
12949 self.build_call_with_param_attributes(
12950 self.intrinsics.memory_init,
12951 &[
12952 vmctx.as_basic_value_enum().into(),
12953 mem.into(),
12954 segment.into(),
12955 dest.into(),
12956 src.into(),
12957 len.into(),
12958 ],
12959 "",
12960 )?;
12961 }
12962 Operator::DataDrop { data_index } => {
12963 let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
12964 self.build_call_with_param_attributes(
12965 self.intrinsics.data_drop,
12966 &[vmctx.as_basic_value_enum().into(), segment.into()],
12967 "",
12968 )?;
12969 }
12970 Operator::MemoryCopy { dst_mem, src_mem } => {
12971 let _dst = dst_mem;
12973 let (memory_copy, src) = if let Some(local_memory_index) = self
12974 .wasm_module
12975 .local_memory_index(MemoryIndex::from_u32(src_mem))
12976 {
12977 (self.intrinsics.memory_copy, local_memory_index.as_u32())
12978 } else {
12979 (self.intrinsics.imported_memory_copy, src_mem)
12980 };
12981
12982 let (dest_pos, src_pos, len) = self.state.pop3()?;
12983 let src_index = self.intrinsics.i32_ty.const_int(src.into(), false);
12984 self.build_call_with_param_attributes(
12985 memory_copy,
12986 &[
12987 vmctx.as_basic_value_enum().into(),
12988 src_index.into(),
12989 dest_pos.into(),
12990 src_pos.into(),
12991 len.into(),
12992 ],
12993 "",
12994 )?;
12995 }
12996 Operator::MemoryFill { mem } => {
12997 let (memory_fill, mem) = if let Some(local_memory_index) = self
12998 .wasm_module
12999 .local_memory_index(MemoryIndex::from_u32(mem))
13000 {
13001 (self.intrinsics.memory_fill, local_memory_index.as_u32())
13002 } else {
13003 (self.intrinsics.imported_memory_fill, mem)
13004 };
13005
13006 let (dst, val, len) = self.state.pop3()?;
13007 let mem_index = self.intrinsics.i32_ty.const_int(mem.into(), false);
13008 self.build_call_with_param_attributes(
13009 memory_fill,
13010 &[
13011 vmctx.as_basic_value_enum().into(),
13012 mem_index.into(),
13013 dst.into(),
13014 val.into(),
13015 len.into(),
13016 ],
13017 "",
13018 )?;
13019 }
13020 Operator::RefNull { hty } => {
13025 let ty = err!(wpheaptype_to_type(hty));
13026 let ty = type_to_llvm(self.intrinsics, ty)?;
13027 self.state.push1(ty.const_zero());
13028 }
13029 Operator::RefIsNull => {
13030 let value = self.state.pop1()?.into_pointer_value();
13031 let is_null = err!(self.builder.build_is_null(value, ""));
13032 let is_null = err!(self.builder.build_int_z_extend(
13033 is_null,
13034 self.intrinsics.i32_ty,
13035 ""
13036 ));
13037 self.state.push1(is_null);
13038 }
13039 Operator::RefFunc { function_index } => {
13040 let index = self
13041 .intrinsics
13042 .i32_ty
13043 .const_int(function_index.into(), false);
13044 let value = self
13045 .build_call_with_param_attributes(
13046 self.intrinsics.func_ref,
13047 &[self.ctx.basic().into(), index.into()],
13048 "",
13049 )?
13050 .try_as_basic_value()
13051 .unwrap_basic();
13052 self.state.push1(value);
13053 }
13054 Operator::TableGet { table } => {
13055 let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
13056 let elem = self.state.pop1()?;
13057 let table_get = if self
13058 .wasm_module
13059 .local_table_index(TableIndex::from_u32(table))
13060 .is_some()
13061 {
13062 self.intrinsics.table_get
13063 } else {
13064 self.intrinsics.imported_table_get
13065 };
13066 let value = self
13067 .build_call_with_param_attributes(
13068 table_get,
13069 &[self.ctx.basic().into(), table_index.into(), elem.into()],
13070 "",
13071 )?
13072 .try_as_basic_value()
13073 .unwrap_basic();
13074 let value = err!(
13075 self.builder.build_bit_cast(
13076 value,
13077 type_to_llvm(
13078 self.intrinsics,
13079 self.wasm_module
13080 .tables
13081 .get(TableIndex::from_u32(table))
13082 .unwrap()
13083 .ty,
13084 )?,
13085 "",
13086 )
13087 );
13088 self.state.push1(value);
13089 }
13090 Operator::TableSet { table } => {
13091 let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
13092 let (elem, value) = self.state.pop2()?;
13093 let value = err!(
13094 self.builder
13095 .build_bit_cast(value, self.intrinsics.ptr_ty, "")
13096 );
13097 let table_set = if self
13098 .wasm_module
13099 .local_table_index(TableIndex::from_u32(table))
13100 .is_some()
13101 {
13102 self.intrinsics.table_set
13103 } else {
13104 self.intrinsics.imported_table_set
13105 };
13106 self.build_call_with_param_attributes(
13107 table_set,
13108 &[
13109 self.ctx.basic().into(),
13110 table_index.into(),
13111 elem.into(),
13112 value.into(),
13113 ],
13114 "",
13115 )?;
13116 }
13117 Operator::TableCopy {
13118 dst_table,
13119 src_table,
13120 } => {
13121 let (dst, src, len) = self.state.pop3()?;
13122 let dst_table = self.intrinsics.i32_ty.const_int(dst_table as u64, false);
13123 let src_table = self.intrinsics.i32_ty.const_int(src_table as u64, false);
13124 self.build_call_with_param_attributes(
13125 self.intrinsics.table_copy,
13126 &[
13127 self.ctx.basic().into(),
13128 dst_table.into(),
13129 src_table.into(),
13130 dst.into(),
13131 src.into(),
13132 len.into(),
13133 ],
13134 "",
13135 )?;
13136 }
13137 Operator::TableInit { elem_index, table } => {
13138 let (dst, src, len) = self.state.pop3()?;
13139 let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
13140 let table = self.intrinsics.i32_ty.const_int(table as u64, false);
13141 self.build_call_with_param_attributes(
13142 self.intrinsics.table_init,
13143 &[
13144 self.ctx.basic().into(),
13145 table.into(),
13146 segment.into(),
13147 dst.into(),
13148 src.into(),
13149 len.into(),
13150 ],
13151 "",
13152 )?;
13153 }
13154 Operator::ElemDrop { elem_index } => {
13155 let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
13156 self.build_call_with_param_attributes(
13157 self.intrinsics.elem_drop,
13158 &[self.ctx.basic().into(), segment.into()],
13159 "",
13160 )?;
13161 }
13162 Operator::TableFill { table } => {
13163 let table = self.intrinsics.i32_ty.const_int(table as u64, false);
13164 let (start, elem, len) = self.state.pop3()?;
13165 let elem = err!(
13166 self.builder
13167 .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
13168 );
13169 self.build_call_with_param_attributes(
13170 self.intrinsics.table_fill,
13171 &[
13172 self.ctx.basic().into(),
13173 table.into(),
13174 start.into(),
13175 elem.into(),
13176 len.into(),
13177 ],
13178 "",
13179 )?;
13180 }
13181 Operator::TableGrow { table } => {
13182 let (elem, delta) = self.state.pop2()?;
13183 let elem = err!(
13184 self.builder
13185 .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
13186 );
13187 let (table_grow, table_index) = if let Some(local_table_index) = self
13188 .wasm_module
13189 .local_table_index(TableIndex::from_u32(table))
13190 {
13191 (self.intrinsics.table_grow, local_table_index.as_u32())
13192 } else {
13193 (self.intrinsics.imported_table_grow, table)
13194 };
13195 let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
13196 let size = self
13197 .build_call_with_param_attributes(
13198 table_grow,
13199 &[
13200 self.ctx.basic().into(),
13201 elem.into(),
13202 delta.into(),
13203 table_index.into(),
13204 ],
13205 "",
13206 )?
13207 .try_as_basic_value()
13208 .unwrap_basic();
13209 self.state.push1(size);
13210 }
13211 Operator::TableSize { table } => {
13212 let (table_size, table_index) = if let Some(local_table_index) = self
13213 .wasm_module
13214 .local_table_index(TableIndex::from_u32(table))
13215 {
13216 (self.intrinsics.table_size, local_table_index.as_u32())
13217 } else {
13218 (self.intrinsics.imported_table_size, table)
13219 };
13220 let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
13221 let size = self
13222 .build_call_with_param_attributes(
13223 table_size,
13224 &[self.ctx.basic().into(), table_index.into()],
13225 "",
13226 )?
13227 .try_as_basic_value()
13228 .unwrap_basic();
13229 self.state.push1(size);
13230 }
13231 Operator::MemoryAtomicWait32 { memarg } => {
13232 let memory_index = MemoryIndex::from_u32(memarg.memory);
13233 let (dst, val, timeout) = self.state.pop3()?;
13234 let wait32_fn_ptr = self.ctx.memory_wait32(memory_index, self.intrinsics)?;
13235 let ret = err!(
13236 self.builder.build_indirect_call(
13237 self.intrinsics.memory_wait32_ty,
13238 wait32_fn_ptr,
13239 &[
13240 vmctx.as_basic_value_enum().into(),
13241 self.intrinsics
13242 .i32_ty
13243 .const_int(memarg.memory as u64, false)
13244 .into(),
13245 dst.into(),
13246 val.into(),
13247 timeout.into(),
13248 ],
13249 "",
13250 )
13251 );
13252 self.state.push1(ret.try_as_basic_value().unwrap_basic());
13253 }
13254 Operator::MemoryAtomicWait64 { memarg } => {
13255 let memory_index = MemoryIndex::from_u32(memarg.memory);
13256 let (dst, val, timeout) = self.state.pop3()?;
13257 let wait64_fn_ptr = self.ctx.memory_wait64(memory_index, self.intrinsics)?;
13258 let ret = err!(
13259 self.builder.build_indirect_call(
13260 self.intrinsics.memory_wait64_ty,
13261 wait64_fn_ptr,
13262 &[
13263 vmctx.as_basic_value_enum().into(),
13264 self.intrinsics
13265 .i32_ty
13266 .const_int(memarg.memory as u64, false)
13267 .into(),
13268 dst.into(),
13269 val.into(),
13270 timeout.into(),
13271 ],
13272 "",
13273 )
13274 );
13275 self.state.push1(ret.try_as_basic_value().unwrap_basic());
13276 }
13277 Operator::MemoryAtomicNotify { memarg } => {
13278 let memory_index = MemoryIndex::from_u32(memarg.memory);
13279 let (dst, count) = self.state.pop2()?;
13280 let notify_fn_ptr = self.ctx.memory_notify(memory_index, self.intrinsics)?;
13281 let cnt = err!(
13282 self.builder.build_indirect_call(
13283 self.intrinsics.memory_notify_ty,
13284 notify_fn_ptr,
13285 &[
13286 vmctx.as_basic_value_enum().into(),
13287 self.intrinsics
13288 .i32_ty
13289 .const_int(memarg.memory as u64, false)
13290 .into(),
13291 dst.into(),
13292 count.into(),
13293 ],
13294 "",
13295 )
13296 );
13297 self.state.push1(cnt.try_as_basic_value().unwrap_basic());
13298 }
13299
13300 Operator::TryTable { try_table } => {
13301 let current_block = self
13302 .builder
13303 .get_insert_block()
13304 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
13305
13306 self.builder.position_at_end(current_block);
13307
13308 let end_block = self.context.append_basic_block(self.function, "try_end");
13309
13310 let end_phis = {
13311 self.builder.position_at_end(end_block);
13312
13313 let phis = self
13314 .module_translation
13315 .blocktype_params_results(&try_table.ty)?
13316 .1
13317 .iter()
13318 .map(|&wp_ty| {
13319 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
13320 type_to_llvm(self.intrinsics, wasm_ty)
13321 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
13322 })
13323 })
13324 .collect::<Result<_, _>>()?;
13325
13326 self.builder.position_at_end(current_block);
13327 phis
13328 };
13329
13330 let catches: Vec<_> = try_table
13334 .catches
13335 .into_iter()
13336 .unique_by(|v| match v {
13337 Catch::One { tag, .. } | Catch::OneRef { tag, .. } => *tag as i32,
13338 Catch::All { .. } | Catch::AllRef { .. } => CATCH_ALL_TAG_VALUE,
13339 })
13340 .collect();
13341
13342 let null = self.intrinsics.ptr_ty.const_zero();
13344
13345 let mut catch_tag_values = vec![];
13346 let mut lpad_clauses: Vec<BasicValueEnum<'ctx>> = catches
13347 .iter()
13348 .map(|catch| match catch {
13349 Catch::All { .. } | Catch::AllRef { .. } => {
13350 catch_tag_values.push(CATCH_ALL_TAG_VALUE as u32);
13351 Ok(null.into())
13352 }
13353 Catch::One { tag, .. } | Catch::OneRef { tag, .. } => {
13354 catch_tag_values.push(*tag);
13355 Ok(self.get_or_insert_tag_type_info_global(*tag as i32))
13356 }
13357 })
13358 .collect::<Result<Vec<BasicValueEnum<'ctx>>, CompileError>>()?;
13359
13360 let mut outer_catch_blocks = vec![];
13364 for outer_landingpad in self.state.landingpads.iter().rev() {
13365 for catch_info @ TagCatchInfo { tag, .. } in &outer_landingpad.tags {
13366 if !catch_tag_values.contains(tag) {
13367 catch_tag_values.push(*tag);
13368 lpad_clauses.push(if *tag as i32 == CATCH_ALL_TAG_VALUE {
13369 null.into()
13370 } else {
13371 *self.tags_cache.get(&(*tag as i32)).expect(
13372 "If a previous try_table encountered a tag, \
13373 it should be in the cache",
13374 )
13375 });
13376 outer_catch_blocks.push(*catch_info);
13377 }
13378 }
13379 }
13380
13381 let mut maybe_lpad_block = None;
13385 let mut catch_blocks = vec![];
13386 if !lpad_clauses.is_empty() {
13387 let lpad_block = self.context.append_basic_block(self.function, "catch");
13388 let catch_all_block =
13389 self.context.append_basic_block(self.function, "catch_all");
13390 let catch_specific_block = self
13391 .context
13392 .append_basic_block(self.function, "catch_specific");
13393 let catch_end_block =
13394 self.context.append_basic_block(self.function, "catch_end");
13395 let rethrow_block = self.context.append_basic_block(self.function, "rethrow");
13396
13397 self.builder.position_at_end(lpad_block);
13398
13399 let res = err!(self.builder.build_landing_pad(
13400 self.intrinsics.lpad_exception_ty,
13401 self.intrinsics.personality,
13402 &lpad_clauses,
13403 false,
13404 "exc_struct",
13405 ));
13406
13407 let res = res.into_struct_value();
13408
13409 let uw_exc = err!(self.builder.build_extract_value(res, 0, "exc_ptr"));
13410 let pre_selector =
13411 err!(self.builder.build_extract_value(res, 1, "pre_selector"));
13412
13413 let pre_selector_is_zero = err!(self.builder.build_int_compare(
13416 IntPredicate::EQ,
13417 pre_selector.into_int_value(),
13418 self.intrinsics.i32_zero,
13419 "pre_selector_is_zero"
13420 ));
13421 err!(self.builder.build_conditional_branch(
13422 pre_selector_is_zero,
13423 catch_all_block,
13424 catch_specific_block
13425 ));
13426
13427 self.builder.position_at_end(catch_all_block);
13428 err!(self.builder.build_unconditional_branch(catch_end_block));
13429
13430 self.builder.position_at_end(catch_specific_block);
13431 let selector_value = self.build_call_with_param_attributes(
13432 self.intrinsics.personality2,
13433 &[self.ctx.basic().into(), uw_exc.into()],
13434 "selector",
13435 )?;
13436 err!(self.builder.build_unconditional_branch(catch_end_block));
13437
13438 self.builder.position_at_end(catch_end_block);
13439 let selector = err!(self.builder.build_phi(self.intrinsics.i32_ty, "selector"));
13440 selector.add_incoming(&[
13441 (
13442 &self
13443 .intrinsics
13444 .i32_ty
13445 .const_int(CATCH_ALL_TAG_VALUE as u64, false),
13446 catch_all_block,
13447 ),
13448 (
13449 &selector_value
13450 .try_as_basic_value()
13451 .unwrap_basic()
13452 .into_int_value(),
13453 catch_specific_block,
13454 ),
13455 ]);
13456
13457 let uw_exc = uw_exc.into_pointer_value();
13502 let exnref = self.build_call_with_param_attributes(
13503 self.intrinsics.exception_into_exnref,
13504 &[uw_exc.into()],
13505 "exnref",
13506 )?;
13507
13508 let exnref = exnref.try_as_basic_value().unwrap_basic().into_int_value();
13509 let selector = selector.as_basic_value().into_int_value();
13510
13511 for catch in catches.iter() {
13512 match catch {
13513 Catch::All { label } => {
13514 let b = self
13515 .context
13516 .append_basic_block(self.function, "catch_all_clause");
13517 self.builder.position_at_end(b);
13518 let frame = self.state.frame_at_depth(*label)?;
13519
13520 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13521
13522 self.builder.position_at_end(catch_end_block);
13523 catch_blocks.push((b, None));
13524 }
13525 Catch::One { tag, label } => {
13526 let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
13527 let signature = &self.wasm_module.signatures[tag_idx];
13528 let params = signature.params();
13529
13530 let b = self.context.append_basic_block(
13531 self.function,
13532 format!("catch_one_clause_{tag}").as_str(),
13533 );
13534 self.builder.position_at_end(b);
13535
13536 let exnref_phi = err!(
13537 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
13538 );
13539 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
13540
13541 let exn_payload_ptr = err!(self.builder.build_direct_call(
13543 self.intrinsics.read_exnref,
13544 &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
13545 "exn_ptr",
13546 ));
13547 let exn_payload_ptr = exn_payload_ptr
13548 .try_as_basic_value()
13549 .unwrap_basic()
13550 .into_pointer_value();
13551
13552 let values = params
13554 .iter()
13555 .enumerate()
13556 .map(|(i, v)| {
13557 let name = format!("value_{i}");
13558 let ptr = err!(unsafe {
13559 self.builder.build_gep(
13560 self.intrinsics.i128_ty,
13561 exn_payload_ptr,
13562 &[self
13563 .intrinsics
13564 .i32_ty
13565 .const_int(i as u64, false)],
13566 format!("{name}_ptr").as_str(),
13567 )
13568 });
13569 err_nt!(self.builder.build_load(
13570 type_to_llvm(self.intrinsics, *v)?,
13571 ptr,
13572 &name,
13573 ))
13574 })
13575 .collect::<Result<Vec<_>, CompileError>>()?;
13576
13577 let frame = self.state.frame_at_depth(*label)?;
13578
13579 for (phi, value) in frame.phis().iter().zip(values.iter()) {
13580 phi.add_incoming(&[(value, b)])
13581 }
13582
13583 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13584
13585 self.builder.position_at_end(catch_end_block);
13586 catch_blocks.push((b, Some(exnref_phi)));
13587 }
13588 Catch::OneRef { label, tag } => {
13589 let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
13590 let signature = &self.wasm_module.signatures[tag_idx];
13591 let params = signature.params();
13592
13593 let b = self.context.append_basic_block(
13594 self.function,
13595 format!("catch_one_ref_clause_{tag}").as_str(),
13596 );
13597 self.builder.position_at_end(b);
13598
13599 let exnref_phi = err!(
13600 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
13601 );
13602 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
13603
13604 let exn_payload_ptr = err!(self.builder.build_direct_call(
13606 self.intrinsics.read_exnref,
13607 &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
13608 "exn_ptr",
13609 ));
13610 let exn_payload_ptr = exn_payload_ptr
13611 .try_as_basic_value()
13612 .unwrap_basic()
13613 .into_pointer_value();
13614
13615 let mut values = params
13617 .iter()
13618 .enumerate()
13619 .map(|(i, v)| {
13620 let name = format!("value_{i}");
13621 let ptr = err!(unsafe {
13622 self.builder.build_gep(
13623 self.intrinsics.i128_ty,
13624 exn_payload_ptr,
13625 &[self
13626 .intrinsics
13627 .i32_ty
13628 .const_int(i as u64, false)],
13629 format!("{name}_ptr").as_str(),
13630 )
13631 });
13632 err_nt!(self.builder.build_load(
13633 type_to_llvm(self.intrinsics, *v)?,
13634 ptr,
13635 &name,
13636 ))
13637 })
13638 .collect::<Result<Vec<_>, CompileError>>()?;
13639
13640 values.push(exnref_phi.as_basic_value());
13641
13642 let frame = self.state.frame_at_depth(*label)?;
13643
13644 for (phi, value) in frame.phis().iter().zip(values.iter()) {
13645 phi.add_incoming(&[(value, b)])
13646 }
13647
13648 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13649
13650 self.builder.position_at_end(catch_end_block);
13651 catch_blocks.push((b, Some(exnref_phi)));
13652 }
13653 Catch::AllRef { label } => {
13654 let b = self
13655 .context
13656 .append_basic_block(self.function, "catch_all_ref_clause");
13657 self.builder.position_at_end(b);
13658
13659 let exnref_phi = err!(
13660 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
13661 );
13662 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
13663
13664 let frame = self.state.frame_at_depth(*label)?;
13665
13666 let phis = frame.phis();
13667
13668 assert_eq!(phis.len(), 1);
13669 phis[0].add_incoming(&[(&exnref_phi.as_basic_value(), b)]);
13670
13671 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13672
13673 self.builder.position_at_end(catch_end_block);
13674 catch_blocks.push((b, Some(exnref_phi)));
13675 }
13676 }
13677 }
13678
13679 for catch_info in &outer_catch_blocks {
13680 if let Some(phi) = catch_info.exnref_phi {
13681 phi.add_incoming(&[(&exnref, catch_end_block)]);
13682 }
13683 }
13684
13685 err!(
13686 self.builder.build_switch(
13687 selector,
13688 rethrow_block,
13689 catch_blocks
13690 .iter()
13691 .enumerate()
13692 .map(|(i, v)| (
13693 self.intrinsics
13694 .i32_ty
13695 .const_int(catch_tag_values[i] as _, false),
13696 v.0
13697 ))
13698 .chain(outer_catch_blocks.iter().map(|catch_info| (
13699 self.intrinsics.i32_ty.const_int(catch_info.tag as _, false),
13700 catch_info.catch_block
13701 )))
13702 .collect::<Vec<_>>()
13703 .as_slice()
13704 )
13705 );
13706
13707 self.builder.position_at_end(rethrow_block);
13711
13712 self.build_call_with_param_attributes(
13713 self.intrinsics.throw,
13714 &[self.ctx.basic().into(), exnref.into()],
13715 "rethrow",
13716 )?;
13717 err!(self.builder.build_unreachable());
13719
13720 maybe_lpad_block = Some(lpad_block);
13721 }
13722
13723 self.builder.position_at_end(current_block);
13725
13726 let catch_tags_and_blocks = catch_tag_values
13729 .into_iter()
13730 .zip(catch_blocks)
13731 .map(|(tag, (block, exnref_phi))| TagCatchInfo {
13732 tag,
13733 catch_block: block,
13734 exnref_phi,
13735 })
13736 .collect::<Vec<_>>();
13737 self.state.push_landingpad(
13738 maybe_lpad_block,
13739 end_block,
13740 end_phis,
13741 &catch_tags_and_blocks,
13742 self.module_translation
13743 .blocktype_params_results(&try_table.ty)?
13744 .0
13745 .len(),
13746 );
13747 }
13748 Operator::Throw { tag_index } => {
13749 let current_block = self
13750 .builder
13751 .get_insert_block()
13752 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
13753
13754 let sig_index = self.wasm_module.tags[TagIndex::from_u32(tag_index)];
13755 let signature = &self.wasm_module.signatures[sig_index];
13756 let params = signature.params();
13757 let values = self.state.popn_save_extra(params.len())?;
13758
13759 values.iter().enumerate().try_for_each(|(i, (v, _))| {
13760 let t = type_to_llvm(self.intrinsics, params[i])?;
13761 if t != v.get_type() {
13762 return Err(CompileError::Codegen(format!(
13763 "Incompatible types: {:?} != {:?}",
13764 t,
13765 v.get_type()
13766 )));
13767 }
13768
13769 Ok(())
13770 })?;
13771
13772 let exnref = err!(
13774 self.builder.build_direct_call(
13775 self.intrinsics.alloc_exception,
13776 &[
13777 self.ctx.basic().into(),
13778 self.intrinsics
13779 .i32_ty
13780 .const_int(tag_index as _, false)
13781 .into()
13782 ],
13783 "exnref",
13784 )
13785 );
13786 let exnref = exnref.try_as_basic_value().unwrap_basic();
13787
13788 let exn_payload_ptr = err!(self.builder.build_direct_call(
13789 self.intrinsics.read_exnref,
13790 &[self.ctx.basic().into(), exnref.into()],
13791 "exn_ptr",
13792 ));
13793 let exn_payload_ptr = exn_payload_ptr
13794 .try_as_basic_value()
13795 .unwrap_basic()
13796 .into_pointer_value();
13797
13798 for (i, value) in values.into_iter().enumerate() {
13799 let ptr = err!(unsafe {
13800 self.builder.build_gep(
13801 self.intrinsics.i128_ty,
13802 exn_payload_ptr,
13803 &[self.intrinsics.i32_ty.const_int(i as u64, false)],
13804 format!("value_{i}_ptr").as_str(),
13805 )
13806 });
13807 err!(self.builder.build_store(ptr, value.0));
13808 }
13809
13810 if let Some(pad) = self.state.get_innermost_landingpad() {
13811 let unreachable_block = self
13812 .context
13813 .append_basic_block(self.function, "_throw_unreachable");
13814
13815 err!(self.builder.build_invoke(
13816 self.intrinsics.throw,
13817 &[self.ctx.basic(), exnref],
13818 unreachable_block,
13819 pad,
13820 "throw",
13821 ));
13822
13823 self.builder.position_at_end(unreachable_block);
13824 err!(self.builder.build_unreachable());
13826
13827 self.builder.position_at_end(current_block);
13828 } else {
13829 self.build_call_with_param_attributes(
13830 self.intrinsics.throw,
13831 &[self.ctx.basic().into(), exnref.into()],
13832 "throw",
13833 )?;
13834 err!(self.builder.build_unreachable());
13836 }
13837
13838 self.state.reachable = false;
13839 }
13840 Operator::ThrowRef => {
13841 let current_block = self
13842 .builder
13843 .get_insert_block()
13844 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
13845
13846 let exnref = self.state.pop1()?;
13847
13848 if let Some(pad) = self.state.get_innermost_landingpad() {
13849 let unreachable_block = self
13850 .context
13851 .append_basic_block(self.function, "_rethrow_unreachable");
13852
13853 err!(self.builder.build_invoke(
13854 self.intrinsics.throw,
13855 &[self.ctx.basic(), exnref],
13856 unreachable_block,
13857 pad,
13858 "throw",
13859 ));
13860
13861 self.builder.position_at_end(unreachable_block);
13862 err!(self.builder.build_unreachable());
13864
13865 self.builder.position_at_end(current_block);
13866 } else {
13867 self.build_call_with_param_attributes(
13868 self.intrinsics.throw,
13869 &[self.ctx.basic().into(), exnref.into()],
13870 "throw",
13871 )?;
13872 err!(self.builder.build_unreachable());
13874 }
13875
13876 self.state.reachable = false;
13877 }
13878 Operator::I64Add128 | Operator::I64Sub128 => {
13879 let (rhs_hi, rhs_hi_info) = self.state.pop1_extra()?;
13880 let (rhs_lo, rhs_lo_info) = self.state.pop1_extra()?;
13881 let (lhs_hi, lhs_hi_info) = self.state.pop1_extra()?;
13882 let (lhs_lo, lhs_lo_info) = self.state.pop1_extra()?;
13883
13884 let lhs_lo = self
13885 .apply_pending_canonicalization(lhs_lo, lhs_lo_info)?
13886 .into_int_value();
13887 let lhs_hi = self
13888 .apply_pending_canonicalization(lhs_hi, lhs_hi_info)?
13889 .into_int_value();
13890 let rhs_lo = self
13891 .apply_pending_canonicalization(rhs_lo, rhs_lo_info)?
13892 .into_int_value();
13893 let rhs_hi = self
13894 .apply_pending_canonicalization(rhs_hi, rhs_hi_info)?
13895 .into_int_value();
13896
13897 let idx0 = self.intrinsics.i32_ty.const_zero();
13898 let idx1 = self.intrinsics.i32_ty.const_int(1, false);
13899
13900 let lhs = self.intrinsics.i64x2_ty.get_undef();
13901 let lhs = err!(self.builder.build_insert_element(lhs, lhs_lo, idx0, ""));
13902 let lhs = err!(self.builder.build_insert_element(lhs, lhs_hi, idx1, ""));
13903 let lhs = err!(
13904 self.builder
13905 .build_bit_cast(lhs, self.intrinsics.i128_ty, "a")
13906 )
13907 .into_int_value();
13908
13909 let rhs = self.intrinsics.i64x2_ty.get_undef();
13910 let rhs = err!(self.builder.build_insert_element(rhs, rhs_lo, idx0, ""));
13911 let rhs = err!(self.builder.build_insert_element(rhs, rhs_hi, idx1, ""));
13912 let rhs = err!(
13913 self.builder
13914 .build_bit_cast(rhs, self.intrinsics.i128_ty, "b")
13915 )
13916 .into_int_value();
13917
13918 let result = err!(match op {
13919 Operator::I64Add128 => self.builder.build_int_add(lhs, rhs, ""),
13920 Operator::I64Sub128 => self.builder.build_int_sub(lhs, rhs, ""),
13921 _ => unreachable!(),
13922 });
13923 let result = err!(self.builder.build_bit_cast(
13924 result,
13925 self.intrinsics.i64x2_ty,
13926 ""
13927 ))
13928 .into_vector_value();
13929 let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
13930 let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
13931
13932 self.state.push1(result_lo);
13933 self.state.push1(result_hi);
13934 }
13935 Operator::I64MulWideS | Operator::I64MulWideU => {
13936 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
13937 let lhs = self
13938 .apply_pending_canonicalization(lhs, lhs_info)?
13939 .into_int_value();
13940 let rhs = self
13941 .apply_pending_canonicalization(rhs, rhs_info)?
13942 .into_int_value();
13943
13944 let lhs = err!(match op {
13945 Operator::I64MulWideS => {
13946 self.builder
13947 .build_int_s_extend(lhs, self.intrinsics.i128_ty, "a")
13948 }
13949 Operator::I64MulWideU => {
13950 self.builder
13951 .build_int_z_extend(lhs, self.intrinsics.i128_ty, "a")
13952 }
13953 _ => unreachable!(),
13954 });
13955 let rhs = err!(match op {
13956 Operator::I64MulWideS => {
13957 self.builder
13958 .build_int_s_extend(rhs, self.intrinsics.i128_ty, "b")
13959 }
13960 Operator::I64MulWideU => {
13961 self.builder
13962 .build_int_z_extend(rhs, self.intrinsics.i128_ty, "b")
13963 }
13964 _ => unreachable!(),
13965 });
13966
13967 let result = err!(self.builder.build_int_mul(lhs, rhs, ""));
13968 let result = err!(self.builder.build_bit_cast(
13969 result,
13970 self.intrinsics.i64x2_ty,
13971 ""
13972 ))
13973 .into_vector_value();
13974 let idx0 = self.intrinsics.i32_ty.const_zero();
13975 let idx1 = self.intrinsics.i32_ty.const_int(1, false);
13976 let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
13977 let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
13978
13979 self.state.push1(result_lo);
13980 self.state.push1(result_hi);
13981 }
13982 _ => {
13983 return Err(CompileError::Codegen(format!(
13984 "Operator {op:?} unimplemented",
13985 )));
13986 }
13987 }
13988
13989 Ok(())
13990 }
13991
13992 fn build_call_with_param_attributes(
13993 &self,
13994 function: FunctionValue<'ctx>,
13995 args: &[BasicMetadataValueEnum<'ctx>],
13996 name: &str,
13997 ) -> Result<CallSiteValue<'ctx>, CompileError> {
13998 let call = self
13999 .builder
14000 .build_call(function, args, name)
14001 .map_err(|e| CompileError::Codegen(e.to_string()))?;
14002
14003 if matches!(
14008 self.target_triple.architecture,
14009 Architecture::Riscv32(..) | Architecture::Riscv64(..)
14010 ) {
14011 let param_types = function.get_type().get_param_types();
14012 for (i, ty) in param_types.into_iter().enumerate() {
14013 if ty == self.context.i32_type().into() {
14014 call.add_attribute(
14015 AttributeLoc::Param(i as u32),
14016 self.context
14017 .create_enum_attribute(Attribute::get_named_enum_kind_id("signext"), 0),
14018 );
14019 call.add_attribute(
14020 AttributeLoc::Param(i as u32),
14021 self.context
14022 .create_enum_attribute(Attribute::get_named_enum_kind_id("noundef"), 0),
14023 );
14024 }
14025 }
14026 }
14027
14028 Ok(call)
14029 }
14030}
14031
14032fn is_f32_arithmetic(bits: u32) -> bool {
14033 let bits = bits & 0x7FFF_FFFF;
14035 bits < 0x7FC0_0000
14036}
14037
14038fn is_f64_arithmetic(bits: u64) -> bool {
14039 let bits = bits & 0x7FFF_FFFF_FFFF_FFFF;
14041 bits < 0x7FF8_0000_0000_0000
14042}