1use std::num::NonZero;
2use std::{collections::HashMap, sync::Arc};
3
4use super::{
5 intrinsics::{
6 CtxType, FunctionCache, GlobalCache, Intrinsics, MemoryCache, tbaa_label, type_to_llvm,
7 },
8 state::{ControlFrame, ExtraInfo, IfElseState, State, TagCatchInfo},
10};
11use crate::{
12 compiler::ModuleBasedSymbolRegistry, config::OptimizationStyle, object_file::CompiledFunction,
13};
14use enumset::EnumSet;
15use inkwell::{
16 AddressSpace, AtomicOrdering, AtomicRMWBinOp, DLLStorageClass, FloatPredicate, IntPredicate,
17 attributes::{Attribute, AttributeLoc},
18 builder::Builder,
19 context::Context,
20 debug_info::{AsDIScope, DIFlags, DIFlagsConstants, DWARFEmissionKind, DWARFSourceLanguage},
21 module::{FlagBehavior, Linkage, Module},
22 passes::PassBuilderOptions,
23 targets::{FileType, TargetData, TargetMachine},
24 types::{BasicType, BasicTypeEnum, FloatMathType, IntType, PointerType, VectorType},
25 values::{
26 BasicMetadataValueEnum, BasicValue, BasicValueEnum, CallSiteValue, FloatValue,
27 FunctionValue, InstructionOpcode, InstructionValue, IntValue, LLVMTailCallKind, PhiValue,
28 PointerValue, VectorValue,
29 },
30};
31use itertools::Itertools;
32use smallvec::SmallVec;
33use target_lexicon::{Architecture, BinaryFormat, OperatingSystem, Triple};
34use wasmer_compiler::WASM_LARGE_FUNCTION_THRESHOLD;
35
36use crate::{
37 abi::{LLVMAbi, get_abi},
38 config::LLVM,
39 error::{err, err_nt},
40 object_file::load_object_file,
41};
42use wasmer_compiler::{
43 CANONICAL_NAN_F32, CANONICAL_NAN_F64, FunctionBinaryReader, FunctionBodyData,
44 GEF32_LEQ_I32_MAX, GEF32_LEQ_I64_MAX, GEF32_LEQ_U32_MAX, GEF32_LEQ_U64_MAX, GEF64_LEQ_I32_MAX,
45 GEF64_LEQ_I64_MAX, GEF64_LEQ_U32_MAX, GEF64_LEQ_U64_MAX, LEF32_GEQ_I32_MIN, LEF32_GEQ_I64_MIN,
46 LEF32_GEQ_U32_MIN, LEF32_GEQ_U64_MIN, LEF64_GEQ_I32_MIN, LEF64_GEQ_I64_MIN, LEF64_GEQ_U32_MIN,
47 LEF64_GEQ_U64_MIN, MiddlewareBinaryReader, ModuleMiddlewareChain, ModuleTranslationState,
48 WasmSourceMap, from_binaryreadererror_wasmerror,
49 misc::{CompiledFunctionExt, CompiledKind},
50 types::{
51 relocation::RelocationTarget,
52 symbols::{Symbol, SymbolRegistry},
53 },
54 wasmparser::{Catch, MemArg, Operator},
55 wpheaptype_to_type, wptype_to_type,
56};
57use wasmer_types::{
58 CompileError, FunctionIndex, FunctionType, GlobalIndex, LocalFunctionIndex, MemoryIndex,
59 ModuleInfo, SignatureHash, SignatureIndex, TableIndex, Type, target::CpuFeature,
60};
61use wasmer_types::{TagIndex, entity::PrimaryMap};
62use wasmer_vm::{MemoryStyle, TableStyle, VMOffsets};
63
64const FUNCTION_SECTION_ELF: &str = "__TEXT,wasmer_function";
65const FUNCTION_SECTION_MACHO: &str = "__TEXT";
66const FUNCTION_SEGMENT_MACHO: &str = "wasmer_function";
67
68const CATCH_ALL_TAG_VALUE: i32 = i32::MAX;
74
75pub struct FuncTranslator {
76 ctx: Context,
77 target_triple: Triple,
78 target_machines: HashMap<OptimizationStyle, TargetMachine>,
79 abi: LLVMAbi,
80 binary_fmt: BinaryFormat,
81 func_section: String,
82 pointer_width: u8,
83 cpu_features: EnumSet<CpuFeature>,
84 non_volatile_memory_ops: bool,
85 source_map: Arc<WasmSourceMap>,
86 wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
87}
88
89impl wasmer_compiler::FuncTranslator for FuncTranslator {}
90
91impl FuncTranslator {
92 #[allow(clippy::too_many_arguments)]
93 pub fn new(
94 target_triple: Triple,
95 target_machines: HashMap<OptimizationStyle, TargetMachine>,
96 binary_fmt: BinaryFormat,
97 pointer_width: u8,
98 cpu_features: EnumSet<CpuFeature>,
99 non_volatile_memory_ops: bool,
100 source_map: Arc<WasmSourceMap>,
101 wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
102 ) -> Result<Self, CompileError> {
103 let abi_source_tm = target_machines
104 .get(&OptimizationStyle::ForSpeed)
105 .expect("target_machines must contain OptimizationStyle::ForSpeed");
106 let abi = get_abi(abi_source_tm)?;
107 Ok(Self {
108 ctx: Context::create(),
109 target_triple,
110 target_machines,
111 abi,
112 func_section: match binary_fmt {
113 BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
114 BinaryFormat::Macho => FUNCTION_SEGMENT_MACHO.to_string(),
115 _ => {
116 return Err(CompileError::UnsupportedTarget(format!(
117 "Unsupported binary format: {binary_fmt:?}"
118 )));
119 }
120 },
121 binary_fmt,
122 pointer_width,
123 cpu_features,
124 non_volatile_memory_ops,
125 source_map,
126 wasm_apply_data_relocs_fn_index,
127 })
128 }
129
130 #[allow(clippy::too_many_arguments)]
131 pub fn translate_to_module(
132 &self,
133 wasm_module: &ModuleInfo,
134 module_translation: &ModuleTranslationState,
135 signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
136 local_func_index: &LocalFunctionIndex,
137 function_body: &FunctionBodyData,
138 config: &LLVM,
139 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
140 _table_styles: &PrimaryMap<TableIndex, TableStyle>,
141 symbol_registry: &dyn SymbolRegistry,
142 target: &Triple,
143 opt_style: OptimizationStyle,
144 ) -> Result<Module<'_>, CompileError> {
145 let func_index = wasm_module.func_index(*local_func_index);
147 let function =
148 CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
149
150 let m0_is_enabled = memory_styles
153 .get(MemoryIndex::from_u32(0))
154 .is_some_and(|memory| matches!(memory, MemoryStyle::Static));
155
156 let (function_name, module_name) = if config.experimental_artifact {
157 (function.linkage_name(), String::new())
158 } else {
159 let function_name =
160 symbol_registry.symbol_to_name(Symbol::LocalFunction(*local_func_index));
161 let module_name = match wasm_module.name.as_ref() {
162 None => format!("<anonymous module> function {function_name}"),
163 Some(module_name) => format!("module {module_name} function {function_name}"),
164 };
165 (function_name, module_name)
166 };
167
168 let module = self.ctx.create_module(module_name.as_str());
169
170 let target_machine = &self.target_machines.values().next().unwrap();
171 let target_triple = target_machine.get_triple();
172 let target_data = target_machine.get_target_data();
173 module.set_triple(&target_triple);
174 module.set_data_layout(&target_data.get_data_layout());
175 let wasm_fn_type = wasm_module
176 .signatures
177 .get(wasm_module.functions[func_index])
178 .unwrap();
179
180 let offsets = VMOffsets::new(self.pointer_width, wasm_module);
181 let intrinsics = Intrinsics::declare(
182 &module,
183 &self.ctx,
184 &target_data,
185 &self.target_triple,
186 &self.binary_fmt,
187 );
188 let (func_type, func_attrs) = self.abi.func_type_to_llvm(
189 &self.ctx,
190 &intrinsics,
191 Some(&offsets),
192 wasm_fn_type,
193 m0_is_enabled,
194 )?;
195
196 let func = module.add_function(&function_name, func_type, Some(Linkage::External));
197 let debug_info = if config.experimental_artifact {
198 let source_location = self.source_map.first_in_function(function_body);
199 let debug_metadata_version = self
200 .ctx
201 .i32_type()
202 .const_int(inkwell::debug_info::debug_metadata_version().into(), false);
203 module.add_basic_value_flag(
204 "Debug Info Version",
205 FlagBehavior::Warning,
206 debug_metadata_version,
207 );
208 module.add_basic_value_flag(
209 "Dwarf Version",
210 FlagBehavior::Warning,
211 self.ctx.i32_type().const_int(4, false),
212 );
213
214 let fallback_source_file = wasm_module.name();
215 let (source_file, source_directory) = source_location
216 .map(|location| (location.file.as_str(), location.directory.as_str()))
217 .unwrap_or((&fallback_source_file, "."));
218 let (dibuilder, compile_unit) = module.create_debug_info_builder(
219 true,
220 DWARFSourceLanguage::C,
221 source_file,
222 source_directory,
223 "wasmer",
224 true,
225 "",
226 0,
227 "",
228 DWARFEmissionKind::Full,
229 0,
230 false,
231 false,
232 "",
233 "",
234 );
235 let subroutine_type = dibuilder.create_subroutine_type(
236 compile_unit.get_file(),
237 None,
238 &[],
239 DIFlags::PUBLIC,
240 );
241 let function_name = wasm_module.get_function_name(func_index);
242 let start_line = source_location
243 .map(|location| location.line)
244 .unwrap_or_else(|| (function_body.module_offset as u32).saturating_add(1));
245 let subprogram = dibuilder.create_function(
246 compile_unit.as_debug_info_scope(),
247 &function_name,
248 None,
249 compile_unit.get_file(),
250 start_line,
251 subroutine_type,
252 false,
253 true,
254 start_line,
255 DIFlags::PUBLIC,
256 true,
257 );
258 func.set_subprogram(subprogram);
259 Some((dibuilder, subprogram))
260 } else {
261 None
262 };
263 for (attr, attr_loc) in &func_attrs {
264 func.add_attribute(*attr_loc, *attr);
265 }
266
267 if !matches!(target.operating_system, OperatingSystem::Windows) {
268 func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe);
269 }
270
271 func.add_attribute(AttributeLoc::Function, intrinsics.uwtable);
272 func.add_attribute(AttributeLoc::Function, intrinsics.frame_pointer);
273
274 let section = match self.binary_fmt {
275 BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
276 BinaryFormat::Macho => {
277 format!("{FUNCTION_SECTION_MACHO},{FUNCTION_SEGMENT_MACHO}")
278 }
279 _ => {
280 return Err(CompileError::UnsupportedTarget(format!(
281 "Unsupported binary format: {:?}",
282 self.binary_fmt
283 )));
284 }
285 };
286
287 func.set_personality_function(intrinsics.personality);
288 if !config.experimental_artifact {
289 func.as_global_value().set_section(Some(§ion));
290 }
291
292 func.set_linkage(Linkage::DLLExport);
293 func.as_global_value()
294 .set_dll_storage_class(DLLStorageClass::Export);
295
296 let entry = self.ctx.append_basic_block(func, "entry");
297 let start_of_code = self.ctx.append_basic_block(func, "start_of_code");
298 let return_ = self.ctx.append_basic_block(func, "return");
299 let alloca_builder = self.ctx.create_builder();
300 let cache_builder = self.ctx.create_builder();
301 let builder = self.ctx.create_builder();
302 cache_builder.position_at_end(entry);
303 let br = err!(cache_builder.build_unconditional_branch(start_of_code));
304 alloca_builder.position_before(&br);
305 cache_builder.position_before(&br);
306 builder.position_at_end(start_of_code);
307
308 let mut state = State::new();
309 builder.position_at_end(return_);
310 let phis: SmallVec<[PhiValue; 1]> = wasm_fn_type
311 .results()
312 .iter()
313 .map(|&wasm_ty| {
314 type_to_llvm(&intrinsics, wasm_ty).map(|ty| builder.build_phi(ty, "").unwrap())
315 })
316 .collect::<Result<_, _>>()?;
317 state.push_block(return_, phis, 0);
318 builder.position_at_end(start_of_code);
319
320 let mut reader = MiddlewareBinaryReader::new_with_offset(
321 function_body.data,
322 function_body.module_offset,
323 );
324 reader.set_middleware_chain(
325 config
326 .middlewares
327 .generate_function_middleware_chain(*local_func_index),
328 );
329
330 let mut params = vec![];
331 let first_param =
332 if func_type.get_return_type().is_none() && wasm_fn_type.results().len() > 1 {
333 if m0_is_enabled { 3 } else { 2 }
334 } else if m0_is_enabled {
335 2
336 } else {
337 1
338 };
339 let mut is_first_alloca = true;
340 let mut insert_alloca = |ty, name: String| -> Result<PointerValue, CompileError> {
341 let alloca = err!(alloca_builder.build_alloca(ty, &name));
342 if is_first_alloca {
343 alloca_builder.position_at(entry, &alloca.as_instruction_value().unwrap());
344 is_first_alloca = false;
345 }
346 Ok(alloca)
347 };
348
349 for idx in 0..wasm_fn_type.params().len() {
367 let ty = wasm_fn_type.params()[idx];
368 let ty = type_to_llvm(&intrinsics, ty)?;
369 let value = func
370 .get_nth_param((idx as u32).checked_add(first_param).unwrap())
371 .unwrap();
372 let alloca = insert_alloca(ty, format!("param_{idx}"))?;
373 err!(cache_builder.build_store(alloca, value));
374 params.push((ty, alloca));
375 }
376
377 let mut locals = vec![];
378 let num_locals = reader.read_local_count()?;
379 for idx in 0..num_locals {
380 let (count, ty) = reader.read_local_decl()?;
381 let ty = err!(wptype_to_type(ty));
382 let ty = type_to_llvm(&intrinsics, ty)?;
383 for _ in 0..count {
384 let alloca = insert_alloca(ty, format!("local_{idx}"))?;
385 err!(cache_builder.build_store(alloca, ty.const_zero()));
386 locals.push((ty, alloca));
387 }
388 }
389
390 let mut params_locals = params.clone();
391 params_locals.extend(locals.iter().cloned());
392
393 let mut m0_param = None;
394
395 if m0_is_enabled {
396 let m0 = self.abi.get_m0_ptr_param(&func);
397 m0.set_name("m0_base_ptr");
398 m0_param = Some(m0);
399 }
400
401 let mut fcg = LLVMFunctionCodeGenerator {
402 m0_param,
403 context: &self.ctx,
404 builder,
405 alloca_builder,
406 intrinsics: &intrinsics,
407 target_data: &target_data,
408 state,
409 function: func,
410 locals: params_locals,
411 ctx: CtxType::new(
412 wasm_module,
413 &func,
414 &cache_builder,
415 &self.abi,
416 self.pointer_width,
417 m0_param,
418 ),
419 unreachable_depth: 0,
420 memory_styles,
421 _table_styles,
422 module: &module,
423 module_translation,
424 signature_hashes,
425 wasm_module,
426 symbol_registry,
427 abi: &self.abi,
428 config,
429 target_triple: self.target_triple.clone(),
430 tags_cache: HashMap::new(),
431 binary_fmt: self.binary_fmt,
432 cpu_features: self.cpu_features,
433 non_volatile_memory_ops: self.non_volatile_memory_ops,
434 };
435
436 fcg.ctx.add_func(
437 func_index,
438 func.as_global_value().as_pointer_value(),
439 func_type,
440 fcg.ctx.basic(),
441 &func_attrs,
442 );
443
444 while fcg.state.has_control_frames() {
445 let pos = reader.current_position() as u32;
446 let original_pos = reader.original_position() as u32;
447 let op = reader.read_operator()?;
448 if let Some((dibuilder, subprogram)) = debug_info.as_ref() {
449 let (line, column, scope) =
450 if let Some(location) = self.source_map.get(u64::from(original_pos)) {
451 let file = dibuilder.create_file(&location.file, &location.directory);
452 let block = dibuilder.create_lexical_block(
454 subprogram.as_debug_info_scope(),
455 file,
456 location.line,
457 location.column,
458 );
459 (location.line, location.column, block.as_debug_info_scope())
460 } else {
461 (
462 original_pos.saturating_add(1),
463 1,
464 subprogram.as_debug_info_scope(),
465 )
466 };
467 let loc = dibuilder.create_debug_location(&self.ctx, line, column, scope, None);
468 fcg.builder.set_current_debug_location(loc);
469 }
470 fcg.translate_operator(op, pos)?;
471 }
472
473 fcg.finalize(wasm_fn_type)?;
474 if let Some((dibuilder, _)) = debug_info {
475 dibuilder.finalize();
476 }
477
478 if let Some(ref callbacks) = config.callbacks {
479 callbacks.preopt_ir(&function, &wasm_module.hash_string(), &module);
480 }
481
482 let mut passes = vec![];
483 if config.enable_verifier {
484 passes.push("verify");
485 }
486
487 match opt_style {
488 OptimizationStyle::Disabled => {
489 passes.push("default<O0>");
490 }
491 OptimizationStyle::ForSize => {
492 passes.push("default<O1>");
494 }
495 OptimizationStyle::ForSpeed => {
496 passes.push("sccp");
497 passes.push("early-cse");
498 passes.push("adce");
500 passes.push("sroa");
501 passes.push("aggressive-instcombine");
502 passes.push("jump-threading");
503 passes.push("simplifycfg");
505 passes.push("reassociate");
506 passes.push("loop-rotate");
507 passes.push("indvars");
508 passes.push("sccp");
512 passes.push("reassociate");
513 passes.push("simplifycfg");
514 passes.push("gvn");
515 passes.push("memcpyopt");
516 passes.push("dse");
517 passes.push("dce");
518 passes.push("reassociate");
520 passes.push("simplifycfg");
521 passes.push("mem2reg");
522 }
523 }
524
525 module
526 .run_passes(
527 &passes.join(","),
528 target_machine,
529 PassBuilderOptions::create(),
530 )
531 .unwrap();
532
533 if let Some(ref callbacks) = config.callbacks {
534 callbacks.postopt_ir(&function, &wasm_module.hash_string(), &module);
535 }
536
537 Ok(module)
538 }
539
540 #[allow(clippy::too_many_arguments)]
541 pub fn translate(
542 &self,
543 wasm_module: &ModuleInfo,
544 module_translation: &ModuleTranslationState,
545 signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
546 local_func_index: &LocalFunctionIndex,
547 function_body: &FunctionBodyData,
548 config: &LLVM,
549 memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
550 table_styles: &PrimaryMap<TableIndex, TableStyle>,
551 symbol_registry: &ModuleBasedSymbolRegistry,
552 target: &Triple,
553 ) -> Result<CompiledFunction, CompileError> {
554 let func_index = wasm_module.func_index(*local_func_index);
555 let opt_style = if Some(func_index) == self.wasm_apply_data_relocs_fn_index {
556 OptimizationStyle::Disabled
560 } else if function_body.data.len() as u64 > WASM_LARGE_FUNCTION_THRESHOLD {
561 OptimizationStyle::ForSize
562 } else {
563 OptimizationStyle::ForSpeed
564 };
565 let module = self.translate_to_module(
566 wasm_module,
567 module_translation,
568 signature_hashes,
569 local_func_index,
570 function_body,
571 config,
572 memory_styles,
573 table_styles,
574 symbol_registry,
575 target,
576 opt_style,
577 )?;
578 let function =
579 CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
580
581 let target_machine = self.target_machines.get(&opt_style).unwrap();
582 let memory_buffer = target_machine
583 .write_to_memory_buffer(&module, FileType::Object)
584 .unwrap();
585
586 if let Some(ref callbacks) = config.callbacks {
587 let module_hash = wasm_module.hash().map(|m| m.to_string());
588 callbacks.obj_memory_buffer(&function, &module_hash, &memory_buffer);
589 let asm_buffer = target_machine
590 .write_to_memory_buffer(&module, FileType::Assembly)
591 .unwrap();
592 callbacks.asm_memory_buffer(&function, &module_hash, &asm_buffer)
593 }
594
595 if config.experimental_artifact {
596 Ok(CompiledFunction::Elf(memory_buffer.as_slice().to_vec()))
597 } else {
598 Ok(CompiledFunction::Rkyv(Box::new(load_object_file(
599 memory_buffer.as_slice(),
600 &self.func_section,
601 RelocationTarget::LocalFunc(*local_func_index),
602 |name: &str| {
603 Ok({
604 let name = if matches!(self.binary_fmt, BinaryFormat::Macho) {
605 name.strip_prefix("_").unwrap_or(name)
606 } else {
607 name
608 }
609 .to_string();
610 if let Some(Symbol::LocalFunction(local_func_index)) =
611 symbol_registry.name_to_symbol(&name)
612 {
613 Some(RelocationTarget::LocalFunc(local_func_index))
614 } else {
615 None
616 }
617 })
618 },
619 self.binary_fmt,
620 &self.target_triple,
621 )?)))
622 }
623 }
624}
625
626impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
627 fn splat_vector(
629 &self,
630 value: BasicValueEnum<'ctx>,
631 vec_ty: VectorType<'ctx>,
632 ) -> Result<VectorValue<'ctx>, CompileError> {
633 err_nt!(
636 self.builder.build_shuffle_vector(
637 err!(self.builder.build_insert_element(
638 vec_ty.get_undef(),
639 value,
640 self.intrinsics.i32_zero,
641 "",
642 )),
643 vec_ty.get_undef(),
644 self.intrinsics
645 .i32_ty
646 .vec_type(vec_ty.get_size())
647 .const_zero(),
648 "",
649 )
650 )
651 }
652
653 #[allow(clippy::too_many_arguments)]
656 fn trunc_sat<T: FloatMathType<'ctx>>(
657 &self,
658 fvec_ty: T,
659 ivec_ty: T::MathConvType,
660 lower_bound: u64, upper_bound: u64, int_min_value: u64,
663 int_max_value: u64,
664 value: IntValue<'ctx>,
665 ) -> Result<VectorValue<'ctx>, CompileError> {
666 let fvec_ty = fvec_ty.as_basic_type_enum().into_vector_type();
680 let ivec_ty = ivec_ty.as_basic_type_enum().into_vector_type();
681 let fvec_element_ty = fvec_ty.get_element_type().into_float_type();
682 let ivec_element_ty = ivec_ty.get_element_type().into_int_type();
683
684 let is_signed = int_min_value != 0;
685 let int_min_value = self.splat_vector(
686 ivec_element_ty
687 .const_int(int_min_value, is_signed)
688 .as_basic_value_enum(),
689 ivec_ty,
690 )?;
691 let int_max_value = self.splat_vector(
692 ivec_element_ty
693 .const_int(int_max_value, is_signed)
694 .as_basic_value_enum(),
695 ivec_ty,
696 )?;
697 let lower_bound = if is_signed {
698 err!(self.builder.build_signed_int_to_float(
699 ivec_element_ty.const_int(lower_bound, is_signed),
700 fvec_element_ty,
701 "",
702 ))
703 } else {
704 err!(self.builder.build_unsigned_int_to_float(
705 ivec_element_ty.const_int(lower_bound, is_signed),
706 fvec_element_ty,
707 "",
708 ))
709 };
710 let upper_bound = if is_signed {
711 err!(self.builder.build_signed_int_to_float(
712 ivec_element_ty.const_int(upper_bound, is_signed),
713 fvec_element_ty,
714 "",
715 ))
716 } else {
717 err!(self.builder.build_unsigned_int_to_float(
718 ivec_element_ty.const_int(upper_bound, is_signed),
719 fvec_element_ty,
720 "",
721 ))
722 };
723
724 let value = err!(self.builder.build_bit_cast(value, fvec_ty, "")).into_vector_value();
725 let zero = fvec_ty.const_zero();
726 let lower_bound = self.splat_vector(lower_bound.as_basic_value_enum(), fvec_ty)?;
727 let upper_bound = self.splat_vector(upper_bound.as_basic_value_enum(), fvec_ty)?;
728 let nan_cmp =
729 err!(
730 self.builder
731 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
732 );
733 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
734 FloatPredicate::OGT,
735 value,
736 upper_bound,
737 "above_upper_bound",
738 ));
739 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
740 FloatPredicate::OLT,
741 value,
742 lower_bound,
743 "below_lower_bound",
744 ));
745 let not_representable = err!(self.builder.build_or(
746 err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
747 below_lower_bound_cmp,
748 "not_representable_as_int",
749 ));
750 let value =
751 err!(
752 self.builder
753 .build_select(not_representable, zero, value, "safe_to_convert")
754 )
755 .into_vector_value();
756 let value = if is_signed {
757 self.builder
758 .build_float_to_signed_int(value, ivec_ty, "as_int")
759 } else {
760 self.builder
761 .build_float_to_unsigned_int(value, ivec_ty, "as_int")
762 };
763
764 let value = err!(value);
765 let value =
766 err!(
767 self.builder
768 .build_select(above_upper_bound_cmp, int_max_value, value, "")
769 )
770 .into_vector_value();
771 err_nt!(
772 self.builder
773 .build_select(below_lower_bound_cmp, int_min_value, value, "")
774 .map(|v| v.into_vector_value())
775 )
776 }
777
778 #[allow(clippy::too_many_arguments)]
781 fn trunc_sat_into_int<T: FloatMathType<'ctx>>(
782 &self,
783 fvec_ty: T,
784 ivec_ty: T::MathConvType,
785 lower_bound: u64, upper_bound: u64, int_min_value: u64,
788 int_max_value: u64,
789 value: IntValue<'ctx>,
790 ) -> Result<IntValue<'ctx>, CompileError> {
791 let res = self.trunc_sat(
792 fvec_ty,
793 ivec_ty,
794 lower_bound,
795 upper_bound,
796 int_min_value,
797 int_max_value,
798 value,
799 )?;
800 err_nt!(
801 self.builder
802 .build_bit_cast(res, self.intrinsics.i128_ty, "")
803 .map(|v| v.into_int_value())
804 )
805 }
806
807 fn trunc_sat_scalar(
810 &self,
811 int_ty: IntType<'ctx>,
812 lower_bound: u64, upper_bound: u64, int_min_value: u64,
815 int_max_value: u64,
816 value: FloatValue<'ctx>,
817 ) -> Result<IntValue<'ctx>, CompileError> {
818 let is_signed = int_min_value != 0;
834 let int_min_value = int_ty.const_int(int_min_value, is_signed);
835 let int_max_value = int_ty.const_int(int_max_value, is_signed);
836
837 let lower_bound = if is_signed {
838 err!(self.builder.build_signed_int_to_float(
839 int_ty.const_int(lower_bound, is_signed),
840 value.get_type(),
841 "",
842 ))
843 } else {
844 err!(self.builder.build_unsigned_int_to_float(
845 int_ty.const_int(lower_bound, is_signed),
846 value.get_type(),
847 "",
848 ))
849 };
850 let upper_bound = if is_signed {
851 err!(self.builder.build_signed_int_to_float(
852 int_ty.const_int(upper_bound, is_signed),
853 value.get_type(),
854 "",
855 ))
856 } else {
857 err!(self.builder.build_unsigned_int_to_float(
858 int_ty.const_int(upper_bound, is_signed),
859 value.get_type(),
860 "",
861 ))
862 };
863
864 let zero = value.get_type().const_zero();
865
866 let nan_cmp =
867 err!(
868 self.builder
869 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
870 );
871 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
872 FloatPredicate::OGT,
873 value,
874 upper_bound,
875 "above_upper_bound",
876 ));
877 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
878 FloatPredicate::OLT,
879 value,
880 lower_bound,
881 "below_lower_bound",
882 ));
883 let not_representable = err!(self.builder.build_or(
884 err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
885 below_lower_bound_cmp,
886 "not_representable_as_int",
887 ));
888 let value =
889 err!(
890 self.builder
891 .build_select(not_representable, zero, value, "safe_to_convert")
892 )
893 .into_float_value();
894 let value = if is_signed {
895 err!(
896 self.builder
897 .build_float_to_signed_int(value, int_ty, "as_int")
898 )
899 } else {
900 err!(
901 self.builder
902 .build_float_to_unsigned_int(value, int_ty, "as_int")
903 )
904 };
905 let value =
906 err!(
907 self.builder
908 .build_select(above_upper_bound_cmp, int_max_value, value, "")
909 )
910 .into_int_value();
911 let value =
912 err!(
913 self.builder
914 .build_select(below_lower_bound_cmp, int_min_value, value, "")
915 )
916 .into_int_value();
917
918 err_nt!(
919 self.builder
920 .build_bit_cast(value, int_ty, "")
921 .map(|v| v.into_int_value())
922 )
923 }
924
925 fn trap_if_not_representable_as_int(
926 &self,
927 lower_bound: u64, upper_bound: u64, value: FloatValue<'ctx>,
930 ) -> Result<(), CompileError> {
931 let float_ty = value.get_type();
932 let int_ty = if float_ty == self.intrinsics.f32_ty {
933 self.intrinsics.i32_ty
934 } else {
935 self.intrinsics.i64_ty
936 };
937
938 let lower_bound = err!(self.builder.build_bit_cast(
939 int_ty.const_int(lower_bound, false),
940 float_ty,
941 ""
942 ))
943 .into_float_value();
944 let upper_bound = err!(self.builder.build_bit_cast(
945 int_ty.const_int(upper_bound, false),
946 float_ty,
947 ""
948 ))
949 .into_float_value();
950
951 let above_upper_bound_cmp = err!(self.builder.build_float_compare(
955 FloatPredicate::UGT,
956 value,
957 upper_bound,
958 "above_upper_bound",
959 ));
960 let below_lower_bound_cmp = err!(self.builder.build_float_compare(
961 FloatPredicate::ULT,
962 value,
963 lower_bound,
964 "below_lower_bound",
965 ));
966 let out_of_bounds = err!(self.builder.build_or(
967 above_upper_bound_cmp,
968 below_lower_bound_cmp,
969 "out_of_bounds",
970 ));
971
972 let failure_block = self
973 .context
974 .append_basic_block(self.function, "conversion_failure_block");
975 let continue_block = self
976 .context
977 .append_basic_block(self.function, "conversion_success_block");
978
979 err!(
980 self.builder
981 .build_conditional_branch(out_of_bounds, failure_block, continue_block)
982 );
983 self.builder.position_at_end(failure_block);
984 let is_nan =
985 err!(
986 self.builder
987 .build_float_compare(FloatPredicate::UNO, value, value, "is_nan")
988 );
989 let trap_code = err!(self.builder.build_select(
990 is_nan,
991 self.intrinsics.trap_bad_conversion_to_integer,
992 self.intrinsics.trap_illegal_arithmetic,
993 "",
994 ));
995 self.build_call_with_param_attributes(
996 self.intrinsics.throw_trap,
997 &[trap_code.into()],
998 "throw",
999 )?;
1000 err!(self.builder.build_unreachable());
1001 self.builder.position_at_end(continue_block);
1002
1003 Ok(())
1004 }
1005
1006 fn trap_if_zero_or_overflow(
1007 &self,
1008 left: IntValue<'ctx>,
1009 right: IntValue<'ctx>,
1010 ) -> Result<(), CompileError> {
1011 let int_type = left.get_type();
1012
1013 let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
1014 let min_value = int_type.const_int(i32::MIN as u64, false);
1015 let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
1016 (min_value, neg_one_value)
1017 } else if int_type == self.intrinsics.i64_ty {
1018 let min_value = int_type.const_int(i64::MIN as u64, false);
1019 let neg_one_value = int_type.const_int(-1i64 as u64, false);
1020 (min_value, neg_one_value)
1021 } else {
1022 unreachable!()
1023 };
1024
1025 let divisor_is_zero = err!(self.builder.build_int_compare(
1026 IntPredicate::EQ,
1027 right,
1028 int_type.const_zero(),
1029 "divisor_is_zero",
1030 ));
1031 let should_trap = err!(self.builder.build_or(
1032 divisor_is_zero,
1033 err!(self.builder.build_and(
1034 err!(self.builder.build_int_compare(
1035 IntPredicate::EQ,
1036 left,
1037 min_value,
1038 "left_is_min"
1039 )),
1040 err!(self.builder.build_int_compare(
1041 IntPredicate::EQ,
1042 right,
1043 neg_one_value,
1044 "right_is_neg_one",
1045 )),
1046 "div_will_overflow",
1047 )),
1048 "div_should_trap",
1049 ));
1050
1051 let should_trap = self
1052 .build_call_with_param_attributes(
1053 self.intrinsics.expect_i1,
1054 &[
1055 should_trap.into(),
1056 self.intrinsics.i1_ty.const_zero().into(),
1057 ],
1058 "should_trap_expect",
1059 )?
1060 .try_as_basic_value()
1061 .unwrap_basic()
1062 .into_int_value();
1063
1064 let shouldnt_trap_block = self
1065 .context
1066 .append_basic_block(self.function, "shouldnt_trap_block");
1067 let should_trap_block = self
1068 .context
1069 .append_basic_block(self.function, "should_trap_block");
1070 err!(self.builder.build_conditional_branch(
1071 should_trap,
1072 should_trap_block,
1073 shouldnt_trap_block
1074 ));
1075 self.builder.position_at_end(should_trap_block);
1076 let trap_code = err!(self.builder.build_select(
1077 divisor_is_zero,
1078 self.intrinsics.trap_integer_division_by_zero,
1079 self.intrinsics.trap_illegal_arithmetic,
1080 "",
1081 ));
1082 err!(
1083 self.builder
1084 .build_call(self.intrinsics.throw_trap, &[trap_code.into()], "throw")
1085 );
1086 err!(self.builder.build_unreachable());
1087 self.builder.position_at_end(shouldnt_trap_block);
1088
1089 Ok(())
1090 }
1091
1092 fn trap_if_zero(&self, value: IntValue<'ctx>) -> Result<(), CompileError> {
1093 let int_type = value.get_type();
1094 let should_trap = err!(self.builder.build_int_compare(
1095 IntPredicate::EQ,
1096 value,
1097 int_type.const_zero(),
1098 "divisor_is_zero",
1099 ));
1100
1101 let should_trap = self
1102 .build_call_with_param_attributes(
1103 self.intrinsics.expect_i1,
1104 &[
1105 should_trap.into(),
1106 self.intrinsics.i1_ty.const_zero().into(),
1107 ],
1108 "should_trap_expect",
1109 )?
1110 .try_as_basic_value()
1111 .unwrap_basic()
1112 .into_int_value();
1113
1114 let shouldnt_trap_block = self
1115 .context
1116 .append_basic_block(self.function, "shouldnt_trap_block");
1117 let should_trap_block = self
1118 .context
1119 .append_basic_block(self.function, "should_trap_block");
1120 err!(self.builder.build_conditional_branch(
1121 should_trap,
1122 should_trap_block,
1123 shouldnt_trap_block
1124 ));
1125 self.builder.position_at_end(should_trap_block);
1126 self.build_call_with_param_attributes(
1127 self.intrinsics.throw_trap,
1128 &[self.intrinsics.trap_integer_division_by_zero.into()],
1129 "throw",
1130 )?;
1131 err!(self.builder.build_unreachable());
1132 self.builder.position_at_end(shouldnt_trap_block);
1133
1134 Ok(())
1135 }
1136
1137 fn v128_into_int_vec(
1138 &self,
1139 value: BasicValueEnum<'ctx>,
1140 info: ExtraInfo,
1141 int_vec_ty: VectorType<'ctx>,
1142 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1143 let (value, info) = if self.config.enable_nan_canonicalization {
1144 if info.has_pending_f32_nan() {
1145 let value = err!(
1146 self.builder
1147 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1148 );
1149 (self.canonicalize_nans(value)?, info.strip_pending())
1150 } else if info.has_pending_f64_nan() {
1151 let value = err!(
1152 self.builder
1153 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1154 );
1155 (self.canonicalize_nans(value)?, info.strip_pending())
1156 } else {
1157 (value, info)
1158 }
1159 } else {
1160 (value, info)
1161 };
1162 Ok((
1163 err!(self.builder.build_bit_cast(value, int_vec_ty, "")).into_vector_value(),
1164 info,
1165 ))
1166 }
1167
1168 fn v128_into_i8x16(
1169 &self,
1170 value: BasicValueEnum<'ctx>,
1171 info: ExtraInfo,
1172 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1173 self.v128_into_int_vec(value, info, self.intrinsics.i8x16_ty)
1174 }
1175
1176 fn v128_into_i16x8(
1177 &self,
1178 value: BasicValueEnum<'ctx>,
1179 info: ExtraInfo,
1180 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1181 self.v128_into_int_vec(value, info, self.intrinsics.i16x8_ty)
1182 }
1183
1184 fn v128_into_i32x4(
1185 &self,
1186 value: BasicValueEnum<'ctx>,
1187 info: ExtraInfo,
1188 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1189 self.v128_into_int_vec(value, info, self.intrinsics.i32x4_ty)
1190 }
1191
1192 fn v128_into_i64x2(
1193 &self,
1194 value: BasicValueEnum<'ctx>,
1195 info: ExtraInfo,
1196 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1197 self.v128_into_int_vec(value, info, self.intrinsics.i64x2_ty)
1198 }
1199
1200 fn v128_into_f32x4(
1203 &self,
1204 value: BasicValueEnum<'ctx>,
1205 info: ExtraInfo,
1206 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1207 let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f64_nan()
1208 {
1209 let value = err!(
1210 self.builder
1211 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1212 );
1213 (self.canonicalize_nans(value)?, info.strip_pending())
1214 } else {
1215 (value, info)
1216 };
1217 Ok((
1218 err!(
1219 self.builder
1220 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1221 )
1222 .into_vector_value(),
1223 info,
1224 ))
1225 }
1226
1227 fn v128_into_f64x2(
1230 &self,
1231 value: BasicValueEnum<'ctx>,
1232 info: ExtraInfo,
1233 ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1234 let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f32_nan()
1235 {
1236 let value = err!(
1237 self.builder
1238 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1239 );
1240 (self.canonicalize_nans(value)?, info.strip_pending())
1241 } else {
1242 (value, info)
1243 };
1244 Ok((
1245 err!(
1246 self.builder
1247 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1248 )
1249 .into_vector_value(),
1250 info,
1251 ))
1252 }
1253
1254 fn apply_pending_canonicalization(
1255 &self,
1256 value: BasicValueEnum<'ctx>,
1257 info: ExtraInfo,
1258 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1259 if !self.config.enable_nan_canonicalization {
1260 return Ok(value);
1261 }
1262
1263 if info.has_pending_f32_nan() {
1264 if value.get_type().is_vector_type()
1265 || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1266 {
1267 let ty = value.get_type();
1268 let value = err!(
1269 self.builder
1270 .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1271 );
1272 let value = self.canonicalize_nans(value)?;
1273 err_nt!(self.builder.build_bit_cast(value, ty, ""))
1274 } else {
1275 self.canonicalize_nans(value)
1276 }
1277 } else if info.has_pending_f64_nan() {
1278 if value.get_type().is_vector_type()
1279 || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1280 {
1281 let ty = value.get_type();
1282 let value = err!(
1283 self.builder
1284 .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1285 );
1286 let value = self.canonicalize_nans(value)?;
1287 err_nt!(self.builder.build_bit_cast(value, ty, ""))
1288 } else {
1289 self.canonicalize_nans(value)
1290 }
1291 } else {
1292 Ok(value)
1293 }
1294 }
1295
1296 fn canonicalize_nans(
1298 &self,
1299 value: BasicValueEnum<'ctx>,
1300 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1301 if !self.config.enable_nan_canonicalization {
1302 return Ok(value);
1303 }
1304
1305 let f_ty = value.get_type();
1306 if f_ty.is_vector_type() {
1307 let value = value.into_vector_value();
1308 let f_ty = f_ty.into_vector_type();
1309 let zero = f_ty.const_zero();
1310 let nan_cmp =
1311 err!(
1312 self.builder
1313 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1314 );
1315 let canonical_qnan = f_ty
1316 .get_element_type()
1317 .into_float_type()
1318 .const_float(f64::NAN);
1319 let canonical_qnan = self.splat_vector(canonical_qnan.as_basic_value_enum(), f_ty)?;
1320 err_nt!(
1321 self.builder
1322 .build_select(nan_cmp, canonical_qnan, value, "")
1323 .map(|v| v.as_basic_value_enum())
1324 )
1325 } else {
1326 let value = value.into_float_value();
1327 let f_ty = f_ty.into_float_type();
1328 let zero = f_ty.const_zero();
1329 let nan_cmp =
1330 err!(
1331 self.builder
1332 .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1333 );
1334 let canonical_qnan = f_ty.const_float(f64::NAN);
1335 err_nt!(
1336 self.builder
1337 .build_select(nan_cmp, canonical_qnan, value, "")
1338 .map(|v| v.as_basic_value_enum())
1339 )
1340 }
1341 }
1342
1343 fn annotate_user_memaccess(
1344 &mut self,
1345 memory_index: MemoryIndex,
1346 _memarg: &MemArg,
1347 alignment: u32,
1348 memaccess: InstructionValue<'ctx>,
1349 ) -> Result<(), CompileError> {
1350 match memaccess.get_opcode() {
1351 InstructionOpcode::Load | InstructionOpcode::Store => {
1352 memaccess.set_alignment(alignment).unwrap();
1353 }
1354 _ => {}
1355 };
1356 if !self.non_volatile_memory_ops {
1357 if let MemoryCache::Static { base_ptr: _ } = self.ctx.memory(
1361 memory_index,
1362 self.intrinsics,
1363 self.module,
1364 self.memory_styles,
1365 )? {
1366 memaccess.set_volatile(true).map_err(|err| {
1368 CompileError::Codegen(format!(
1369 "could not set volatile on memory operation: {err}"
1370 ))
1371 })?;
1372 }
1373 }
1374 tbaa_label(
1375 self.module,
1376 self.intrinsics,
1377 format!("memory {}", memory_index.as_u32()),
1378 memaccess,
1379 );
1380 Ok(())
1381 }
1382
1383 fn build_annotated_load<T: BasicType<'ctx>>(
1384 &mut self,
1385 pointee_ty: T,
1386 offset: IntValue<'ctx>,
1387 memarg: &MemArg,
1388 alignment: u32,
1389 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1390 let memory_index = MemoryIndex::from_u32(memarg.memory);
1391 let pointee_size = usize::try_from(self.target_data.get_store_size(&pointee_ty))
1392 .map_err(|_| CompileError::Codegen("pointee type size does not fit in usize".into()))?;
1393 let effective_address = self.resolve_memory_ptr(
1394 memory_index,
1395 memarg,
1396 self.intrinsics.ptr_ty,
1397 offset,
1398 pointee_size,
1399 )?;
1400 let result = err!(self.builder.build_load(pointee_ty, effective_address, ""));
1401 self.annotate_user_memaccess(
1402 MemoryIndex::from_u32(memarg.memory),
1403 memarg,
1404 alignment,
1405 result.as_instruction_value().unwrap(),
1406 )?;
1407 Ok(result)
1408 }
1409
1410 fn build_annotated_atomic_load(
1411 &mut self,
1412 outer_ty: IntType<'ctx>,
1413 inner_ty: IntType<'ctx>,
1414 offset: IntValue<'ctx>,
1415 memarg: &MemArg,
1416 ) -> Result<IntValue<'ctx>, CompileError> {
1417 let alignment = 2u32.pow(memarg.align as u32);
1418 let memory_index = MemoryIndex::from_u32(memarg.memory);
1419 let inner_size =
1420 usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1421 CompileError::Codegen("atomic inner type size does not fit in usize".into())
1422 })?;
1423 let outer_size =
1424 usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1425 CompileError::Codegen("atomic outer type size does not fit in usize".into())
1426 })?;
1427
1428 let effective_address = self.resolve_memory_ptr(
1429 memory_index,
1430 memarg,
1431 self.intrinsics.ptr_ty,
1432 offset,
1433 inner_size,
1434 )?;
1435 self.trap_if_misaligned(
1436 memarg,
1437 effective_address,
1438 u8::try_from(inner_size).map_err(|_| {
1439 CompileError::Codegen("atomic inner type size does not fit in u8".into())
1440 })?,
1441 )?;
1442
1443 let result = err!(
1444 self.builder
1445 .build_load(inner_ty, effective_address, "atomic_load")
1446 );
1447 let load = result.into_int_value();
1448 let load_inst = load.as_instruction_value().unwrap();
1449 self.annotate_user_memaccess(memory_index, memarg, alignment, load_inst)?;
1450 load_inst
1451 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
1452 .unwrap();
1453
1454 if inner_size < outer_size {
1455 Ok(err_nt!(
1456 self.builder.build_int_z_extend(load, outer_ty, "")
1457 )?)
1458 } else {
1459 Ok(load)
1460 }
1461 }
1462
1463 fn build_annotated_store<T: BasicType<'ctx>>(
1464 &mut self,
1465 pointee_ty: T,
1466 offset: IntValue<'ctx>,
1467 value: BasicValueEnum<'ctx>,
1468 memarg: &MemArg,
1469 alignment: u32,
1470 ) -> Result<(), CompileError> {
1471 let memory_index = MemoryIndex::from_u32(memarg.memory);
1472 let pointee_size = usize::try_from(self.target_data.get_store_size(&pointee_ty))
1473 .map_err(|_| CompileError::Codegen("pointee type size does not fit in usize".into()))?;
1474 let effective_address = self.resolve_memory_ptr(
1475 memory_index,
1476 memarg,
1477 self.intrinsics.ptr_ty,
1478 offset,
1479 pointee_size,
1480 )?;
1481
1482 if !self.non_volatile_memory_ops {
1485 self.build_annotated_load(pointee_ty, offset, memarg, alignment)?;
1486 }
1487
1488 let store = err!(self.builder.build_store(effective_address, value));
1489 self.annotate_user_memaccess(memory_index, memarg, alignment, store)
1490 }
1491
1492 fn build_annotated_atomic_store(
1493 &mut self,
1494 outer_ty: IntType<'ctx>,
1495 inner_ty: IntType<'ctx>,
1496 offset: IntValue<'ctx>,
1497 value: IntValue<'ctx>,
1498 memarg: &MemArg,
1499 ) -> Result<(), CompileError> {
1500 let alignment = 2u32.pow(memarg.align as u32);
1501 let memory_index = MemoryIndex::from_u32(memarg.memory);
1502 let inner_size =
1503 usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1504 CompileError::Codegen("atomic inner type size does not fit in usize".into())
1505 })?;
1506 let outer_size =
1507 usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1508 CompileError::Codegen("atomic outer type size does not fit in usize".into())
1509 })?;
1510
1511 let effective_address = self.resolve_memory_ptr(
1512 memory_index,
1513 memarg,
1514 self.intrinsics.ptr_ty,
1515 offset,
1516 inner_size,
1517 )?;
1518 self.trap_if_misaligned(
1519 memarg,
1520 effective_address,
1521 u8::try_from(inner_size).map_err(|_| {
1522 CompileError::Codegen("atomic inner type size does not fit in u8".into())
1523 })?,
1524 )?;
1525
1526 let value = if inner_size < outer_size {
1527 err!(self.builder.build_int_truncate(value, inner_ty, ""))
1528 } else {
1529 value
1530 };
1531 let store = err!(self.builder.build_store(effective_address, value));
1532 self.annotate_user_memaccess(memory_index, memarg, alignment, store)?;
1533 store
1534 .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
1535 .unwrap();
1536 Ok(())
1537 }
1538
1539 fn build_annotated_atomic_rmw(
1540 &mut self,
1541 outer_ty: IntType<'ctx>,
1542 inner_ty: IntType<'ctx>,
1543 offset: IntValue<'ctx>,
1544 value: IntValue<'ctx>,
1545 memarg: &MemArg,
1546 op: AtomicRMWBinOp,
1547 ) -> Result<IntValue<'ctx>, CompileError> {
1548 let alignment = 2u32.pow(memarg.align as u32);
1549 let memory_index = MemoryIndex::from_u32(memarg.memory);
1550 let inner_size =
1551 usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1552 CompileError::Codegen("atomic inner type size does not fit in usize".into())
1553 })?;
1554 let outer_size =
1555 usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1556 CompileError::Codegen("atomic outer type size does not fit in usize".into())
1557 })?;
1558
1559 let effective_address = self.resolve_memory_ptr(
1560 memory_index,
1561 memarg,
1562 self.intrinsics.ptr_ty,
1563 offset,
1564 inner_size,
1565 )?;
1566 self.trap_if_misaligned(
1567 memarg,
1568 effective_address,
1569 u8::try_from(inner_size).map_err(|_| {
1570 CompileError::Codegen("atomic inner type size does not fit in u8".into())
1571 })?,
1572 )?;
1573 let value = if inner_size < outer_size {
1574 err!(self.builder.build_int_truncate(value, inner_ty, ""))
1575 } else {
1576 value
1577 };
1578 let old = self
1579 .builder
1580 .build_atomicrmw(
1581 op,
1582 effective_address,
1583 value,
1584 AtomicOrdering::SequentiallyConsistent,
1585 )
1586 .unwrap();
1587 self.annotate_user_memaccess(
1588 memory_index,
1589 memarg,
1590 alignment,
1591 old.as_instruction_value().unwrap(),
1592 )?;
1593
1594 let value = if inner_size < outer_size {
1595 err!(self.builder.build_int_z_extend(old, outer_ty, ""))
1596 } else {
1597 old
1598 };
1599 Ok(value)
1600 }
1601
1602 fn build_annotated_atomic_rmw_cmpxchg(
1603 &mut self,
1604 outer_ty: IntType<'ctx>,
1605 inner_ty: IntType<'ctx>,
1606 offset: IntValue<'ctx>,
1607 cmp: IntValue<'ctx>,
1608 new: IntValue<'ctx>,
1609 memarg: &MemArg,
1610 ) -> Result<IntValue<'ctx>, CompileError> {
1611 let alignment = 2u32.pow(memarg.align as u32);
1612 let memory_index = MemoryIndex::from_u32(memarg.memory);
1613 let inner_size =
1614 usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1615 CompileError::Codegen("atomic inner type size does not fit in usize".into())
1616 })?;
1617 let outer_size =
1618 usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1619 CompileError::Codegen("atomic outer type size does not fit in usize".into())
1620 })?;
1621
1622 let effective_address = self.resolve_memory_ptr(
1623 memory_index,
1624 memarg,
1625 self.intrinsics.ptr_ty,
1626 offset,
1627 inner_size,
1628 )?;
1629 self.trap_if_misaligned(
1630 memarg,
1631 effective_address,
1632 u8::try_from(inner_size).map_err(|_| {
1633 CompileError::Codegen("atomic inner type size does not fit in u8".into())
1634 })?,
1635 )?;
1636 let (cmp, new) = if inner_size < outer_size {
1637 (
1638 err!(self.builder.build_int_truncate(cmp, inner_ty, "")),
1639 err!(self.builder.build_int_truncate(new, inner_ty, "")),
1640 )
1641 } else {
1642 (cmp, new)
1643 };
1644 let old = self
1645 .builder
1646 .build_cmpxchg(
1647 effective_address,
1648 cmp,
1649 new,
1650 AtomicOrdering::SequentiallyConsistent,
1651 AtomicOrdering::SequentiallyConsistent,
1652 )
1653 .unwrap();
1654 self.annotate_user_memaccess(
1655 memory_index,
1656 memarg,
1657 alignment,
1658 old.as_instruction_value().unwrap(),
1659 )?;
1660 let old = self
1661 .builder
1662 .build_extract_value(old, 0, "")
1663 .unwrap()
1664 .into_int_value();
1665
1666 let value = if inner_size < outer_size {
1667 err!(self.builder.build_int_z_extend(old, outer_ty, ""))
1668 } else {
1669 old
1670 };
1671 Ok(value)
1672 }
1673
1674 fn translate_atomic_rmw(
1675 &mut self,
1676 outer_ty: IntType<'ctx>,
1677 inner_ty: IntType<'ctx>,
1678 memarg: &MemArg,
1679 op: AtomicRMWBinOp,
1680 extra_info: Option<ExtraInfo>,
1681 ) -> Result<(), CompileError> {
1682 let value = self.state.pop1()?.into_int_value();
1683 let offset = self.state.pop1()?.into_int_value();
1684 let old = self.build_annotated_atomic_rmw(outer_ty, inner_ty, offset, value, memarg, op)?;
1685 if let Some(extra_info) = extra_info {
1686 self.state.push1_extra(old, extra_info);
1687 } else {
1688 self.state.push1(old);
1689 }
1690 Ok(())
1691 }
1692
1693 fn translate_atomic_rmw_cmpxchg(
1694 &mut self,
1695 outer_ty: IntType<'ctx>,
1696 inner_ty: IntType<'ctx>,
1697 memarg: &MemArg,
1698 extra_info: Option<ExtraInfo>,
1699 ) -> Result<(), CompileError> {
1700 let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
1701 let cmp = self
1702 .apply_pending_canonicalization(cmp, cmp_info)?
1703 .into_int_value();
1704 let new = self
1705 .apply_pending_canonicalization(new, new_info)?
1706 .into_int_value();
1707 let offset = self.state.pop1()?.into_int_value();
1708 let old =
1709 self.build_annotated_atomic_rmw_cmpxchg(outer_ty, inner_ty, offset, cmp, new, memarg)?;
1710 if let Some(extra_info) = extra_info {
1711 self.state.push1_extra(old, extra_info);
1712 } else {
1713 self.state.push1(old);
1714 }
1715 Ok(())
1716 }
1717
1718 fn fold_atomic_mem_addr(
1719 &self,
1720 addr: BasicValueEnum<'ctx>,
1721 memarg: &MemArg,
1722 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1723 let addr = addr.into_int_value();
1724 let addr = if memarg.offset > 0 {
1725 let extended_addr = err!(self.builder.build_int_z_extend(
1726 addr,
1727 self.intrinsics.i64_ty,
1728 "atomic_addr_extended"
1729 ));
1730 let effective_addr = err!(self.builder.build_int_add(
1731 extended_addr,
1732 self.intrinsics.i64_ty.const_int(memarg.offset, false),
1733 "atomic_effective_addr"
1734 ));
1735 let out_of_bounds = err!(self.builder.build_int_compare(
1736 IntPredicate::UGE,
1737 effective_addr,
1738 self.intrinsics.i64_ty.const_int(0x1_0000_0000, false),
1739 "atomic_addr_out_of_bounds"
1740 ));
1741 let continue_block = self
1742 .context
1743 .append_basic_block(self.function, "atomic_addr_in_bounds_block");
1744 let trap_block = self
1745 .context
1746 .append_basic_block(self.function, "atomic_addr_out_of_bounds_block");
1747 err!(
1748 self.builder
1749 .build_conditional_branch(out_of_bounds, trap_block, continue_block)
1750 );
1751
1752 self.builder.position_at_end(trap_block);
1753 self.build_call_with_param_attributes(
1754 self.intrinsics.throw_trap,
1755 &[self.intrinsics.trap_memory_oob.into()],
1756 "throw",
1757 )?;
1758 err!(self.builder.build_unreachable());
1759
1760 self.builder.position_at_end(continue_block);
1761 err!(self.builder.build_int_truncate(
1762 effective_addr,
1763 self.intrinsics.i32_ty,
1764 "atomic_effective_addr_i32"
1765 ))
1766 } else {
1767 addr
1768 };
1769
1770 Ok(addr.as_basic_value_enum())
1772 }
1773
1774 fn resolve_memory_ptr(
1775 &mut self,
1776 memory_index: MemoryIndex,
1777 memarg: &MemArg,
1778 ptr_ty: PointerType<'ctx>,
1779 var_offset: IntValue<'ctx>,
1780 value_size: usize,
1781 ) -> Result<PointerValue<'ctx>, CompileError> {
1782 let builder = &self.builder;
1783 let intrinsics = &self.intrinsics;
1784 let context = &self.context;
1785 let function = &self.function;
1786
1787 let imm_offset = intrinsics.i64_ty.const_int(memarg.offset, false);
1789 let var_offset = err!(builder.build_int_z_extend(var_offset, intrinsics.i64_ty, ""));
1790 let offset = err!(builder.build_int_add(var_offset, imm_offset, ""));
1791
1792 let base_ptr = if let (0, Some(m0)) = (memory_index.as_u32(), self.m0_param) {
1794 m0
1795 } else {
1796 match self
1797 .ctx
1798 .memory(memory_index, intrinsics, self.module, self.memory_styles)?
1799 {
1800 MemoryCache::Dynamic {
1801 ptr_to_base_ptr,
1802 ptr_to_current_length,
1803 } => {
1804 let minimum = self.wasm_module.memories[memory_index].minimum;
1806 let value_size_v = intrinsics.i64_ty.const_int(value_size as u64, false);
1807 let ptr_in_bounds = if offset.is_const() {
1808 let load_offset_end =
1811 offset.const_add(value_size_v).get_zero_extended_constant();
1812 if load_offset_end.is_some_and(|load_offset_end| {
1813 load_offset_end <= minimum.bytes().0 as u64
1814 }) {
1815 Some(intrinsics.i64_ty.const_int(1, false))
1816 } else {
1817 None
1818 }
1819 } else {
1820 None
1821 };
1822
1823 let ptr_in_bounds = match ptr_in_bounds {
1824 Some(ptr) => ptr,
1825 None => {
1826 let load_offset_end = err!(builder.build_int_add(
1827 offset,
1828 value_size_v,
1829 "load_offset_end"
1830 ));
1831
1832 let current_length = err!(builder.build_load(
1833 self.intrinsics.i32_ty,
1834 ptr_to_current_length,
1835 "current_length"
1836 ))
1837 .into_int_value();
1838 tbaa_label(
1839 self.module,
1840 self.intrinsics,
1841 format!("memory {} length", memory_index.as_u32()),
1842 current_length.as_instruction_value().unwrap(),
1843 );
1844 let current_length = err!(builder.build_int_z_extend(
1845 current_length,
1846 intrinsics.i64_ty,
1847 "current_length_zextd"
1848 ));
1849
1850 err!(builder.build_int_compare(
1851 IntPredicate::ULE,
1852 load_offset_end,
1853 current_length,
1854 "ptr_in_bounds",
1855 ))
1856 }
1857 };
1858
1859 if !ptr_in_bounds.is_constant_int()
1860 || ptr_in_bounds.get_zero_extended_constant().unwrap() != 1
1861 {
1862 let ptr_in_bounds = err!(self.build_call_with_param_attributes(
1868 intrinsics.expect_i1,
1869 &[
1870 ptr_in_bounds.into(),
1871 intrinsics.i1_ty.const_int(1, true).into(),
1872 ],
1873 "ptr_in_bounds_expect",
1874 ))
1875 .try_as_basic_value()
1876 .unwrap_basic()
1877 .into_int_value();
1878
1879 let in_bounds_continue_block =
1880 context.append_basic_block(*function, "in_bounds_continue_block");
1881 let not_in_bounds_block =
1882 context.append_basic_block(*function, "not_in_bounds_block");
1883 err!(builder.build_conditional_branch(
1884 ptr_in_bounds,
1885 in_bounds_continue_block,
1886 not_in_bounds_block,
1887 ));
1888 builder.position_at_end(not_in_bounds_block);
1889 err!(self.build_call_with_param_attributes(
1890 intrinsics.throw_trap,
1891 &[intrinsics.trap_memory_oob.into()],
1892 "throw",
1893 ));
1894 err!(builder.build_unreachable());
1895 builder.position_at_end(in_bounds_continue_block);
1896 }
1897 let ptr_to_base =
1898 err!(builder.build_load(intrinsics.ptr_ty, ptr_to_base_ptr, "ptr_to_base"))
1899 .into_pointer_value();
1900 tbaa_label(
1901 self.module,
1902 self.intrinsics,
1903 format!("memory base_ptr {}", memory_index.as_u32()),
1904 ptr_to_base.as_instruction_value().unwrap(),
1905 );
1906 ptr_to_base
1907 }
1908 MemoryCache::Static { base_ptr } => base_ptr,
1909 }
1910 };
1911 let value_ptr = unsafe {
1912 err!(builder.build_gep(self.intrinsics.i8_ty, base_ptr, &[offset], "mem_value_ptr"))
1913 };
1914 err_nt!(
1915 builder
1916 .build_bit_cast(value_ptr, ptr_ty, "mem_value")
1917 .map(|v| v.into_pointer_value())
1918 )
1919 }
1920
1921 fn trap_if_misaligned(
1922 &self,
1923 _memarg: &MemArg,
1924 ptr: PointerValue<'ctx>,
1925 align: u8,
1926 ) -> Result<(), CompileError> {
1927 if align <= 1 {
1928 return Ok(());
1929 }
1930 let value = err!(self.builder.build_ptr_to_int(
1931 ptr,
1932 self.intrinsics.i64_ty,
1933 "mischeck_value"
1934 ));
1935 let and = err!(self.builder.build_and(
1936 value,
1937 self.intrinsics.i64_ty.const_int((align - 1).into(), false),
1938 "misaligncheck",
1939 ));
1940 let aligned = err!(self.builder.build_int_compare(
1941 IntPredicate::EQ,
1942 and,
1943 self.intrinsics.i64_zero,
1944 "is_aligned"
1945 ));
1946 let aligned = self
1947 .build_call_with_param_attributes(
1948 self.intrinsics.expect_i1,
1949 &[
1950 aligned.into(),
1951 self.intrinsics.i1_ty.const_int(1, false).into(),
1952 ],
1953 "is_aligned_expect",
1954 )?
1955 .try_as_basic_value()
1956 .unwrap_basic()
1957 .into_int_value();
1958
1959 let continue_block = self
1960 .context
1961 .append_basic_block(self.function, "aligned_access_continue_block");
1962 let not_aligned_block = self
1963 .context
1964 .append_basic_block(self.function, "misaligned_trap_block");
1965 err!(
1966 self.builder
1967 .build_conditional_branch(aligned, continue_block, not_aligned_block)
1968 );
1969
1970 self.builder.position_at_end(not_aligned_block);
1971 self.build_call_with_param_attributes(
1972 self.intrinsics.throw_trap,
1973 &[self.intrinsics.trap_unaligned_atomic.into()],
1974 "throw",
1975 )?;
1976 err!(self.builder.build_unreachable());
1977
1978 self.builder.position_at_end(continue_block);
1979 Ok(())
1980 }
1981
1982 fn finalize(&mut self, wasm_fn_type: &FunctionType) -> Result<(), CompileError> {
1983 let func_type = self.function.get_type();
1984
1985 let results = self.state.popn_save_extra(wasm_fn_type.results().len())?;
1986 let results = err!(
1987 results
1988 .into_iter()
1989 .map(|(v, i)| self.apply_pending_canonicalization(v, i))
1990 .collect::<Result<Vec<_>, _>>()
1991 );
1992
1993 if wasm_fn_type.results().is_empty() {
1994 err!(self.builder.build_return(None));
1995 } else if self.abi.is_sret(wasm_fn_type)? {
1996 let sret = self
1997 .function
1998 .get_first_param()
1999 .unwrap()
2000 .into_pointer_value();
2001 let llvm_params: Vec<_> = wasm_fn_type
2002 .results()
2003 .iter()
2004 .map(|x| type_to_llvm(self.intrinsics, *x).unwrap())
2005 .collect();
2006 let mut struct_value = self
2007 .context
2008 .struct_type(llvm_params.as_slice(), false)
2009 .get_undef();
2010 for (idx, value) in results.into_iter().enumerate() {
2011 let value = err!(self.builder.build_bit_cast(
2012 value,
2013 type_to_llvm(self.intrinsics, wasm_fn_type.results()[idx])?,
2014 "",
2015 ));
2016 struct_value =
2017 err!(
2018 self.builder
2019 .build_insert_value(struct_value, value, idx as u32, "")
2020 )
2021 .into_struct_value();
2022 }
2023 err!(self.builder.build_store(sret, struct_value));
2024 err!(self.builder.build_return(None));
2025 } else {
2026 err!(
2027 self.builder
2028 .build_return(Some(&self.abi.pack_values_for_register_return(
2029 self.intrinsics,
2030 &self.builder,
2031 &results,
2032 wasm_fn_type,
2033 &func_type,
2034 )?))
2035 );
2036 }
2037 Ok(())
2038 }
2039
2040 fn get_or_insert_tag_type_info_global(&mut self, tag: i32) -> BasicValueEnum<'ctx> {
2043 if let Some(tag) = self.tags_cache.get(&tag) {
2044 return *tag;
2045 }
2046
2047 let tag_ty = self
2048 .context
2049 .struct_type(&[self.intrinsics.i32_ty.into()], false);
2050 let tag_glbl = self.module.add_global(
2051 tag_ty,
2052 Some(AddressSpace::default()),
2053 &format!("__wasmer_eh_type_info_{tag}"),
2054 );
2055 tag_glbl.set_initializer(
2056 &tag_ty
2057 .const_named_struct(&[self.intrinsics.i32_ty.const_int(tag as _, false).into()])
2058 .as_basic_value_enum(),
2059 );
2060
2061 tag_glbl.set_linkage(Linkage::LinkOnceODR);
2062 tag_glbl.set_constant(true);
2063 if matches!(self.binary_fmt, target_lexicon::BinaryFormat::Macho) {
2071 tag_glbl.set_section(Some(&format!("{FUNCTION_SECTION_MACHO},_eh_ti_{tag}")));
2072 }
2073
2074 let tag_glbl = tag_glbl.as_basic_value_enum();
2075
2076 self.tags_cache.insert(tag, tag_glbl);
2077 tag_glbl
2078 }
2079
2080 fn emit_return_call(
2081 &mut self,
2082 call_site: CallSiteValue<'ctx>,
2083 callee_llvm_func_type: inkwell::types::FunctionType<'ctx>,
2084 ) -> Result<(), CompileError> {
2085 let tail_call_kind = if self.function.get_type() == callee_llvm_func_type {
2092 LLVMTailCallKind::LLVMTailCallKindMustTail
2093 } else {
2094 LLVMTailCallKind::LLVMTailCallKindTail
2095 };
2096 call_site.set_tail_call_kind(tail_call_kind);
2097
2098 if self.function.get_type().get_return_type().is_none() {
2099 err!(self.builder.build_return(None));
2100 } else {
2101 let ret = call_site.try_as_basic_value();
2102 if ret.is_instruction() {
2103 return Err(CompileError::Codegen(
2104 "return_call expected a non-void call result".to_string(),
2105 ));
2106 }
2107 err!(self.builder.build_return(Some(&ret.unwrap_basic())));
2108 }
2109 Ok(())
2110 }
2111
2112 fn current_sret_ptr(&self, func_type: &FunctionType) -> Option<PointerValue<'ctx>> {
2114 self.abi.is_sret(func_type).ok().map(|_| {
2115 self.function
2116 .get_first_param()
2117 .unwrap()
2118 .into_pointer_value()
2119 })
2120 }
2121
2122 fn build_m0_indirect_call(
2123 &mut self,
2124 table_index: u32,
2125 ctx_ptr: PointerValue<'ctx>,
2126 func_type: &FunctionType,
2127 func_ptr: PointerValue<'ctx>,
2128 func_index: IntValue<'ctx>,
2129 is_return_call: bool,
2130 ) -> Result<(), CompileError> {
2131 let Some(m0) = self.m0_param else {
2132 return Err(CompileError::Codegen(
2133 "Call to build_m0_indirect_call without m0 parameter!".to_string(),
2134 ));
2135 };
2136
2137 let params = self.state.popn_save_extra(func_type.params().len())?;
2138
2139 let mut local_func_indices = vec![];
2140 let mut foreign_func_indices = vec![];
2141
2142 for t in &self.wasm_module.table_initializers {
2143 if t.table_index.as_u32() == table_index {
2144 for (func_in_table_idx, func_idx) in t.elements.iter().enumerate() {
2145 if self.wasm_module.local_func_index(*func_idx).is_some() {
2146 local_func_indices.push(func_in_table_idx)
2147 } else {
2148 foreign_func_indices.push(func_in_table_idx)
2149 }
2150 }
2151 break;
2152 }
2153 }
2154
2155 let needs_switch = !local_func_indices.is_empty() && !foreign_func_indices.is_empty();
2156
2157 if needs_switch {
2158 let foreign_idx_block = self
2159 .context
2160 .append_basic_block(self.function, "foreign_call_block");
2161 let local_idx_block = self
2162 .context
2163 .append_basic_block(self.function, "local_call_block");
2164 let unreachable_indirect_call_branch_block = self
2165 .context
2166 .append_basic_block(self.function, "unreachable_indirect_call_branch");
2167
2168 let cont =
2169 (!is_return_call).then(|| self.context.append_basic_block(self.function, "cont"));
2170
2171 err!(
2172 self.builder.build_switch(
2173 func_index,
2174 unreachable_indirect_call_branch_block,
2175 &local_func_indices
2176 .into_iter()
2177 .map(|v| (
2178 self.intrinsics.i32_ty.const_int(v as _, false),
2179 local_idx_block
2180 ))
2181 .chain(foreign_func_indices.into_iter().map(|v| (
2182 self.intrinsics.i32_ty.const_int(v as _, false),
2183 foreign_idx_block
2184 )))
2185 .collect_vec()
2186 )
2187 );
2188
2189 self.builder
2190 .position_at_end(unreachable_indirect_call_branch_block);
2191 err!(self.builder.build_unreachable());
2192
2193 self.builder.position_at_end(local_idx_block);
2195 let (local_call_site, local_llvm_func_type) = self.build_indirect_call_with_params(
2196 ctx_ptr,
2197 func_type,
2198 func_ptr,
2199 Some(m0),
2200 is_return_call,
2201 ¶ms,
2202 )?;
2203
2204 let local_rets = if is_return_call {
2205 self.emit_return_call(local_call_site, local_llvm_func_type)?;
2206 Vec::new()
2207 } else {
2208 let rets = self.abi.rets_from_call(
2209 &self.builder,
2210 self.intrinsics,
2211 local_call_site,
2212 func_type,
2213 )?;
2214 err!(
2215 self.builder
2216 .build_unconditional_branch(cont.expect("non-return call requires cont"))
2217 );
2218 rets
2219 };
2220 let local_call_block = self
2221 .builder
2222 .get_insert_block()
2223 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2224
2225 self.builder.position_at_end(foreign_idx_block);
2226 let (foreign_call_site, foreign_llvm_func_type) = self
2227 .build_indirect_call_with_params(
2228 ctx_ptr,
2229 func_type,
2230 func_ptr,
2231 None,
2232 is_return_call,
2233 ¶ms,
2234 )?;
2235
2236 let foreign_rets = if is_return_call {
2237 self.emit_return_call(foreign_call_site, foreign_llvm_func_type)?;
2238 Vec::new()
2239 } else {
2240 let rets = self.abi.rets_from_call(
2241 &self.builder,
2242 self.intrinsics,
2243 foreign_call_site,
2244 func_type,
2245 )?;
2246 err!(
2247 self.builder
2248 .build_unconditional_branch(cont.expect("non-return call requires cont"))
2249 );
2250 rets
2251 };
2252 let foreign_call_block = self
2253 .builder
2254 .get_insert_block()
2255 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2256
2257 if is_return_call {
2258 return Ok(());
2259 }
2260
2261 self.builder
2262 .position_at_end(cont.expect("non-return call requires cont"));
2263
2264 if foreign_rets.len() != local_rets.len() {
2265 return Err(CompileError::Codegen(format!(
2266 "mismatched return counts in indirect call branches: foreign={}, local={}.",
2267 foreign_rets.len(),
2268 local_rets.len()
2269 )));
2270 }
2271
2272 for (foreign_ret, local_ret) in foreign_rets.iter().zip(local_rets.iter()) {
2273 let v = err!(self.builder.build_phi(foreign_ret.get_type(), ""));
2274 v.add_incoming(&[
2275 (foreign_ret, foreign_call_block),
2276 (local_ret, local_call_block),
2277 ]);
2278 self.state.push1(v.as_basic_value());
2279 }
2280 } else if foreign_func_indices.is_empty() {
2281 let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
2282 ctx_ptr,
2283 func_type,
2284 func_ptr,
2285 Some(m0),
2286 is_return_call,
2287 ¶ms,
2288 )?;
2289
2290 if is_return_call {
2291 self.emit_return_call(call_site, llvm_func_type)?;
2292 } else {
2293 self.abi
2294 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2295 .iter()
2296 .for_each(|ret| self.state.push1(*ret));
2297 }
2298 } else {
2299 let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
2300 ctx_ptr,
2301 func_type,
2302 func_ptr,
2303 None,
2304 is_return_call,
2305 ¶ms,
2306 )?;
2307 if is_return_call {
2308 self.emit_return_call(call_site, llvm_func_type)?;
2309 } else {
2310 self.abi
2311 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2312 .iter()
2313 .for_each(|ret| self.state.push1(*ret));
2314 }
2315 }
2316
2317 Ok(())
2318 }
2319
2320 fn build_indirect_call(
2321 &mut self,
2322 ctx_ptr: PointerValue<'ctx>,
2323 func_type: &FunctionType,
2324 func_ptr: PointerValue<'ctx>,
2325 m0_param: Option<PointerValue<'ctx>>,
2326 is_return_call: bool,
2327 ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
2328 let params = self.state.popn_save_extra(func_type.params().len())?;
2329 self.build_indirect_call_with_params(
2330 ctx_ptr,
2331 func_type,
2332 func_ptr,
2333 m0_param,
2334 is_return_call,
2335 ¶ms,
2336 )
2337 }
2338
2339 fn build_indirect_call_with_params(
2340 &mut self,
2341 ctx_ptr: PointerValue<'ctx>,
2342 func_type: &FunctionType,
2343 func_ptr: PointerValue<'ctx>,
2344 m0_param: Option<PointerValue<'ctx>>,
2345 is_return_call: bool,
2346 params: &[(BasicValueEnum<'ctx>, ExtraInfo)],
2347 ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
2348 let (llvm_func_type, llvm_func_attrs) = self.abi.func_type_to_llvm(
2349 self.context,
2350 self.intrinsics,
2351 Some(self.ctx.get_offsets()),
2352 func_type,
2353 m0_param.is_some(),
2354 )?;
2355
2356 let params = params
2358 .iter()
2359 .zip(func_type.params().iter())
2360 .map(|((v, info), wasm_ty)| match wasm_ty {
2361 Type::F32 => err_nt!(self.builder.build_bit_cast(
2362 self.apply_pending_canonicalization(*v, *info)?,
2363 self.intrinsics.f32_ty,
2364 "",
2365 )),
2366 Type::F64 => err_nt!(self.builder.build_bit_cast(
2367 self.apply_pending_canonicalization(*v, *info)?,
2368 self.intrinsics.f64_ty,
2369 "",
2370 )),
2371 Type::V128 => self.apply_pending_canonicalization(*v, *info),
2372 _ => Ok(*v),
2373 })
2374 .collect::<Result<Vec<_>, _>>()?;
2375
2376 let params = self.abi.args_to_call(
2377 &self.alloca_builder,
2378 func_type,
2379 &llvm_func_type,
2380 ctx_ptr,
2381 params.as_slice(),
2382 self.intrinsics,
2383 m0_param,
2384 is_return_call
2385 .then(|| self.current_sret_ptr(func_type))
2386 .flatten(),
2387 )?;
2388
2389 let typed_func_ptr = err!(self.builder.build_pointer_cast(
2390 func_ptr,
2391 self.context.ptr_type(AddressSpace::default()),
2392 "typed_func_ptr",
2393 ));
2394
2395 let call_site_local = self.build_indirect_call_or_invoke(
2396 llvm_func_type,
2397 typed_func_ptr,
2398 params.as_slice(),
2399 "then_block",
2400 is_return_call,
2401 )?;
2402 for (attr, attr_loc) in llvm_func_attrs {
2403 call_site_local.add_attribute(attr_loc, attr);
2404 }
2405
2406 Ok((call_site_local, llvm_func_type))
2407 }
2408
2409 fn build_indirect_call_or_invoke(
2410 &mut self,
2411 llvm_func_type: inkwell::types::FunctionType<'ctx>,
2412 func_ptr: PointerValue<'ctx>,
2413 params: &[BasicValueEnum<'ctx>],
2414 then_block_name: &str,
2415 is_return_call: bool,
2416 ) -> Result<CallSiteValue<'ctx>, CompileError> {
2417 if let Some(lpad) = self.state.get_innermost_landingpad()
2420 && !is_return_call
2421 {
2422 let then_block = self
2423 .context
2424 .append_basic_block(self.function, then_block_name);
2425
2426 let ret = err!(self.builder.build_indirect_invoke(
2427 llvm_func_type,
2428 func_ptr,
2429 params,
2430 then_block,
2431 lpad,
2432 "",
2433 ));
2434
2435 self.builder.position_at_end(then_block);
2436 Ok(ret)
2437 } else {
2438 let call_params = params
2439 .iter()
2440 .copied()
2441 .map(Into::into)
2442 .collect::<Vec<BasicMetadataValueEnum>>();
2443 Ok(err!(self.builder.build_indirect_call(
2444 llvm_func_type,
2445 func_ptr,
2446 call_params.as_slice(),
2447 ""
2448 )))
2449 }
2450 }
2451}
2452
2453pub struct LLVMFunctionCodeGenerator<'ctx, 'a> {
2454 m0_param: Option<PointerValue<'ctx>>,
2455 context: &'ctx Context,
2456 builder: Builder<'ctx>,
2457 alloca_builder: Builder<'ctx>,
2458 intrinsics: &'a Intrinsics<'ctx>,
2459 target_data: &'a TargetData,
2460 state: State<'ctx>,
2461 function: FunctionValue<'ctx>,
2462 locals: Vec<(BasicTypeEnum<'ctx>, PointerValue<'ctx>)>, ctx: CtxType<'ctx, 'a>,
2464 unreachable_depth: usize,
2465 memory_styles: &'a PrimaryMap<MemoryIndex, MemoryStyle>,
2466 _table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
2467 module: &'a Module<'ctx>,
2468 module_translation: &'a ModuleTranslationState,
2469 signature_hashes: &'a PrimaryMap<SignatureIndex, SignatureHash>,
2470 wasm_module: &'a ModuleInfo,
2471 #[allow(dead_code)]
2472 symbol_registry: &'a dyn SymbolRegistry,
2473 abi: &'a LLVMAbi,
2474 config: &'a LLVM,
2475 target_triple: Triple,
2476 tags_cache: HashMap<i32, BasicValueEnum<'ctx>>,
2477 binary_fmt: target_lexicon::BinaryFormat,
2478 cpu_features: EnumSet<CpuFeature>,
2479 non_volatile_memory_ops: bool,
2480}
2481
2482impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
2483 fn quiet_nan(&self, value: BasicValueEnum<'ctx>) -> Result<BasicValueEnum<'ctx>, CompileError> {
2484 let intrinsic = if value
2485 .get_type()
2486 .eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2487 {
2488 Some(self.intrinsics.add_f32)
2489 } else if value
2490 .get_type()
2491 .eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2492 {
2493 Some(self.intrinsics.add_f64)
2494 } else if value
2495 .get_type()
2496 .eq(&self.intrinsics.f32x4_ty.as_basic_type_enum())
2497 {
2498 Some(self.intrinsics.add_f32x4)
2499 } else if value
2500 .get_type()
2501 .eq(&self.intrinsics.f64x2_ty.as_basic_type_enum())
2502 {
2503 Some(self.intrinsics.add_f64x2)
2504 } else {
2505 None
2506 };
2507
2508 match intrinsic {
2509 Some(intrinsic) => err_nt!(
2510 self.builder
2511 .build_call(
2512 intrinsic,
2513 &[
2514 value.into(),
2515 value.get_type().const_zero().into(),
2516 self.intrinsics.fp_rounding_md,
2517 self.intrinsics.fp_exception_md,
2518 ],
2519 "",
2520 )
2521 .map(|v| v.try_as_basic_value().unwrap_basic())
2522 ),
2523 None => Ok(value),
2524 }
2525 }
2526
2527 fn finalize_minmax_result(
2528 &self,
2529 value: BasicValueEnum<'ctx>,
2530 ) -> Result<BasicValueEnum<'ctx>, CompileError> {
2531 let ty = value.get_type();
2532 if ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2533 || ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2534 {
2535 let value = value.into_float_value();
2536 let is_nan = err!(self.builder.build_float_compare(
2537 FloatPredicate::UNO,
2538 value,
2539 value,
2540 "res_is_nan"
2541 ));
2542 let quiet = self.quiet_nan(value.as_basic_value_enum())?;
2543 let result =
2544 err!(
2545 self.builder
2546 .build_select(is_nan, quiet, value.as_basic_value_enum(), "")
2547 );
2548 Ok(result.as_basic_value_enum())
2549 } else if ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum()) {
2550 let value = value.into_vector_value();
2551 let is_nan = self
2552 .build_call_with_param_attributes(
2553 self.intrinsics.cmp_f32x4,
2554 &[
2555 value.into(),
2556 value.into(),
2557 self.intrinsics.fp_uno_md,
2558 self.intrinsics.fp_exception_md,
2559 ],
2560 "",
2561 )?
2562 .try_as_basic_value()
2563 .unwrap_basic()
2564 .into_vector_value();
2565 let quiet = self
2566 .quiet_nan(value.as_basic_value_enum())?
2567 .into_vector_value();
2568 let result = err!(self.builder.build_select(
2569 is_nan,
2570 quiet.as_basic_value_enum(),
2571 value.as_basic_value_enum(),
2572 "",
2573 ));
2574 Ok(result.as_basic_value_enum())
2575 } else if ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum()) {
2576 let value = value.into_vector_value();
2577 let is_nan = self
2578 .build_call_with_param_attributes(
2579 self.intrinsics.cmp_f64x2,
2580 &[
2581 value.into(),
2582 value.into(),
2583 self.intrinsics.fp_uno_md,
2584 self.intrinsics.fp_exception_md,
2585 ],
2586 "",
2587 )?
2588 .try_as_basic_value()
2589 .unwrap_basic()
2590 .into_vector_value();
2591 let quiet = self
2592 .quiet_nan(value.as_basic_value_enum())?
2593 .into_vector_value();
2594 let result = err!(self.builder.build_select(
2595 is_nan,
2596 quiet.as_basic_value_enum(),
2597 value.as_basic_value_enum(),
2598 "",
2599 ));
2600 Ok(result.as_basic_value_enum())
2601 } else {
2602 Ok(value)
2603 }
2604 }
2605
2606 fn finalize_rounding_result(
2607 &self,
2608 value: BasicValueEnum<'ctx>,
2609 info: ExtraInfo,
2610 ) -> Result<(BasicValueEnum<'ctx>, ExtraInfo), CompileError> {
2611 let ty = value.get_type();
2612 let is_f32 = ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum());
2613 let is_f64 = ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum());
2614 let is_f32x4 = ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum());
2615 let is_f64x2 = ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum());
2616 debug_assert!(is_f32 || is_f64 || is_f32x4 || is_f64x2);
2617
2618 if matches!(self.target_triple.architecture, Architecture::Riscv64(..)) {
2619 if is_f32 || is_f64 {
2620 let input = value.into_float_value();
2621 let is_nan = err!(self.builder.build_float_compare(
2622 FloatPredicate::UNO,
2623 input,
2624 input,
2625 "res_is_nan",
2626 ));
2627 let canonical_nan_bits = if is_f32 {
2628 self.intrinsics
2629 .i32_ty
2630 .const_int(CANONICAL_NAN_F32 as _, false)
2631 } else {
2632 self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false)
2633 };
2634 let canonical_nan = err!(self.builder.build_bit_cast(
2635 canonical_nan_bits,
2636 ty,
2637 "canonical_nan",
2638 ));
2639 let res =
2640 err!(
2641 self.builder
2642 .build_select(is_nan, canonical_nan, value, "canonical_nan",)
2643 );
2644 Ok((res, info))
2645 } else if is_f32x4 {
2646 let value = value.into_vector_value();
2647 let is_nan = err!(self.builder.build_call(
2648 self.intrinsics.cmp_f32x4,
2649 &[
2650 value.into(),
2651 value.into(),
2652 self.intrinsics.fp_uno_md,
2653 self.intrinsics.fp_exception_md,
2654 ],
2655 "",
2656 ))
2657 .try_as_basic_value()
2658 .unwrap_basic()
2659 .into_vector_value();
2660 let canonical_nan_bits = self
2661 .intrinsics
2662 .i32_ty
2663 .const_int(CANONICAL_NAN_F32 as _, false);
2664 let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 4]);
2665 let canonical_nan = err!(self.builder.build_bit_cast(
2666 canonical_nan_bits,
2667 self.intrinsics.f32x4_ty,
2668 "canonical_nan",
2669 ));
2670 let res = err!(self.builder.build_select(
2671 is_nan,
2672 canonical_nan.as_basic_value_enum(),
2673 value.as_basic_value_enum(),
2674 "canonical_nan",
2675 ));
2676 Ok((res, info))
2677 } else {
2678 let value = value.into_vector_value();
2679 let is_nan = err!(self.builder.build_call(
2680 self.intrinsics.cmp_f64x2,
2681 &[
2682 value.into(),
2683 value.into(),
2684 self.intrinsics.fp_uno_md,
2685 self.intrinsics.fp_exception_md,
2686 ],
2687 "",
2688 ))
2689 .try_as_basic_value()
2690 .unwrap_basic()
2691 .into_vector_value();
2692 let canonical_nan_bits = self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false);
2693 let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 2]);
2694 let canonical_nan = err!(self.builder.build_bit_cast(
2695 canonical_nan_bits,
2696 self.intrinsics.f64x2_ty,
2697 "canonical_nan",
2698 ));
2699 let res = err!(self.builder.build_select(
2700 is_nan,
2701 canonical_nan.as_basic_value_enum(),
2702 value.as_basic_value_enum(),
2703 "canonical_nan",
2704 ));
2705 Ok((res, info))
2706 }
2707 } else {
2708 Ok((
2709 value,
2710 (info
2711 | if is_f32 || is_f32x4 {
2712 ExtraInfo::pending_f32_nan()
2713 } else {
2714 ExtraInfo::pending_f64_nan()
2715 })?,
2716 ))
2717 }
2718 }
2719
2720 fn translate_control_flow_operator(&mut self, op: Operator) -> Result<(), CompileError> {
2723 match op {
2724 Operator::Block { blockty } => {
2725 let current_block = self
2726 .builder
2727 .get_insert_block()
2728 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2729
2730 let end_block = self.context.append_basic_block(self.function, "end");
2731 self.builder.position_at_end(end_block);
2732
2733 let phis: SmallVec<[PhiValue<'ctx>; 1]> = self
2734 .module_translation
2735 .blocktype_params_results(&blockty)?
2736 .1
2737 .iter()
2738 .map(|&wp_ty| {
2739 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2740 type_to_llvm(self.intrinsics, wasm_ty)
2741 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2742 })
2743 })
2744 .collect::<Result<_, _>>()?;
2745
2746 self.state.push_block(
2747 end_block,
2748 phis,
2749 self.module_translation
2750 .blocktype_params_results(&blockty)?
2751 .0
2752 .len(),
2753 );
2754 self.builder.position_at_end(current_block);
2755 }
2756 Operator::Loop { blockty } => {
2757 let loop_body = self.context.append_basic_block(self.function, "loop_body");
2758 let loop_next = self.context.append_basic_block(self.function, "loop_outer");
2759 let pre_loop_block = self.builder.get_insert_block().unwrap();
2760
2761 let blocktypes = self.module_translation.blocktype_params_results(&blockty)?;
2762
2763 self.builder.position_at_end(loop_next);
2764 let phis = blocktypes
2765 .1
2766 .iter()
2767 .map(|&wp_ty| {
2768 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2769 type_to_llvm(self.intrinsics, wasm_ty)
2770 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2771 })
2772 })
2773 .collect::<Result<_, _>>()?;
2774 self.builder.position_at_end(loop_body);
2775 let loop_phis: SmallVec<[PhiValue<'ctx>; 1]> = blocktypes
2776 .0
2777 .iter()
2778 .map(|&wp_ty| {
2779 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2780 type_to_llvm(self.intrinsics, wasm_ty)
2781 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2782 })
2783 })
2784 .collect::<Result<_, _>>()?;
2785
2786 self.builder.position_at_end(pre_loop_block);
2790 for phi in loop_phis.iter().rev() {
2791 let (value, info) = self.state.pop1_extra()?;
2792 let value = self.apply_pending_canonicalization(value, info)?;
2793 phi.add_incoming(&[(&value, pre_loop_block)]);
2794 }
2795
2796 err!(self.builder.build_unconditional_branch(loop_body));
2797
2798 self.builder.position_at_end(loop_body);
2799 for phi in &loop_phis {
2800 self.state.push1(phi.as_basic_value());
2801 }
2802
2803 let num_inputs = loop_phis.len();
2804 self.state
2805 .push_loop(loop_body, loop_next, loop_phis, phis, num_inputs);
2806 }
2807 Operator::Br { relative_depth } => {
2808 let frame = self.state.frame_at_depth(relative_depth)?;
2809
2810 let current_block = self
2811 .builder
2812 .get_insert_block()
2813 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2814
2815 let phis = if frame.is_loop() {
2816 frame.loop_body_phis()
2817 } else {
2818 frame.phis()
2819 };
2820
2821 let len = phis.len();
2822 let values = self.state.peekn_extra(len)?;
2823 let values = values
2824 .iter()
2825 .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2826 .collect::<Result<Vec<_>, _>>()?;
2827
2828 for (phi, value) in phis.iter().zip(values) {
2832 phi.add_incoming(&[(&value, current_block)]);
2833 }
2834
2835 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2836
2837 self.state.popn(len)?;
2838 self.state.reachable = false;
2839 }
2840 Operator::BrIf { relative_depth } => {
2841 let cond = self.state.pop1()?;
2842 let frame = self.state.frame_at_depth(relative_depth)?;
2843
2844 let current_block = self
2845 .builder
2846 .get_insert_block()
2847 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2848
2849 let phis = if frame.is_loop() {
2850 frame.loop_body_phis()
2851 } else {
2852 frame.phis()
2853 };
2854
2855 let param_stack = self.state.peekn_extra(phis.len())?;
2856 let param_stack = param_stack
2857 .iter()
2858 .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2859 .collect::<Result<Vec<_>, _>>()?;
2860
2861 for (phi, value) in phis.iter().zip(param_stack) {
2862 phi.add_incoming(&[(&value, current_block)]);
2863 }
2864
2865 let else_block = self.context.append_basic_block(self.function, "else");
2866
2867 let cond_value = err!(self.builder.build_int_compare(
2868 IntPredicate::NE,
2869 cond.into_int_value(),
2870 self.intrinsics.i32_zero,
2871 "",
2872 ));
2873 err!(self.builder.build_conditional_branch(
2874 cond_value,
2875 *frame.br_dest(),
2876 else_block
2877 ));
2878 self.builder.position_at_end(else_block);
2879 }
2880 Operator::BrTable { ref targets } => {
2881 let current_block = self
2882 .builder
2883 .get_insert_block()
2884 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2885
2886 let index = self.state.pop1()?;
2887
2888 let default_frame = self.state.frame_at_depth(targets.default())?;
2889
2890 let phis = if default_frame.is_loop() {
2891 default_frame.loop_body_phis()
2892 } else {
2893 default_frame.phis()
2894 };
2895 let args = self.state.peekn(phis.len())?;
2896
2897 for (phi, value) in phis.iter().zip(args.iter()) {
2898 phi.add_incoming(&[(value, current_block)]);
2899 }
2900
2901 let cases: Vec<_> = targets
2902 .targets()
2903 .enumerate()
2904 .map(|(case_index, depth)| {
2905 let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
2906 let frame_result: Result<&ControlFrame, CompileError> =
2907 self.state.frame_at_depth(depth);
2908 let frame = match frame_result {
2909 Ok(v) => v,
2910 Err(e) => return Err(e),
2911 };
2912 let case_index_literal =
2913 self.context.i32_type().const_int(case_index as u64, false);
2914 let phis = if frame.is_loop() {
2915 frame.loop_body_phis()
2916 } else {
2917 frame.phis()
2918 };
2919 for (phi, value) in phis.iter().zip(args.iter()) {
2920 phi.add_incoming(&[(value, current_block)]);
2921 }
2922
2923 Ok((case_index_literal, *frame.br_dest()))
2924 })
2925 .collect::<Result<_, _>>()?;
2926
2927 err!(self.builder.build_switch(
2928 index.into_int_value(),
2929 *default_frame.br_dest(),
2930 &cases[..],
2931 ));
2932
2933 let args_len = args.len();
2934 self.state.popn(args_len)?;
2935 self.state.reachable = false;
2936 }
2937 Operator::If { blockty } => {
2938 let current_block = self
2939 .builder
2940 .get_insert_block()
2941 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2942 let if_then_block = self.context.append_basic_block(self.function, "if_then");
2943 let if_else_block = self.context.append_basic_block(self.function, "if_else");
2944 let end_block = self.context.append_basic_block(self.function, "if_end");
2945
2946 let end_phis = {
2947 self.builder.position_at_end(end_block);
2948
2949 let phis = self
2950 .module_translation
2951 .blocktype_params_results(&blockty)?
2952 .1
2953 .iter()
2954 .map(|&wp_ty| {
2955 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2956 type_to_llvm(self.intrinsics, wasm_ty)
2957 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2958 })
2959 })
2960 .collect::<Result<_, _>>()?;
2961
2962 self.builder.position_at_end(current_block);
2963 phis
2964 };
2965
2966 let block_param_types = self
2967 .module_translation
2968 .blocktype_params_results(&blockty)?
2969 .0
2970 .iter()
2971 .map(|&wp_ty| {
2972 err_nt!(wptype_to_type(wp_ty))
2973 .and_then(|wasm_ty| type_to_llvm(self.intrinsics, wasm_ty))
2974 })
2975 .collect::<Result<Vec<_>, _>>()?;
2976
2977 self.builder.position_at_end(if_else_block);
2979 let else_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2980 .iter()
2981 .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2982 .collect::<Result<SmallVec<_>, _>>()?;
2983 self.builder.position_at_end(if_then_block);
2984 let then_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2985 .iter()
2986 .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2987 .collect::<Result<SmallVec<_>, _>>()?;
2988
2989 let cond = self.state.pop1()?;
2991
2992 self.builder.position_at_end(current_block);
2996 for (else_phi, then_phi) in else_phis.iter().rev().zip(then_phis.iter().rev()) {
2997 let (value, info) = self.state.pop1_extra()?;
2998 let value = self.apply_pending_canonicalization(value, info)?;
2999 else_phi.add_incoming(&[(&value, current_block)]);
3000 then_phi.add_incoming(&[(&value, current_block)]);
3001 }
3002
3003 let cond_value = err!(self.builder.build_int_compare(
3004 IntPredicate::NE,
3005 cond.into_int_value(),
3006 self.intrinsics.i32_zero,
3007 "",
3008 ));
3009
3010 err!(self.builder.build_conditional_branch(
3011 cond_value,
3012 if_then_block,
3013 if_else_block
3014 ));
3015
3016 self.builder.position_at_end(if_then_block);
3017 for phi in then_phis.iter() {
3018 self.state.push1(phi.as_basic_value());
3019 }
3020
3021 self.state.push_if(
3022 if_then_block,
3023 if_else_block,
3024 end_block,
3025 then_phis,
3026 else_phis,
3027 end_phis,
3028 block_param_types.len(),
3029 );
3030 }
3031 Operator::Else => {
3032 if self.state.reachable {
3033 let frame = self.state.frame_at_depth(0)?;
3034 let current_block = self.builder.get_insert_block().ok_or_else(|| {
3035 CompileError::Codegen("not currently in a block".to_string())
3036 })?;
3037
3038 for phi in frame.phis().to_vec().iter().rev() {
3039 let (value, info) = self.state.pop1_extra()?;
3040 let value = self.apply_pending_canonicalization(value, info)?;
3041 phi.add_incoming(&[(&value, current_block)])
3042 }
3043
3044 let frame = self.state.frame_at_depth(0)?;
3045 err!(self.builder.build_unconditional_branch(*frame.code_after()));
3046 }
3047
3048 let (if_else_block, if_else_state) = if let ControlFrame::IfElse {
3049 if_else,
3050 if_else_state,
3051 ..
3052 } = self.state.frame_at_depth_mut(0)?
3053 {
3054 (if_else, if_else_state)
3055 } else {
3056 unreachable!()
3057 };
3058
3059 *if_else_state = IfElseState::Else;
3060
3061 self.builder.position_at_end(*if_else_block);
3062 self.state.reachable = true;
3063
3064 if let ControlFrame::IfElse { else_phis, .. } = self.state.frame_at_depth(0)? {
3065 for phi in else_phis.clone().iter() {
3067 self.state.push1(phi.as_basic_value());
3068 }
3069 };
3070 }
3071
3072 Operator::End => {
3073 let frame = self.state.pop_frame()?;
3074 let current_block = self
3075 .builder
3076 .get_insert_block()
3077 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
3078
3079 if self.state.reachable {
3080 for phi in frame.phis().iter().rev() {
3081 let (value, info) = self.state.pop1_extra()?;
3082 let value = self.apply_pending_canonicalization(value, info)?;
3083 phi.add_incoming(&[(&value, current_block)]);
3084 }
3085
3086 err!(self.builder.build_unconditional_branch(*frame.code_after()));
3087 }
3088
3089 if let ControlFrame::IfElse {
3090 if_else,
3091 next,
3092 if_else_state: IfElseState::If,
3093 else_phis,
3094 ..
3095 } = &frame
3096 {
3097 for (phi, else_phi) in frame.phis().iter().zip(else_phis.iter()) {
3098 phi.add_incoming(&[(&else_phi.as_basic_value(), *if_else)]);
3099 }
3100 self.builder.position_at_end(*if_else);
3101 err!(self.builder.build_unconditional_branch(*next));
3102 } else if let ControlFrame::Landingpad { .. } = &frame {
3103 self.state.pop_landingpad();
3104 };
3105
3106 self.builder.position_at_end(*frame.code_after());
3107 self.state.reset_stack(&frame);
3108
3109 self.state.reachable = true;
3110
3111 for phi in frame.phis() {
3113 if phi.count_incoming() != 0 {
3114 self.state.push1(phi.as_basic_value());
3115 } else {
3116 let basic_ty = phi.as_basic_value().get_type();
3123 let placeholder_value = basic_ty.const_zero();
3124 self.state.push1(placeholder_value);
3125 phi.as_instruction().erase_from_basic_block();
3126 }
3127 }
3128 }
3129 Operator::Return => {
3130 let current_block = self
3131 .builder
3132 .get_insert_block()
3133 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
3134
3135 let frame = self.state.outermost_frame()?;
3136 for phi in frame.phis().to_vec().iter().rev() {
3137 let (arg, info) = self.state.pop1_extra()?;
3138 let arg = self.apply_pending_canonicalization(arg, info)?;
3139 phi.add_incoming(&[(&arg, current_block)]);
3140 }
3141 let frame = self.state.outermost_frame()?;
3142 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
3143
3144 self.state.reachable = false;
3145 }
3146
3147 Operator::Unreachable => {
3148 self.build_call_with_param_attributes(
3149 self.intrinsics.throw_trap,
3150 &[self.intrinsics.trap_unreachable.into()],
3151 "throw",
3152 )?;
3153 err!(self.builder.build_unreachable());
3154
3155 self.state.reachable = false;
3156 }
3157 _ => unreachable!(),
3158 }
3159
3160 Ok(())
3161 }
3162
3163 fn translate_basic_operator(&mut self, op: Operator) -> Result<(), CompileError> {
3166 let vmctx = &self.ctx.basic().into_pointer_value();
3167
3168 match op {
3169 Operator::Nop => {
3170 }
3172 Operator::Drop => {
3173 self.state.pop1()?;
3174 }
3175
3176 Operator::I32Const { value } => {
3178 let i = self.intrinsics.i32_ty.const_int(value as u64, false);
3179 let info = if is_f32_arithmetic(value as u32) {
3180 ExtraInfo::arithmetic_f32()
3181 } else {
3182 Default::default()
3183 };
3184 self.state.push1_extra(i, info);
3185 }
3186 Operator::I64Const { value } => {
3187 let i = self.intrinsics.i64_ty.const_int(value as u64, false);
3188 let info = if is_f64_arithmetic(value as u64) {
3189 ExtraInfo::arithmetic_f64()
3190 } else {
3191 Default::default()
3192 };
3193 self.state.push1_extra(i, info);
3194 }
3195 Operator::F32Const { value } => {
3196 let bits = self.intrinsics.i32_ty.const_int(value.bits() as u64, false);
3197 let info = if is_f32_arithmetic(value.bits()) {
3198 ExtraInfo::arithmetic_f32()
3199 } else {
3200 Default::default()
3201 };
3202 let f = err!(
3203 self.builder
3204 .build_bit_cast(bits, self.intrinsics.f32_ty, "f")
3205 );
3206 self.state.push1_extra(f, info);
3207 }
3208 Operator::F64Const { value } => {
3209 let bits = self.intrinsics.i64_ty.const_int(value.bits(), false);
3210 let info = if is_f64_arithmetic(value.bits()) {
3211 ExtraInfo::arithmetic_f64()
3212 } else {
3213 Default::default()
3214 };
3215 let f = err!(
3216 self.builder
3217 .build_bit_cast(bits, self.intrinsics.f64_ty, "f")
3218 );
3219 self.state.push1_extra(f, info);
3220 }
3221 Operator::V128Const { value } => {
3222 let mut hi: [u8; 8] = Default::default();
3223 let mut lo: [u8; 8] = Default::default();
3224 hi.copy_from_slice(&value.bytes()[0..8]);
3225 lo.copy_from_slice(&value.bytes()[8..16]);
3226 let packed = [u64::from_le_bytes(hi), u64::from_le_bytes(lo)];
3227 let i = self
3228 .intrinsics
3229 .i128_ty
3230 .const_int_arbitrary_precision(&packed);
3231 let mut quad1: [u8; 4] = Default::default();
3232 let mut quad2: [u8; 4] = Default::default();
3233 let mut quad3: [u8; 4] = Default::default();
3234 let mut quad4: [u8; 4] = Default::default();
3235 quad1.copy_from_slice(&value.bytes()[0..4]);
3236 quad2.copy_from_slice(&value.bytes()[4..8]);
3237 quad3.copy_from_slice(&value.bytes()[8..12]);
3238 quad4.copy_from_slice(&value.bytes()[12..16]);
3239 let mut info: ExtraInfo = Default::default();
3240 if is_f32_arithmetic(u32::from_le_bytes(quad1))
3241 && is_f32_arithmetic(u32::from_le_bytes(quad2))
3242 && is_f32_arithmetic(u32::from_le_bytes(quad3))
3243 && is_f32_arithmetic(u32::from_le_bytes(quad4))
3244 {
3245 info |= ExtraInfo::arithmetic_f32();
3246 }
3247 if is_f64_arithmetic(packed[0]) && is_f64_arithmetic(packed[1]) {
3248 info |= ExtraInfo::arithmetic_f64();
3249 }
3250 self.state.push1_extra(i, info);
3251 }
3252
3253 Operator::I8x16Splat => {
3254 let (v, i) = self.state.pop1_extra()?;
3255 let v = v.into_int_value();
3256 let v = err!(
3257 self.builder
3258 .build_int_truncate(v, self.intrinsics.i8_ty, "")
3259 );
3260 let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
3261 let res = err!(
3262 self.builder
3263 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3264 );
3265 self.state.push1_extra(res, i);
3266 }
3267 Operator::I16x8Splat => {
3268 let (v, i) = self.state.pop1_extra()?;
3269 let v = v.into_int_value();
3270 let v = err!(
3271 self.builder
3272 .build_int_truncate(v, self.intrinsics.i16_ty, "")
3273 );
3274 let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
3275 let res = err!(
3276 self.builder
3277 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3278 );
3279 self.state.push1_extra(res, i);
3280 }
3281 Operator::I32x4Splat => {
3282 let (v, i) = self.state.pop1_extra()?;
3283 let res = self.splat_vector(v, self.intrinsics.i32x4_ty)?;
3284 let res = err!(
3285 self.builder
3286 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3287 );
3288 self.state.push1_extra(res, i);
3289 }
3290 Operator::I64x2Splat => {
3291 let (v, i) = self.state.pop1_extra()?;
3292 let res = self.splat_vector(v, self.intrinsics.i64x2_ty)?;
3293 let res = err!(
3294 self.builder
3295 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3296 );
3297 self.state.push1_extra(res, i);
3298 }
3299 Operator::F32x4Splat => {
3300 let (v, i) = self.state.pop1_extra()?;
3301 let res = self.splat_vector(v, self.intrinsics.f32x4_ty)?;
3302 let res = err!(
3303 self.builder
3304 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3305 );
3306 self.state.push1_extra(res, i);
3309 }
3310 Operator::F64x2Splat => {
3311 let (v, i) = self.state.pop1_extra()?;
3312 let res = self.splat_vector(v, self.intrinsics.f64x2_ty)?;
3313 let res = err!(
3314 self.builder
3315 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3316 );
3317 self.state.push1_extra(res, i);
3320 }
3321
3322 Operator::LocalGet { local_index } => {
3324 let (type_value, pointer_value) = self.locals[local_index as usize];
3325 let v = err!(self.builder.build_load(
3326 type_value,
3327 pointer_value,
3328 &format!("local_{local_index}_get")
3329 ));
3330 tbaa_label(
3331 self.module,
3332 self.intrinsics,
3333 format!("local {local_index}"),
3334 v.as_instruction_value().unwrap(),
3335 );
3336 self.state.push1(v);
3337 }
3338 Operator::LocalSet { local_index } => {
3339 let pointer_value = self.locals[local_index as usize].1;
3340 let (v, i) = self.state.pop1_extra()?;
3341 let v = self.apply_pending_canonicalization(v, i)?;
3342 let store = err!(self.builder.build_store(pointer_value, v));
3343 tbaa_label(
3344 self.module,
3345 self.intrinsics,
3346 format!("local {local_index}"),
3347 store,
3348 );
3349 }
3350 Operator::LocalTee { local_index } => {
3351 let pointer_value = self.locals[local_index as usize].1;
3352 let (v, i) = self.state.peek1_extra()?;
3353 let v = self.apply_pending_canonicalization(v, i)?;
3354 let store = err!(self.builder.build_store(pointer_value, v));
3355 tbaa_label(
3356 self.module,
3357 self.intrinsics,
3358 format!("local {local_index}"),
3359 store,
3360 );
3361 }
3362
3363 Operator::GlobalGet { global_index } => {
3364 let global_index = GlobalIndex::from_u32(global_index);
3365 match self
3366 .ctx
3367 .global(global_index, self.intrinsics, self.module)?
3368 {
3369 GlobalCache::Const { value } => {
3370 self.state.push1(*value);
3371 }
3372 GlobalCache::Mut {
3373 ptr_to_value,
3374 value_type,
3375 } => {
3376 let value = err!(self.builder.build_load(*value_type, *ptr_to_value, ""));
3377 tbaa_label(
3378 self.module,
3379 self.intrinsics,
3380 format!("global {}", global_index.as_u32()),
3381 value.as_instruction_value().unwrap(),
3382 );
3383 self.state.push1(value);
3384 }
3385 }
3386 }
3387 Operator::GlobalSet { global_index } => {
3388 let global_index = GlobalIndex::from_u32(global_index);
3389 match self
3390 .ctx
3391 .global(global_index, self.intrinsics, self.module)?
3392 {
3393 GlobalCache::Const { value: _ } => {
3394 return Err(CompileError::Codegen(format!(
3395 "global.set on immutable global index {}",
3396 global_index.as_u32()
3397 )));
3398 }
3399 GlobalCache::Mut { ptr_to_value, .. } => {
3400 let ptr_to_value = *ptr_to_value;
3401 let (value, info) = self.state.pop1_extra()?;
3402 let value = self.apply_pending_canonicalization(value, info)?;
3403 let store = err!(self.builder.build_store(ptr_to_value, value));
3404 tbaa_label(
3405 self.module,
3406 self.intrinsics,
3407 format!("global {}", global_index.as_u32()),
3408 store,
3409 );
3410 }
3411 }
3412 }
3413
3414 Operator::TypedSelect { .. } | Operator::Select => {
3417 let ((v1, i1), (v2, i2), (cond, _)) = self.state.pop3_extra()?;
3418 let (v1, i1, v2, i2) = if i1.has_pending_f32_nan() != i2.has_pending_f32_nan()
3426 || i1.has_pending_f64_nan() != i2.has_pending_f64_nan()
3427 {
3428 (
3429 self.apply_pending_canonicalization(v1, i1)?,
3430 i1.strip_pending(),
3431 self.apply_pending_canonicalization(v2, i2)?,
3432 i2.strip_pending(),
3433 )
3434 } else {
3435 (v1, i1, v2, i2)
3436 };
3437 let cond_value = err!(self.builder.build_int_compare(
3438 IntPredicate::NE,
3439 cond.into_int_value(),
3440 self.intrinsics.i32_zero,
3441 "",
3442 ));
3443 let res = err!(self.builder.build_select(cond_value, v1, v2, ""));
3444 let info = {
3445 let mut info = (i1.strip_pending() & i2.strip_pending())?;
3446 if i1.has_pending_f32_nan() {
3447 debug_assert!(i2.has_pending_f32_nan());
3448 info = (info | ExtraInfo::pending_f32_nan())?;
3449 }
3450 if i1.has_pending_f64_nan() {
3451 debug_assert!(i2.has_pending_f64_nan());
3452 info = (info | ExtraInfo::pending_f64_nan())?;
3453 }
3454 info
3455 };
3456 self.state.push1_extra(res, info);
3457 }
3458 Operator::Call { function_index } | Operator::ReturnCall { function_index } => {
3459 let is_return_call = matches!(op, Operator::ReturnCall { .. });
3460 let func_index = FunctionIndex::from_u32(function_index);
3461 let sigindex = &self.wasm_module.functions[func_index];
3462 let func_type = &self.wasm_module.signatures[*sigindex];
3463
3464 let FunctionCache {
3465 func,
3466 llvm_func_type,
3467 vmctx: callee_vmctx,
3468 imported_include_m0_param,
3469 attrs,
3470 } = if let Some(local_func_index) = self.wasm_module.local_func_index(func_index) {
3471 self.ctx.local_func(
3472 local_func_index,
3473 func_index,
3474 self.intrinsics,
3475 self.module,
3476 self.context,
3477 func_type,
3478 &CompiledKind::Local(local_func_index, String::new()).linkage_name(),
3479 )?
3480 } else {
3481 self.ctx
3482 .imported_func(func_index, self.intrinsics, self.context, func_type)?
3483 };
3484 let llvm_func_type = *llvm_func_type;
3485 let func = *func;
3486 let callee_vmctx = *callee_vmctx;
3487 let imported_include_m0_param = *imported_include_m0_param;
3488 let attrs = attrs.clone();
3489
3490 let params = self.state.popn_save_extra(func_type.params().len())?;
3496
3497 let params = params
3499 .iter()
3500 .zip(func_type.params().iter())
3501 .map(|((v, info), wasm_ty)| match wasm_ty {
3502 Type::F32 => err_nt!(self.builder.build_bit_cast(
3503 self.apply_pending_canonicalization(*v, *info)?,
3504 self.intrinsics.f32_ty,
3505 "",
3506 )),
3507 Type::F64 => err_nt!(self.builder.build_bit_cast(
3508 self.apply_pending_canonicalization(*v, *info)?,
3509 self.intrinsics.f64_ty,
3510 "",
3511 )),
3512 Type::V128 => self.apply_pending_canonicalization(*v, *info),
3513 _ => Ok(*v),
3514 })
3515 .collect::<Result<Vec<_>, _>>()?;
3516
3517 if let (Some(m0_param), Some(include_m0_param)) =
3518 (self.m0_param, imported_include_m0_param)
3519 {
3520 let (llvm_func_type_no_m0, llvm_func_attrs_no_m0) =
3524 self.abi.func_type_to_llvm(
3525 self.context,
3526 self.intrinsics,
3527 Some(self.ctx.get_offsets()),
3528 func_type,
3529 false,
3530 )?;
3531 let params_with_m0 = self.abi.args_to_call(
3532 &self.alloca_builder,
3533 func_type,
3534 &llvm_func_type,
3535 callee_vmctx.into_pointer_value(),
3536 params.as_slice(),
3537 self.intrinsics,
3538 Some(m0_param),
3539 is_return_call
3540 .then(|| self.current_sret_ptr(func_type))
3541 .flatten(),
3542 )?;
3543 let params_no_m0 = self.abi.args_to_call(
3544 &self.alloca_builder,
3545 func_type,
3546 &llvm_func_type_no_m0,
3547 callee_vmctx.into_pointer_value(),
3548 params.as_slice(),
3549 self.intrinsics,
3550 None,
3551 is_return_call
3552 .then(|| self.current_sret_ptr(func_type))
3553 .flatten(),
3554 )?;
3555
3556 let include_m0_call_block = self
3557 .context
3558 .append_basic_block(self.function, "call_block_with_m0");
3559 let skip_m0_call_block =
3560 self.context.append_basic_block(self.function, "call_block");
3561 let call_cont = self.context.append_basic_block(self.function, "call_cont");
3562 err!(self.builder.build_conditional_branch(
3563 include_m0_param,
3564 include_m0_call_block,
3565 skip_m0_call_block,
3566 ));
3567
3568 self.builder.position_at_end(include_m0_call_block);
3569 let call_site_with_m0 = self.build_indirect_call_or_invoke(
3570 llvm_func_type,
3571 func,
3572 params_with_m0.as_slice(),
3573 "then_block_with_m0",
3574 is_return_call,
3575 )?;
3576 for (attr, attr_loc) in &attrs {
3577 call_site_with_m0.add_attribute(*attr_loc, *attr);
3578 }
3579 let rets_with_m0 = self.abi.rets_from_call(
3580 &self.builder,
3581 self.intrinsics,
3582 call_site_with_m0,
3583 func_type,
3584 )?;
3585 let with_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3586 CompileError::Codegen(
3587 "missing insertion block after call with m0".to_string(),
3588 )
3589 })?;
3590 err!(self.builder.build_unconditional_branch(call_cont));
3591
3592 self.builder.position_at_end(skip_m0_call_block);
3593 let call_site_no_m0 = self.build_indirect_call_or_invoke(
3594 llvm_func_type_no_m0,
3595 func,
3596 params_no_m0.as_slice(),
3597 "then_block",
3598 is_return_call,
3599 )?;
3600 for (attr, attr_loc) in &llvm_func_attrs_no_m0 {
3601 call_site_no_m0.add_attribute(*attr_loc, *attr);
3602 }
3603 let rets_no_m0 = self.abi.rets_from_call(
3604 &self.builder,
3605 self.intrinsics,
3606 call_site_no_m0,
3607 func_type,
3608 )?;
3609 let no_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3610 CompileError::Codegen(
3611 "missing insertion block after call without m0".to_string(),
3612 )
3613 })?;
3614 err!(self.builder.build_unconditional_branch(call_cont));
3615
3616 self.builder.position_at_end(call_cont);
3617 for i in 0..rets_with_m0.len() {
3618 let with_m0 = rets_with_m0[i];
3619 let no_m0 = rets_no_m0[i];
3620 let phi = err!(self.builder.build_phi(with_m0.get_type(), ""));
3621 phi.add_incoming(&[(&with_m0, with_m0_pred), (&no_m0, no_m0_pred)]);
3622 self.state.push1(phi.as_basic_value());
3623 }
3624 } else {
3625 let params = self.abi.args_to_call(
3626 &self.alloca_builder,
3627 func_type,
3628 &llvm_func_type,
3629 callee_vmctx.into_pointer_value(),
3630 params.as_slice(),
3631 self.intrinsics,
3632 self.m0_param,
3633 if is_return_call {
3634 self.current_sret_ptr(func_type)
3635 } else {
3636 None
3637 },
3638 )?;
3639
3640 let call_site = self.build_indirect_call_or_invoke(
3641 llvm_func_type,
3642 func,
3643 params.as_slice(),
3644 "then_block",
3645 is_return_call,
3646 )?;
3647 for (attr, attr_loc) in attrs {
3648 call_site.add_attribute(attr_loc, attr);
3649 }
3650
3651 if is_return_call {
3652 self.emit_return_call(call_site, llvm_func_type)?;
3653 self.state.reachable = false;
3654 } else {
3655 self.abi
3656 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3657 .iter()
3658 .for_each(|ret| self.state.push1(*ret));
3659 }
3660 }
3661 }
3662 Operator::CallIndirect {
3663 type_index,
3664 table_index,
3665 }
3666 | Operator::ReturnCallIndirect {
3667 type_index,
3668 table_index,
3669 } => {
3670 let is_return_call = matches!(op, Operator::ReturnCallIndirect { .. });
3671 let sigindex = SignatureIndex::from_u32(type_index);
3672 let table_index = TableIndex::from_u32(table_index);
3673 let func_type = &self.wasm_module.signatures[sigindex];
3674 let table = self.wasm_module.tables.get(table_index).unwrap();
3675 let local_fixed_funcref_table = self
3676 .wasm_module
3677 .local_table_index(table_index)
3678 .filter(|_| table.is_fixed_funcref_table());
3679 let expected_signature_hash = self
3680 .intrinsics
3681 .i32_ty
3682 .const_int(u64::from(self.signature_hashes[sigindex].as_u32()), false);
3683
3684 let func_index = self.state.pop1()?.into_int_value();
3685 let generic_table = if local_fixed_funcref_table.is_none() {
3686 Some(self.ctx.table(
3687 table_index,
3688 self.intrinsics,
3689 self.module,
3690 &self.builder,
3691 )?)
3692 } else {
3693 None
3694 };
3695
3696 let table_bound = if local_fixed_funcref_table.is_some() {
3697 self.intrinsics
3698 .i32_ty
3699 .const_int(table.minimum.into(), false)
3700 } else {
3701 let (_, table_bound) = *generic_table.as_ref().unwrap();
3702 err!(self.builder.build_int_truncate(
3703 table_bound,
3704 self.intrinsics.i32_ty,
3705 "truncated_table_bounds",
3706 ))
3707 };
3708
3709 let index_in_bounds = err!(self.builder.build_int_compare(
3711 IntPredicate::ULT,
3712 func_index,
3713 table_bound,
3714 "index_in_bounds",
3715 ));
3716
3717 let index_in_bounds = self
3718 .build_call_with_param_attributes(
3719 self.intrinsics.expect_i1,
3720 &[
3721 index_in_bounds.into(),
3722 self.intrinsics.i1_ty.const_int(1, false).into(),
3723 ],
3724 "index_in_bounds_expect",
3725 )?
3726 .try_as_basic_value()
3727 .unwrap_basic()
3728 .into_int_value();
3729
3730 let in_bounds_continue_block = self
3731 .context
3732 .append_basic_block(self.function, "in_bounds_continue_block");
3733 let not_in_bounds_block = self
3734 .context
3735 .append_basic_block(self.function, "not_in_bounds_block");
3736 err!(self.builder.build_conditional_branch(
3737 index_in_bounds,
3738 in_bounds_continue_block,
3739 not_in_bounds_block,
3740 ));
3741 self.builder.position_at_end(not_in_bounds_block);
3742 self.build_call_with_param_attributes(
3743 self.intrinsics.throw_trap,
3744 &[self.intrinsics.trap_table_access_oob.into()],
3745 "throw",
3746 )?;
3747 err!(self.builder.build_unreachable());
3748 self.builder.position_at_end(in_bounds_continue_block);
3749
3750 let anyfunc_struct_ptr = if let Some(local_table_index) = local_fixed_funcref_table
3751 {
3752 let anyfuncs = self.ctx.fixed_funcref_table_anyfuncs(
3753 local_table_index,
3754 self.intrinsics,
3755 &self.builder,
3756 )?;
3757 unsafe {
3758 err!(self.builder.build_in_bounds_gep(
3759 self.intrinsics.anyfunc_ty,
3760 anyfuncs,
3761 &[func_index],
3762 "anyfunc_struct_ptr",
3763 ))
3764 }
3765 } else {
3766 let (table_base, _) = *generic_table.as_ref().unwrap();
3767
3768 let casted_table_base = err!(self.builder.build_pointer_cast(
3771 table_base,
3772 self.context.ptr_type(AddressSpace::default()),
3773 "casted_table_base",
3774 ));
3775
3776 let funcref_ptr = unsafe {
3777 err!(self.builder.build_in_bounds_gep(
3778 self.intrinsics.ptr_ty,
3779 casted_table_base,
3780 &[func_index],
3781 "funcref_ptr",
3782 ))
3783 };
3784
3785 let anyfunc_struct_ptr = err!(self.builder.build_load(
3787 self.intrinsics.ptr_ty,
3788 funcref_ptr,
3789 "anyfunc_struct_ptr",
3790 ))
3791 .into_pointer_value();
3792
3793 if !table.readonly {
3794 let funcref_not_null = err!(
3796 self.builder
3797 .build_is_not_null(anyfunc_struct_ptr, "null_funcref_check")
3798 );
3799
3800 let funcref_continue_deref_block = self
3801 .context
3802 .append_basic_block(self.function, "funcref_continue_deref_block");
3803
3804 let funcref_is_null_block = self
3805 .context
3806 .append_basic_block(self.function, "funcref_is_null_block");
3807 err!(self.builder.build_conditional_branch(
3808 funcref_not_null,
3809 funcref_continue_deref_block,
3810 funcref_is_null_block,
3811 ));
3812 self.builder.position_at_end(funcref_is_null_block);
3813 self.build_call_with_param_attributes(
3814 self.intrinsics.throw_trap,
3815 &[self.intrinsics.trap_call_indirect_null.into()],
3816 "throw",
3817 )?;
3818 err!(self.builder.build_unreachable());
3819 self.builder.position_at_end(funcref_continue_deref_block);
3820 }
3821
3822 anyfunc_struct_ptr
3823 };
3824
3825 let sig_hash_ptr = self
3827 .builder
3828 .build_struct_gep(
3829 self.intrinsics.anyfunc_ty,
3830 anyfunc_struct_ptr,
3831 1,
3832 "sig_hash_ptr",
3833 )
3834 .unwrap();
3835 let func_ptr_ptr = self
3836 .builder
3837 .build_struct_gep(
3838 self.intrinsics.anyfunc_ty,
3839 anyfunc_struct_ptr,
3840 0,
3841 "func_ptr_ptr",
3842 )
3843 .unwrap();
3844 let (func_ptr, found_signature_hash) = (
3845 err!(
3846 self.builder
3847 .build_load(self.intrinsics.ptr_ty, func_ptr_ptr, "func_ptr")
3848 )
3849 .into_pointer_value(),
3850 err!(
3851 self.builder
3852 .build_load(self.intrinsics.i32_ty, sig_hash_ptr, "sig_hash")
3853 )
3854 .into_int_value(),
3855 );
3856
3857 let elem_initialized = err!(self.builder.build_is_not_null(func_ptr, ""));
3861
3862 let sig_hashes_equal = err!(self.builder.build_int_compare(
3865 IntPredicate::EQ,
3866 expected_signature_hash,
3867 found_signature_hash,
3868 "sig_hashes_equal",
3869 ));
3870
3871 let initialized_and_sig_hashes_match = err!(self.builder.build_and(
3872 elem_initialized,
3873 sig_hashes_equal,
3874 ""
3875 ));
3876
3877 let initialized_and_sig_hashes_match = self
3879 .build_call_with_param_attributes(
3880 self.intrinsics.expect_i1,
3881 &[
3882 initialized_and_sig_hashes_match.into(),
3883 self.intrinsics.i1_ty.const_int(1, false).into(),
3884 ],
3885 "initialized_and_sig_hashes_match_expect",
3886 )?
3887 .try_as_basic_value()
3888 .unwrap_basic()
3889 .into_int_value();
3890
3891 let continue_block = self
3892 .context
3893 .append_basic_block(self.function, "continue_block");
3894 let sighashes_notequal_block = self
3895 .context
3896 .append_basic_block(self.function, "sighashes_notequal_block");
3897 err!(self.builder.build_conditional_branch(
3898 initialized_and_sig_hashes_match,
3899 continue_block,
3900 sighashes_notequal_block,
3901 ));
3902
3903 self.builder.position_at_end(sighashes_notequal_block);
3904 let trap_code = err!(self.builder.build_select(
3905 elem_initialized,
3906 self.intrinsics.trap_call_indirect_sig,
3907 self.intrinsics.trap_call_indirect_null,
3908 "",
3909 ));
3910 self.build_call_with_param_attributes(
3911 self.intrinsics.throw_trap,
3912 &[trap_code.into()],
3913 "throw",
3914 )?;
3915 err!(self.builder.build_unreachable());
3916 self.builder.position_at_end(continue_block);
3917
3918 let callee_vmctx = if table.readonly {
3919 *vmctx
3920 } else {
3921 let ctx_ptr_ptr = self
3922 .builder
3923 .build_struct_gep(
3924 self.intrinsics.anyfunc_ty,
3925 anyfunc_struct_ptr,
3926 2,
3927 "ctx_ptr_ptr",
3928 )
3929 .unwrap();
3930 err!(
3931 self.builder
3932 .build_load(self.intrinsics.ptr_ty, ctx_ptr_ptr, "ctx_ptr")
3933 )
3934 .into_pointer_value()
3935 };
3936
3937 if self.m0_param.is_some() {
3938 self.build_m0_indirect_call(
3939 table_index.as_u32(),
3940 callee_vmctx,
3941 func_type,
3942 func_ptr,
3943 func_index,
3944 is_return_call,
3945 )?;
3946 } else {
3947 let (call_site, llvm_func_type) = self.build_indirect_call(
3948 callee_vmctx,
3949 func_type,
3950 func_ptr,
3951 None,
3952 is_return_call,
3953 )?;
3954
3955 if is_return_call {
3956 self.emit_return_call(call_site, llvm_func_type)?;
3957 } else {
3958 self.abi
3959 .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3960 .iter()
3961 .for_each(|ret| self.state.push1(*ret));
3962 }
3963 }
3964
3965 if is_return_call {
3966 self.state.reachable = false;
3967 }
3968 }
3969 _ => unreachable!(),
3970 }
3971 Ok(())
3972 }
3973
3974 fn translate_integer_arithmetic_operator(&mut self, op: Operator) -> Result<(), CompileError> {
3977 match op {
3978 Operator::I32Add | Operator::I64Add => {
3979 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3980 let v1 = self.apply_pending_canonicalization(v1, i1)?;
3981 let v2 = self.apply_pending_canonicalization(v2, i2)?;
3982 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3983 let res = err!(self.builder.build_int_add(v1, v2, ""));
3984 self.state.push1(res);
3985 }
3986 Operator::I8x16Add => {
3987 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3988 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3989 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3990 let res = err!(self.builder.build_int_add(v1, v2, ""));
3991 let res = err!(
3992 self.builder
3993 .build_bit_cast(res, self.intrinsics.i128_ty, "")
3994 );
3995 self.state.push1(res);
3996 }
3997 Operator::I16x8Add => {
3998 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3999 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4000 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4001 let res = err!(self.builder.build_int_add(v1, v2, ""));
4002 let res = err!(
4003 self.builder
4004 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4005 );
4006 self.state.push1(res);
4007 }
4008 Operator::I16x8ExtAddPairwiseI8x16S | Operator::I16x8ExtAddPairwiseI8x16U => {
4009 let extend_op = match op {
4010 Operator::I16x8ExtAddPairwiseI8x16S => {
4011 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, "")
4012 }
4013 Operator::I16x8ExtAddPairwiseI8x16U => {
4014 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, "")
4015 }
4016 _ => unreachable!("Unhandled internal variant"),
4017 };
4018 let (v, i) = self.state.pop1_extra()?;
4019 let (v, _) = self.v128_into_i8x16(v, i)?;
4020
4021 let left = err!(self.builder.build_shuffle_vector(
4022 v,
4023 v.get_type().get_undef(),
4024 VectorType::const_vector(&[
4025 self.intrinsics.i32_consts[0],
4026 self.intrinsics.i32_consts[2],
4027 self.intrinsics.i32_consts[4],
4028 self.intrinsics.i32_consts[6],
4029 self.intrinsics.i32_consts[8],
4030 self.intrinsics.i32_consts[10],
4031 self.intrinsics.i32_consts[12],
4032 self.intrinsics.i32_consts[14],
4033 ]),
4034 "",
4035 ));
4036 let left = err!(extend_op(self, left));
4037 let right = err!(self.builder.build_shuffle_vector(
4038 v,
4039 v.get_type().get_undef(),
4040 VectorType::const_vector(&[
4041 self.intrinsics.i32_consts[1],
4042 self.intrinsics.i32_consts[3],
4043 self.intrinsics.i32_consts[5],
4044 self.intrinsics.i32_consts[7],
4045 self.intrinsics.i32_consts[9],
4046 self.intrinsics.i32_consts[11],
4047 self.intrinsics.i32_consts[13],
4048 self.intrinsics.i32_consts[15],
4049 ]),
4050 "",
4051 ));
4052 let right = err!(extend_op(self, right));
4053
4054 let res = err!(self.builder.build_int_add(left, right, ""));
4055 let res = err!(
4056 self.builder
4057 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4058 );
4059 self.state.push1(res);
4060 }
4061 Operator::I32x4Add => {
4062 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4063 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4064 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4065 let res = err!(self.builder.build_int_add(v1, v2, ""));
4066 let res = err!(
4067 self.builder
4068 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4069 );
4070 self.state.push1(res);
4071 }
4072 Operator::I32x4ExtAddPairwiseI16x8S | Operator::I32x4ExtAddPairwiseI16x8U => {
4073 let extend_op = match op {
4074 Operator::I32x4ExtAddPairwiseI16x8S => {
4075 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
4076 }
4077 Operator::I32x4ExtAddPairwiseI16x8U => {
4078 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
4079 }
4080 _ => unreachable!("Unhandled internal variant"),
4081 };
4082 let (v, i) = self.state.pop1_extra()?;
4083 let (v, _) = self.v128_into_i16x8(v, i)?;
4084
4085 let left = err!(self.builder.build_shuffle_vector(
4086 v,
4087 v.get_type().get_undef(),
4088 VectorType::const_vector(&[
4089 self.intrinsics.i32_consts[0],
4090 self.intrinsics.i32_consts[2],
4091 self.intrinsics.i32_consts[4],
4092 self.intrinsics.i32_consts[6],
4093 ]),
4094 "",
4095 ));
4096 let left = err!(extend_op(self, left));
4097 let right = err!(self.builder.build_shuffle_vector(
4098 v,
4099 v.get_type().get_undef(),
4100 VectorType::const_vector(&[
4101 self.intrinsics.i32_consts[1],
4102 self.intrinsics.i32_consts[3],
4103 self.intrinsics.i32_consts[5],
4104 self.intrinsics.i32_consts[7],
4105 ]),
4106 "",
4107 ));
4108 let right = err!(extend_op(self, right));
4109
4110 let res = err!(self.builder.build_int_add(left, right, ""));
4111 let res = err!(
4112 self.builder
4113 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4114 );
4115 self.state.push1(res);
4116 }
4117 Operator::I64x2Add => {
4118 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4119 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4120 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4121 let res = err!(self.builder.build_int_add(v1, v2, ""));
4122 let res = err!(
4123 self.builder
4124 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4125 );
4126 self.state.push1(res);
4127 }
4128 Operator::I8x16AddSatS => {
4129 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4130 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4131 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4132 let res = self
4133 .build_call_with_param_attributes(
4134 self.intrinsics.sadd_sat_i8x16,
4135 &[v1.into(), v2.into()],
4136 "",
4137 )?
4138 .try_as_basic_value()
4139 .unwrap_basic();
4140 let res = err!(
4141 self.builder
4142 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4143 );
4144 self.state.push1(res);
4145 }
4146 Operator::I16x8AddSatS => {
4147 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4148 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4149 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4150 let res = self
4151 .build_call_with_param_attributes(
4152 self.intrinsics.sadd_sat_i16x8,
4153 &[v1.into(), v2.into()],
4154 "",
4155 )?
4156 .try_as_basic_value()
4157 .unwrap_basic();
4158 let res = err!(
4159 self.builder
4160 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4161 );
4162 self.state.push1(res);
4163 }
4164 Operator::I8x16AddSatU => {
4165 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4166 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4167 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4168 let res = self
4169 .build_call_with_param_attributes(
4170 self.intrinsics.uadd_sat_i8x16,
4171 &[v1.into(), v2.into()],
4172 "",
4173 )?
4174 .try_as_basic_value()
4175 .unwrap_basic();
4176 let res = err!(
4177 self.builder
4178 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4179 );
4180 self.state.push1(res);
4181 }
4182 Operator::I16x8AddSatU => {
4183 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4184 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4185 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4186 let res = self
4187 .build_call_with_param_attributes(
4188 self.intrinsics.uadd_sat_i16x8,
4189 &[v1.into(), v2.into()],
4190 "",
4191 )?
4192 .try_as_basic_value()
4193 .unwrap_basic();
4194 let res = err!(
4195 self.builder
4196 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4197 );
4198 self.state.push1(res);
4199 }
4200 Operator::I32Sub | Operator::I64Sub => {
4201 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4202 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4203 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4204 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4205 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4206 self.state.push1(res);
4207 }
4208 Operator::I8x16Sub => {
4209 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4210 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4211 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4212 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4213 let res = err!(
4214 self.builder
4215 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4216 );
4217 self.state.push1(res);
4218 }
4219 Operator::I16x8Sub => {
4220 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4221 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4222 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4223 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4224 let res = err!(
4225 self.builder
4226 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4227 );
4228 self.state.push1(res);
4229 }
4230 Operator::I32x4Sub => {
4231 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4232 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4233 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4234 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4235 let res = err!(
4236 self.builder
4237 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4238 );
4239 self.state.push1(res);
4240 }
4241 Operator::I64x2Sub => {
4242 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4243 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4244 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4245 let res = err!(self.builder.build_int_sub(v1, v2, ""));
4246 let res = err!(
4247 self.builder
4248 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4249 );
4250 self.state.push1(res);
4251 }
4252 Operator::I8x16SubSatS => {
4253 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4254 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4255 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4256 let res = self
4257 .build_call_with_param_attributes(
4258 self.intrinsics.ssub_sat_i8x16,
4259 &[v1.into(), v2.into()],
4260 "",
4261 )?
4262 .try_as_basic_value()
4263 .unwrap_basic();
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::I16x8SubSatS => {
4271 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4272 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4273 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4274 let res = self
4275 .build_call_with_param_attributes(
4276 self.intrinsics.ssub_sat_i16x8,
4277 &[v1.into(), v2.into()],
4278 "",
4279 )?
4280 .try_as_basic_value()
4281 .unwrap_basic();
4282 let res = err!(
4283 self.builder
4284 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4285 );
4286 self.state.push1(res);
4287 }
4288 Operator::I8x16SubSatU => {
4289 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4290 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4291 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4292 let res = self
4293 .build_call_with_param_attributes(
4294 self.intrinsics.usub_sat_i8x16,
4295 &[v1.into(), v2.into()],
4296 "",
4297 )?
4298 .try_as_basic_value()
4299 .unwrap_basic();
4300 let res = err!(
4301 self.builder
4302 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4303 );
4304 self.state.push1(res);
4305 }
4306 Operator::I16x8SubSatU => {
4307 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4308 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4309 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4310 let res = self
4311 .build_call_with_param_attributes(
4312 self.intrinsics.usub_sat_i16x8,
4313 &[v1.into(), v2.into()],
4314 "",
4315 )?
4316 .try_as_basic_value()
4317 .unwrap_basic();
4318 let res = err!(
4319 self.builder
4320 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4321 );
4322 self.state.push1(res);
4323 }
4324 Operator::I32Mul | Operator::I64Mul => {
4325 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4326 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4327 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4328 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4329 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4330 self.state.push1(res);
4331 }
4332 Operator::I16x8Mul => {
4333 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4334 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4335 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4336 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4337 let res = err!(
4338 self.builder
4339 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4340 );
4341 self.state.push1(res);
4342 }
4343 Operator::I32x4Mul => {
4344 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4345 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4346 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4347 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4348 let res = err!(
4349 self.builder
4350 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4351 );
4352 self.state.push1(res);
4353 }
4354 Operator::I64x2Mul => {
4355 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4356 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4357 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4358 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4359 let res = err!(
4360 self.builder
4361 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4362 );
4363 self.state.push1(res);
4364 }
4365 Operator::I16x8RelaxedQ15mulrS if self.cpu_features.contains(CpuFeature::SSSE3) => {
4366 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4367 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4368 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4369 let res = self
4370 .build_call_with_param_attributes(
4371 self.intrinsics.x86_64.pmulhrsw128,
4372 &[v1.into(), v2.into()],
4373 "",
4374 )?
4375 .try_as_basic_value()
4376 .unwrap_basic();
4377 let res = err!(
4378 self.builder
4379 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4380 );
4381 self.state.push1(res);
4382 }
4383 Operator::I16x8Q15MulrSatS | Operator::I16x8RelaxedQ15mulrS => {
4384 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4385 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4386 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4387
4388 let max_value = self.intrinsics.i16_ty.const_int(i16::MAX as u64, false);
4389 let max_values = VectorType::const_vector(&[max_value; 8]);
4390
4391 let v1 = err!(
4392 self.builder
4393 .build_int_s_extend(v1, self.intrinsics.i32x8_ty, "")
4394 );
4395 let v2 = err!(
4396 self.builder
4397 .build_int_s_extend(v2, self.intrinsics.i32x8_ty, "")
4398 );
4399 let res = err!(self.builder.build_int_mul(v1, v2, ""));
4400
4401 let bit = self.intrinsics.i32_ty.const_int(0x4000, false);
4403 let bits = VectorType::const_vector(&[bit; 8]);
4404
4405 let res = err!(self.builder.build_int_add(res, bits, ""));
4406
4407 let fifteen = self.intrinsics.i32_consts[15];
4408 let fifteens = VectorType::const_vector(&[fifteen; 8]);
4409
4410 let res = err!(self.builder.build_right_shift(res, fifteens, true, ""));
4411 let saturate_up = {
4412 let max_values = err!(self.builder.build_int_s_extend(
4413 max_values,
4414 self.intrinsics.i32x8_ty,
4415 ""
4416 ));
4417 err!(
4418 self.builder
4419 .build_int_compare(IntPredicate::SGT, res, max_values, "")
4420 )
4421 };
4422
4423 let res = err!(
4424 self.builder
4425 .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
4426 );
4427
4428 let res = err!(self.builder.build_select(saturate_up, max_values, res, ""))
4429 .into_vector_value();
4430 let res = err!(
4431 self.builder
4432 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4433 );
4434 self.state.push1(res);
4435 }
4436 Operator::I16x8ExtMulLowI8x16S
4437 | Operator::I16x8ExtMulLowI8x16U
4438 | Operator::I16x8ExtMulHighI8x16S
4439 | Operator::I16x8ExtMulHighI8x16U => {
4440 let extend_op = match op {
4441 Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulHighI8x16S => {
4442 |s: &Self, v| -> Result<VectorValue, CompileError> {
4443 err_nt!(s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, ""))
4444 }
4445 }
4446 Operator::I16x8ExtMulLowI8x16U | Operator::I16x8ExtMulHighI8x16U => {
4447 |s: &Self, v| -> Result<VectorValue, CompileError> {
4448 err_nt!(s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, ""))
4449 }
4450 }
4451 _ => unreachable!("Unhandled internal variant"),
4452 };
4453 let shuffle_array = match op {
4454 Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulLowI8x16U => [
4455 self.intrinsics.i32_consts[0],
4456 self.intrinsics.i32_consts[1],
4457 self.intrinsics.i32_consts[2],
4458 self.intrinsics.i32_consts[3],
4459 self.intrinsics.i32_consts[4],
4460 self.intrinsics.i32_consts[5],
4461 self.intrinsics.i32_consts[6],
4462 self.intrinsics.i32_consts[7],
4463 ],
4464 Operator::I16x8ExtMulHighI8x16S | Operator::I16x8ExtMulHighI8x16U => [
4465 self.intrinsics.i32_consts[8],
4466 self.intrinsics.i32_consts[9],
4467 self.intrinsics.i32_consts[10],
4468 self.intrinsics.i32_consts[11],
4469 self.intrinsics.i32_consts[12],
4470 self.intrinsics.i32_consts[13],
4471 self.intrinsics.i32_consts[14],
4472 self.intrinsics.i32_consts[15],
4473 ],
4474 _ => unreachable!("Unhandled internal variant"),
4475 };
4476 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4477 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4478 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4479 let val1 = err!(self.builder.build_shuffle_vector(
4480 v1,
4481 v1.get_type().get_undef(),
4482 VectorType::const_vector(&shuffle_array),
4483 "",
4484 ));
4485 let val1 = err!(extend_op(self, val1));
4486 let val2 = err!(self.builder.build_shuffle_vector(
4487 v2,
4488 v2.get_type().get_undef(),
4489 VectorType::const_vector(&shuffle_array),
4490 "",
4491 ));
4492 let val2 = err!(extend_op(self, val2));
4493 let res = err!(self.builder.build_int_mul(val1, val2, ""));
4494 let res = err!(
4495 self.builder
4496 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4497 );
4498 self.state.push1(res);
4499 }
4500 Operator::I32x4ExtMulLowI16x8S
4501 | Operator::I32x4ExtMulLowI16x8U
4502 | Operator::I32x4ExtMulHighI16x8S
4503 | Operator::I32x4ExtMulHighI16x8U => {
4504 let extend_op = match op {
4505 Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulHighI16x8S => {
4506 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
4507 }
4508 Operator::I32x4ExtMulLowI16x8U | Operator::I32x4ExtMulHighI16x8U => {
4509 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
4510 }
4511 _ => unreachable!("Unhandled internal variant"),
4512 };
4513 let shuffle_array = match op {
4514 Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulLowI16x8U => [
4515 self.intrinsics.i32_consts[0],
4516 self.intrinsics.i32_consts[1],
4517 self.intrinsics.i32_consts[2],
4518 self.intrinsics.i32_consts[3],
4519 ],
4520 Operator::I32x4ExtMulHighI16x8S | Operator::I32x4ExtMulHighI16x8U => [
4521 self.intrinsics.i32_consts[4],
4522 self.intrinsics.i32_consts[5],
4523 self.intrinsics.i32_consts[6],
4524 self.intrinsics.i32_consts[7],
4525 ],
4526 _ => unreachable!("Unhandled internal variant"),
4527 };
4528 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4529 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4530 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4531 let val1 = err!(self.builder.build_shuffle_vector(
4532 v1,
4533 v1.get_type().get_undef(),
4534 VectorType::const_vector(&shuffle_array),
4535 "",
4536 ));
4537 let val1 = err!(extend_op(self, val1));
4538 let val2 = err!(self.builder.build_shuffle_vector(
4539 v2,
4540 v2.get_type().get_undef(),
4541 VectorType::const_vector(&shuffle_array),
4542 "",
4543 ));
4544 let val2 = err!(extend_op(self, val2));
4545 let res = err!(self.builder.build_int_mul(val1, val2, ""));
4546 let res = err!(
4547 self.builder
4548 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4549 );
4550 self.state.push1(res);
4551 }
4552 Operator::I64x2ExtMulLowI32x4S
4553 | Operator::I64x2ExtMulLowI32x4U
4554 | Operator::I64x2ExtMulHighI32x4S
4555 | Operator::I64x2ExtMulHighI32x4U => {
4556 let extend_op = match op {
4557 Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulHighI32x4S => {
4558 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
4559 }
4560 Operator::I64x2ExtMulLowI32x4U | Operator::I64x2ExtMulHighI32x4U => {
4561 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
4562 }
4563 _ => unreachable!("Unhandled internal variant"),
4564 };
4565 let shuffle_array = match op {
4566 Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulLowI32x4U => {
4567 [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
4568 }
4569 Operator::I64x2ExtMulHighI32x4S | Operator::I64x2ExtMulHighI32x4U => {
4570 [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
4571 }
4572 _ => unreachable!("Unhandled internal variant"),
4573 };
4574 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4575 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4576 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4577 let val1 = err!(self.builder.build_shuffle_vector(
4578 v1,
4579 v1.get_type().get_undef(),
4580 VectorType::const_vector(&shuffle_array),
4581 "",
4582 ));
4583 let val1 = err!(extend_op(self, val1));
4584 let val2 = err!(self.builder.build_shuffle_vector(
4585 v2,
4586 v2.get_type().get_undef(),
4587 VectorType::const_vector(&shuffle_array),
4588 "",
4589 ));
4590 let val2 = err!(extend_op(self, val2));
4591 let res = err!(self.builder.build_int_mul(val1, val2, ""));
4592 let res = err!(
4593 self.builder
4594 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4595 );
4596 self.state.push1(res);
4597 }
4598 Operator::I32x4DotI16x8S => {
4599 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4600 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4601 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4602 let low_i16 = [
4603 self.intrinsics.i32_consts[0],
4604 self.intrinsics.i32_consts[2],
4605 self.intrinsics.i32_consts[4],
4606 self.intrinsics.i32_consts[6],
4607 ];
4608 let high_i16 = [
4609 self.intrinsics.i32_consts[1],
4610 self.intrinsics.i32_consts[3],
4611 self.intrinsics.i32_consts[5],
4612 self.intrinsics.i32_consts[7],
4613 ];
4614 let v1_low = err!(self.builder.build_shuffle_vector(
4615 v1,
4616 v1.get_type().get_undef(),
4617 VectorType::const_vector(&low_i16),
4618 "",
4619 ));
4620 let v1_low = err!(self.builder.build_int_s_extend(
4621 v1_low,
4622 self.intrinsics.i32x4_ty,
4623 ""
4624 ));
4625 let v1_high = err!(self.builder.build_shuffle_vector(
4626 v1,
4627 v1.get_type().get_undef(),
4628 VectorType::const_vector(&high_i16),
4629 "",
4630 ));
4631 let v1_high = err!(self.builder.build_int_s_extend(
4632 v1_high,
4633 self.intrinsics.i32x4_ty,
4634 ""
4635 ));
4636 let v2_low = err!(self.builder.build_shuffle_vector(
4637 v2,
4638 v2.get_type().get_undef(),
4639 VectorType::const_vector(&low_i16),
4640 "",
4641 ));
4642 let v2_low = err!(self.builder.build_int_s_extend(
4643 v2_low,
4644 self.intrinsics.i32x4_ty,
4645 ""
4646 ));
4647 let v2_high = err!(self.builder.build_shuffle_vector(
4648 v2,
4649 v2.get_type().get_undef(),
4650 VectorType::const_vector(&high_i16),
4651 "",
4652 ));
4653 let v2_high = err!(self.builder.build_int_s_extend(
4654 v2_high,
4655 self.intrinsics.i32x4_ty,
4656 ""
4657 ));
4658 let low_product = err!(self.builder.build_int_mul(v1_low, v2_low, ""));
4659 let high_product = err!(self.builder.build_int_mul(v1_high, v2_high, ""));
4660
4661 let res = err!(self.builder.build_int_add(low_product, high_product, ""));
4662 let res = err!(
4663 self.builder
4664 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4665 );
4666 self.state.push1(res);
4667 }
4668 Operator::I16x8RelaxedDotI8x16I7x16S
4669 if self.cpu_features.contains(CpuFeature::SSSE3) =>
4670 {
4671 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4672 let (a, _) = self.v128_into_i8x16(v1, i1)?;
4673 let (b, _) = self.v128_into_i8x16(v2, i2)?;
4674
4675 let res = self
4676 .build_call_with_param_attributes(
4677 self.intrinsics.x86_64.pmaddubsw128,
4678 &[b.into(), a.into()],
4679 "",
4680 )?
4681 .try_as_basic_value()
4682 .unwrap_basic()
4683 .into_vector_value();
4684 let res = err!(
4685 self.builder
4686 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4687 );
4688 self.state.push1(res);
4689 }
4690 Operator::I16x8RelaxedDotI8x16I7x16S => {
4691 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4692 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4693 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4694
4695 let left_indices = [
4696 self.intrinsics.i32_consts[0],
4697 self.intrinsics.i32_consts[2],
4698 self.intrinsics.i32_consts[4],
4699 self.intrinsics.i32_consts[6],
4700 self.intrinsics.i32_consts[8],
4701 self.intrinsics.i32_consts[10],
4702 self.intrinsics.i32_consts[12],
4703 self.intrinsics.i32_consts[14],
4704 ];
4705 let right_indices = [
4706 self.intrinsics.i32_consts[1],
4707 self.intrinsics.i32_consts[3],
4708 self.intrinsics.i32_consts[5],
4709 self.intrinsics.i32_consts[7],
4710 self.intrinsics.i32_consts[9],
4711 self.intrinsics.i32_consts[11],
4712 self.intrinsics.i32_consts[13],
4713 self.intrinsics.i32_consts[15],
4714 ];
4715
4716 let v1_left = err!(self.builder.build_shuffle_vector(
4717 v1,
4718 v1.get_type().get_undef(),
4719 VectorType::const_vector(&left_indices),
4720 "",
4721 ));
4722 let v1_left = err!(self.builder.build_int_s_extend(
4723 v1_left,
4724 self.intrinsics.i16x8_ty,
4725 ""
4726 ));
4727 let v1_right = err!(self.builder.build_shuffle_vector(
4728 v1,
4729 v1.get_type().get_undef(),
4730 VectorType::const_vector(&right_indices),
4731 "",
4732 ));
4733 let v1_right = err!(self.builder.build_int_s_extend(
4734 v1_right,
4735 self.intrinsics.i16x8_ty,
4736 ""
4737 ));
4738
4739 let v2_left = err!(self.builder.build_shuffle_vector(
4740 v2,
4741 v2.get_type().get_undef(),
4742 VectorType::const_vector(&left_indices),
4743 "",
4744 ));
4745 let v2_left = err!(self.builder.build_int_s_extend(
4746 v2_left,
4747 self.intrinsics.i16x8_ty,
4748 ""
4749 ));
4750 let v2_right = err!(self.builder.build_shuffle_vector(
4751 v2,
4752 v2.get_type().get_undef(),
4753 VectorType::const_vector(&right_indices),
4754 "",
4755 ));
4756 let v2_right = err!(self.builder.build_int_s_extend(
4757 v2_right,
4758 self.intrinsics.i16x8_ty,
4759 ""
4760 ));
4761
4762 let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4763 let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4764 let res = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4765 let res = err!(
4766 self.builder
4767 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4768 );
4769 self.state.push1(res);
4770 }
4771 Operator::I32x4RelaxedDotI8x16I7x16AddS
4772 if self.cpu_features.contains(CpuFeature::SSSE3) =>
4773 {
4774 let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4775 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4776 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4777 let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4778
4779 let dot16 = self
4782 .build_call_with_param_attributes(
4783 self.intrinsics.x86_64.pmaddubsw128,
4784 &[v2.into(), v1.into()],
4785 "",
4786 )?
4787 .try_as_basic_value()
4788 .unwrap_basic()
4789 .into_vector_value();
4790 let ones =
4791 VectorType::const_vector(&[self.intrinsics.i16_ty.const_int(1, false); 8]);
4792 let dot32 = self
4793 .build_call_with_param_attributes(
4794 self.intrinsics.x86_64.pmaddwd128,
4795 &[dot16.into(), ones.into()],
4796 "",
4797 )?
4798 .try_as_basic_value()
4799 .unwrap_basic()
4800 .into_vector_value();
4801 let res = err!(self.builder.build_int_add(dot32, acc, ""));
4802 let res = err!(
4803 self.builder
4804 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4805 );
4806 self.state.push1(res);
4807 }
4808 Operator::I32x4RelaxedDotI8x16I7x16AddS => {
4809 let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4810 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4811 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4812 let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4813
4814 let left_indices = [
4815 self.intrinsics.i32_consts[0],
4816 self.intrinsics.i32_consts[2],
4817 self.intrinsics.i32_consts[4],
4818 self.intrinsics.i32_consts[6],
4819 self.intrinsics.i32_consts[8],
4820 self.intrinsics.i32_consts[10],
4821 self.intrinsics.i32_consts[12],
4822 self.intrinsics.i32_consts[14],
4823 ];
4824 let right_indices = [
4825 self.intrinsics.i32_consts[1],
4826 self.intrinsics.i32_consts[3],
4827 self.intrinsics.i32_consts[5],
4828 self.intrinsics.i32_consts[7],
4829 self.intrinsics.i32_consts[9],
4830 self.intrinsics.i32_consts[11],
4831 self.intrinsics.i32_consts[13],
4832 self.intrinsics.i32_consts[15],
4833 ];
4834
4835 let v1_left = err!(self.builder.build_shuffle_vector(
4836 v1,
4837 v1.get_type().get_undef(),
4838 VectorType::const_vector(&left_indices),
4839 "",
4840 ));
4841 let v1_left = err!(self.builder.build_int_s_extend(
4842 v1_left,
4843 self.intrinsics.i16x8_ty,
4844 ""
4845 ));
4846 let v1_right = err!(self.builder.build_shuffle_vector(
4847 v1,
4848 v1.get_type().get_undef(),
4849 VectorType::const_vector(&right_indices),
4850 "",
4851 ));
4852 let v1_right = err!(self.builder.build_int_s_extend(
4853 v1_right,
4854 self.intrinsics.i16x8_ty,
4855 ""
4856 ));
4857
4858 let v2_left = err!(self.builder.build_shuffle_vector(
4859 v2,
4860 v2.get_type().get_undef(),
4861 VectorType::const_vector(&left_indices),
4862 "",
4863 ));
4864 let v2_left = err!(self.builder.build_int_s_extend(
4865 v2_left,
4866 self.intrinsics.i16x8_ty,
4867 ""
4868 ));
4869 let v2_right = err!(self.builder.build_shuffle_vector(
4870 v2,
4871 v2.get_type().get_undef(),
4872 VectorType::const_vector(&right_indices),
4873 "",
4874 ));
4875 let v2_right = err!(self.builder.build_int_s_extend(
4876 v2_right,
4877 self.intrinsics.i16x8_ty,
4878 ""
4879 ));
4880
4881 let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4882 let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4883 let dot16 = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4884
4885 let pair_left = err!(self.builder.build_shuffle_vector(
4886 dot16,
4887 dot16.get_type().get_undef(),
4888 VectorType::const_vector(&[
4889 self.intrinsics.i32_consts[0],
4890 self.intrinsics.i32_consts[2],
4891 self.intrinsics.i32_consts[4],
4892 self.intrinsics.i32_consts[6],
4893 ]),
4894 "",
4895 ));
4896 let pair_left = err!(self.builder.build_int_s_extend(
4897 pair_left,
4898 self.intrinsics.i32x4_ty,
4899 ""
4900 ));
4901 let pair_right = err!(self.builder.build_shuffle_vector(
4902 dot16,
4903 dot16.get_type().get_undef(),
4904 VectorType::const_vector(&[
4905 self.intrinsics.i32_consts[1],
4906 self.intrinsics.i32_consts[3],
4907 self.intrinsics.i32_consts[5],
4908 self.intrinsics.i32_consts[7],
4909 ]),
4910 "",
4911 ));
4912 let pair_right = err!(self.builder.build_int_s_extend(
4913 pair_right,
4914 self.intrinsics.i32x4_ty,
4915 ""
4916 ));
4917 let dot32 = err!(self.builder.build_int_add(pair_left, pair_right, ""));
4918 let res = err!(self.builder.build_int_add(dot32, acc, ""));
4919 let res = err!(
4920 self.builder
4921 .build_bit_cast(res, self.intrinsics.i128_ty, "")
4922 );
4923 self.state.push1(res);
4924 }
4925 Operator::I32DivS | Operator::I64DivS => {
4926 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4927 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4928 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4929 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4930
4931 self.trap_if_zero_or_overflow(v1, v2)?;
4932
4933 let res = err!(self.builder.build_int_signed_div(v1, v2, ""));
4934 self.state.push1(res);
4935 }
4936 Operator::I32DivU | Operator::I64DivU => {
4937 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4938 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4939 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4940 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4941
4942 self.trap_if_zero(v2)?;
4943
4944 let res = err!(self.builder.build_int_unsigned_div(v1, v2, ""));
4945 self.state.push1(res);
4946 }
4947 Operator::I32RemS | Operator::I64RemS => {
4948 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4949 let v1 = self.apply_pending_canonicalization(v1, i1)?;
4950 let v2 = self.apply_pending_canonicalization(v2, i2)?;
4951 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4952 let int_type = v1.get_type();
4953 let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
4954 let min_value = int_type.const_int(i32::MIN as u64, false);
4955 let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
4956 (min_value, neg_one_value)
4957 } else if int_type == self.intrinsics.i64_ty {
4958 let min_value = int_type.const_int(i64::MIN as u64, false);
4959 let neg_one_value = int_type.const_int(-1i64 as u64, false);
4960 (min_value, neg_one_value)
4961 } else {
4962 unreachable!()
4963 };
4964
4965 self.trap_if_zero(v2)?;
4966
4967 let will_overflow = err!(self.builder.build_and(
4979 err!(self.builder.build_int_compare(
4980 IntPredicate::EQ,
4981 v1,
4982 min_value,
4983 "left_is_min"
4984 )),
4985 err!(self.builder.build_int_compare(
4986 IntPredicate::EQ,
4987 v2,
4988 neg_one_value,
4989 "right_is_neg_one",
4990 )),
4991 "srem_will_overflow",
4992 ));
4993 let v1 =
4994 err!(
4995 self.builder
4996 .build_select(will_overflow, int_type.const_zero(), v1, "")
4997 )
4998 .into_int_value();
4999 let res = err!(self.builder.build_int_signed_rem(v1, v2, ""));
5000 self.state.push1(res);
5001 }
5002 Operator::I32RemU | Operator::I64RemU => {
5003 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5004 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5005 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5006 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5007
5008 self.trap_if_zero(v2)?;
5009
5010 let res = err!(self.builder.build_int_unsigned_rem(v1, v2, ""));
5011 self.state.push1(res);
5012 }
5013 Operator::I32And | Operator::I64And | Operator::V128And => {
5014 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5015 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5016 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5017 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5018 let res = err!(self.builder.build_and(v1, v2, ""));
5019 self.state.push1(res);
5020 }
5021 Operator::I32Or | Operator::I64Or | Operator::V128Or => {
5022 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5023 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5024 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5025 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5026 let res = err!(self.builder.build_or(v1, v2, ""));
5027 self.state.push1(res);
5028 }
5029 Operator::I32Xor | Operator::I64Xor | Operator::V128Xor => {
5030 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5031 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5032 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5033 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5034 let res = err!(self.builder.build_xor(v1, v2, ""));
5035 self.state.push1(res);
5036 }
5037 Operator::V128AndNot => {
5038 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5039 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5040 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5041 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5042 let v2 = err!(self.builder.build_not(v2, ""));
5043 let res = err!(self.builder.build_and(v1, v2, ""));
5044 self.state.push1(res);
5045 }
5046 Operator::I8x16RelaxedLaneselect
5047 | Operator::I16x8RelaxedLaneselect
5048 | Operator::I32x4RelaxedLaneselect
5049 | Operator::I64x2RelaxedLaneselect
5050 if self.cpu_features.contains(CpuFeature::SSE41) =>
5051 {
5052 let ((v1, i1), (v2, i2), (mask, mask_info)) = self.state.pop3_extra()?;
5053 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5054 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5055 let mask = self.apply_pending_canonicalization(mask, mask_info)?;
5056
5057 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5058 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5059 let (mask, _) = self.v128_into_i8x16(mask, mask_info)?;
5060 let res = self
5061 .build_call_with_param_attributes(
5062 self.intrinsics.x86_64.pblendvb,
5063 &[v2.into(), v1.into(), mask.into()],
5064 "",
5065 )?
5066 .try_as_basic_value()
5067 .unwrap_basic();
5068 let res = err!(
5069 self.builder
5070 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5071 );
5072 self.state.push1(res);
5073 }
5074 Operator::I8x16RelaxedLaneselect
5075 | Operator::I16x8RelaxedLaneselect
5076 | Operator::I32x4RelaxedLaneselect
5077 | Operator::I64x2RelaxedLaneselect
5078 | Operator::V128Bitselect => {
5079 let ((v1, i1), (v2, i2), (cond, cond_info)) = self.state.pop3_extra()?;
5080 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5081 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5082 let cond = self.apply_pending_canonicalization(cond, cond_info)?;
5083 let v1 = err!(
5084 self.builder
5085 .build_bit_cast(v1, self.intrinsics.i1x128_ty, "")
5086 )
5087 .into_vector_value();
5088 let v2 = err!(
5089 self.builder
5090 .build_bit_cast(v2, self.intrinsics.i1x128_ty, "")
5091 )
5092 .into_vector_value();
5093 let cond = err!(
5094 self.builder
5095 .build_bit_cast(cond, self.intrinsics.i1x128_ty, "")
5096 )
5097 .into_vector_value();
5098 let res = err!(self.builder.build_select(cond, v1, v2, ""));
5099 let res = err!(
5100 self.builder
5101 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5102 );
5103 self.state.push1(res);
5104 }
5105 Operator::I8x16Bitmask => {
5106 let (v, i) = self.state.pop1_extra()?;
5107 let (v, _) = self.v128_into_i8x16(v, i)?;
5108
5109 let zeros = self.intrinsics.i8x16_ty.const_zero();
5110 let res = err!(
5111 self.builder
5112 .build_int_compare(IntPredicate::SLT, v, zeros, "")
5113 );
5114 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i16_ty, ""))
5115 .into_int_value();
5116 let res = err!(
5117 self.builder
5118 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5119 );
5120 self.state.push1(res);
5121 }
5122 Operator::I16x8Bitmask => {
5123 let (v, i) = self.state.pop1_extra()?;
5124 let (v, _) = self.v128_into_i16x8(v, i)?;
5125
5126 let zeros = self.intrinsics.i16x8_ty.const_zero();
5127 let res = err!(
5128 self.builder
5129 .build_int_compare(IntPredicate::SLT, v, zeros, "")
5130 );
5131 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i8_ty, ""))
5132 .into_int_value();
5133 let res = err!(
5134 self.builder
5135 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5136 );
5137 self.state.push1(res);
5138 }
5139 Operator::I32x4Bitmask => {
5140 let (v, i) = self.state.pop1_extra()?;
5141 let (v, _) = self.v128_into_i32x4(v, i)?;
5142
5143 let zeros = self.intrinsics.i32x4_ty.const_zero();
5144 let res = err!(
5145 self.builder
5146 .build_int_compare(IntPredicate::SLT, v, zeros, "")
5147 );
5148 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i4_ty, ""))
5149 .into_int_value();
5150 let res = err!(
5151 self.builder
5152 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5153 );
5154 self.state.push1(res);
5155 }
5156 Operator::I64x2Bitmask => {
5157 let (v, i) = self.state.pop1_extra()?;
5158 let (v, _) = self.v128_into_i64x2(v, i)?;
5159
5160 let zeros = self.intrinsics.i64x2_ty.const_zero();
5161 let res = err!(
5162 self.builder
5163 .build_int_compare(IntPredicate::SLT, v, zeros, "")
5164 );
5165 let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i2_ty, ""))
5166 .into_int_value();
5167 let res = err!(
5168 self.builder
5169 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5170 );
5171 self.state.push1(res);
5172 }
5173 Operator::I32Shl => {
5174 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5175 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5176 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5177 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5178 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5179 let v2 = err!(self.builder.build_and(v2, mask, ""));
5180 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5181 self.state.push1(res);
5182 }
5183 Operator::I64Shl => {
5184 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5185 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5186 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5187 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5188 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5189 let v2 = err!(self.builder.build_and(v2, mask, ""));
5190 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5191 self.state.push1(res);
5192 }
5193 Operator::I8x16Shl => {
5194 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5195 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5196 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5197 let v2 = v2.into_int_value();
5198 let v2 = err!(
5199 self.builder
5200 .build_and(v2, self.intrinsics.i32_consts[7], "")
5201 );
5202 let v2 = err!(
5203 self.builder
5204 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5205 );
5206 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5207 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5208 let res = err!(
5209 self.builder
5210 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5211 );
5212 self.state.push1(res);
5213 }
5214 Operator::I16x8Shl => {
5215 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5216 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5217 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5218 let v2 = v2.into_int_value();
5219 let v2 = err!(
5220 self.builder
5221 .build_and(v2, self.intrinsics.i32_consts[15], "")
5222 );
5223 let v2 = err!(
5224 self.builder
5225 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5226 );
5227 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5228 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5229 let res = err!(
5230 self.builder
5231 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5232 );
5233 self.state.push1(res);
5234 }
5235 Operator::I32x4Shl => {
5236 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5237 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5238 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5239 let v2 = v2.into_int_value();
5240 let v2 = err!(self.builder.build_and(
5241 v2,
5242 self.intrinsics.i32_ty.const_int(31, false),
5243 ""
5244 ));
5245 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5246 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5247 let res = err!(
5248 self.builder
5249 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5250 );
5251 self.state.push1(res);
5252 }
5253 Operator::I64x2Shl => {
5254 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5255 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5256 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5257 let v2 = v2.into_int_value();
5258 let v2 = err!(self.builder.build_and(
5259 v2,
5260 self.intrinsics.i32_ty.const_int(63, false),
5261 ""
5262 ));
5263 let v2 = err!(
5264 self.builder
5265 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5266 );
5267 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5268 let res = err!(self.builder.build_left_shift(v1, v2, ""));
5269 let res = err!(
5270 self.builder
5271 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5272 );
5273 self.state.push1(res);
5274 }
5275 Operator::I32ShrS => {
5276 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5277 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5278 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5279 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5280 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5281 let v2 = err!(self.builder.build_and(v2, mask, ""));
5282 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5283 self.state.push1(res);
5284 }
5285 Operator::I64ShrS => {
5286 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5287 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5288 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5289 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5290 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5291 let v2 = err!(self.builder.build_and(v2, mask, ""));
5292 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5293 self.state.push1(res);
5294 }
5295 Operator::I8x16ShrS => {
5296 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5297 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5298 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5299 let v2 = v2.into_int_value();
5300 let v2 = err!(
5301 self.builder
5302 .build_and(v2, self.intrinsics.i32_consts[7], "")
5303 );
5304 let v2 = err!(
5305 self.builder
5306 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5307 );
5308 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5309 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5310 let res = err!(
5311 self.builder
5312 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5313 );
5314 self.state.push1(res);
5315 }
5316 Operator::I16x8ShrS => {
5317 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5318 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5319 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5320 let v2 = v2.into_int_value();
5321 let v2 = err!(
5322 self.builder
5323 .build_and(v2, self.intrinsics.i32_consts[15], "")
5324 );
5325 let v2 = err!(
5326 self.builder
5327 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5328 );
5329 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5330 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5331 let res = err!(
5332 self.builder
5333 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5334 );
5335 self.state.push1(res);
5336 }
5337 Operator::I32x4ShrS => {
5338 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5339 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5340 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5341 let v2 = v2.into_int_value();
5342 let v2 = err!(self.builder.build_and(
5343 v2,
5344 self.intrinsics.i32_ty.const_int(31, false),
5345 ""
5346 ));
5347 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5348 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5349 let res = err!(
5350 self.builder
5351 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5352 );
5353 self.state.push1(res);
5354 }
5355 Operator::I64x2ShrS => {
5356 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5357 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5358 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5359 let v2 = v2.into_int_value();
5360 let v2 = err!(self.builder.build_and(
5361 v2,
5362 self.intrinsics.i32_ty.const_int(63, false),
5363 ""
5364 ));
5365 let v2 = err!(
5366 self.builder
5367 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5368 );
5369 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5370 let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5371 let res = err!(
5372 self.builder
5373 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5374 );
5375 self.state.push1(res);
5376 }
5377 Operator::I32ShrU => {
5378 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5379 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5380 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5381 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5382 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5383 let v2 = err!(self.builder.build_and(v2, mask, ""));
5384 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5385 self.state.push1(res);
5386 }
5387 Operator::I64ShrU => {
5388 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5389 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5390 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5391 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5392 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5393 let v2 = err!(self.builder.build_and(v2, mask, ""));
5394 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5395 self.state.push1(res);
5396 }
5397 Operator::I8x16ShrU => {
5398 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5399 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5400 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5401 let v2 = v2.into_int_value();
5402 let v2 = err!(
5403 self.builder
5404 .build_and(v2, self.intrinsics.i32_consts[7], "")
5405 );
5406 let v2 = err!(
5407 self.builder
5408 .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5409 );
5410 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5411 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5412 let res = err!(
5413 self.builder
5414 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5415 );
5416 self.state.push1(res);
5417 }
5418 Operator::I16x8ShrU => {
5419 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5420 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5421 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5422 let v2 = v2.into_int_value();
5423 let v2 = err!(
5424 self.builder
5425 .build_and(v2, self.intrinsics.i32_consts[15], "")
5426 );
5427 let v2 = err!(
5428 self.builder
5429 .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5430 );
5431 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5432 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5433 let res = err!(
5434 self.builder
5435 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5436 );
5437 self.state.push1(res);
5438 }
5439 Operator::I32x4ShrU => {
5440 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5441 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5442 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5443 let v2 = v2.into_int_value();
5444 let v2 = err!(self.builder.build_and(
5445 v2,
5446 self.intrinsics.i32_ty.const_int(31, false),
5447 ""
5448 ));
5449 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5450 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5451 let res = err!(
5452 self.builder
5453 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5454 );
5455 self.state.push1(res);
5456 }
5457 Operator::I64x2ShrU => {
5458 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5459 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5460 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5461 let v2 = v2.into_int_value();
5462 let v2 = err!(self.builder.build_and(
5463 v2,
5464 self.intrinsics.i32_ty.const_int(63, false),
5465 ""
5466 ));
5467 let v2 = err!(
5468 self.builder
5469 .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5470 );
5471 let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5472 let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5473 let res = err!(
5474 self.builder
5475 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5476 );
5477 self.state.push1(res);
5478 }
5479 Operator::I32Rotl => {
5480 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5481 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5482 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5483 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5484 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5485 let v2 = err!(self.builder.build_and(v2, mask, ""));
5486 let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5487 let rhs = {
5488 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5489 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5490 err!(self.builder.build_right_shift(v1, rhs, false, ""))
5491 };
5492 let res = err!(self.builder.build_or(lhs, rhs, ""));
5493 self.state.push1(res);
5494 }
5495 Operator::I64Rotl => {
5496 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5497 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5498 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5499 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5500 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5501 let v2 = err!(self.builder.build_and(v2, mask, ""));
5502 let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5503 let rhs = {
5504 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5505 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5506 err!(self.builder.build_right_shift(v1, rhs, false, ""))
5507 };
5508 let res = err!(self.builder.build_or(lhs, rhs, ""));
5509 self.state.push1(res);
5510 }
5511 Operator::I32Rotr => {
5512 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5513 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5514 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5515 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5516 let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5517 let v2 = err!(self.builder.build_and(v2, mask, ""));
5518 let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5519 let rhs = {
5520 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5521 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5522 err!(self.builder.build_left_shift(v1, rhs, ""))
5523 };
5524 let res = err!(self.builder.build_or(lhs, rhs, ""));
5525 self.state.push1(res);
5526 }
5527 Operator::I64Rotr => {
5528 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5529 let v1 = self.apply_pending_canonicalization(v1, i1)?;
5530 let v2 = self.apply_pending_canonicalization(v2, i2)?;
5531 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5532 let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5533 let v2 = err!(self.builder.build_and(v2, mask, ""));
5534 let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5535 let rhs = {
5536 let negv2 = err!(self.builder.build_int_neg(v2, ""));
5537 let rhs = err!(self.builder.build_and(negv2, mask, ""));
5538 err!(self.builder.build_left_shift(v1, rhs, ""))
5539 };
5540 let res = err!(self.builder.build_or(lhs, rhs, ""));
5541 self.state.push1(res);
5542 }
5543 Operator::I32Clz => {
5544 let (input, info) = self.state.pop1_extra()?;
5545 let input = self.apply_pending_canonicalization(input, info)?;
5546 let is_zero_undef = self.intrinsics.i1_zero;
5547 let res = self
5548 .build_call_with_param_attributes(
5549 self.intrinsics.ctlz_i32,
5550 &[input.into(), is_zero_undef.into()],
5551 "",
5552 )?
5553 .try_as_basic_value()
5554 .unwrap_basic();
5555 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5556 }
5557 Operator::I64Clz => {
5558 let (input, info) = self.state.pop1_extra()?;
5559 let input = self.apply_pending_canonicalization(input, info)?;
5560 let is_zero_undef = self.intrinsics.i1_zero;
5561 let res = self
5562 .build_call_with_param_attributes(
5563 self.intrinsics.ctlz_i64,
5564 &[input.into(), is_zero_undef.into()],
5565 "",
5566 )?
5567 .try_as_basic_value()
5568 .unwrap_basic();
5569 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5570 }
5571 Operator::I32Ctz => {
5572 let (input, info) = self.state.pop1_extra()?;
5573 let input = self.apply_pending_canonicalization(input, info)?;
5574 let is_zero_undef = self.intrinsics.i1_zero;
5575 let res = self
5576 .build_call_with_param_attributes(
5577 self.intrinsics.cttz_i32,
5578 &[input.into(), is_zero_undef.into()],
5579 "",
5580 )?
5581 .try_as_basic_value()
5582 .unwrap_basic();
5583 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5584 }
5585 Operator::I64Ctz => {
5586 let (input, info) = self.state.pop1_extra()?;
5587 let input = self.apply_pending_canonicalization(input, info)?;
5588 let is_zero_undef = self.intrinsics.i1_zero;
5589 let res = self
5590 .build_call_with_param_attributes(
5591 self.intrinsics.cttz_i64,
5592 &[input.into(), is_zero_undef.into()],
5593 "",
5594 )?
5595 .try_as_basic_value()
5596 .unwrap_basic();
5597 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5598 }
5599 Operator::I8x16Popcnt => {
5600 let (v, i) = self.state.pop1_extra()?;
5601 let (v, _) = self.v128_into_i8x16(v, i)?;
5602 let res = self
5603 .build_call_with_param_attributes(self.intrinsics.ctpop_i8x16, &[v.into()], "")?
5604 .try_as_basic_value()
5605 .unwrap_basic();
5606 let res = err!(
5607 self.builder
5608 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5609 );
5610 self.state.push1(res);
5611 }
5612 Operator::I32Popcnt => {
5613 let (input, info) = self.state.pop1_extra()?;
5614 let input = self.apply_pending_canonicalization(input, info)?;
5615 let res = self
5616 .build_call_with_param_attributes(
5617 self.intrinsics.ctpop_i32,
5618 &[input.into()],
5619 "",
5620 )?
5621 .try_as_basic_value()
5622 .unwrap_basic();
5623 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5624 }
5625 Operator::I64Popcnt => {
5626 let (input, info) = self.state.pop1_extra()?;
5627 let input = self.apply_pending_canonicalization(input, info)?;
5628 let res = self
5629 .build_call_with_param_attributes(
5630 self.intrinsics.ctpop_i64,
5631 &[input.into()],
5632 "",
5633 )?
5634 .try_as_basic_value()
5635 .unwrap_basic();
5636 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5637 }
5638 Operator::I32Eqz => {
5639 let input = self.state.pop1()?.into_int_value();
5640 let cond = err!(self.builder.build_int_compare(
5641 IntPredicate::EQ,
5642 input,
5643 self.intrinsics.i32_zero,
5644 "",
5645 ));
5646 let res = err!(
5647 self.builder
5648 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5649 );
5650 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5651 }
5652 Operator::I64Eqz => {
5653 let input = self.state.pop1()?.into_int_value();
5654 let cond = err!(self.builder.build_int_compare(
5655 IntPredicate::EQ,
5656 input,
5657 self.intrinsics.i64_zero,
5658 "",
5659 ));
5660 let res = err!(
5661 self.builder
5662 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5663 );
5664 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5665 }
5666 Operator::I8x16Abs => {
5667 let (v, i) = self.state.pop1_extra()?;
5668 let (v, _) = self.v128_into_i8x16(v, i)?;
5669
5670 let seven = self.intrinsics.i8_ty.const_int(7, false);
5671 let seven = VectorType::const_vector(&[seven; 16]);
5672 let all_sign_bits = err!(self.builder.build_right_shift(v, seven, true, ""));
5673 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5674 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5675 let res = err!(
5676 self.builder
5677 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5678 );
5679 self.state.push1(res);
5680 }
5681 Operator::I16x8Abs => {
5682 let (v, i) = self.state.pop1_extra()?;
5683 let (v, _) = self.v128_into_i16x8(v, i)?;
5684
5685 let fifteen = self.intrinsics.i16_ty.const_int(15, false);
5686 let fifteen = VectorType::const_vector(&[fifteen; 8]);
5687 let all_sign_bits = err!(self.builder.build_right_shift(v, fifteen, true, ""));
5688 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5689 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5690 let res = err!(
5691 self.builder
5692 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5693 );
5694 self.state.push1(res);
5695 }
5696 Operator::I32x4Abs => {
5697 let (v, i) = self.state.pop1_extra()?;
5698 let (v, _) = self.v128_into_i32x4(v, i)?;
5699
5700 let thirtyone = self.intrinsics.i32_ty.const_int(31, false);
5701 let thirtyone = VectorType::const_vector(&[thirtyone; 4]);
5702 let all_sign_bits = err!(self.builder.build_right_shift(v, thirtyone, true, ""));
5703 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5704 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5705 let res = err!(
5706 self.builder
5707 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5708 );
5709 self.state.push1(res);
5710 }
5711 Operator::I64x2Abs => {
5712 let (v, i) = self.state.pop1_extra()?;
5713 let (v, _) = self.v128_into_i64x2(v, i)?;
5714
5715 let sixtythree = self.intrinsics.i64_ty.const_int(63, false);
5716 let sixtythree = VectorType::const_vector(&[sixtythree; 2]);
5717 let all_sign_bits = err!(self.builder.build_right_shift(v, sixtythree, true, ""));
5718 let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5719 let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5720 let res = err!(
5721 self.builder
5722 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5723 );
5724 self.state.push1(res);
5725 }
5726 Operator::I8x16MinS => {
5727 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5728 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5729 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5730 let cmp = err!(
5731 self.builder
5732 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5733 );
5734 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5735 let res = err!(
5736 self.builder
5737 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5738 );
5739 self.state.push1(res);
5740 }
5741 Operator::I8x16MinU => {
5742 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5743 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5744 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5745 let cmp = err!(
5746 self.builder
5747 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5748 );
5749 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5750 let res = err!(
5751 self.builder
5752 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5753 );
5754 self.state.push1(res);
5755 }
5756 Operator::I8x16MaxS => {
5757 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5758 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5759 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5760 let cmp = err!(
5761 self.builder
5762 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5763 );
5764 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5765 let res = err!(
5766 self.builder
5767 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5768 );
5769 self.state.push1(res);
5770 }
5771 Operator::I8x16MaxU => {
5772 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5773 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5774 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5775 let cmp = err!(
5776 self.builder
5777 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5778 );
5779 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5780 let res = err!(
5781 self.builder
5782 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5783 );
5784 self.state.push1(res);
5785 }
5786 Operator::I16x8MinS => {
5787 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5788 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5789 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5790 let cmp = err!(
5791 self.builder
5792 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5793 );
5794 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5795 let res = err!(
5796 self.builder
5797 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5798 );
5799 self.state.push1(res);
5800 }
5801 Operator::I16x8MinU => {
5802 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5803 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5804 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5805 let cmp = err!(
5806 self.builder
5807 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5808 );
5809 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5810 let res = err!(
5811 self.builder
5812 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5813 );
5814 self.state.push1(res);
5815 }
5816 Operator::I16x8MaxS => {
5817 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5818 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5819 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5820 let cmp = err!(
5821 self.builder
5822 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5823 );
5824 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5825 let res = err!(
5826 self.builder
5827 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5828 );
5829 self.state.push1(res);
5830 }
5831 Operator::I16x8MaxU => {
5832 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5833 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5834 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5835 let cmp = err!(
5836 self.builder
5837 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5838 );
5839 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5840 let res = err!(
5841 self.builder
5842 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5843 );
5844 self.state.push1(res);
5845 }
5846 Operator::I32x4MinS => {
5847 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5848 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5849 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5850 let cmp = err!(
5851 self.builder
5852 .build_int_compare(IntPredicate::SLT, v1, v2, "")
5853 );
5854 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5855 let res = err!(
5856 self.builder
5857 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5858 );
5859 self.state.push1(res);
5860 }
5861 Operator::I32x4MinU => {
5862 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5863 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5864 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5865 let cmp = err!(
5866 self.builder
5867 .build_int_compare(IntPredicate::ULT, v1, v2, "")
5868 );
5869 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5870 let res = err!(
5871 self.builder
5872 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5873 );
5874 self.state.push1(res);
5875 }
5876 Operator::I32x4MaxS => {
5877 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5878 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5879 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5880 let cmp = err!(
5881 self.builder
5882 .build_int_compare(IntPredicate::SGT, v1, v2, "")
5883 );
5884 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5885 let res = err!(
5886 self.builder
5887 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5888 );
5889 self.state.push1(res);
5890 }
5891 Operator::I32x4MaxU => {
5892 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5893 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5894 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5895 let cmp = err!(
5896 self.builder
5897 .build_int_compare(IntPredicate::UGT, v1, v2, "")
5898 );
5899 let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5900 let res = err!(
5901 self.builder
5902 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5903 );
5904 self.state.push1(res);
5905 }
5906 Operator::I8x16AvgrU => {
5907 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5908 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5909 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5910
5911 let ext_ty = self.intrinsics.i16_ty.vec_type(16);
5922 let one = self.intrinsics.i16_ty.const_int(1, false);
5923 let one = VectorType::const_vector(&[one; 16]);
5924
5925 let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5926 let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5927 let res = err!(self.builder.build_int_add(
5928 err!(self.builder.build_int_add(one, v1, "")),
5929 v2,
5930 ""
5931 ));
5932 let res = err!(self.builder.build_right_shift(res, one, false, ""));
5933 let res = err!(
5934 self.builder
5935 .build_int_truncate(res, self.intrinsics.i8x16_ty, "")
5936 );
5937 let res = err!(
5938 self.builder
5939 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5940 );
5941 self.state.push1(res);
5942 }
5943 Operator::I16x8AvgrU => {
5944 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5945 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5946 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5947
5948 let ext_ty = self.intrinsics.i32_ty.vec_type(8);
5959 let one = self.intrinsics.i32_consts[1];
5960 let one = VectorType::const_vector(&[one; 8]);
5961
5962 let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5963 let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5964 let res = err!(self.builder.build_int_add(
5965 err!(self.builder.build_int_add(one, v1, "")),
5966 v2,
5967 ""
5968 ));
5969 let res = err!(self.builder.build_right_shift(res, one, false, ""));
5970 let res = err!(
5971 self.builder
5972 .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
5973 );
5974 let res = err!(
5975 self.builder
5976 .build_bit_cast(res, self.intrinsics.i128_ty, "")
5977 );
5978 self.state.push1(res);
5979 }
5980 Operator::I64Add128 | Operator::I64Sub128 => {
5981 let (rhs_hi, rhs_hi_info) = self.state.pop1_extra()?;
5982 let (rhs_lo, rhs_lo_info) = self.state.pop1_extra()?;
5983 let (lhs_hi, lhs_hi_info) = self.state.pop1_extra()?;
5984 let (lhs_lo, lhs_lo_info) = self.state.pop1_extra()?;
5985
5986 let lhs_lo = self
5987 .apply_pending_canonicalization(lhs_lo, lhs_lo_info)?
5988 .into_int_value();
5989 let lhs_hi = self
5990 .apply_pending_canonicalization(lhs_hi, lhs_hi_info)?
5991 .into_int_value();
5992 let rhs_lo = self
5993 .apply_pending_canonicalization(rhs_lo, rhs_lo_info)?
5994 .into_int_value();
5995 let rhs_hi = self
5996 .apply_pending_canonicalization(rhs_hi, rhs_hi_info)?
5997 .into_int_value();
5998
5999 let idx0 = self.intrinsics.i32_ty.const_zero();
6000 let idx1 = self.intrinsics.i32_ty.const_int(1, false);
6001
6002 let lhs = self.intrinsics.i64x2_ty.get_undef();
6003 let lhs = err!(self.builder.build_insert_element(lhs, lhs_lo, idx0, ""));
6004 let lhs = err!(self.builder.build_insert_element(lhs, lhs_hi, idx1, ""));
6005 let lhs = err!(
6006 self.builder
6007 .build_bit_cast(lhs, self.intrinsics.i128_ty, "a")
6008 )
6009 .into_int_value();
6010
6011 let rhs = self.intrinsics.i64x2_ty.get_undef();
6012 let rhs = err!(self.builder.build_insert_element(rhs, rhs_lo, idx0, ""));
6013 let rhs = err!(self.builder.build_insert_element(rhs, rhs_hi, idx1, ""));
6014 let rhs = err!(
6015 self.builder
6016 .build_bit_cast(rhs, self.intrinsics.i128_ty, "b")
6017 )
6018 .into_int_value();
6019
6020 let result = err!(match op {
6021 Operator::I64Add128 => self.builder.build_int_add(lhs, rhs, ""),
6022 Operator::I64Sub128 => self.builder.build_int_sub(lhs, rhs, ""),
6023 _ => unreachable!(),
6024 });
6025 let result = err!(self.builder.build_bit_cast(
6026 result,
6027 self.intrinsics.i64x2_ty,
6028 ""
6029 ))
6030 .into_vector_value();
6031 let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
6032 let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
6033
6034 self.state.push1(result_lo);
6035 self.state.push1(result_hi);
6036 }
6037 Operator::I64MulWideS | Operator::I64MulWideU => {
6038 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6039 let lhs = self
6040 .apply_pending_canonicalization(lhs, lhs_info)?
6041 .into_int_value();
6042 let rhs = self
6043 .apply_pending_canonicalization(rhs, rhs_info)?
6044 .into_int_value();
6045
6046 let lhs = err!(match op {
6047 Operator::I64MulWideS => {
6048 self.builder
6049 .build_int_s_extend(lhs, self.intrinsics.i128_ty, "a")
6050 }
6051 Operator::I64MulWideU => {
6052 self.builder
6053 .build_int_z_extend(lhs, self.intrinsics.i128_ty, "a")
6054 }
6055 _ => unreachable!(),
6056 });
6057 let rhs = err!(match op {
6058 Operator::I64MulWideS => {
6059 self.builder
6060 .build_int_s_extend(rhs, self.intrinsics.i128_ty, "b")
6061 }
6062 Operator::I64MulWideU => {
6063 self.builder
6064 .build_int_z_extend(rhs, self.intrinsics.i128_ty, "b")
6065 }
6066 _ => unreachable!(),
6067 });
6068
6069 let result = err!(self.builder.build_int_mul(lhs, rhs, ""));
6070 let result = err!(self.builder.build_bit_cast(
6071 result,
6072 self.intrinsics.i64x2_ty,
6073 ""
6074 ))
6075 .into_vector_value();
6076 let idx0 = self.intrinsics.i32_ty.const_zero();
6077 let idx1 = self.intrinsics.i32_ty.const_int(1, false);
6078 let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
6079 let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
6080
6081 self.state.push1(result_lo);
6082 self.state.push1(result_hi);
6083 }
6084 _ => unreachable!(),
6085 }
6086 Ok(())
6087 }
6088
6089 fn translate_floating_point_arithmetic_operator(
6092 &mut self,
6093 op: Operator,
6094 ) -> Result<(), CompileError> {
6095 match op {
6096 Operator::F32Add => {
6097 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6098 let res = self
6099 .build_call_with_param_attributes(
6100 self.intrinsics.add_f32,
6101 &[
6102 v1.into(),
6103 v2.into(),
6104 self.intrinsics.fp_rounding_md,
6105 self.intrinsics.fp_exception_md,
6106 ],
6107 "",
6108 )?
6109 .try_as_basic_value()
6110 .unwrap_basic();
6111 self.state.push1_extra(
6112 res,
6113 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6114 );
6115 }
6116 Operator::F64Add => {
6117 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6118 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6119 let res = self
6120 .build_call_with_param_attributes(
6121 self.intrinsics.add_f64,
6122 &[
6123 v1.into(),
6124 v2.into(),
6125 self.intrinsics.fp_rounding_md,
6126 self.intrinsics.fp_exception_md,
6127 ],
6128 "",
6129 )?
6130 .try_as_basic_value()
6131 .unwrap_basic();
6132 self.state.push1_extra(
6133 res,
6134 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6135 );
6136 }
6137 Operator::F32x4Add => {
6138 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6139 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6140 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6141 let res = self
6142 .build_call_with_param_attributes(
6143 self.intrinsics.add_f32x4,
6144 &[
6145 v1.into(),
6146 v2.into(),
6147 self.intrinsics.fp_rounding_md,
6148 self.intrinsics.fp_exception_md,
6149 ],
6150 "",
6151 )?
6152 .try_as_basic_value()
6153 .unwrap_basic();
6154 let res = err!(
6155 self.builder
6156 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6157 );
6158 self.state.push1_extra(
6159 res,
6160 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6161 );
6162 }
6163 Operator::F64x2Add => {
6164 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6165 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6166 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6167 let res = self
6168 .build_call_with_param_attributes(
6169 self.intrinsics.add_f64x2,
6170 &[
6171 v1.into(),
6172 v2.into(),
6173 self.intrinsics.fp_rounding_md,
6174 self.intrinsics.fp_exception_md,
6175 ],
6176 "",
6177 )?
6178 .try_as_basic_value()
6179 .unwrap_basic();
6180 let res = err!(
6181 self.builder
6182 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6183 );
6184 self.state.push1_extra(
6185 res,
6186 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6187 );
6188 }
6189 Operator::F32Sub => {
6190 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6191 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6192 let res = self
6193 .build_call_with_param_attributes(
6194 self.intrinsics.sub_f32,
6195 &[
6196 v1.into(),
6197 v2.into(),
6198 self.intrinsics.fp_rounding_md,
6199 self.intrinsics.fp_exception_md,
6200 ],
6201 "",
6202 )?
6203 .try_as_basic_value()
6204 .unwrap_basic();
6205 self.state.push1_extra(
6206 res,
6207 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6208 );
6209 }
6210 Operator::F64Sub => {
6211 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6212 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6213 let res = self
6214 .build_call_with_param_attributes(
6215 self.intrinsics.sub_f64,
6216 &[
6217 v1.into(),
6218 v2.into(),
6219 self.intrinsics.fp_rounding_md,
6220 self.intrinsics.fp_exception_md,
6221 ],
6222 "",
6223 )?
6224 .try_as_basic_value()
6225 .unwrap_basic();
6226 self.state.push1_extra(
6227 res,
6228 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6229 );
6230 }
6231 Operator::F32x4Sub => {
6232 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6233 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6234 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6235 let res = self
6236 .build_call_with_param_attributes(
6237 self.intrinsics.sub_f32x4,
6238 &[
6239 v1.into(),
6240 v2.into(),
6241 self.intrinsics.fp_rounding_md,
6242 self.intrinsics.fp_exception_md,
6243 ],
6244 "",
6245 )?
6246 .try_as_basic_value()
6247 .unwrap_basic();
6248 let res = err!(
6249 self.builder
6250 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6251 );
6252 self.state.push1_extra(
6253 res,
6254 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6255 );
6256 }
6257 Operator::F64x2Sub => {
6258 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6259 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6260 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6261 let res = self
6262 .build_call_with_param_attributes(
6263 self.intrinsics.sub_f64x2,
6264 &[
6265 v1.into(),
6266 v2.into(),
6267 self.intrinsics.fp_rounding_md,
6268 self.intrinsics.fp_exception_md,
6269 ],
6270 "",
6271 )?
6272 .try_as_basic_value()
6273 .unwrap_basic();
6274 let res = err!(
6275 self.builder
6276 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6277 );
6278 self.state.push1_extra(
6279 res,
6280 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6281 );
6282 }
6283 Operator::F32Mul => {
6284 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6285 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6286 let res = self
6287 .build_call_with_param_attributes(
6288 self.intrinsics.mul_f32,
6289 &[
6290 v1.into(),
6291 v2.into(),
6292 self.intrinsics.fp_rounding_md,
6293 self.intrinsics.fp_exception_md,
6294 ],
6295 "",
6296 )?
6297 .try_as_basic_value()
6298 .unwrap_basic();
6299 self.state.push1_extra(
6300 res,
6301 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6302 );
6303 }
6304 Operator::F64Mul => {
6305 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6306 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6307 let res = self
6308 .build_call_with_param_attributes(
6309 self.intrinsics.mul_f64,
6310 &[
6311 v1.into(),
6312 v2.into(),
6313 self.intrinsics.fp_rounding_md,
6314 self.intrinsics.fp_exception_md,
6315 ],
6316 "",
6317 )?
6318 .try_as_basic_value()
6319 .unwrap_basic();
6320 self.state.push1_extra(
6321 res,
6322 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6323 );
6324 }
6325 Operator::F32x4Mul => {
6326 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6327 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6328 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6329 let res = self
6330 .build_call_with_param_attributes(
6331 self.intrinsics.mul_f32x4,
6332 &[
6333 v1.into(),
6334 v2.into(),
6335 self.intrinsics.fp_rounding_md,
6336 self.intrinsics.fp_exception_md,
6337 ],
6338 "",
6339 )?
6340 .try_as_basic_value()
6341 .unwrap_basic();
6342 let res = err!(
6343 self.builder
6344 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6345 );
6346 self.state.push1_extra(
6347 res,
6348 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6349 );
6350 }
6351 Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd
6352 if self.cpu_features.contains(CpuFeature::FMA) =>
6353 {
6354 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6355 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6356 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6357 let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
6358
6359 let v1 = match op {
6360 Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6361 _ => v1,
6362 };
6363 let res = self
6364 .build_call_with_param_attributes(
6365 self.intrinsics.muladd_f32x4,
6366 &[
6367 v1.into(),
6368 v2.into(),
6369 v3.into(),
6370 self.intrinsics.fp_rounding_md,
6371 self.intrinsics.fp_exception_md,
6372 ],
6373 "",
6374 )?
6375 .try_as_basic_value()
6376 .unwrap_basic();
6377 let res = err!(
6378 self.builder
6379 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6380 );
6381 let info = (i1.strip_pending() & i2.strip_pending())?;
6382 let info = (info & i3.strip_pending())?;
6383 let info = (info | ExtraInfo::pending_f32_nan())?;
6384 self.state.push1_extra(res, info);
6385 }
6386 Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd => {
6387 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6388 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6389 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6390 let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
6391
6392 let v1 = match op {
6393 Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6394 _ => v1,
6395 };
6396 let mul = self
6397 .build_call_with_param_attributes(
6398 self.intrinsics.mul_f32x4,
6399 &[
6400 v1.into(),
6401 v2.into(),
6402 self.intrinsics.fp_rounding_md,
6403 self.intrinsics.fp_exception_md,
6404 ],
6405 "",
6406 )?
6407 .try_as_basic_value()
6408 .unwrap_basic();
6409 let mul = mul.into_vector_value();
6410 let res = self
6411 .build_call_with_param_attributes(
6412 self.intrinsics.add_f32x4,
6413 &[
6414 mul.into(),
6415 v3.into(),
6416 self.intrinsics.fp_rounding_md,
6417 self.intrinsics.fp_exception_md,
6418 ],
6419 "",
6420 )?
6421 .try_as_basic_value()
6422 .unwrap_basic();
6423 let res = err!(
6424 self.builder
6425 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6426 );
6427 let info = (i1.strip_pending() & i2.strip_pending())?;
6428 let info = (info & i3.strip_pending())?;
6429 let info = (info | ExtraInfo::pending_f32_nan())?;
6430 self.state.push1_extra(res, info);
6431 }
6432 Operator::F64x2Mul => {
6433 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6434 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6435 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6436 let res = self
6437 .build_call_with_param_attributes(
6438 self.intrinsics.mul_f64x2,
6439 &[
6440 v1.into(),
6441 v2.into(),
6442 self.intrinsics.fp_rounding_md,
6443 self.intrinsics.fp_exception_md,
6444 ],
6445 "",
6446 )?
6447 .try_as_basic_value()
6448 .unwrap_basic();
6449 let res = err!(
6450 self.builder
6451 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6452 );
6453 self.state.push1_extra(
6454 res,
6455 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6456 );
6457 }
6458 Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd
6459 if self.cpu_features.contains(CpuFeature::FMA) =>
6460 {
6461 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6462 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6463 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6464 let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
6465
6466 let v1 = match op {
6467 Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6468 _ => v1,
6469 };
6470 let res = self
6471 .build_call_with_param_attributes(
6472 self.intrinsics.muladd_f64x2,
6473 &[
6474 v1.into(),
6475 v2.into(),
6476 v3.into(),
6477 self.intrinsics.fp_rounding_md,
6478 self.intrinsics.fp_exception_md,
6479 ],
6480 "",
6481 )?
6482 .try_as_basic_value()
6483 .unwrap_basic();
6484 let res = err!(
6485 self.builder
6486 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6487 );
6488 let info = (i1.strip_pending() & i2.strip_pending())?;
6489 let info = (info & i3.strip_pending())?;
6490 let info = (info | ExtraInfo::pending_f64_nan())?;
6491 self.state.push1_extra(res, info);
6492 }
6493 Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd => {
6494 let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6495 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6496 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6497 let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
6498
6499 let v1 = match op {
6500 Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6501 _ => v1,
6502 };
6503 let mul = self
6504 .build_call_with_param_attributes(
6505 self.intrinsics.mul_f64x2,
6506 &[
6507 v1.into(),
6508 v2.into(),
6509 self.intrinsics.fp_rounding_md,
6510 self.intrinsics.fp_exception_md,
6511 ],
6512 "",
6513 )?
6514 .try_as_basic_value()
6515 .unwrap_basic();
6516 let mul = mul.into_vector_value();
6517 let res = self
6518 .build_call_with_param_attributes(
6519 self.intrinsics.add_f64x2,
6520 &[
6521 mul.into(),
6522 v3.into(),
6523 self.intrinsics.fp_rounding_md,
6524 self.intrinsics.fp_exception_md,
6525 ],
6526 "",
6527 )?
6528 .try_as_basic_value()
6529 .unwrap_basic();
6530 let res = err!(
6531 self.builder
6532 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6533 );
6534 let info = (i1.strip_pending() & i2.strip_pending())?;
6535 let info = (info & i3.strip_pending())?;
6536 let info = (info | ExtraInfo::pending_f64_nan())?;
6537 self.state.push1_extra(res, info);
6538 }
6539 Operator::F32Div => {
6540 let (v1, v2) = self.state.pop2()?;
6541 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6542 let res = self
6543 .build_call_with_param_attributes(
6544 self.intrinsics.div_f32,
6545 &[
6546 v1.into(),
6547 v2.into(),
6548 self.intrinsics.fp_rounding_md,
6549 self.intrinsics.fp_exception_md,
6550 ],
6551 "",
6552 )?
6553 .try_as_basic_value()
6554 .unwrap_basic();
6555 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6556 }
6557 Operator::F64Div => {
6558 let (v1, v2) = self.state.pop2()?;
6559 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6560 let res = self
6561 .build_call_with_param_attributes(
6562 self.intrinsics.div_f64,
6563 &[
6564 v1.into(),
6565 v2.into(),
6566 self.intrinsics.fp_rounding_md,
6567 self.intrinsics.fp_exception_md,
6568 ],
6569 "",
6570 )?
6571 .try_as_basic_value()
6572 .unwrap_basic();
6573 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6574 }
6575 Operator::F32x4Div => {
6576 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6577 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
6578 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
6579 let res = self
6580 .build_call_with_param_attributes(
6581 self.intrinsics.div_f32x4,
6582 &[
6583 v1.into(),
6584 v2.into(),
6585 self.intrinsics.fp_rounding_md,
6586 self.intrinsics.fp_exception_md,
6587 ],
6588 "",
6589 )?
6590 .try_as_basic_value()
6591 .unwrap_basic();
6592 let res = err!(
6593 self.builder
6594 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6595 );
6596 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6597 }
6598 Operator::F64x2Div => {
6599 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6600 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
6601 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
6602 let res = self
6603 .build_call_with_param_attributes(
6604 self.intrinsics.div_f64x2,
6605 &[
6606 v1.into(),
6607 v2.into(),
6608 self.intrinsics.fp_rounding_md,
6609 self.intrinsics.fp_exception_md,
6610 ],
6611 "",
6612 )?
6613 .try_as_basic_value()
6614 .unwrap_basic();
6615 let res = err!(
6616 self.builder
6617 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6618 );
6619 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6620 }
6621 Operator::F32Sqrt => {
6622 let input = self.state.pop1()?;
6623 let res = self
6624 .build_call_with_param_attributes(
6625 self.intrinsics.sqrt_f32,
6626 &[input.into()],
6627 "",
6628 )?
6629 .try_as_basic_value()
6630 .unwrap_basic();
6631 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6632 }
6633 Operator::F64Sqrt => {
6634 let input = self.state.pop1()?;
6635 let res = self
6636 .build_call_with_param_attributes(
6637 self.intrinsics.sqrt_f64,
6638 &[input.into()],
6639 "",
6640 )?
6641 .try_as_basic_value()
6642 .unwrap_basic();
6643 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6644 }
6645 Operator::F32x4Sqrt => {
6646 let (v, i) = self.state.pop1_extra()?;
6647 let (v, _) = self.v128_into_f32x4(v, i)?;
6648 let res = self
6649 .build_call_with_param_attributes(self.intrinsics.sqrt_f32x4, &[v.into()], "")?
6650 .try_as_basic_value()
6651 .unwrap_basic();
6652 let bits = err!(
6653 self.builder
6654 .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6655 );
6656 self.state.push1_extra(bits, ExtraInfo::pending_f32_nan());
6657 }
6658 Operator::F64x2Sqrt => {
6659 let (v, i) = self.state.pop1_extra()?;
6660 let (v, _) = self.v128_into_f64x2(v, i)?;
6661 let res = self
6662 .build_call_with_param_attributes(self.intrinsics.sqrt_f64x2, &[v.into()], "")?
6663 .try_as_basic_value()
6664 .unwrap_basic();
6665 let bits = err!(
6666 self.builder
6667 .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6668 );
6669 self.state.push1(bits);
6670 }
6671 Operator::F32Min => {
6672 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6673 let lhs = self
6674 .apply_pending_canonicalization(lhs, lhs_info)?
6675 .into_float_value();
6676 let rhs = self
6677 .apply_pending_canonicalization(rhs, rhs_info)?
6678 .into_float_value();
6679
6680 let res = self
6681 .build_call_with_param_attributes(
6682 self.intrinsics.minimum_f32,
6683 &[lhs.into(), rhs.into()],
6684 "",
6685 )?
6686 .try_as_basic_value()
6687 .unwrap_basic();
6688
6689 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6690 let res = res.into_float_value();
6691
6692 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6693 }
6694 Operator::F64Min => {
6695 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6696 let lhs = self
6697 .apply_pending_canonicalization(lhs, lhs_info)?
6698 .into_float_value();
6699 let rhs = self
6700 .apply_pending_canonicalization(rhs, rhs_info)?
6701 .into_float_value();
6702
6703 let res = self
6704 .build_call_with_param_attributes(
6705 self.intrinsics.minimum_f64,
6706 &[lhs.into(), rhs.into()],
6707 "",
6708 )?
6709 .try_as_basic_value()
6710 .unwrap_basic();
6711
6712 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6713 let res = res.into_float_value();
6714
6715 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6716 }
6717 Operator::F32x4RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6718 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6719 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6720 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6721 let res = self
6722 .build_call_with_param_attributes(
6723 self.intrinsics.x86_64.min_ps,
6724 &[v1.into(), v2.into()],
6725 "",
6726 )?
6727 .try_as_basic_value()
6728 .unwrap_basic();
6729 let res = err!(
6730 self.builder
6731 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6732 );
6733 self.state.push1_extra(
6734 res,
6735 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6736 );
6737 }
6738 Operator::F32x4Min | Operator::F32x4RelaxedMin => {
6739 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6740 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6741 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6742 let res = self
6743 .build_call_with_param_attributes(
6744 self.intrinsics.minimum_f32x4,
6745 &[v1.into(), v2.into()],
6746 "",
6747 )?
6748 .try_as_basic_value()
6749 .unwrap_basic();
6750
6751 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6752 let res = res.into_vector_value();
6753
6754 let res = err!(
6755 self.builder
6756 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6757 );
6758 self.state.push1_extra(
6759 res,
6760 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6761 );
6762 }
6763 Operator::F32x4PMin => {
6764 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6766 let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6767 let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6768 let cmp = err!(
6769 self.builder
6770 .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6771 );
6772 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6773 let res = err!(
6774 self.builder
6775 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6776 );
6777 self.state.push1(res);
6778 }
6779 Operator::F64x2RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6780 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6781 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6782 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6783 let res = self
6784 .build_call_with_param_attributes(
6785 self.intrinsics.x86_64.min_pd,
6786 &[v1.into(), v2.into()],
6787 "",
6788 )?
6789 .try_as_basic_value()
6790 .unwrap_basic();
6791 let res = err!(
6792 self.builder
6793 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6794 );
6795 self.state.push1_extra(
6796 res,
6797 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6798 );
6799 }
6800 Operator::F64x2Min | Operator::F64x2RelaxedMin => {
6801 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6802 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6803 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6804 let res = self
6805 .build_call_with_param_attributes(
6806 self.intrinsics.minimum_f64x2,
6807 &[v1.into(), v2.into()],
6808 "",
6809 )?
6810 .try_as_basic_value()
6811 .unwrap_basic();
6812
6813 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6814 let res = res.into_vector_value();
6815
6816 let res = err!(
6817 self.builder
6818 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6819 );
6820 self.state.push1_extra(
6821 res,
6822 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6823 );
6824 }
6825 Operator::F64x2PMin => {
6826 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6828 let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6829 let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6830 let cmp = err!(
6831 self.builder
6832 .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6833 );
6834 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
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::F32Max => {
6842 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6843 let lhs = self
6844 .apply_pending_canonicalization(lhs, lhs_info)?
6845 .into_float_value();
6846 let rhs = self
6847 .apply_pending_canonicalization(rhs, rhs_info)?
6848 .into_float_value();
6849
6850 let res = self
6851 .build_call_with_param_attributes(
6852 self.intrinsics.maximum_f32,
6853 &[lhs.into(), rhs.into()],
6854 "",
6855 )?
6856 .try_as_basic_value()
6857 .unwrap_basic();
6858
6859 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6860 let res = res.into_float_value();
6861
6862 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6863 }
6864 Operator::F64Max => {
6865 let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6866 let lhs = self
6867 .apply_pending_canonicalization(lhs, lhs_info)?
6868 .into_float_value();
6869 let rhs = self
6870 .apply_pending_canonicalization(rhs, rhs_info)?
6871 .into_float_value();
6872
6873 let res = self
6874 .build_call_with_param_attributes(
6875 self.intrinsics.maximum_f64,
6876 &[lhs.into(), rhs.into()],
6877 "",
6878 )?
6879 .try_as_basic_value()
6880 .unwrap_basic();
6881
6882 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6883 let res = res.into_float_value();
6884
6885 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6886 }
6887 Operator::F32x4RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6888 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6889 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6890 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6891 let res = self
6892 .build_call_with_param_attributes(
6893 self.intrinsics.x86_64.max_ps,
6894 &[v1.into(), v2.into()],
6895 "",
6896 )?
6897 .try_as_basic_value()
6898 .unwrap_basic();
6899 let res = err!(
6900 self.builder
6901 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6902 );
6903 self.state.push1_extra(
6904 res,
6905 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6906 );
6907 }
6908 Operator::F32x4Max | Operator::F32x4RelaxedMax => {
6909 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6910 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6911 let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6912 let res = self
6913 .build_call_with_param_attributes(
6914 self.intrinsics.maximum_f32x4,
6915 &[v1.into(), v2.into()],
6916 "",
6917 )?
6918 .try_as_basic_value()
6919 .unwrap_basic();
6920
6921 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6922 let res = res.into_vector_value();
6923
6924 let res = err!(
6925 self.builder
6926 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6927 );
6928 self.state.push1_extra(
6929 res,
6930 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6931 );
6932 }
6933 Operator::F32x4PMax => {
6934 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6936 let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6937 let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6938 let cmp = err!(
6939 self.builder
6940 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6941 );
6942 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6943
6944 let res = err!(
6945 self.builder
6946 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6947 );
6948 self.state.push1(res);
6949 }
6950 Operator::F64x2RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6951 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6952 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6953 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6954 let res = self
6955 .build_call_with_param_attributes(
6956 self.intrinsics.x86_64.max_pd,
6957 &[v1.into(), v2.into()],
6958 "",
6959 )?
6960 .try_as_basic_value()
6961 .unwrap_basic();
6962 let res = err!(
6963 self.builder
6964 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6965 );
6966 self.state.push1_extra(
6967 res,
6968 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6969 );
6970 }
6971 Operator::F64x2Max | Operator::F64x2RelaxedMax => {
6972 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6973 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6974 let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6975 let res = self
6976 .build_call_with_param_attributes(
6977 self.intrinsics.maximum_f64x2,
6978 &[v1.into(), v2.into()],
6979 "",
6980 )?
6981 .try_as_basic_value()
6982 .unwrap_basic();
6983
6984 let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6985 let res = res.into_vector_value();
6986
6987 let res = err!(
6988 self.builder
6989 .build_bit_cast(res, self.intrinsics.i128_ty, "")
6990 );
6991 self.state.push1_extra(
6992 res,
6993 ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6994 );
6995 }
6996 Operator::F64x2PMax => {
6997 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6999 let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
7000 let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
7001 let cmp = err!(
7002 self.builder
7003 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7004 );
7005 let res = err!(self.builder.build_select(cmp, v2, v1, ""));
7006 let res = err!(
7007 self.builder
7008 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7009 );
7010 self.state.push1(res);
7011 }
7012 Operator::F32Ceil => {
7013 let (input, info) = self.state.pop1_extra()?;
7014 let res = err!(self.build_call_with_param_attributes(
7015 self.intrinsics.ceil_f32,
7016 &[input.into()],
7017 ""
7018 ))
7019 .try_as_basic_value()
7020 .unwrap_basic();
7021 let (res, info) = self.finalize_rounding_result(res, info)?;
7022 self.state.push1_extra(res, info);
7023 }
7024 Operator::F32x4Ceil => {
7025 let (v, i) = self.state.pop1_extra()?;
7026 let (v, _) = self.v128_into_f32x4(v, i)?;
7027 let res = err!(self.build_call_with_param_attributes(
7028 self.intrinsics.ceil_f32x4,
7029 &[v.into()],
7030 ""
7031 ))
7032 .try_as_basic_value()
7033 .unwrap_basic();
7034 let (res, info) = self.finalize_rounding_result(res, i)?;
7035 let res = err!(
7036 self.builder
7037 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7038 );
7039 self.state.push1_extra(res, info);
7040 }
7041 Operator::F64Ceil => {
7042 let (input, info) = self.state.pop1_extra()?;
7043 let res = err!(self.build_call_with_param_attributes(
7044 self.intrinsics.ceil_f64,
7045 &[input.into()],
7046 ""
7047 ))
7048 .try_as_basic_value()
7049 .unwrap_basic();
7050 let (res, info) = self.finalize_rounding_result(res, info)?;
7051 self.state.push1_extra(res, info);
7052 }
7053 Operator::F64x2Ceil => {
7054 let (v, i) = self.state.pop1_extra()?;
7055 let (v, _) = self.v128_into_f64x2(v, i)?;
7056 let res = err!(self.build_call_with_param_attributes(
7057 self.intrinsics.ceil_f64x2,
7058 &[v.into()],
7059 ""
7060 ))
7061 .try_as_basic_value()
7062 .unwrap_basic();
7063 let (res, info) = self.finalize_rounding_result(res, i)?;
7064 let res = err!(
7065 self.builder
7066 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7067 );
7068 self.state.push1_extra(res, info);
7069 }
7070 Operator::F32Floor => {
7071 let (input, info) = self.state.pop1_extra()?;
7072 let res = err!(self.build_call_with_param_attributes(
7073 self.intrinsics.floor_f32,
7074 &[input.into()],
7075 ""
7076 ))
7077 .try_as_basic_value()
7078 .unwrap_basic();
7079 let (res, info) = self.finalize_rounding_result(res, info)?;
7080 self.state.push1_extra(res, info);
7081 }
7082 Operator::F32x4Floor => {
7083 let (v, i) = self.state.pop1_extra()?;
7084 let (v, _) = self.v128_into_f32x4(v, i)?;
7085 let res = err!(self.build_call_with_param_attributes(
7086 self.intrinsics.floor_f32x4,
7087 &[v.into()],
7088 ""
7089 ))
7090 .try_as_basic_value()
7091 .unwrap_basic();
7092 let (res, info) = self.finalize_rounding_result(res, i)?;
7093 let res = err!(
7094 self.builder
7095 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7096 );
7097 self.state.push1_extra(res, info);
7098 }
7099 Operator::F64Floor => {
7100 let (input, info) = self.state.pop1_extra()?;
7101 let res = err!(self.build_call_with_param_attributes(
7102 self.intrinsics.floor_f64,
7103 &[input.into()],
7104 ""
7105 ))
7106 .try_as_basic_value()
7107 .unwrap_basic();
7108 let (res, info) = self.finalize_rounding_result(res, info)?;
7109 self.state.push1_extra(res, info);
7110 }
7111 Operator::F64x2Floor => {
7112 let (v, i) = self.state.pop1_extra()?;
7113 let (v, _) = self.v128_into_f64x2(v, i)?;
7114 let res = err!(self.build_call_with_param_attributes(
7115 self.intrinsics.floor_f64x2,
7116 &[v.into()],
7117 ""
7118 ))
7119 .try_as_basic_value()
7120 .unwrap_basic();
7121 let (res, info) = self.finalize_rounding_result(res, i)?;
7122 let res = err!(
7123 self.builder
7124 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7125 );
7126 self.state.push1_extra(res, info);
7127 }
7128 Operator::F32Trunc => {
7129 let (v, info) = self.state.pop1_extra()?;
7130 let res = err!(
7131 self.builder
7132 .build_call(self.intrinsics.trunc_f32, &[v.into()], "")
7133 )
7134 .try_as_basic_value()
7135 .unwrap_basic();
7136 let (res, info) = self.finalize_rounding_result(res, info)?;
7137 self.state.push1_extra(res, info);
7138 }
7139 Operator::F32x4Trunc => {
7140 let (v, i) = self.state.pop1_extra()?;
7141 let (v, _) = self.v128_into_f32x4(v, i)?;
7142 let res = err!(self.build_call_with_param_attributes(
7143 self.intrinsics.trunc_f32x4,
7144 &[v.into()],
7145 ""
7146 ))
7147 .try_as_basic_value()
7148 .unwrap_basic();
7149 let (res, info) = self.finalize_rounding_result(res, i)?;
7150 let res = err!(
7151 self.builder
7152 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7153 );
7154 self.state.push1_extra(res, info);
7155 }
7156 Operator::F64Trunc => {
7157 let (v, info) = self.state.pop1_extra()?;
7158 let res = err!(
7159 self.builder
7160 .build_call(self.intrinsics.trunc_f64, &[v.into()], "")
7161 )
7162 .try_as_basic_value()
7163 .unwrap_basic();
7164 let (res, info) = self.finalize_rounding_result(res, info)?;
7165 self.state.push1_extra(res, info);
7166 }
7167 Operator::F64x2Trunc => {
7168 let (v, i) = self.state.pop1_extra()?;
7169 let (v, _) = self.v128_into_f64x2(v, i)?;
7170 let res = err!(self.build_call_with_param_attributes(
7171 self.intrinsics.trunc_f64x2,
7172 &[v.into()],
7173 ""
7174 ))
7175 .try_as_basic_value()
7176 .unwrap_basic();
7177 let (res, info) = self.finalize_rounding_result(res, i)?;
7178 let res = err!(
7179 self.builder
7180 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7181 );
7182 self.state.push1_extra(res, info);
7183 }
7184 Operator::F32Nearest => {
7185 let (v, info) = self.state.pop1_extra()?;
7186 let res = err!(self.build_call_with_param_attributes(
7187 self.intrinsics.nearbyint_f32,
7188 &[v.into()],
7189 ""
7190 ))
7191 .try_as_basic_value()
7192 .unwrap_basic();
7193 let (res, info) = self.finalize_rounding_result(res, info)?;
7194 self.state.push1_extra(res, info);
7195 }
7196 Operator::F32x4Nearest => {
7197 let (v, i) = self.state.pop1_extra()?;
7198 let (v, _) = self.v128_into_f32x4(v, i)?;
7199 let res = err!(self.build_call_with_param_attributes(
7200 self.intrinsics.nearbyint_f32x4,
7201 &[v.into()],
7202 ""
7203 ))
7204 .try_as_basic_value()
7205 .unwrap_basic();
7206 let (res, info) = self.finalize_rounding_result(res, i)?;
7207 let res = err!(
7208 self.builder
7209 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7210 );
7211 self.state.push1_extra(res, info);
7212 }
7213 Operator::F64Nearest => {
7214 let (v, info) = self.state.pop1_extra()?;
7215 let res = err!(self.build_call_with_param_attributes(
7216 self.intrinsics.nearbyint_f64,
7217 &[v.into()],
7218 ""
7219 ))
7220 .try_as_basic_value()
7221 .unwrap_basic();
7222 let (res, info) = self.finalize_rounding_result(res, info)?;
7223 self.state.push1_extra(res, info);
7224 }
7225 Operator::F64x2Nearest => {
7226 let (v, i) = self.state.pop1_extra()?;
7227 let (v, _) = self.v128_into_f64x2(v, i)?;
7228 let res = err!(self.build_call_with_param_attributes(
7229 self.intrinsics.nearbyint_f64x2,
7230 &[v.into()],
7231 ""
7232 ))
7233 .try_as_basic_value()
7234 .unwrap_basic();
7235 let (res, info) = self.finalize_rounding_result(res, i)?;
7236 let res = err!(
7237 self.builder
7238 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7239 );
7240 self.state.push1_extra(res, info);
7241 }
7242 Operator::F32Abs => {
7243 let (v, i) = self.state.pop1_extra()?;
7244 let v = self.apply_pending_canonicalization(v, i)?;
7245 let res = err!(
7246 self.builder
7247 .build_call(self.intrinsics.fabs_f32, &[v.into()], "")
7248 )
7249 .try_as_basic_value()
7250 .unwrap_basic();
7251 self.state.push1_extra(res, i.strip_pending());
7254 }
7255 Operator::F64Abs => {
7256 let (v, i) = self.state.pop1_extra()?;
7257 let v = self.apply_pending_canonicalization(v, i)?;
7258 let res = err!(
7259 self.builder
7260 .build_call(self.intrinsics.fabs_f64, &[v.into()], "")
7261 )
7262 .try_as_basic_value()
7263 .unwrap_basic();
7264 self.state.push1_extra(res, i.strip_pending());
7267 }
7268 Operator::F32x4Abs => {
7269 let (v, i) = self.state.pop1_extra()?;
7270 let v = err!(self.builder.build_bit_cast(
7271 v.into_int_value(),
7272 self.intrinsics.f32x4_ty,
7273 ""
7274 ));
7275 let v = self.apply_pending_canonicalization(v, i)?;
7276 let res = self
7277 .build_call_with_param_attributes(self.intrinsics.fabs_f32x4, &[v.into()], "")?
7278 .try_as_basic_value()
7279 .unwrap_basic();
7280 let res = err!(
7281 self.builder
7282 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7283 );
7284 self.state.push1_extra(res, i.strip_pending());
7287 }
7288 Operator::F64x2Abs => {
7289 let (v, i) = self.state.pop1_extra()?;
7290 let v = err!(self.builder.build_bit_cast(
7291 v.into_int_value(),
7292 self.intrinsics.f64x2_ty,
7293 ""
7294 ));
7295 let v = self.apply_pending_canonicalization(v, i)?;
7296 let res = self
7297 .build_call_with_param_attributes(self.intrinsics.fabs_f64x2, &[v.into()], "")?
7298 .try_as_basic_value()
7299 .unwrap_basic();
7300 let res = err!(
7301 self.builder
7302 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7303 );
7304 self.state.push1_extra(res, i.strip_pending());
7307 }
7308 Operator::F32x4Neg => {
7309 let (v, i) = self.state.pop1_extra()?;
7310 let v = err!(self.builder.build_bit_cast(
7311 v.into_int_value(),
7312 self.intrinsics.f32x4_ty,
7313 ""
7314 ));
7315 let v = self
7316 .apply_pending_canonicalization(v, i)?
7317 .into_vector_value();
7318 let res = err!(self.builder.build_float_neg(v, ""));
7319 let res = err!(
7320 self.builder
7321 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7322 );
7323 self.state.push1_extra(res, i.strip_pending());
7326 }
7327 Operator::F64x2Neg => {
7328 let (v, i) = self.state.pop1_extra()?;
7329 let v = err!(self.builder.build_bit_cast(
7330 v.into_int_value(),
7331 self.intrinsics.f64x2_ty,
7332 ""
7333 ));
7334 let v = self
7335 .apply_pending_canonicalization(v, i)?
7336 .into_vector_value();
7337 let res = err!(self.builder.build_float_neg(v, ""));
7338 let res = err!(
7339 self.builder
7340 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7341 );
7342 self.state.push1_extra(res, i.strip_pending());
7345 }
7346 Operator::F32Neg | Operator::F64Neg => {
7347 let (v, i) = self.state.pop1_extra()?;
7348 let v = self
7349 .apply_pending_canonicalization(v, i)?
7350 .into_float_value();
7351 let res = err!(self.builder.build_float_neg(v, ""));
7352 self.state.push1_extra(res, i.strip_pending());
7355 }
7356 Operator::F32Copysign => {
7357 let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
7358 let mag = self.apply_pending_canonicalization(mag, mag_info)?;
7359 let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
7360 let res = self
7361 .build_call_with_param_attributes(
7362 self.intrinsics.copysign_f32,
7363 &[mag.into(), sgn.into()],
7364 "",
7365 )?
7366 .try_as_basic_value()
7367 .unwrap_basic();
7368 self.state.push1_extra(res, mag_info.strip_pending());
7371 }
7372 Operator::F64Copysign => {
7373 let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
7374 let mag = self.apply_pending_canonicalization(mag, mag_info)?;
7375 let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
7376 let res = self
7377 .build_call_with_param_attributes(
7378 self.intrinsics.copysign_f64,
7379 &[mag.into(), sgn.into()],
7380 "",
7381 )?
7382 .try_as_basic_value()
7383 .unwrap_basic();
7384 self.state.push1_extra(res, mag_info.strip_pending());
7387 }
7388 _ => unreachable!(),
7389 }
7390 Ok(())
7391 }
7392
7393 fn translate_integer_comparison_operator(&mut self, op: Operator) -> Result<(), CompileError> {
7396 match op {
7397 Operator::I32Eq | Operator::I64Eq => {
7398 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7399 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7400 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7401 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7402 let cond = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7403 let res = err!(
7404 self.builder
7405 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7406 );
7407 self.state.push1_extra(
7408 res,
7409 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7410 );
7411 }
7412 Operator::I8x16Eq => {
7413 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7414 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7415 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7416 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7417 let res = err!(
7418 self.builder
7419 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7420 );
7421 let res = err!(
7422 self.builder
7423 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7424 );
7425 self.state.push1(res);
7426 }
7427 Operator::I16x8Eq => {
7428 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7429 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7430 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7431 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7432 let res = err!(
7433 self.builder
7434 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7435 );
7436 let res = err!(
7437 self.builder
7438 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7439 );
7440 self.state.push1(res);
7441 }
7442 Operator::I32x4Eq => {
7443 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7444 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7445 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7446 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7447 let res = err!(
7448 self.builder
7449 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7450 );
7451 let res = err!(
7452 self.builder
7453 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7454 );
7455 self.state.push1(res);
7456 }
7457 Operator::I64x2Eq => {
7458 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7459 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7460 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7461 let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7462 let res = err!(
7463 self.builder
7464 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7465 );
7466 let res = err!(
7467 self.builder
7468 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7469 );
7470 self.state.push1(res);
7471 }
7472 Operator::I32Ne | Operator::I64Ne => {
7473 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7474 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7475 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7476 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7477 let cond = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7478 let res = err!(
7479 self.builder
7480 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7481 );
7482 self.state.push1_extra(
7483 res,
7484 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7485 );
7486 }
7487 Operator::I8x16Ne => {
7488 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7489 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7490 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7491 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7492 let res = err!(
7493 self.builder
7494 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7495 );
7496 let res = err!(
7497 self.builder
7498 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7499 );
7500 self.state.push1(res);
7501 }
7502 Operator::I16x8Ne => {
7503 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7504 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7505 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7506 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7507 let res = err!(
7508 self.builder
7509 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7510 );
7511 let res = err!(
7512 self.builder
7513 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7514 );
7515 self.state.push1(res);
7516 }
7517 Operator::I32x4Ne => {
7518 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7519 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7520 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7521 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7522 let res = err!(
7523 self.builder
7524 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7525 );
7526 let res = err!(
7527 self.builder
7528 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7529 );
7530 self.state.push1(res);
7531 }
7532 Operator::I64x2Ne => {
7533 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7534 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7535 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7536 let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7537 let res = err!(
7538 self.builder
7539 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7540 );
7541 let res = err!(
7542 self.builder
7543 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7544 );
7545 self.state.push1(res);
7546 }
7547 Operator::I32LtS | Operator::I64LtS => {
7548 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7549 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7550 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7551 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7552 let cond = err!(
7553 self.builder
7554 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7555 );
7556 let res = err!(
7557 self.builder
7558 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7559 );
7560 self.state.push1_extra(
7561 res,
7562 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7563 );
7564 }
7565 Operator::I8x16LtS => {
7566 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7567 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7568 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7569 let res = err!(
7570 self.builder
7571 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7572 );
7573 let res = err!(
7574 self.builder
7575 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7576 );
7577 let res = err!(
7578 self.builder
7579 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7580 );
7581 self.state.push1(res);
7582 }
7583 Operator::I16x8LtS => {
7584 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7585 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7586 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7587 let res = err!(
7588 self.builder
7589 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7590 );
7591 let res = err!(
7592 self.builder
7593 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7594 );
7595 let res = err!(
7596 self.builder
7597 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7598 );
7599 self.state.push1(res);
7600 }
7601 Operator::I32x4LtS => {
7602 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7603 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7604 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7605 let res = err!(
7606 self.builder
7607 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7608 );
7609 let res = err!(
7610 self.builder
7611 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7612 );
7613 let res = err!(
7614 self.builder
7615 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7616 );
7617 self.state.push1(res);
7618 }
7619 Operator::I64x2LtS => {
7620 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7621 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7622 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7623 let res = err!(
7624 self.builder
7625 .build_int_compare(IntPredicate::SLT, v1, v2, "")
7626 );
7627 let res = err!(
7628 self.builder
7629 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7630 );
7631 let res = err!(
7632 self.builder
7633 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7634 );
7635 self.state.push1(res);
7636 }
7637 Operator::I32LtU | Operator::I64LtU => {
7638 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7639 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7640 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7641 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7642 let cond = err!(
7643 self.builder
7644 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7645 );
7646 let res = err!(
7647 self.builder
7648 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7649 );
7650 self.state.push1(res);
7651 }
7652 Operator::I8x16LtU => {
7653 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7654 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7655 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7656 let res = err!(
7657 self.builder
7658 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7659 );
7660 let res = err!(
7661 self.builder
7662 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7663 );
7664 let res = err!(
7665 self.builder
7666 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7667 );
7668 self.state.push1(res);
7669 }
7670 Operator::I16x8LtU => {
7671 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7672 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7673 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7674 let res = err!(
7675 self.builder
7676 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7677 );
7678 let res = err!(
7679 self.builder
7680 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7681 );
7682 let res = err!(
7683 self.builder
7684 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7685 );
7686 self.state.push1(res);
7687 }
7688 Operator::I32x4LtU => {
7689 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7690 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7691 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7692 let res = err!(
7693 self.builder
7694 .build_int_compare(IntPredicate::ULT, v1, v2, "")
7695 );
7696 let res = err!(
7697 self.builder
7698 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7699 );
7700 let res = err!(
7701 self.builder
7702 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7703 );
7704 self.state.push1(res);
7705 }
7706 Operator::I32LeS | Operator::I64LeS => {
7707 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7708 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7709 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7710 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7711 let cond = err!(
7712 self.builder
7713 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7714 );
7715 let res = err!(
7716 self.builder
7717 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7718 );
7719 self.state.push1_extra(
7720 res,
7721 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7722 );
7723 }
7724 Operator::I8x16LeS => {
7725 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7726 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7727 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7728 let res = err!(
7729 self.builder
7730 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7731 );
7732 let res = err!(
7733 self.builder
7734 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7735 );
7736 let res = err!(
7737 self.builder
7738 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7739 );
7740 self.state.push1(res);
7741 }
7742 Operator::I16x8LeS => {
7743 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7744 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7745 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7746 let res = err!(
7747 self.builder
7748 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7749 );
7750 let res = err!(
7751 self.builder
7752 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7753 );
7754 let res = err!(
7755 self.builder
7756 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7757 );
7758 self.state.push1(res);
7759 }
7760 Operator::I32x4LeS => {
7761 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7762 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7763 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7764 let res = err!(
7765 self.builder
7766 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7767 );
7768 let res = err!(
7769 self.builder
7770 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7771 );
7772 let res = err!(
7773 self.builder
7774 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7775 );
7776 self.state.push1(res);
7777 }
7778 Operator::I64x2LeS => {
7779 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7780 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7781 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7782 let res = err!(
7783 self.builder
7784 .build_int_compare(IntPredicate::SLE, v1, v2, "")
7785 );
7786 let res = err!(
7787 self.builder
7788 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7789 );
7790 let res = err!(
7791 self.builder
7792 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7793 );
7794 self.state.push1(res);
7795 }
7796 Operator::I32LeU | Operator::I64LeU => {
7797 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7798 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7799 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7800 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7801 let cond = err!(
7802 self.builder
7803 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7804 );
7805 let res = err!(
7806 self.builder
7807 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7808 );
7809 self.state.push1_extra(
7810 res,
7811 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7812 );
7813 }
7814 Operator::I8x16LeU => {
7815 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7816 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7817 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7818 let res = err!(
7819 self.builder
7820 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7821 );
7822 let res = err!(
7823 self.builder
7824 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7825 );
7826 let res = err!(
7827 self.builder
7828 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7829 );
7830 self.state.push1(res);
7831 }
7832 Operator::I16x8LeU => {
7833 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7834 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7835 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7836 let res = err!(
7837 self.builder
7838 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7839 );
7840 let res = err!(
7841 self.builder
7842 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7843 );
7844 let res = err!(
7845 self.builder
7846 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7847 );
7848 self.state.push1(res);
7849 }
7850 Operator::I32x4LeU => {
7851 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7852 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7853 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7854 let res = err!(
7855 self.builder
7856 .build_int_compare(IntPredicate::ULE, v1, v2, "")
7857 );
7858 let res = err!(
7859 self.builder
7860 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7861 );
7862 let res = err!(
7863 self.builder
7864 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7865 );
7866 self.state.push1(res);
7867 }
7868 Operator::I32GtS | Operator::I64GtS => {
7869 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7870 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7871 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7872 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7873 let cond = err!(
7874 self.builder
7875 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7876 );
7877 let res = err!(
7878 self.builder
7879 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7880 );
7881 self.state.push1_extra(
7882 res,
7883 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7884 );
7885 }
7886 Operator::I8x16GtS => {
7887 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7888 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7889 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7890 let res = err!(
7891 self.builder
7892 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7893 );
7894 let res = err!(
7895 self.builder
7896 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7897 );
7898 let res = err!(
7899 self.builder
7900 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7901 );
7902 self.state.push1(res);
7903 }
7904 Operator::I16x8GtS => {
7905 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7906 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7907 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7908 let res = err!(
7909 self.builder
7910 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7911 );
7912 let res = err!(
7913 self.builder
7914 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7915 );
7916 let res = err!(
7917 self.builder
7918 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7919 );
7920 self.state.push1(res);
7921 }
7922 Operator::I32x4GtS => {
7923 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7924 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7925 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7926 let res = err!(
7927 self.builder
7928 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7929 );
7930 let res = err!(
7931 self.builder
7932 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7933 );
7934 let res = err!(
7935 self.builder
7936 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7937 );
7938 self.state.push1(res);
7939 }
7940 Operator::I64x2GtS => {
7941 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7942 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7943 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7944 let res = err!(
7945 self.builder
7946 .build_int_compare(IntPredicate::SGT, v1, v2, "")
7947 );
7948 let res = err!(
7949 self.builder
7950 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7951 );
7952 let res = err!(
7953 self.builder
7954 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7955 );
7956 self.state.push1(res);
7957 }
7958 Operator::I32GtU | Operator::I64GtU => {
7959 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7960 let v1 = self.apply_pending_canonicalization(v1, i1)?;
7961 let v2 = self.apply_pending_canonicalization(v2, i2)?;
7962 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7963 let cond = err!(
7964 self.builder
7965 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7966 );
7967 let res = err!(
7968 self.builder
7969 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7970 );
7971 self.state.push1_extra(
7972 res,
7973 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7974 );
7975 }
7976 Operator::I8x16GtU => {
7977 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7978 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7979 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7980 let res = err!(
7981 self.builder
7982 .build_int_compare(IntPredicate::UGT, v1, v2, "")
7983 );
7984 let res = err!(
7985 self.builder
7986 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7987 );
7988 let res = err!(
7989 self.builder
7990 .build_bit_cast(res, self.intrinsics.i128_ty, "")
7991 );
7992 self.state.push1(res);
7993 }
7994 Operator::I16x8GtU => {
7995 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7996 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7997 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7998 let res = err!(
7999 self.builder
8000 .build_int_compare(IntPredicate::UGT, v1, v2, "")
8001 );
8002 let res = err!(
8003 self.builder
8004 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
8005 );
8006 let res = err!(
8007 self.builder
8008 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8009 );
8010 self.state.push1(res);
8011 }
8012 Operator::I32x4GtU => {
8013 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8014 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8015 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8016 let res = err!(
8017 self.builder
8018 .build_int_compare(IntPredicate::UGT, v1, v2, "")
8019 );
8020 let res = err!(
8021 self.builder
8022 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8023 );
8024 let res = err!(
8025 self.builder
8026 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8027 );
8028 self.state.push1(res);
8029 }
8030 Operator::I32GeS | Operator::I64GeS => {
8031 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8032 let v1 = self.apply_pending_canonicalization(v1, i1)?;
8033 let v2 = self.apply_pending_canonicalization(v2, i2)?;
8034 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
8035 let cond = err!(
8036 self.builder
8037 .build_int_compare(IntPredicate::SGE, v1, v2, "")
8038 );
8039 let res = err!(
8040 self.builder
8041 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8042 );
8043 self.state.push1(res);
8044 }
8045 Operator::I8x16GeS => {
8046 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8047 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
8048 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
8049 let res = err!(
8050 self.builder
8051 .build_int_compare(IntPredicate::SGE, v1, v2, "")
8052 );
8053 let res = err!(
8054 self.builder
8055 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
8056 );
8057 let res = err!(
8058 self.builder
8059 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8060 );
8061 self.state.push1(res);
8062 }
8063 Operator::I16x8GeS => {
8064 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8065 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8066 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8067 let res = err!(
8068 self.builder
8069 .build_int_compare(IntPredicate::SGE, v1, v2, "")
8070 );
8071 let res = err!(
8072 self.builder
8073 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
8074 );
8075 let res = err!(
8076 self.builder
8077 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8078 );
8079 self.state.push1(res);
8080 }
8081 Operator::I32x4GeS => {
8082 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8083 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8084 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8085 let res = err!(
8086 self.builder
8087 .build_int_compare(IntPredicate::SGE, v1, v2, "")
8088 );
8089 let res = err!(
8090 self.builder
8091 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8092 );
8093 let res = err!(
8094 self.builder
8095 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8096 );
8097 self.state.push1(res);
8098 }
8099 Operator::I64x2GeS => {
8100 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8101 let (v1, _) = self.v128_into_i64x2(v1, i1)?;
8102 let (v2, _) = self.v128_into_i64x2(v2, i2)?;
8103 let res = err!(
8104 self.builder
8105 .build_int_compare(IntPredicate::SGE, v1, v2, "")
8106 );
8107 let res = err!(
8108 self.builder
8109 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8110 );
8111 let res = err!(
8112 self.builder
8113 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8114 );
8115 self.state.push1(res);
8116 }
8117 Operator::I32GeU | Operator::I64GeU => {
8118 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8119 let v1 = self.apply_pending_canonicalization(v1, i1)?;
8120 let v2 = self.apply_pending_canonicalization(v2, i2)?;
8121 let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
8122 let cond = err!(
8123 self.builder
8124 .build_int_compare(IntPredicate::UGE, v1, v2, "")
8125 );
8126 let res = err!(
8127 self.builder
8128 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8129 );
8130 self.state.push1_extra(
8131 res,
8132 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8133 );
8134 }
8135 Operator::I8x16GeU => {
8136 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8137 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
8138 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
8139 let res = err!(
8140 self.builder
8141 .build_int_compare(IntPredicate::UGE, v1, v2, "")
8142 );
8143 let res = err!(
8144 self.builder
8145 .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
8146 );
8147 let res = err!(
8148 self.builder
8149 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8150 );
8151 self.state.push1(res);
8152 }
8153 Operator::I16x8GeU => {
8154 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8155 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8156 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8157 let res = err!(
8158 self.builder
8159 .build_int_compare(IntPredicate::UGE, v1, v2, "")
8160 );
8161 let res = err!(
8162 self.builder
8163 .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
8164 );
8165 let res = err!(
8166 self.builder
8167 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8168 );
8169 self.state.push1(res);
8170 }
8171 Operator::I32x4GeU => {
8172 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8173 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8174 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8175 let res = err!(
8176 self.builder
8177 .build_int_compare(IntPredicate::UGE, v1, v2, "")
8178 );
8179 let res = err!(
8180 self.builder
8181 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8182 );
8183 let res = err!(
8184 self.builder
8185 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8186 );
8187 self.state.push1(res);
8188 }
8189 _ => unreachable!(),
8190 }
8191 Ok(())
8192 }
8193
8194 fn translate_floating_point_comparison_operator(
8197 &mut self,
8198 op: Operator,
8199 ) -> Result<(), CompileError> {
8200 match op {
8201 Operator::F32Eq | Operator::F64Eq => {
8202 let (v1, v2) = self.state.pop2()?;
8203 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8204 let cond = err!(
8205 self.builder
8206 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8207 );
8208 let res = err!(
8209 self.builder
8210 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8211 );
8212 self.state.push1_extra(
8213 res,
8214 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8215 );
8216 }
8217 Operator::F32x4Eq => {
8218 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8219 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8220 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8221 let res = err!(
8222 self.builder
8223 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8224 );
8225 let res = err!(
8226 self.builder
8227 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8228 );
8229 let res = err!(
8230 self.builder
8231 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8232 );
8233 self.state.push1(res);
8234 }
8235 Operator::F64x2Eq => {
8236 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8237 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8238 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8239 let res = err!(
8240 self.builder
8241 .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8242 );
8243 let res = err!(
8244 self.builder
8245 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8246 );
8247 let res = err!(
8248 self.builder
8249 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8250 );
8251 self.state.push1(res);
8252 }
8253 Operator::F32Ne | Operator::F64Ne => {
8254 let (v1, v2) = self.state.pop2()?;
8255 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8256 let cond = err!(
8257 self.builder
8258 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8259 );
8260 let res = err!(
8261 self.builder
8262 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8263 );
8264 self.state.push1_extra(
8265 res,
8266 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8267 );
8268 }
8269 Operator::F32x4Ne => {
8270 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8271 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8272 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8273 let res = err!(
8274 self.builder
8275 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8276 );
8277 let res = err!(
8278 self.builder
8279 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8280 );
8281 let res = err!(
8282 self.builder
8283 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8284 );
8285 self.state.push1(res);
8286 }
8287 Operator::F64x2Ne => {
8288 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8289 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8290 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8291 let res = err!(
8292 self.builder
8293 .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8294 );
8295 let res = err!(
8296 self.builder
8297 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8298 );
8299 let res = err!(
8300 self.builder
8301 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8302 );
8303 self.state.push1(res);
8304 }
8305 Operator::F32Lt | Operator::F64Lt => {
8306 let (v1, v2) = self.state.pop2()?;
8307 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8308 let cond = err!(
8309 self.builder
8310 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8311 );
8312 let res = err!(
8313 self.builder
8314 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8315 );
8316 self.state.push1_extra(
8317 res,
8318 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8319 );
8320 }
8321 Operator::F32x4Lt => {
8322 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8323 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8324 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8325 let res = err!(
8326 self.builder
8327 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8328 );
8329 let res = err!(
8330 self.builder
8331 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8332 );
8333 let res = err!(
8334 self.builder
8335 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8336 );
8337 self.state.push1(res);
8338 }
8339 Operator::F64x2Lt => {
8340 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8341 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8342 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8343 let res = err!(
8344 self.builder
8345 .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8346 );
8347 let res = err!(
8348 self.builder
8349 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8350 );
8351 let res = err!(
8352 self.builder
8353 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8354 );
8355 self.state.push1(res);
8356 }
8357 Operator::F32Le | Operator::F64Le => {
8358 let (v1, v2) = self.state.pop2()?;
8359 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8360 let cond = err!(
8361 self.builder
8362 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8363 );
8364 let res = err!(
8365 self.builder
8366 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8367 );
8368 self.state.push1_extra(
8369 res,
8370 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8371 );
8372 }
8373 Operator::F32x4Le => {
8374 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8375 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8376 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8377 let res = err!(
8378 self.builder
8379 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8380 );
8381 let res = err!(
8382 self.builder
8383 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8384 );
8385 let res = err!(
8386 self.builder
8387 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8388 );
8389 self.state.push1(res);
8390 }
8391 Operator::F64x2Le => {
8392 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8393 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8394 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8395 let res = err!(
8396 self.builder
8397 .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8398 );
8399 let res = err!(
8400 self.builder
8401 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8402 );
8403 let res = err!(
8404 self.builder
8405 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8406 );
8407 self.state.push1(res);
8408 }
8409 Operator::F32Gt | Operator::F64Gt => {
8410 let (v1, v2) = self.state.pop2()?;
8411 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8412 let cond = err!(
8413 self.builder
8414 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8415 );
8416 let res = err!(
8417 self.builder
8418 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8419 );
8420 self.state.push1_extra(
8421 res,
8422 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8423 );
8424 }
8425 Operator::F32x4Gt => {
8426 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8427 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8428 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8429 let res = err!(
8430 self.builder
8431 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8432 );
8433 let res = err!(
8434 self.builder
8435 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8436 );
8437 let res = err!(
8438 self.builder
8439 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8440 );
8441 self.state.push1(res);
8442 }
8443 Operator::F64x2Gt => {
8444 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8445 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8446 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8447 let res = err!(
8448 self.builder
8449 .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8450 );
8451 let res = err!(
8452 self.builder
8453 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8454 );
8455 let res = err!(
8456 self.builder
8457 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8458 );
8459 self.state.push1(res);
8460 }
8461 Operator::F32Ge | Operator::F64Ge => {
8462 let (v1, v2) = self.state.pop2()?;
8463 let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8464 let cond = err!(
8465 self.builder
8466 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8467 );
8468 let res = err!(
8469 self.builder
8470 .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8471 );
8472 self.state.push1_extra(
8473 res,
8474 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8475 );
8476 }
8477 Operator::F32x4Ge => {
8478 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8479 let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8480 let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8481 let res = err!(
8482 self.builder
8483 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8484 );
8485 let res = err!(
8486 self.builder
8487 .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8488 );
8489 let res = err!(
8490 self.builder
8491 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8492 );
8493 self.state.push1(res);
8494 }
8495 Operator::F64x2Ge => {
8496 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8497 let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8498 let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8499 let res = err!(
8500 self.builder
8501 .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8502 );
8503 let res = err!(
8504 self.builder
8505 .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8506 );
8507 let res = err!(
8508 self.builder
8509 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8510 );
8511 self.state.push1(res);
8512 }
8513 _ => unreachable!(),
8514 }
8515 Ok(())
8516 }
8517
8518 fn translate_conversion_operator(&mut self, op: Operator) -> Result<(), CompileError> {
8521 match op {
8522 Operator::I32WrapI64 => {
8523 let (v, i) = self.state.pop1_extra()?;
8524 let v = self.apply_pending_canonicalization(v, i)?;
8525 let v = v.into_int_value();
8526 let res = err!(
8527 self.builder
8528 .build_int_truncate(v, self.intrinsics.i32_ty, "")
8529 );
8530 self.state.push1(res);
8531 }
8532 Operator::I64ExtendI32S => {
8533 let (v, i) = self.state.pop1_extra()?;
8534 let v = self.apply_pending_canonicalization(v, i)?;
8535 let v = v.into_int_value();
8536 let res = err!(
8537 self.builder
8538 .build_int_s_extend(v, self.intrinsics.i64_ty, "")
8539 );
8540 self.state.push1(res);
8541 }
8542 Operator::I64ExtendI32U => {
8543 let (v, i) = self.state.pop1_extra()?;
8544 let v = self.apply_pending_canonicalization(v, i)?;
8545 let v = v.into_int_value();
8546 let res = err!(
8547 self.builder
8548 .build_int_z_extend(v, self.intrinsics.i64_ty, "")
8549 );
8550 self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
8551 }
8552 Operator::I16x8ExtendLowI8x16S => {
8553 let (v, i) = self.state.pop1_extra()?;
8554 let (v, _) = self.v128_into_i8x16(v, i)?;
8555 let low = err!(self.builder.build_shuffle_vector(
8556 v,
8557 v.get_type().get_undef(),
8558 VectorType::const_vector(&[
8559 self.intrinsics.i32_consts[0],
8560 self.intrinsics.i32_consts[1],
8561 self.intrinsics.i32_consts[2],
8562 self.intrinsics.i32_consts[3],
8563 self.intrinsics.i32_consts[4],
8564 self.intrinsics.i32_consts[5],
8565 self.intrinsics.i32_consts[6],
8566 self.intrinsics.i32_consts[7],
8567 ]),
8568 "",
8569 ));
8570 let res = err!(
8571 self.builder
8572 .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
8573 );
8574 let res = err!(
8575 self.builder
8576 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8577 );
8578 self.state.push1(res);
8579 }
8580 Operator::I16x8ExtendHighI8x16S => {
8581 let (v, i) = self.state.pop1_extra()?;
8582 let (v, _) = self.v128_into_i8x16(v, i)?;
8583 let low = err!(self.builder.build_shuffle_vector(
8584 v,
8585 v.get_type().get_undef(),
8586 VectorType::const_vector(&[
8587 self.intrinsics.i32_consts[8],
8588 self.intrinsics.i32_consts[9],
8589 self.intrinsics.i32_consts[10],
8590 self.intrinsics.i32_consts[11],
8591 self.intrinsics.i32_consts[12],
8592 self.intrinsics.i32_consts[13],
8593 self.intrinsics.i32_consts[14],
8594 self.intrinsics.i32_consts[15],
8595 ]),
8596 "",
8597 ));
8598 let res = err!(
8599 self.builder
8600 .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
8601 );
8602 let res = err!(
8603 self.builder
8604 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8605 );
8606 self.state.push1(res);
8607 }
8608 Operator::I16x8ExtendLowI8x16U => {
8609 let (v, i) = self.state.pop1_extra()?;
8610 let (v, _) = self.v128_into_i8x16(v, i)?;
8611 let low = err!(self.builder.build_shuffle_vector(
8612 v,
8613 v.get_type().get_undef(),
8614 VectorType::const_vector(&[
8615 self.intrinsics.i32_consts[0],
8616 self.intrinsics.i32_consts[1],
8617 self.intrinsics.i32_consts[2],
8618 self.intrinsics.i32_consts[3],
8619 self.intrinsics.i32_consts[4],
8620 self.intrinsics.i32_consts[5],
8621 self.intrinsics.i32_consts[6],
8622 self.intrinsics.i32_consts[7],
8623 ]),
8624 "",
8625 ));
8626 let res = err!(
8627 self.builder
8628 .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8629 );
8630 let res = err!(
8631 self.builder
8632 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8633 );
8634 self.state.push1(res);
8635 }
8636 Operator::I16x8ExtendHighI8x16U => {
8637 let (v, i) = self.state.pop1_extra()?;
8638 let (v, _) = self.v128_into_i8x16(v, i)?;
8639 let low = err!(self.builder.build_shuffle_vector(
8640 v,
8641 v.get_type().get_undef(),
8642 VectorType::const_vector(&[
8643 self.intrinsics.i32_consts[8],
8644 self.intrinsics.i32_consts[9],
8645 self.intrinsics.i32_consts[10],
8646 self.intrinsics.i32_consts[11],
8647 self.intrinsics.i32_consts[12],
8648 self.intrinsics.i32_consts[13],
8649 self.intrinsics.i32_consts[14],
8650 self.intrinsics.i32_consts[15],
8651 ]),
8652 "",
8653 ));
8654 let res = err!(
8655 self.builder
8656 .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8657 );
8658 let res = err!(
8659 self.builder
8660 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8661 );
8662 self.state.push1(res);
8663 }
8664 Operator::I32x4ExtendLowI16x8S => {
8665 let (v, i) = self.state.pop1_extra()?;
8666 let (v, _) = self.v128_into_i16x8(v, i)?;
8667 let low = err!(self.builder.build_shuffle_vector(
8668 v,
8669 v.get_type().get_undef(),
8670 VectorType::const_vector(&[
8671 self.intrinsics.i32_consts[0],
8672 self.intrinsics.i32_consts[1],
8673 self.intrinsics.i32_consts[2],
8674 self.intrinsics.i32_consts[3],
8675 ]),
8676 "",
8677 ));
8678 let res = err!(
8679 self.builder
8680 .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8681 );
8682 let res = err!(
8683 self.builder
8684 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8685 );
8686 self.state.push1(res);
8687 }
8688 Operator::I32x4ExtendHighI16x8S => {
8689 let (v, i) = self.state.pop1_extra()?;
8690 let (v, _) = self.v128_into_i16x8(v, i)?;
8691 let low = err!(self.builder.build_shuffle_vector(
8692 v,
8693 v.get_type().get_undef(),
8694 VectorType::const_vector(&[
8695 self.intrinsics.i32_consts[4],
8696 self.intrinsics.i32_consts[5],
8697 self.intrinsics.i32_consts[6],
8698 self.intrinsics.i32_consts[7],
8699 ]),
8700 "",
8701 ));
8702 let res = err!(
8703 self.builder
8704 .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8705 );
8706 let res = err!(
8707 self.builder
8708 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8709 );
8710 self.state.push1(res);
8711 }
8712 Operator::I32x4ExtendLowI16x8U => {
8713 let (v, i) = self.state.pop1_extra()?;
8714 let (v, _) = self.v128_into_i16x8(v, i)?;
8715 let low = err!(self.builder.build_shuffle_vector(
8716 v,
8717 v.get_type().get_undef(),
8718 VectorType::const_vector(&[
8719 self.intrinsics.i32_consts[0],
8720 self.intrinsics.i32_consts[1],
8721 self.intrinsics.i32_consts[2],
8722 self.intrinsics.i32_consts[3],
8723 ]),
8724 "",
8725 ));
8726 let res = err!(
8727 self.builder
8728 .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8729 );
8730 let res = err!(
8731 self.builder
8732 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8733 );
8734 self.state.push1(res);
8735 }
8736 Operator::I32x4ExtendHighI16x8U => {
8737 let (v, i) = self.state.pop1_extra()?;
8738 let (v, _) = self.v128_into_i16x8(v, i)?;
8739 let low = err!(self.builder.build_shuffle_vector(
8740 v,
8741 v.get_type().get_undef(),
8742 VectorType::const_vector(&[
8743 self.intrinsics.i32_consts[4],
8744 self.intrinsics.i32_consts[5],
8745 self.intrinsics.i32_consts[6],
8746 self.intrinsics.i32_consts[7],
8747 ]),
8748 "",
8749 ));
8750 let res = err!(
8751 self.builder
8752 .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8753 );
8754 let res = err!(
8755 self.builder
8756 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8757 );
8758 self.state.push1(res);
8759 }
8760 Operator::I64x2ExtendLowI32x4U
8761 | Operator::I64x2ExtendLowI32x4S
8762 | Operator::I64x2ExtendHighI32x4U
8763 | Operator::I64x2ExtendHighI32x4S => {
8764 let extend = match op {
8765 Operator::I64x2ExtendLowI32x4U | Operator::I64x2ExtendHighI32x4U => {
8766 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
8767 }
8768 Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendHighI32x4S => {
8769 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
8770 }
8771 _ => unreachable!("Unhandled inner case"),
8772 };
8773 let indices = match op {
8774 Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendLowI32x4U => {
8775 [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
8776 }
8777 Operator::I64x2ExtendHighI32x4S | Operator::I64x2ExtendHighI32x4U => {
8778 [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
8779 }
8780 _ => unreachable!("Unhandled inner case"),
8781 };
8782 let (v, i) = self.state.pop1_extra()?;
8783 let (v, _) = self.v128_into_i32x4(v, i)?;
8784 let low = err!(self.builder.build_shuffle_vector(
8785 v,
8786 v.get_type().get_undef(),
8787 VectorType::const_vector(&indices),
8788 "",
8789 ));
8790 let res = err!(extend(self, low));
8791 let res = err!(
8792 self.builder
8793 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8794 );
8795 self.state.push1(res);
8796 }
8797 Operator::I8x16NarrowI16x8S => {
8798 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8799 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8800 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8801 let min = self.intrinsics.i16_ty.const_int(0xff80, false);
8802 let max = self.intrinsics.i16_ty.const_int(0x007f, false);
8803 let min = VectorType::const_vector(&[min; 8]);
8804 let max = VectorType::const_vector(&[max; 8]);
8805 let apply_min_clamp_v1 =
8806 err!(
8807 self.builder
8808 .build_int_compare(IntPredicate::SLT, v1, min, "")
8809 );
8810 let apply_max_clamp_v1 =
8811 err!(
8812 self.builder
8813 .build_int_compare(IntPredicate::SGT, v1, max, "")
8814 );
8815 let apply_min_clamp_v2 =
8816 err!(
8817 self.builder
8818 .build_int_compare(IntPredicate::SLT, v2, min, "")
8819 );
8820 let apply_max_clamp_v2 =
8821 err!(
8822 self.builder
8823 .build_int_compare(IntPredicate::SGT, v2, max, "")
8824 );
8825 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8826 .into_vector_value();
8827 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8828 .into_vector_value();
8829 let v1 = err!(self.builder.build_int_truncate(
8830 v1,
8831 self.intrinsics.i8_ty.vec_type(8),
8832 ""
8833 ));
8834 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8835 .into_vector_value();
8836 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8837 .into_vector_value();
8838 let v2 = err!(self.builder.build_int_truncate(
8839 v2,
8840 self.intrinsics.i8_ty.vec_type(8),
8841 ""
8842 ));
8843 let res = err!(self.builder.build_shuffle_vector(
8844 v1,
8845 v2,
8846 VectorType::const_vector(&[
8847 self.intrinsics.i32_consts[0],
8848 self.intrinsics.i32_consts[1],
8849 self.intrinsics.i32_consts[2],
8850 self.intrinsics.i32_consts[3],
8851 self.intrinsics.i32_consts[4],
8852 self.intrinsics.i32_consts[5],
8853 self.intrinsics.i32_consts[6],
8854 self.intrinsics.i32_consts[7],
8855 self.intrinsics.i32_consts[8],
8856 self.intrinsics.i32_consts[9],
8857 self.intrinsics.i32_consts[10],
8858 self.intrinsics.i32_consts[11],
8859 self.intrinsics.i32_consts[12],
8860 self.intrinsics.i32_consts[13],
8861 self.intrinsics.i32_consts[14],
8862 self.intrinsics.i32_consts[15],
8863 ]),
8864 "",
8865 ));
8866 let res = err!(
8867 self.builder
8868 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8869 );
8870 self.state.push1(res);
8871 }
8872 Operator::I8x16NarrowI16x8U => {
8873 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8874 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8875 let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8876 let min = self.intrinsics.i16x8_ty.const_zero();
8877 let max = self.intrinsics.i16_ty.const_int(0x00ff, false);
8878 let max = VectorType::const_vector(&[max; 8]);
8879 let apply_min_clamp_v1 =
8880 err!(
8881 self.builder
8882 .build_int_compare(IntPredicate::SLT, v1, min, "")
8883 );
8884 let apply_max_clamp_v1 =
8885 err!(
8886 self.builder
8887 .build_int_compare(IntPredicate::SGT, v1, max, "")
8888 );
8889 let apply_min_clamp_v2 =
8890 err!(
8891 self.builder
8892 .build_int_compare(IntPredicate::SLT, v2, min, "")
8893 );
8894 let apply_max_clamp_v2 =
8895 err!(
8896 self.builder
8897 .build_int_compare(IntPredicate::SGT, v2, max, "")
8898 );
8899 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8900 .into_vector_value();
8901 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8902 .into_vector_value();
8903 let v1 = err!(self.builder.build_int_truncate(
8904 v1,
8905 self.intrinsics.i8_ty.vec_type(8),
8906 ""
8907 ));
8908 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8909 .into_vector_value();
8910 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8911 .into_vector_value();
8912 let v2 = err!(self.builder.build_int_truncate(
8913 v2,
8914 self.intrinsics.i8_ty.vec_type(8),
8915 ""
8916 ));
8917 let res = err!(self.builder.build_shuffle_vector(
8918 v1,
8919 v2,
8920 VectorType::const_vector(&[
8921 self.intrinsics.i32_consts[0],
8922 self.intrinsics.i32_consts[1],
8923 self.intrinsics.i32_consts[2],
8924 self.intrinsics.i32_consts[3],
8925 self.intrinsics.i32_consts[4],
8926 self.intrinsics.i32_consts[5],
8927 self.intrinsics.i32_consts[6],
8928 self.intrinsics.i32_consts[7],
8929 self.intrinsics.i32_consts[8],
8930 self.intrinsics.i32_consts[9],
8931 self.intrinsics.i32_consts[10],
8932 self.intrinsics.i32_consts[11],
8933 self.intrinsics.i32_consts[12],
8934 self.intrinsics.i32_consts[13],
8935 self.intrinsics.i32_consts[14],
8936 self.intrinsics.i32_consts[15],
8937 ]),
8938 "",
8939 ));
8940 let res = err!(
8941 self.builder
8942 .build_bit_cast(res, self.intrinsics.i128_ty, "")
8943 );
8944 self.state.push1(res);
8945 }
8946 Operator::I16x8NarrowI32x4S => {
8947 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8948 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8949 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8950 let min = self.intrinsics.i32_ty.const_int(0xffff8000, false);
8951 let max = self.intrinsics.i32_ty.const_int(0x00007fff, false);
8952 let min = VectorType::const_vector(&[min; 4]);
8953 let max = VectorType::const_vector(&[max; 4]);
8954 let apply_min_clamp_v1 =
8955 err!(
8956 self.builder
8957 .build_int_compare(IntPredicate::SLT, v1, min, "")
8958 );
8959 let apply_max_clamp_v1 =
8960 err!(
8961 self.builder
8962 .build_int_compare(IntPredicate::SGT, v1, max, "")
8963 );
8964 let apply_min_clamp_v2 =
8965 err!(
8966 self.builder
8967 .build_int_compare(IntPredicate::SLT, v2, min, "")
8968 );
8969 let apply_max_clamp_v2 =
8970 err!(
8971 self.builder
8972 .build_int_compare(IntPredicate::SGT, v2, max, "")
8973 );
8974 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8975 .into_vector_value();
8976 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8977 .into_vector_value();
8978 let v1 = err!(self.builder.build_int_truncate(
8979 v1,
8980 self.intrinsics.i16_ty.vec_type(4),
8981 ""
8982 ));
8983 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8984 .into_vector_value();
8985 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8986 .into_vector_value();
8987 let v2 = err!(self.builder.build_int_truncate(
8988 v2,
8989 self.intrinsics.i16_ty.vec_type(4),
8990 ""
8991 ));
8992 let res = err!(self.builder.build_shuffle_vector(
8993 v1,
8994 v2,
8995 VectorType::const_vector(&[
8996 self.intrinsics.i32_consts[0],
8997 self.intrinsics.i32_consts[1],
8998 self.intrinsics.i32_consts[2],
8999 self.intrinsics.i32_consts[3],
9000 self.intrinsics.i32_consts[4],
9001 self.intrinsics.i32_consts[5],
9002 self.intrinsics.i32_consts[6],
9003 self.intrinsics.i32_consts[7],
9004 ]),
9005 "",
9006 ));
9007 let res = err!(
9008 self.builder
9009 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9010 );
9011 self.state.push1(res);
9012 }
9013 Operator::I16x8NarrowI32x4U => {
9014 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
9015 let (v1, _) = self.v128_into_i32x4(v1, i1)?;
9016 let (v2, _) = self.v128_into_i32x4(v2, i2)?;
9017 let min = self.intrinsics.i32x4_ty.const_zero();
9018 let max = self.intrinsics.i32_ty.const_int(0xffff, false);
9019 let max = VectorType::const_vector(&[max; 4]);
9020 let apply_min_clamp_v1 =
9021 err!(
9022 self.builder
9023 .build_int_compare(IntPredicate::SLT, v1, min, "")
9024 );
9025 let apply_max_clamp_v1 =
9026 err!(
9027 self.builder
9028 .build_int_compare(IntPredicate::SGT, v1, max, "")
9029 );
9030 let apply_min_clamp_v2 =
9031 err!(
9032 self.builder
9033 .build_int_compare(IntPredicate::SLT, v2, min, "")
9034 );
9035 let apply_max_clamp_v2 =
9036 err!(
9037 self.builder
9038 .build_int_compare(IntPredicate::SGT, v2, max, "")
9039 );
9040 let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
9041 .into_vector_value();
9042 let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
9043 .into_vector_value();
9044 let v1 = err!(self.builder.build_int_truncate(
9045 v1,
9046 self.intrinsics.i16_ty.vec_type(4),
9047 ""
9048 ));
9049 let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
9050 .into_vector_value();
9051 let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
9052 .into_vector_value();
9053 let v2 = err!(self.builder.build_int_truncate(
9054 v2,
9055 self.intrinsics.i16_ty.vec_type(4),
9056 ""
9057 ));
9058 let res = err!(self.builder.build_shuffle_vector(
9059 v1,
9060 v2,
9061 VectorType::const_vector(&[
9062 self.intrinsics.i32_consts[0],
9063 self.intrinsics.i32_consts[1],
9064 self.intrinsics.i32_consts[2],
9065 self.intrinsics.i32_consts[3],
9066 self.intrinsics.i32_consts[4],
9067 self.intrinsics.i32_consts[5],
9068 self.intrinsics.i32_consts[6],
9069 self.intrinsics.i32_consts[7],
9070 ]),
9071 "",
9072 ));
9073 let res = err!(
9074 self.builder
9075 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9076 );
9077 self.state.push1(res);
9078 }
9079 Operator::I32x4RelaxedTruncF32x4S if self.cpu_features.contains(CpuFeature::SSE2) => {
9080 let (v, i) = self.state.pop1_extra()?;
9081 let (v, _) = self.v128_into_f32x4(v, i)?;
9082 let res = self
9083 .build_call_with_param_attributes(
9084 self.intrinsics.x86_64.cvttps2dq,
9085 &[v.into()],
9086 "",
9087 )?
9088 .try_as_basic_value()
9089 .unwrap_basic();
9090 let res = err!(
9091 self.builder
9092 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9093 );
9094 self.state.push1(res);
9095 }
9096 Operator::I32x4TruncSatF32x4S | Operator::I32x4RelaxedTruncF32x4S => {
9097 let (v, i) = self.state.pop1_extra()?;
9098 let v = self.apply_pending_canonicalization(v, i)?;
9099 let v = v.into_int_value();
9100 let res = self.trunc_sat_into_int(
9101 self.intrinsics.f32x4_ty,
9102 self.intrinsics.i32x4_ty,
9103 LEF32_GEQ_I32_MIN,
9104 GEF32_LEQ_I32_MAX,
9105 i32::MIN as u64,
9106 i32::MAX as u64,
9107 v,
9108 )?;
9109 self.state.push1(res);
9110 }
9111 Operator::I32x4RelaxedTruncF32x4U
9112 if self.cpu_features.contains(CpuFeature::AVX512F)
9113 && self.cpu_features.contains(CpuFeature::AVX512VL) =>
9114 {
9115 let (v, i) = self.state.pop1_extra()?;
9116 let (v, _) = self.v128_into_f32x4(v, i)?;
9117 let res = self
9118 .build_call_with_param_attributes(
9119 self.intrinsics.x86_64.cvtps2udq128,
9120 &[
9121 v.into(),
9122 self.intrinsics.i32x4_ty.const_zero().into(),
9123 self.intrinsics.i8_ty.const_int(0xff, false).into(),
9124 ],
9125 "",
9126 )?
9127 .try_as_basic_value()
9128 .unwrap_basic();
9129 let res = err!(
9130 self.builder
9131 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9132 );
9133 self.state.push1(res);
9134 }
9135 Operator::I32x4TruncSatF32x4U | Operator::I32x4RelaxedTruncF32x4U => {
9136 let (v, i) = self.state.pop1_extra()?;
9137 let v = self.apply_pending_canonicalization(v, i)?;
9138 let v = v.into_int_value();
9139 let res = self.trunc_sat_into_int(
9140 self.intrinsics.f32x4_ty,
9141 self.intrinsics.i32x4_ty,
9142 LEF32_GEQ_U32_MIN,
9143 GEF32_LEQ_U32_MAX,
9144 u32::MIN as u64,
9145 u32::MAX as u64,
9146 v,
9147 )?;
9148 self.state.push1(res);
9149 }
9150 Operator::I32x4RelaxedTruncF64x2SZero
9151 if self.cpu_features.contains(CpuFeature::SSE2) =>
9152 {
9153 let (v, i) = self.state.pop1_extra()?;
9154 let (v, _) = self.v128_into_f64x2(v, i)?;
9155 let res = self
9156 .build_call_with_param_attributes(
9157 self.intrinsics.x86_64.cvtpd2dq,
9158 &[v.into()],
9159 "",
9160 )?
9161 .try_as_basic_value()
9162 .unwrap_basic();
9163 let res = err!(
9164 self.builder
9165 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9166 );
9167 self.state.push1(res);
9168 }
9169 Operator::I32x4RelaxedTruncF64x2UZero
9170 if self.cpu_features.contains(CpuFeature::AVX512F)
9171 && self.cpu_features.contains(CpuFeature::AVX512VL) =>
9172 {
9173 let (v, i) = self.state.pop1_extra()?;
9174 let (v, _) = self.v128_into_f64x2(v, i)?;
9175 let res = self
9176 .build_call_with_param_attributes(
9177 self.intrinsics.x86_64.cvtpd2udq128,
9178 &[
9179 v.into(),
9180 self.intrinsics.i32x4_ty.const_zero().into(),
9181 self.intrinsics.i8_ty.const_int(0xff, false).into(),
9182 ],
9183 "",
9184 )?
9185 .try_as_basic_value()
9186 .unwrap_basic();
9187 let res = err!(
9188 self.builder
9189 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9190 );
9191 self.state.push1(res);
9192 }
9193 Operator::I32x4TruncSatF64x2SZero
9194 | Operator::I32x4TruncSatF64x2UZero
9195 | Operator::I32x4RelaxedTruncF64x2SZero
9196 | Operator::I32x4RelaxedTruncF64x2UZero => {
9197 let ((min, max), (cmp_min, cmp_max)) = match op {
9198 Operator::I32x4TruncSatF64x2SZero => (
9199 (i32::MIN as u64, i32::MAX as u64),
9200 (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
9201 ),
9202 Operator::I32x4TruncSatF64x2UZero => (
9203 (u32::MIN as u64, u32::MAX as u64),
9204 (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
9205 ),
9206 Operator::I32x4RelaxedTruncF64x2SZero => (
9207 (i32::MIN as u64, i32::MAX as u64),
9208 (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
9209 ),
9210 Operator::I32x4RelaxedTruncF64x2UZero => (
9211 (u32::MIN as u64, u32::MAX as u64),
9212 (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
9213 ),
9214 _ => unreachable!("Unhandled internal variant"),
9215 };
9216 let (v, i) = self.state.pop1_extra()?;
9217 let v = self.apply_pending_canonicalization(v, i)?;
9218 let v = v.into_int_value();
9219 let res = self.trunc_sat(
9220 self.intrinsics.f64x2_ty,
9221 self.intrinsics.i32_ty.vec_type(2),
9222 cmp_min,
9223 cmp_max,
9224 min,
9225 max,
9226 v,
9227 )?;
9228
9229 let zero = self.intrinsics.i32_consts[0];
9230 let zeros = VectorType::const_vector(&[zero; 2]);
9231 let res = err!(self.builder.build_shuffle_vector(
9232 res,
9233 zeros,
9234 VectorType::const_vector(&[
9235 self.intrinsics.i32_consts[0],
9236 self.intrinsics.i32_consts[1],
9237 self.intrinsics.i32_consts[2],
9238 self.intrinsics.i32_consts[3],
9239 ]),
9240 "",
9241 ));
9242 let res = err!(
9243 self.builder
9244 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9245 );
9246 self.state.push1(res);
9247 }
9248 Operator::I32TruncF32S => {
9279 let v1 = self.state.pop1()?.into_float_value();
9280 self.trap_if_not_representable_as_int(
9281 0xcf000000, 0x4effffff, v1,
9284 )?;
9285 let res = err!(self.builder.build_float_to_signed_int(
9286 v1,
9287 self.intrinsics.i32_ty,
9288 ""
9289 ));
9290 self.state.push1(res);
9291 }
9292 Operator::I32TruncF64S => {
9293 let v1 = self.state.pop1()?.into_float_value();
9294 self.trap_if_not_representable_as_int(
9295 0xc1e00000001fffff, 0x41dfffffffffffff, v1,
9298 )?;
9299 let res = err!(self.builder.build_float_to_signed_int(
9300 v1,
9301 self.intrinsics.i32_ty,
9302 ""
9303 ));
9304 self.state.push1(res);
9305 }
9306 Operator::I32TruncSatF32S => {
9307 let (v, i) = self.state.pop1_extra()?;
9308 let v = self.apply_pending_canonicalization(v, i)?;
9309 let v = v.into_float_value();
9310 let res = self.trunc_sat_scalar(
9311 self.intrinsics.i32_ty,
9312 LEF32_GEQ_I32_MIN,
9313 GEF32_LEQ_I32_MAX,
9314 i32::MIN as u32 as u64,
9315 i32::MAX as u32 as u64,
9316 v,
9317 )?;
9318 self.state.push1(res);
9319 }
9320 Operator::I32TruncSatF64S => {
9321 let (v, i) = self.state.pop1_extra()?;
9322 let v = self.apply_pending_canonicalization(v, i)?;
9323 let v = v.into_float_value();
9324 let res = self.trunc_sat_scalar(
9325 self.intrinsics.i32_ty,
9326 LEF64_GEQ_I32_MIN,
9327 GEF64_LEQ_I32_MAX,
9328 i32::MIN as u64,
9329 i32::MAX as u64,
9330 v,
9331 )?;
9332 self.state.push1(res);
9333 }
9334 Operator::I64TruncF32S => {
9335 let v1 = self.state.pop1()?.into_float_value();
9336 self.trap_if_not_representable_as_int(
9337 0xdf000000, 0x5effffff, v1,
9340 )?;
9341 let res = err!(self.builder.build_float_to_signed_int(
9342 v1,
9343 self.intrinsics.i64_ty,
9344 ""
9345 ));
9346 self.state.push1(res);
9347 }
9348 Operator::I64TruncF64S => {
9349 let v1 = self.state.pop1()?.into_float_value();
9350 self.trap_if_not_representable_as_int(
9351 0xc3e0000000000000, 0x43dfffffffffffff, v1,
9354 )?;
9355 let res = err!(self.builder.build_float_to_signed_int(
9356 v1,
9357 self.intrinsics.i64_ty,
9358 ""
9359 ));
9360 self.state.push1(res);
9361 }
9362 Operator::I64TruncSatF32S => {
9363 let (v, i) = self.state.pop1_extra()?;
9364 let v = self.apply_pending_canonicalization(v, i)?;
9365 let v = v.into_float_value();
9366 let res = self.trunc_sat_scalar(
9367 self.intrinsics.i64_ty,
9368 LEF32_GEQ_I64_MIN,
9369 GEF32_LEQ_I64_MAX,
9370 i64::MIN as u64,
9371 i64::MAX as u64,
9372 v,
9373 )?;
9374 self.state.push1(res);
9375 }
9376 Operator::I64TruncSatF64S => {
9377 let (v, i) = self.state.pop1_extra()?;
9378 let v = self.apply_pending_canonicalization(v, i)?;
9379 let v = v.into_float_value();
9380 let res = self.trunc_sat_scalar(
9381 self.intrinsics.i64_ty,
9382 LEF64_GEQ_I64_MIN,
9383 GEF64_LEQ_I64_MAX,
9384 i64::MIN as u64,
9385 i64::MAX as u64,
9386 v,
9387 )?;
9388 self.state.push1(res);
9389 }
9390 Operator::I32TruncF32U => {
9391 let v1 = self.state.pop1()?.into_float_value();
9392 self.trap_if_not_representable_as_int(
9393 0xbf7fffff, 0x4f7fffff, v1,
9396 )?;
9397 let res = err!(self.builder.build_float_to_unsigned_int(
9398 v1,
9399 self.intrinsics.i32_ty,
9400 ""
9401 ));
9402 self.state.push1(res);
9403 }
9404 Operator::I32TruncF64U => {
9405 let v1 = self.state.pop1()?.into_float_value();
9406 self.trap_if_not_representable_as_int(
9407 0xbfefffffffffffff, 0x41efffffffffffff, v1,
9410 )?;
9411 let res = err!(self.builder.build_float_to_unsigned_int(
9412 v1,
9413 self.intrinsics.i32_ty,
9414 ""
9415 ));
9416 self.state.push1(res);
9417 }
9418 Operator::I32TruncSatF32U => {
9419 let (v, i) = self.state.pop1_extra()?;
9420 let v = self.apply_pending_canonicalization(v, i)?;
9421 let v = v.into_float_value();
9422 let res = self.trunc_sat_scalar(
9423 self.intrinsics.i32_ty,
9424 LEF32_GEQ_U32_MIN,
9425 GEF32_LEQ_U32_MAX,
9426 u32::MIN as u64,
9427 u32::MAX as u64,
9428 v,
9429 )?;
9430 self.state.push1(res);
9431 }
9432 Operator::I32TruncSatF64U => {
9433 let (v, i) = self.state.pop1_extra()?;
9434 let v = self.apply_pending_canonicalization(v, i)?;
9435 let v = v.into_float_value();
9436 let res = self.trunc_sat_scalar(
9437 self.intrinsics.i32_ty,
9438 LEF64_GEQ_U32_MIN,
9439 GEF64_LEQ_U32_MAX,
9440 u32::MIN as u64,
9441 u32::MAX as u64,
9442 v,
9443 )?;
9444 self.state.push1(res);
9445 }
9446 Operator::I64TruncF32U => {
9447 let v1 = self.state.pop1()?.into_float_value();
9448 self.trap_if_not_representable_as_int(
9449 0xbf7fffff, 0x5f7fffff, v1,
9452 )?;
9453 let res = err!(self.builder.build_float_to_unsigned_int(
9454 v1,
9455 self.intrinsics.i64_ty,
9456 ""
9457 ));
9458 self.state.push1(res);
9459 }
9460 Operator::I64TruncF64U => {
9461 let v1 = self.state.pop1()?.into_float_value();
9462 self.trap_if_not_representable_as_int(
9463 0xbfefffffffffffff, 0x43efffffffffffff, v1,
9466 )?;
9467 let res = err!(self.builder.build_float_to_unsigned_int(
9468 v1,
9469 self.intrinsics.i64_ty,
9470 ""
9471 ));
9472 self.state.push1(res);
9473 }
9474 Operator::I64TruncSatF32U => {
9475 let (v, i) = self.state.pop1_extra()?;
9476 let v = self.apply_pending_canonicalization(v, i)?;
9477 let v = v.into_float_value();
9478 let res = self.trunc_sat_scalar(
9479 self.intrinsics.i64_ty,
9480 LEF32_GEQ_U64_MIN,
9481 GEF32_LEQ_U64_MAX,
9482 u64::MIN,
9483 u64::MAX,
9484 v,
9485 )?;
9486 self.state.push1(res);
9487 }
9488 Operator::I64TruncSatF64U => {
9489 let (v, i) = self.state.pop1_extra()?;
9490 let v = self.apply_pending_canonicalization(v, i)?;
9491 let v = v.into_float_value();
9492 let res = self.trunc_sat_scalar(
9493 self.intrinsics.i64_ty,
9494 LEF64_GEQ_U64_MIN,
9495 GEF64_LEQ_U64_MAX,
9496 u64::MIN,
9497 u64::MAX,
9498 v,
9499 )?;
9500 self.state.push1(res);
9501 }
9502 Operator::F32DemoteF64 => {
9503 let v = self.state.pop1()?;
9504 let v = v.into_float_value();
9505 let res = self
9506 .build_call_with_param_attributes(
9507 self.intrinsics.fptrunc_f64,
9508 &[
9509 v.into(),
9510 self.intrinsics.fp_rounding_md,
9511 self.intrinsics.fp_exception_md,
9512 ],
9513 "",
9514 )?
9515 .try_as_basic_value()
9516 .unwrap_basic();
9517 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9518 }
9519 Operator::F64PromoteF32 => {
9520 let v = self.state.pop1()?;
9521 let v = v.into_float_value();
9522 let res = self
9523 .build_call_with_param_attributes(
9524 self.intrinsics.fpext_f32,
9525 &[v.into(), self.intrinsics.fp_exception_md],
9526 "",
9527 )?
9528 .try_as_basic_value()
9529 .unwrap_basic();
9530 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9531 }
9532 Operator::F32ConvertI32S | Operator::F32ConvertI64S => {
9533 let (v, i) = self.state.pop1_extra()?;
9534 let v = self.apply_pending_canonicalization(v, i)?;
9535 let v = v.into_int_value();
9536 let res = err!(self.builder.build_signed_int_to_float(
9537 v,
9538 self.intrinsics.f32_ty,
9539 ""
9540 ));
9541 self.state.push1(res);
9542 }
9543 Operator::F64ConvertI32S | Operator::F64ConvertI64S => {
9544 let (v, i) = self.state.pop1_extra()?;
9545 let v = self.apply_pending_canonicalization(v, i)?;
9546 let v = v.into_int_value();
9547 let res = err!(self.builder.build_signed_int_to_float(
9548 v,
9549 self.intrinsics.f64_ty,
9550 ""
9551 ));
9552 self.state.push1(res);
9553 }
9554 Operator::F32ConvertI32U | Operator::F32ConvertI64U => {
9555 let (v, i) = self.state.pop1_extra()?;
9556 let v = self.apply_pending_canonicalization(v, i)?;
9557 let v = v.into_int_value();
9558 let res = err!(self.builder.build_unsigned_int_to_float(
9559 v,
9560 self.intrinsics.f32_ty,
9561 ""
9562 ));
9563 self.state.push1(res);
9564 }
9565 Operator::F64ConvertI32U | Operator::F64ConvertI64U => {
9566 let (v, i) = self.state.pop1_extra()?;
9567 let v = self.apply_pending_canonicalization(v, i)?;
9568 let v = v.into_int_value();
9569 let res = err!(self.builder.build_unsigned_int_to_float(
9570 v,
9571 self.intrinsics.f64_ty,
9572 ""
9573 ));
9574 self.state.push1(res);
9575 }
9576 Operator::F32x4ConvertI32x4S => {
9577 let v = self.state.pop1()?;
9578 let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
9579 .into_vector_value();
9580 let res = err!(self.builder.build_signed_int_to_float(
9581 v,
9582 self.intrinsics.f32x4_ty,
9583 ""
9584 ));
9585 let res = err!(
9586 self.builder
9587 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9588 );
9589 self.state.push1(res);
9590 }
9591 Operator::F32x4ConvertI32x4U => {
9592 let v = self.state.pop1()?;
9593 let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
9594 .into_vector_value();
9595 let res = err!(self.builder.build_unsigned_int_to_float(
9596 v,
9597 self.intrinsics.f32x4_ty,
9598 ""
9599 ));
9600 let res = err!(
9601 self.builder
9602 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9603 );
9604 self.state.push1(res);
9605 }
9606 Operator::F64x2ConvertLowI32x4S | Operator::F64x2ConvertLowI32x4U => {
9607 let extend = match op {
9608 Operator::F64x2ConvertLowI32x4U => {
9609 |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
9610 }
9611 Operator::F64x2ConvertLowI32x4S => {
9612 |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
9613 }
9614 _ => unreachable!("Unhandled inner case"),
9615 };
9616 let (v, i) = self.state.pop1_extra()?;
9617 let (v, _) = self.v128_into_i32x4(v, i)?;
9618 let low = err!(self.builder.build_shuffle_vector(
9619 v,
9620 v.get_type().get_undef(),
9621 VectorType::const_vector(&[
9622 self.intrinsics.i32_consts[0],
9623 self.intrinsics.i32_consts[1],
9624 ]),
9625 "",
9626 ));
9627 let res = err!(extend(self, low));
9628 let res = err!(self.builder.build_signed_int_to_float(
9629 res,
9630 self.intrinsics.f64x2_ty,
9631 ""
9632 ));
9633 let res = err!(
9634 self.builder
9635 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9636 );
9637 self.state.push1(res);
9638 }
9639 Operator::F64x2PromoteLowF32x4 => {
9640 let (v, i) = self.state.pop1_extra()?;
9641 let (v, _) = self.v128_into_f32x4(v, i)?;
9642 let low = err!(self.builder.build_shuffle_vector(
9643 v,
9644 v.get_type().get_undef(),
9645 VectorType::const_vector(&[
9646 self.intrinsics.i32_consts[0],
9647 self.intrinsics.i32_consts[1],
9648 ]),
9649 "",
9650 ));
9651 let res = err!(
9652 self.builder
9653 .build_float_ext(low, self.intrinsics.f64x2_ty, "")
9654 );
9655 let res = err!(
9656 self.builder
9657 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9658 );
9659 self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9660 }
9661 Operator::F32x4DemoteF64x2Zero => {
9662 let (v, i) = self.state.pop1_extra()?;
9663 let (v, _) = self.v128_into_f64x2(v, i)?;
9664 let f32x2_ty = self.intrinsics.f32_ty.vec_type(2);
9665 let res = err!(self.builder.build_float_trunc(v, f32x2_ty, ""));
9666 let zeros = f32x2_ty.const_zero();
9667 let res = err!(self.builder.build_shuffle_vector(
9668 res,
9669 zeros,
9670 VectorType::const_vector(&[
9671 self.intrinsics.i32_consts[0],
9672 self.intrinsics.i32_consts[1],
9673 self.intrinsics.i32_consts[2],
9674 self.intrinsics.i32_consts[3],
9675 ]),
9676 "",
9677 ));
9678 let res = err!(
9679 self.builder
9680 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9681 );
9682 self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9683 }
9684 Operator::I32ReinterpretF32 => {
9709 let (v, i) = self.state.pop1_extra()?;
9710 let v = self.apply_pending_canonicalization(v, i)?;
9711 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i32_ty, ""));
9712 self.state.push1_extra(ret, ExtraInfo::arithmetic_f32());
9713 }
9714 Operator::I64ReinterpretF64 => {
9715 let (v, i) = self.state.pop1_extra()?;
9716 let v = self.apply_pending_canonicalization(v, i)?;
9717 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i64_ty, ""));
9718 self.state.push1_extra(ret, ExtraInfo::arithmetic_f64());
9719 }
9720 Operator::F32ReinterpretI32 => {
9721 let (v, i) = self.state.pop1_extra()?;
9722 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f32_ty, ""));
9723 self.state.push1_extra(ret, i);
9724 }
9725 Operator::F64ReinterpretI64 => {
9726 let (v, i) = self.state.pop1_extra()?;
9727 let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f64_ty, ""));
9728 self.state.push1_extra(ret, i);
9729 }
9730 _ => unreachable!(),
9731 }
9732 Ok(())
9733 }
9734
9735 fn translate_sign_extension_operator(&mut self, op: Operator) -> Result<(), CompileError> {
9738 match op {
9739 Operator::I32Extend8S => {
9740 let value = self.state.pop1()?.into_int_value();
9741 let narrow_value = err!(self.builder.build_int_truncate(
9742 value,
9743 self.intrinsics.i8_ty,
9744 ""
9745 ));
9746 let extended_value = err!(self.builder.build_int_s_extend(
9747 narrow_value,
9748 self.intrinsics.i32_ty,
9749 ""
9750 ));
9751 self.state.push1(extended_value);
9752 }
9753 Operator::I32Extend16S => {
9754 let value = self.state.pop1()?.into_int_value();
9755 let narrow_value = err!(self.builder.build_int_truncate(
9756 value,
9757 self.intrinsics.i16_ty,
9758 ""
9759 ));
9760 let extended_value = err!(self.builder.build_int_s_extend(
9761 narrow_value,
9762 self.intrinsics.i32_ty,
9763 ""
9764 ));
9765 self.state.push1(extended_value);
9766 }
9767 Operator::I64Extend8S => {
9768 let value = self.state.pop1()?.into_int_value();
9769 let narrow_value = err!(self.builder.build_int_truncate(
9770 value,
9771 self.intrinsics.i8_ty,
9772 ""
9773 ));
9774 let extended_value = err!(self.builder.build_int_s_extend(
9775 narrow_value,
9776 self.intrinsics.i64_ty,
9777 ""
9778 ));
9779 self.state.push1(extended_value);
9780 }
9781 Operator::I64Extend16S => {
9782 let value = self.state.pop1()?.into_int_value();
9783 let narrow_value = err!(self.builder.build_int_truncate(
9784 value,
9785 self.intrinsics.i16_ty,
9786 ""
9787 ));
9788 let extended_value = err!(self.builder.build_int_s_extend(
9789 narrow_value,
9790 self.intrinsics.i64_ty,
9791 ""
9792 ));
9793 self.state.push1(extended_value);
9794 }
9795 Operator::I64Extend32S => {
9796 let value = self.state.pop1()?.into_int_value();
9797 let narrow_value = err!(self.builder.build_int_truncate(
9798 value,
9799 self.intrinsics.i32_ty,
9800 ""
9801 ));
9802 let extended_value = err!(self.builder.build_int_s_extend(
9803 narrow_value,
9804 self.intrinsics.i64_ty,
9805 ""
9806 ));
9807 self.state.push1(extended_value);
9808 }
9809 _ => unreachable!(),
9810 }
9811 Ok(())
9812 }
9813
9814 fn translate_memory_operator(&mut self, op: Operator) -> Result<(), CompileError> {
9817 let vmctx = &self.ctx.basic().into_pointer_value();
9818
9819 match op {
9820 Operator::I32Load { ref memarg } => {
9821 let offset = self.state.pop1()?.into_int_value();
9822 let result =
9823 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9824 self.state.push1(result);
9825 }
9826 Operator::I64Load { ref memarg } => {
9827 let offset = self.state.pop1()?.into_int_value();
9828 let result =
9829 self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
9830 self.state.push1(result);
9831 }
9832 Operator::F32Load { ref memarg } => {
9833 let offset = self.state.pop1()?.into_int_value();
9834 let result =
9835 self.build_annotated_load(self.intrinsics.f32_ty, offset, memarg, 1)?;
9836 self.state.push1(result);
9837 }
9838 Operator::F64Load { ref memarg } => {
9839 let offset = self.state.pop1()?.into_int_value();
9840 let result =
9841 self.build_annotated_load(self.intrinsics.f64_ty, offset, memarg, 1)?;
9842 self.state.push1(result);
9843 }
9844 Operator::V128Load { ref memarg } => {
9845 let offset = self.state.pop1()?.into_int_value();
9846 let result =
9847 self.build_annotated_load(self.intrinsics.i128_ty, offset, memarg, 1)?;
9848 self.state.push1(result);
9849 }
9850 Operator::V128Load8Lane { ref memarg, lane } => {
9851 let (v, i) = self.state.pop1_extra()?;
9852 let (v, _i) = self.v128_into_i8x16(v, i)?;
9853 let offset = self.state.pop1()?.into_int_value();
9854 let element =
9855 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9856 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9857 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9858 let res = err!(
9859 self.builder
9860 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9861 );
9862 self.state.push1(res);
9863 }
9864 Operator::V128Load16Lane { ref memarg, lane } => {
9865 let (v, i) = self.state.pop1_extra()?;
9866 let (v, i) = self.v128_into_i16x8(v, i)?;
9867 let offset = self.state.pop1()?.into_int_value();
9868 let element =
9869 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9870 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9871 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9872 let res = err!(
9873 self.builder
9874 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9875 );
9876 self.state.push1_extra(res, i);
9877 }
9878 Operator::V128Load32Lane { ref memarg, lane } => {
9879 let (v, i) = self.state.pop1_extra()?;
9880 let (v, i) = self.v128_into_i32x4(v, i)?;
9881 let offset = self.state.pop1()?.into_int_value();
9882 let element =
9883 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9884 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9885 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9886 let res = err!(
9887 self.builder
9888 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9889 );
9890 self.state.push1_extra(res, i);
9891 }
9892 Operator::V128Load64Lane { ref memarg, lane } => {
9893 let (v, i) = self.state.pop1_extra()?;
9894 let (v, i) = self.v128_into_i64x2(v, i)?;
9895 let offset = self.state.pop1()?.into_int_value();
9896 let element =
9897 self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
9898 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9899 let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9900 let res = err!(
9901 self.builder
9902 .build_bit_cast(res, self.intrinsics.i128_ty, "")
9903 );
9904 self.state.push1_extra(res, i);
9905 }
9906
9907 Operator::I32Store { ref memarg } => {
9908 let value = self.state.pop1()?;
9909 let offset = self.state.pop1()?.into_int_value();
9910 self.build_annotated_store(self.intrinsics.i32_ty, offset, value, memarg, 1)?;
9911 }
9912 Operator::I64Store { ref memarg } => {
9913 let value = self.state.pop1()?;
9914 let offset = self.state.pop1()?.into_int_value();
9915 self.build_annotated_store(self.intrinsics.i64_ty, offset, value, memarg, 1)?;
9916 }
9917 Operator::F32Store { ref memarg } => {
9918 let (v, i) = self.state.pop1_extra()?;
9919 let v = self.apply_pending_canonicalization(v, i)?;
9920 let offset = self.state.pop1()?.into_int_value();
9921 self.build_annotated_store(self.intrinsics.f32_ty, offset, v, memarg, 1)?;
9922 }
9923 Operator::F64Store { ref memarg } => {
9924 let (v, i) = self.state.pop1_extra()?;
9925 let v = self.apply_pending_canonicalization(v, i)?;
9926 let offset = self.state.pop1()?.into_int_value();
9927 self.build_annotated_store(self.intrinsics.f64_ty, offset, v, memarg, 1)?;
9928 }
9929 Operator::V128Store { ref memarg } => {
9930 let (v, i) = self.state.pop1_extra()?;
9931 let v = self.apply_pending_canonicalization(v, i)?;
9932 let offset = self.state.pop1()?.into_int_value();
9933 self.build_annotated_store(self.intrinsics.i128_ty, offset, v, memarg, 1)?;
9934 }
9935 Operator::V128Store8Lane { ref memarg, lane } => {
9936 let (v, i) = self.state.pop1_extra()?;
9937 let (v, _i) = self.v128_into_i8x16(v, i)?;
9938 let offset = self.state.pop1()?.into_int_value();
9939 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9940 let val = err!(self.builder.build_extract_element(v, idx, ""));
9941 self.build_annotated_store(self.intrinsics.i8_ty, offset, val, memarg, 1)?;
9942 }
9943 Operator::V128Store16Lane { ref memarg, lane } => {
9944 let (v, i) = self.state.pop1_extra()?;
9945 let (v, _i) = self.v128_into_i16x8(v, i)?;
9946 let offset = self.state.pop1()?.into_int_value();
9947 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9948 let val = err!(self.builder.build_extract_element(v, idx, ""));
9949 self.build_annotated_store(self.intrinsics.i16_ty, offset, val, memarg, 1)?;
9950 }
9951 Operator::V128Store32Lane { ref memarg, lane } => {
9952 let (v, i) = self.state.pop1_extra()?;
9953 let (v, _i) = self.v128_into_i32x4(v, i)?;
9954 let offset = self.state.pop1()?.into_int_value();
9955 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9956 let val = err!(self.builder.build_extract_element(v, idx, ""));
9957 self.build_annotated_store(self.intrinsics.i32_ty, offset, val, memarg, 1)?;
9958 }
9959 Operator::V128Store64Lane { ref memarg, lane } => {
9960 let (v, i) = self.state.pop1_extra()?;
9961 let (v, _i) = self.v128_into_i64x2(v, i)?;
9962 let offset = self.state.pop1()?.into_int_value();
9963 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9964 let val = err!(self.builder.build_extract_element(v, idx, ""));
9965 self.build_annotated_store(self.intrinsics.i64_ty, offset, val, memarg, 1)?;
9966 }
9967 Operator::I32Load8S { ref memarg } => {
9968 let offset = self.state.pop1()?.into_int_value();
9969 let narrow_result =
9970 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9971 let result = err!(self.builder.build_int_s_extend(
9972 narrow_result.into_int_value(),
9973 self.intrinsics.i32_ty,
9974 "",
9975 ));
9976 self.state.push1(result);
9977 }
9978 Operator::I32Load16S { ref memarg } => {
9979 let offset = self.state.pop1()?.into_int_value();
9980 let narrow_result =
9981 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9982 let result = err!(self.builder.build_int_s_extend(
9983 narrow_result.into_int_value(),
9984 self.intrinsics.i32_ty,
9985 "",
9986 ));
9987 self.state.push1(result);
9988 }
9989 Operator::I64Load8S { ref memarg } => {
9990 let offset = self.state.pop1()?.into_int_value();
9991 let narrow_result =
9992 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9993 let result = err!(self.builder.build_int_s_extend(
9994 narrow_result.into_int_value(),
9995 self.intrinsics.i64_ty,
9996 ""
9997 ));
9998 self.state.push1(result);
9999 }
10000 Operator::I64Load16S { ref memarg } => {
10001 let offset = self.state.pop1()?.into_int_value();
10002 let narrow_result =
10003 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10004 let result = err!(self.builder.build_int_s_extend(
10005 narrow_result.into_int_value(),
10006 self.intrinsics.i64_ty,
10007 ""
10008 ));
10009 self.state.push1(result);
10010 }
10011 Operator::I64Load32S { ref memarg } => {
10012 let offset = self.state.pop1()?.into_int_value();
10013 let narrow_result =
10014 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10015 let result = err!(self.builder.build_int_s_extend(
10016 narrow_result.into_int_value(),
10017 self.intrinsics.i64_ty,
10018 "",
10019 ));
10020 self.state.push1(result);
10021 }
10022
10023 Operator::I32Load8U { ref memarg } => {
10024 let offset = self.state.pop1()?.into_int_value();
10025 let narrow_result =
10026 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
10027 let result = err!(self.builder.build_int_z_extend(
10028 narrow_result.into_int_value(),
10029 self.intrinsics.i32_ty,
10030 "",
10031 ));
10032 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10033 }
10034 Operator::I32Load16U { ref memarg } => {
10035 let offset = self.state.pop1()?.into_int_value();
10036 let narrow_result =
10037 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10038 let result = err!(self.builder.build_int_z_extend(
10039 narrow_result.into_int_value(),
10040 self.intrinsics.i32_ty,
10041 "",
10042 ));
10043 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10044 }
10045 Operator::I64Load8U { ref memarg } => {
10046 let offset = self.state.pop1()?.into_int_value();
10047 let narrow_result =
10048 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
10049 let result = err!(self.builder.build_int_z_extend(
10050 narrow_result.into_int_value(),
10051 self.intrinsics.i64_ty,
10052 "",
10053 ));
10054 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10055 }
10056 Operator::I64Load16U { ref memarg } => {
10057 let offset = self.state.pop1()?.into_int_value();
10058 let narrow_result =
10059 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10060 let result = err!(self.builder.build_int_z_extend(
10061 narrow_result.into_int_value(),
10062 self.intrinsics.i64_ty,
10063 "",
10064 ));
10065 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10066 }
10067 Operator::I64Load32U { ref memarg } => {
10068 let offset = self.state.pop1()?.into_int_value();
10069 let narrow_result =
10070 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10071 let result = err!(self.builder.build_int_z_extend(
10072 narrow_result.into_int_value(),
10073 self.intrinsics.i64_ty,
10074 "",
10075 ));
10076 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10077 }
10078
10079 Operator::I32Store8 { ref memarg } | Operator::I64Store8 { ref memarg } => {
10080 let value = self.state.pop1()?.into_int_value();
10081 let offset = self.state.pop1()?.into_int_value();
10082 let narrow_value = err!(self.builder.build_int_truncate(
10083 value,
10084 self.intrinsics.i8_ty,
10085 ""
10086 ));
10087 self.build_annotated_store(
10088 self.intrinsics.i8_ty,
10089 offset,
10090 narrow_value.into(),
10091 memarg,
10092 1,
10093 )?;
10094 }
10095 Operator::I32Store16 { ref memarg } | Operator::I64Store16 { ref memarg } => {
10096 let value = self.state.pop1()?.into_int_value();
10097 let offset = self.state.pop1()?.into_int_value();
10098 let narrow_value = err!(self.builder.build_int_truncate(
10099 value,
10100 self.intrinsics.i16_ty,
10101 ""
10102 ));
10103 self.build_annotated_store(
10104 self.intrinsics.i16_ty,
10105 offset,
10106 narrow_value.into(),
10107 memarg,
10108 1,
10109 )?;
10110 }
10111 Operator::I64Store32 { ref memarg } => {
10112 let value = self.state.pop1()?.into_int_value();
10113 let offset = self.state.pop1()?.into_int_value();
10114 let narrow_value = err!(self.builder.build_int_truncate(
10115 value,
10116 self.intrinsics.i32_ty,
10117 ""
10118 ));
10119 self.build_annotated_store(
10120 self.intrinsics.i32_ty,
10121 offset,
10122 narrow_value.into(),
10123 memarg,
10124 1,
10125 )?;
10126 }
10127 Operator::I8x16Neg => {
10128 let (v, i) = self.state.pop1_extra()?;
10129 let (v, _) = self.v128_into_i8x16(v, i)?;
10130 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10131 let res = err!(
10132 self.builder
10133 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10134 );
10135 self.state.push1(res);
10136 }
10137 Operator::I16x8Neg => {
10138 let (v, i) = self.state.pop1_extra()?;
10139 let (v, _) = self.v128_into_i16x8(v, i)?;
10140 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10141 let res = err!(
10142 self.builder
10143 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10144 );
10145 self.state.push1(res);
10146 }
10147 Operator::I32x4Neg => {
10148 let (v, i) = self.state.pop1_extra()?;
10149 let (v, _) = self.v128_into_i32x4(v, i)?;
10150 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10151 let res = err!(
10152 self.builder
10153 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10154 );
10155 self.state.push1(res);
10156 }
10157 Operator::I64x2Neg => {
10158 let (v, i) = self.state.pop1_extra()?;
10159 let (v, _) = self.v128_into_i64x2(v, i)?;
10160 let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10161 let res = err!(
10162 self.builder
10163 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10164 );
10165 self.state.push1(res);
10166 }
10167 Operator::V128Not => {
10168 let (v, i) = self.state.pop1_extra()?;
10169 let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10170 let res = err!(self.builder.build_not(v, ""));
10171 self.state.push1(res);
10172 }
10173 Operator::V128AnyTrue => {
10174 let v = self.state.pop1()?.into_int_value();
10177 let res = err!(self.builder.build_int_compare(
10178 IntPredicate::NE,
10179 v,
10180 v.get_type().const_zero(),
10181 "",
10182 ));
10183 let res = err!(
10184 self.builder
10185 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10186 );
10187 self.state.push1_extra(
10188 res,
10189 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10190 );
10191 }
10192 Operator::I8x16AllTrue
10193 | Operator::I16x8AllTrue
10194 | Operator::I32x4AllTrue
10195 | Operator::I64x2AllTrue => {
10196 let vec_ty = match op {
10197 Operator::I8x16AllTrue => self.intrinsics.i8x16_ty,
10198 Operator::I16x8AllTrue => self.intrinsics.i16x8_ty,
10199 Operator::I32x4AllTrue => self.intrinsics.i32x4_ty,
10200 Operator::I64x2AllTrue => self.intrinsics.i64x2_ty,
10201 _ => unreachable!(),
10202 };
10203 let (v, i) = self.state.pop1_extra()?;
10204 let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10205 let lane_int_ty = self
10206 .context
10207 .custom_width_int_type(NonZero::new(vec_ty.get_size()).unwrap())
10208 .unwrap();
10209 let vec = err!(self.builder.build_bit_cast(v, vec_ty, "vec")).into_vector_value();
10210 let mask = err!(self.builder.build_int_compare(
10211 IntPredicate::NE,
10212 vec,
10213 vec_ty.const_zero(),
10214 "mask",
10215 ));
10216 let cmask =
10217 err!(self.builder.build_bit_cast(mask, lane_int_ty, "cmask")).into_int_value();
10218 let res = err!(self.builder.build_int_compare(
10219 IntPredicate::EQ,
10220 cmask,
10221 lane_int_ty.const_int(u64::MAX, true),
10222 "",
10223 ));
10224 let res = err!(
10225 self.builder
10226 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10227 );
10228 self.state.push1_extra(
10229 res,
10230 (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10231 );
10232 }
10233 Operator::I8x16ExtractLaneS { lane } => {
10234 let (v, i) = self.state.pop1_extra()?;
10235 let (v, _) = self.v128_into_i8x16(v, i)?;
10236 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10237 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10238 let res = err!(
10239 self.builder
10240 .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10241 );
10242 self.state.push1(res);
10243 }
10244 Operator::I8x16ExtractLaneU { lane } => {
10245 let (v, i) = self.state.pop1_extra()?;
10246 let (v, _) = self.v128_into_i8x16(v, i)?;
10247 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10248 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10249 let res = err!(
10250 self.builder
10251 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10252 );
10253 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10254 }
10255 Operator::I16x8ExtractLaneS { lane } => {
10256 let (v, i) = self.state.pop1_extra()?;
10257 let (v, _) = self.v128_into_i16x8(v, i)?;
10258 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10259 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10260 let res = err!(
10261 self.builder
10262 .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10263 );
10264 self.state.push1(res);
10265 }
10266 Operator::I16x8ExtractLaneU { lane } => {
10267 let (v, i) = self.state.pop1_extra()?;
10268 let (v, _) = self.v128_into_i16x8(v, i)?;
10269 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10270 let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10271 let res = err!(
10272 self.builder
10273 .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10274 );
10275 self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10276 }
10277 Operator::I32x4ExtractLane { lane } => {
10278 let (v, i) = self.state.pop1_extra()?;
10279 let (v, i) = self.v128_into_i32x4(v, i)?;
10280 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10281 let res = err!(self.builder.build_extract_element(v, idx, ""));
10282 self.state.push1_extra(res, i);
10283 }
10284 Operator::I64x2ExtractLane { lane } => {
10285 let (v, i) = self.state.pop1_extra()?;
10286 let (v, i) = self.v128_into_i64x2(v, i)?;
10287 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10288 let res = err!(self.builder.build_extract_element(v, idx, ""));
10289 self.state.push1_extra(res, i);
10290 }
10291 Operator::F32x4ExtractLane { lane } => {
10292 let (v, i) = self.state.pop1_extra()?;
10293 let (v, i) = self.v128_into_f32x4(v, i)?;
10294 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10295 let res = err!(self.builder.build_extract_element(v, idx, ""));
10296 self.state.push1_extra(res, i);
10297 }
10298 Operator::F64x2ExtractLane { lane } => {
10299 let (v, i) = self.state.pop1_extra()?;
10300 let (v, i) = self.v128_into_f64x2(v, i)?;
10301 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10302 let res = err!(self.builder.build_extract_element(v, idx, ""));
10303 self.state.push1_extra(res, i);
10304 }
10305 Operator::I8x16ReplaceLane { lane } => {
10306 let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10307 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10308 let v2 = v2.into_int_value();
10309 let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i8_ty, ""));
10310 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10311 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10312 let res = err!(
10313 self.builder
10314 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10315 );
10316 self.state.push1(res);
10317 }
10318 Operator::I16x8ReplaceLane { lane } => {
10319 let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10320 let (v1, _) = self.v128_into_i16x8(v1, i1)?;
10321 let v2 = v2.into_int_value();
10322 let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i16_ty, ""));
10323 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10324 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10325 let res = err!(
10326 self.builder
10327 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10328 );
10329 self.state.push1(res);
10330 }
10331 Operator::I32x4ReplaceLane { lane } => {
10332 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10333 let (v1, i1) = self.v128_into_i32x4(v1, i1)?;
10334 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10335 let v2 = v2.into_int_value();
10336 let i2 = i2.strip_pending();
10337 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10338 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10339 let res = err!(
10340 self.builder
10341 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10342 );
10343 self.state
10344 .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f32())?);
10345 }
10346 Operator::I64x2ReplaceLane { lane } => {
10347 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10348 let (v1, i1) = self.v128_into_i64x2(v1, i1)?;
10349 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10350 let v2 = v2.into_int_value();
10351 let i2 = i2.strip_pending();
10352 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10353 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10354 let res = err!(
10355 self.builder
10356 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10357 );
10358 self.state
10359 .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f64())?);
10360 }
10361 Operator::F32x4ReplaceLane { lane } => {
10362 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10363 let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
10364 let push_pending_f32_nan_to_result =
10365 i1.has_pending_f32_nan() && i2.has_pending_f32_nan();
10366 let (v1, v2) = if !push_pending_f32_nan_to_result {
10367 (
10368 self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10369 .into_vector_value(),
10370 self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10371 .into_float_value(),
10372 )
10373 } else {
10374 (v1, v2.into_float_value())
10375 };
10376 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10377 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10378 let res = err!(
10379 self.builder
10380 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10381 );
10382 let info = if push_pending_f32_nan_to_result {
10383 ExtraInfo::pending_f32_nan()
10384 } else {
10385 (i1.strip_pending() & i2.strip_pending())?
10386 };
10387 self.state.push1_extra(res, info);
10388 }
10389 Operator::F64x2ReplaceLane { lane } => {
10390 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10391 let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
10392 let push_pending_f64_nan_to_result =
10393 i1.has_pending_f64_nan() && i2.has_pending_f64_nan();
10394 let (v1, v2) = if !push_pending_f64_nan_to_result {
10395 (
10396 self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10397 .into_vector_value(),
10398 self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10399 .into_float_value(),
10400 )
10401 } else {
10402 (v1, v2.into_float_value())
10403 };
10404 let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10405 let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10406 let res = err!(
10407 self.builder
10408 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10409 );
10410 let info = if push_pending_f64_nan_to_result {
10411 ExtraInfo::pending_f64_nan()
10412 } else {
10413 (i1.strip_pending() & i2.strip_pending())?
10414 };
10415 self.state.push1_extra(res, info);
10416 }
10417 Operator::I8x16RelaxedSwizzle if self.cpu_features.contains(CpuFeature::SSSE3) => {
10418 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10419 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10420 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10421
10422 let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10423 let (v2, _) = self.v128_into_i8x16(v2, i2)?;
10424 let res = self
10425 .build_call_with_param_attributes(
10426 self.intrinsics.x86_64.pshufb128,
10427 &[v1.into(), v2.into()],
10428 "",
10429 )?
10430 .try_as_basic_value()
10431 .unwrap_basic();
10432 let res = err!(
10433 self.builder
10434 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10435 );
10436 self.state.push1(res);
10437 }
10438 Operator::I8x16Swizzle | Operator::I8x16RelaxedSwizzle => {
10439 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10440 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10441 let v1 = err!(
10442 self.builder
10443 .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10444 )
10445 .into_vector_value();
10446 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10447 let v2 = err!(
10448 self.builder
10449 .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10450 )
10451 .into_vector_value();
10452 let lanes = self.intrinsics.i8_ty.const_int(16, false);
10453 let lanes =
10454 self.splat_vector(lanes.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
10455 let mut res = self.intrinsics.i8x16_ty.get_undef();
10456 let idx_out_of_range = err!(self.builder.build_int_compare(
10457 IntPredicate::UGE,
10458 v2,
10459 lanes,
10460 "idx_out_of_range",
10461 ));
10462 let idx_clamped = err!(self.builder.build_select(
10463 idx_out_of_range,
10464 self.intrinsics.i8x16_ty.const_zero(),
10465 v2,
10466 "idx_clamped",
10467 ))
10468 .into_vector_value();
10469 for i in 0..16 {
10470 let idx = err!(self.builder.build_extract_element(
10471 idx_clamped,
10472 self.intrinsics.i32_ty.const_int(i, false),
10473 "idx",
10474 ))
10475 .into_int_value();
10476 let replace_with_zero = err!(self.builder.build_extract_element(
10477 idx_out_of_range,
10478 self.intrinsics.i32_ty.const_int(i, false),
10479 "replace_with_zero",
10480 ))
10481 .into_int_value();
10482 let elem =
10483 err!(self.builder.build_extract_element(v1, idx, "elem")).into_int_value();
10484 let elem_or_zero = err!(self.builder.build_select(
10485 replace_with_zero,
10486 self.intrinsics.i8_zero,
10487 elem,
10488 "elem_or_zero",
10489 ));
10490 res = err!(self.builder.build_insert_element(
10491 res,
10492 elem_or_zero,
10493 self.intrinsics.i32_ty.const_int(i, false),
10494 "",
10495 ));
10496 }
10497 let res = err!(
10498 self.builder
10499 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10500 );
10501 self.state.push1(res);
10502 }
10503 Operator::I8x16Shuffle { lanes } => {
10504 let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10505 let v1 = self.apply_pending_canonicalization(v1, i1)?;
10506 let v1 = err!(
10507 self.builder
10508 .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10509 )
10510 .into_vector_value();
10511 let v2 = self.apply_pending_canonicalization(v2, i2)?;
10512 let v2 = err!(
10513 self.builder
10514 .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10515 )
10516 .into_vector_value();
10517 let mask = VectorType::const_vector(
10518 lanes
10519 .iter()
10520 .map(|l| self.intrinsics.i32_ty.const_int((*l).into(), false))
10521 .collect::<Vec<IntValue>>()
10522 .as_slice(),
10523 );
10524 let res = err!(self.builder.build_shuffle_vector(v1, v2, mask, ""));
10525 let res = err!(
10526 self.builder
10527 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10528 );
10529 self.state.push1(res);
10530 }
10531 Operator::V128Load8x8S { ref memarg } => {
10532 let offset = self.state.pop1()?.into_int_value();
10533 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10534 let v = err!(
10535 self.builder
10536 .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10537 )
10538 .into_vector_value();
10539 let res = err!(
10540 self.builder
10541 .build_int_s_extend(v, self.intrinsics.i16x8_ty, "")
10542 );
10543 let res = err!(
10544 self.builder
10545 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10546 );
10547 self.state.push1(res);
10548 }
10549 Operator::V128Load8x8U { ref memarg } => {
10550 let offset = self.state.pop1()?.into_int_value();
10551 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10552 let v = err!(
10553 self.builder
10554 .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10555 )
10556 .into_vector_value();
10557 let res = err!(
10558 self.builder
10559 .build_int_z_extend(v, self.intrinsics.i16x8_ty, "")
10560 );
10561 let res = err!(
10562 self.builder
10563 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10564 );
10565 self.state.push1(res);
10566 }
10567 Operator::V128Load16x4S { ref memarg } => {
10568 let offset = self.state.pop1()?.into_int_value();
10569 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10570 let v = err!(self.builder.build_bit_cast(
10571 v,
10572 self.intrinsics.i16_ty.vec_type(4),
10573 ""
10574 ))
10575 .into_vector_value();
10576 let res = err!(
10577 self.builder
10578 .build_int_s_extend(v, self.intrinsics.i32x4_ty, "")
10579 );
10580 let res = err!(
10581 self.builder
10582 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10583 );
10584 self.state.push1(res);
10585 }
10586 Operator::V128Load16x4U { ref memarg } => {
10587 let offset = self.state.pop1()?.into_int_value();
10588 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10589 let v = err!(self.builder.build_bit_cast(
10590 v,
10591 self.intrinsics.i16_ty.vec_type(4),
10592 ""
10593 ))
10594 .into_vector_value();
10595 let res = err!(
10596 self.builder
10597 .build_int_z_extend(v, self.intrinsics.i32x4_ty, "")
10598 );
10599 let res = err!(
10600 self.builder
10601 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10602 );
10603 self.state.push1(res);
10604 }
10605 Operator::V128Load32x2S { ref memarg } => {
10606 let offset = self.state.pop1()?.into_int_value();
10607 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10608 let v = err!(self.builder.build_bit_cast(
10609 v,
10610 self.intrinsics.i32_ty.vec_type(2),
10611 ""
10612 ))
10613 .into_vector_value();
10614 let res = err!(
10615 self.builder
10616 .build_int_s_extend(v, self.intrinsics.i64x2_ty, "")
10617 );
10618 let res = err!(
10619 self.builder
10620 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10621 );
10622 self.state.push1(res);
10623 }
10624 Operator::V128Load32x2U { ref memarg } => {
10625 let offset = self.state.pop1()?.into_int_value();
10626 let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10627 let v = err!(self.builder.build_bit_cast(
10628 v,
10629 self.intrinsics.i32_ty.vec_type(2),
10630 ""
10631 ))
10632 .into_vector_value();
10633 let res = err!(
10634 self.builder
10635 .build_int_z_extend(v, self.intrinsics.i64x2_ty, "")
10636 );
10637 let res = err!(
10638 self.builder
10639 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10640 );
10641 self.state.push1(res);
10642 }
10643 Operator::V128Load32Zero { ref memarg } => {
10644 let offset = self.state.pop1()?.into_int_value();
10645 let element =
10646 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10647 let res = err!(self.builder.build_int_z_extend(
10648 element.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 element =
10657 self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10658 let res = err!(self.builder.build_int_z_extend(
10659 element.into_int_value(),
10660 self.intrinsics.i128_ty,
10661 "",
10662 ));
10663 self.state.push1(res);
10664 }
10665 Operator::V128Load8Splat { ref memarg } => {
10666 let offset = self.state.pop1()?.into_int_value();
10667 let element =
10668 self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
10669 let res = self.splat_vector(element, self.intrinsics.i8x16_ty)?;
10670 let res = err!(
10671 self.builder
10672 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10673 );
10674 self.state.push1(res);
10675 }
10676 Operator::V128Load16Splat { ref memarg } => {
10677 let offset = self.state.pop1()?.into_int_value();
10678 let element =
10679 self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10680 let res = self.splat_vector(element, self.intrinsics.i16x8_ty)?;
10681 let res = err!(
10682 self.builder
10683 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10684 );
10685 self.state.push1(res);
10686 }
10687 Operator::V128Load32Splat { ref memarg } => {
10688 let offset = self.state.pop1()?.into_int_value();
10689 let element =
10690 self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10691 let res = self.splat_vector(element, self.intrinsics.i32x4_ty)?;
10692 let res = err!(
10693 self.builder
10694 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10695 );
10696 self.state.push1(res);
10697 }
10698 Operator::V128Load64Splat { ref memarg } => {
10699 let offset = self.state.pop1()?.into_int_value();
10700 let element =
10701 self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10702 let res = self.splat_vector(element, self.intrinsics.i64x2_ty)?;
10703 let res = err!(
10704 self.builder
10705 .build_bit_cast(res, self.intrinsics.i128_ty, "")
10706 );
10707 self.state.push1(res);
10708 }
10709
10710 Operator::MemoryGrow { mem } => {
10711 let memory_index = MemoryIndex::from_u32(mem);
10712 let index_arg = self
10713 .wasm_module
10714 .local_memory_index(memory_index)
10715 .map_or(mem, |index| index.as_u32());
10716 let delta = self.state.pop1()?;
10717 let grow_fn_ptr = self.ctx.memory_grow(memory_index, self.intrinsics)?;
10718 let grow = err!(
10719 self.builder.build_indirect_call(
10720 self.intrinsics.memory_grow_ty,
10721 grow_fn_ptr,
10722 &[
10723 vmctx.as_basic_value_enum().into(),
10724 delta.into(),
10725 self.intrinsics
10726 .i32_ty
10727 .const_int(index_arg.into(), false)
10728 .into(),
10729 ],
10730 "",
10731 )
10732 );
10733 self.state.push1(grow.try_as_basic_value().unwrap_basic());
10734 }
10735 Operator::MemorySize { mem } => {
10736 let memory_index = MemoryIndex::from_u32(mem);
10737 let index_arg = self
10738 .wasm_module
10739 .local_memory_index(memory_index)
10740 .map_or(mem, |index| index.as_u32());
10741 let size_fn_ptr = self.ctx.memory_size(memory_index, self.intrinsics)?;
10742 let size = err!(
10743 self.builder.build_indirect_call(
10744 self.intrinsics.memory_size_ty,
10745 size_fn_ptr,
10746 &[
10747 vmctx.as_basic_value_enum().into(),
10748 self.intrinsics
10749 .i32_ty
10750 .const_int(index_arg.into(), false)
10751 .into(),
10752 ],
10753 "",
10754 )
10755 );
10756 self.state.push1(size.try_as_basic_value().unwrap_basic());
10758 }
10759 Operator::MemoryInit { data_index, mem } => {
10760 let (dest, src, len) = self.state.pop3()?;
10761 let mem = self.intrinsics.i32_ty.const_int(mem.into(), false);
10762 let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
10763 self.build_call_with_param_attributes(
10764 self.intrinsics.memory_init,
10765 &[
10766 vmctx.as_basic_value_enum().into(),
10767 mem.into(),
10768 segment.into(),
10769 dest.into(),
10770 src.into(),
10771 len.into(),
10772 ],
10773 "",
10774 )?;
10775 }
10776 Operator::DataDrop { data_index } => {
10777 let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
10778 self.build_call_with_param_attributes(
10779 self.intrinsics.data_drop,
10780 &[vmctx.as_basic_value_enum().into(), segment.into()],
10781 "",
10782 )?;
10783 }
10784 Operator::MemoryCopy { dst_mem, src_mem } => {
10785 let (dest_pos, src_pos, len) = self.state.pop3()?;
10786 let dst_index = self.intrinsics.i32_ty.const_int(dst_mem.into(), false);
10787 let src_index = self.intrinsics.i32_ty.const_int(src_mem.into(), false);
10788 self.build_call_with_param_attributes(
10789 self.intrinsics.memory_copy,
10790 &[
10791 vmctx.as_basic_value_enum().into(),
10792 dst_index.into(),
10793 src_index.into(),
10794 dest_pos.into(),
10795 src_pos.into(),
10796 len.into(),
10797 ],
10798 "",
10799 )?;
10800 }
10801 Operator::MemoryFill { mem } => {
10802 let (memory_fill, mem) = if let Some(local_memory_index) = self
10803 .wasm_module
10804 .local_memory_index(MemoryIndex::from_u32(mem))
10805 {
10806 (self.intrinsics.memory_fill, local_memory_index.as_u32())
10807 } else {
10808 (self.intrinsics.imported_memory_fill, mem)
10809 };
10810
10811 let (dst, val, len) = self.state.pop3()?;
10812 let mem_index = self.intrinsics.i32_ty.const_int(mem.into(), false);
10813 self.build_call_with_param_attributes(
10814 memory_fill,
10815 &[
10816 vmctx.as_basic_value_enum().into(),
10817 mem_index.into(),
10818 dst.into(),
10819 val.into(),
10820 len.into(),
10821 ],
10822 "",
10823 )?;
10824 }
10825 _ => unreachable!(),
10826 }
10827 Ok(())
10828 }
10829
10830 fn translate_atomic_memory_operator(&mut self, op: Operator) -> Result<(), CompileError> {
10832 let vmctx = &self.ctx.basic().into_pointer_value();
10833
10834 match op {
10835 Operator::AtomicFence => {
10836 }
10844 Operator::I32AtomicLoad { ref memarg } => {
10845 let offset = self.state.pop1()?.into_int_value();
10846 let result = self.build_annotated_atomic_load(
10847 self.intrinsics.i32_ty,
10848 self.intrinsics.i32_ty,
10849 offset,
10850 memarg,
10851 )?;
10852 self.state.push1(result);
10853 }
10854 Operator::I64AtomicLoad { ref memarg } => {
10855 let offset = self.state.pop1()?.into_int_value();
10856 let result = self.build_annotated_atomic_load(
10857 self.intrinsics.i64_ty,
10858 self.intrinsics.i64_ty,
10859 offset,
10860 memarg,
10861 )?;
10862 self.state.push1(result);
10863 }
10864 Operator::I32AtomicLoad8U { ref memarg } => {
10865 let offset = self.state.pop1()?.into_int_value();
10866 let result = self.build_annotated_atomic_load(
10867 self.intrinsics.i32_ty,
10868 self.intrinsics.i8_ty,
10869 offset,
10870 memarg,
10871 )?;
10872 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10873 }
10874 Operator::I32AtomicLoad16U { ref memarg } => {
10875 let offset = self.state.pop1()?.into_int_value();
10876 let result = self.build_annotated_atomic_load(
10877 self.intrinsics.i32_ty,
10878 self.intrinsics.i16_ty,
10879 offset,
10880 memarg,
10881 )?;
10882 self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10883 }
10884 Operator::I64AtomicLoad8U { ref memarg } => {
10885 let offset = self.state.pop1()?.into_int_value();
10886 let result = self.build_annotated_atomic_load(
10887 self.intrinsics.i64_ty,
10888 self.intrinsics.i8_ty,
10889 offset,
10890 memarg,
10891 )?;
10892 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10893 }
10894 Operator::I64AtomicLoad16U { ref memarg } => {
10895 let offset = self.state.pop1()?.into_int_value();
10896 let result = self.build_annotated_atomic_load(
10897 self.intrinsics.i64_ty,
10898 self.intrinsics.i16_ty,
10899 offset,
10900 memarg,
10901 )?;
10902 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10903 }
10904 Operator::I64AtomicLoad32U { ref memarg } => {
10905 let offset = self.state.pop1()?.into_int_value();
10906 let result = self.build_annotated_atomic_load(
10907 self.intrinsics.i64_ty,
10908 self.intrinsics.i32_ty,
10909 offset,
10910 memarg,
10911 )?;
10912 self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10913 }
10914 Operator::I32AtomicStore { ref memarg } => {
10915 let value = self.state.pop1()?.into_int_value();
10916 let offset = self.state.pop1()?.into_int_value();
10917 self.build_annotated_atomic_store(
10918 self.intrinsics.i32_ty,
10919 self.intrinsics.i32_ty,
10920 offset,
10921 value,
10922 memarg,
10923 )?;
10924 }
10925 Operator::I64AtomicStore { ref memarg } => {
10926 let value = self.state.pop1()?.into_int_value();
10927 let offset = self.state.pop1()?.into_int_value();
10928 self.build_annotated_atomic_store(
10929 self.intrinsics.i64_ty,
10930 self.intrinsics.i64_ty,
10931 offset,
10932 value,
10933 memarg,
10934 )?;
10935 }
10936 Operator::I32AtomicStore8 { ref memarg } | Operator::I64AtomicStore8 { ref memarg } => {
10937 let value = self.state.pop1()?.into_int_value();
10938 let offset = self.state.pop1()?.into_int_value();
10939 self.build_annotated_atomic_store(
10940 value.get_type(),
10941 self.intrinsics.i8_ty,
10942 offset,
10943 value,
10944 memarg,
10945 )?;
10946 }
10947 Operator::I32AtomicStore16 { ref memarg }
10948 | Operator::I64AtomicStore16 { ref memarg } => {
10949 let value = self.state.pop1()?.into_int_value();
10950 let offset = self.state.pop1()?.into_int_value();
10951 self.build_annotated_atomic_store(
10952 value.get_type(),
10953 self.intrinsics.i16_ty,
10954 offset,
10955 value,
10956 memarg,
10957 )?;
10958 }
10959 Operator::I64AtomicStore32 { ref memarg } => {
10960 let value = self.state.pop1()?.into_int_value();
10961 let offset = self.state.pop1()?.into_int_value();
10962 self.build_annotated_atomic_store(
10963 self.intrinsics.i64_ty,
10964 self.intrinsics.i32_ty,
10965 offset,
10966 value,
10967 memarg,
10968 )?;
10969 }
10970 Operator::I32AtomicRmw8AddU { ref memarg } => self.translate_atomic_rmw(
10971 self.intrinsics.i32_ty,
10972 self.intrinsics.i8_ty,
10973 memarg,
10974 AtomicRMWBinOp::Add,
10975 Some(ExtraInfo::arithmetic_f32()),
10976 )?,
10977 Operator::I32AtomicRmw16AddU { ref memarg } => self.translate_atomic_rmw(
10978 self.intrinsics.i32_ty,
10979 self.intrinsics.i16_ty,
10980 memarg,
10981 AtomicRMWBinOp::Add,
10982 Some(ExtraInfo::arithmetic_f32()),
10983 )?,
10984 Operator::I32AtomicRmwAdd { ref memarg } => self.translate_atomic_rmw(
10985 self.intrinsics.i32_ty,
10986 self.intrinsics.i32_ty,
10987 memarg,
10988 AtomicRMWBinOp::Add,
10989 None,
10990 )?,
10991 Operator::I64AtomicRmw8AddU { ref memarg } => self.translate_atomic_rmw(
10992 self.intrinsics.i64_ty,
10993 self.intrinsics.i8_ty,
10994 memarg,
10995 AtomicRMWBinOp::Add,
10996 Some(ExtraInfo::arithmetic_f64()),
10997 )?,
10998 Operator::I64AtomicRmw16AddU { ref memarg } => self.translate_atomic_rmw(
10999 self.intrinsics.i64_ty,
11000 self.intrinsics.i16_ty,
11001 memarg,
11002 AtomicRMWBinOp::Add,
11003 Some(ExtraInfo::arithmetic_f64()),
11004 )?,
11005 Operator::I64AtomicRmw32AddU { ref memarg } => self.translate_atomic_rmw(
11006 self.intrinsics.i64_ty,
11007 self.intrinsics.i32_ty,
11008 memarg,
11009 AtomicRMWBinOp::Add,
11010 Some(ExtraInfo::arithmetic_f64()),
11011 )?,
11012 Operator::I64AtomicRmwAdd { ref memarg } => self.translate_atomic_rmw(
11013 self.intrinsics.i64_ty,
11014 self.intrinsics.i64_ty,
11015 memarg,
11016 AtomicRMWBinOp::Add,
11017 None,
11018 )?,
11019 Operator::I32AtomicRmw8SubU { ref memarg } => self.translate_atomic_rmw(
11020 self.intrinsics.i32_ty,
11021 self.intrinsics.i8_ty,
11022 memarg,
11023 AtomicRMWBinOp::Sub,
11024 Some(ExtraInfo::arithmetic_f32()),
11025 )?,
11026 Operator::I32AtomicRmw16SubU { ref memarg } => self.translate_atomic_rmw(
11027 self.intrinsics.i32_ty,
11028 self.intrinsics.i16_ty,
11029 memarg,
11030 AtomicRMWBinOp::Sub,
11031 Some(ExtraInfo::arithmetic_f32()),
11032 )?,
11033 Operator::I32AtomicRmwSub { ref memarg } => self.translate_atomic_rmw(
11034 self.intrinsics.i32_ty,
11035 self.intrinsics.i32_ty,
11036 memarg,
11037 AtomicRMWBinOp::Sub,
11038 None,
11039 )?,
11040 Operator::I64AtomicRmw8SubU { ref memarg } => self.translate_atomic_rmw(
11041 self.intrinsics.i64_ty,
11042 self.intrinsics.i8_ty,
11043 memarg,
11044 AtomicRMWBinOp::Sub,
11045 Some(ExtraInfo::arithmetic_f32()),
11046 )?,
11047 Operator::I64AtomicRmw16SubU { ref memarg } => self.translate_atomic_rmw(
11048 self.intrinsics.i64_ty,
11049 self.intrinsics.i16_ty,
11050 memarg,
11051 AtomicRMWBinOp::Sub,
11052 Some(ExtraInfo::arithmetic_f64()),
11053 )?,
11054 Operator::I64AtomicRmw32SubU { ref memarg } => self.translate_atomic_rmw(
11055 self.intrinsics.i64_ty,
11056 self.intrinsics.i32_ty,
11057 memarg,
11058 AtomicRMWBinOp::Sub,
11059 Some(ExtraInfo::arithmetic_f64()),
11060 )?,
11061 Operator::I64AtomicRmwSub { ref memarg } => self.translate_atomic_rmw(
11062 self.intrinsics.i64_ty,
11063 self.intrinsics.i64_ty,
11064 memarg,
11065 AtomicRMWBinOp::Sub,
11066 None,
11067 )?,
11068 Operator::I32AtomicRmw8AndU { ref memarg } => self.translate_atomic_rmw(
11069 self.intrinsics.i32_ty,
11070 self.intrinsics.i8_ty,
11071 memarg,
11072 AtomicRMWBinOp::And,
11073 Some(ExtraInfo::arithmetic_f32()),
11074 )?,
11075 Operator::I32AtomicRmw16AndU { ref memarg } => self.translate_atomic_rmw(
11076 self.intrinsics.i32_ty,
11077 self.intrinsics.i16_ty,
11078 memarg,
11079 AtomicRMWBinOp::And,
11080 Some(ExtraInfo::arithmetic_f32()),
11081 )?,
11082 Operator::I32AtomicRmwAnd { ref memarg } => self.translate_atomic_rmw(
11083 self.intrinsics.i32_ty,
11084 self.intrinsics.i32_ty,
11085 memarg,
11086 AtomicRMWBinOp::And,
11087 None,
11088 )?,
11089 Operator::I64AtomicRmw8AndU { ref memarg } => self.translate_atomic_rmw(
11090 self.intrinsics.i64_ty,
11091 self.intrinsics.i8_ty,
11092 memarg,
11093 AtomicRMWBinOp::And,
11094 Some(ExtraInfo::arithmetic_f64()),
11095 )?,
11096 Operator::I64AtomicRmw16AndU { ref memarg } => self.translate_atomic_rmw(
11097 self.intrinsics.i64_ty,
11098 self.intrinsics.i16_ty,
11099 memarg,
11100 AtomicRMWBinOp::And,
11101 Some(ExtraInfo::arithmetic_f64()),
11102 )?,
11103 Operator::I64AtomicRmw32AndU { ref memarg } => self.translate_atomic_rmw(
11104 self.intrinsics.i64_ty,
11105 self.intrinsics.i32_ty,
11106 memarg,
11107 AtomicRMWBinOp::And,
11108 Some(ExtraInfo::arithmetic_f64()),
11109 )?,
11110 Operator::I64AtomicRmwAnd { ref memarg } => self.translate_atomic_rmw(
11111 self.intrinsics.i64_ty,
11112 self.intrinsics.i64_ty,
11113 memarg,
11114 AtomicRMWBinOp::And,
11115 None,
11116 )?,
11117 Operator::I32AtomicRmw8OrU { ref memarg } => self.translate_atomic_rmw(
11118 self.intrinsics.i32_ty,
11119 self.intrinsics.i8_ty,
11120 memarg,
11121 AtomicRMWBinOp::Or,
11122 Some(ExtraInfo::arithmetic_f32()),
11123 )?,
11124 Operator::I32AtomicRmw16OrU { ref memarg } => self.translate_atomic_rmw(
11125 self.intrinsics.i32_ty,
11126 self.intrinsics.i16_ty,
11127 memarg,
11128 AtomicRMWBinOp::Or,
11129 Some(ExtraInfo::arithmetic_f32()),
11130 )?,
11131 Operator::I32AtomicRmwOr { ref memarg } => self.translate_atomic_rmw(
11132 self.intrinsics.i32_ty,
11133 self.intrinsics.i32_ty,
11134 memarg,
11135 AtomicRMWBinOp::Or,
11136 Some(ExtraInfo::arithmetic_f32()),
11137 )?,
11138 Operator::I64AtomicRmw8OrU { ref memarg } => self.translate_atomic_rmw(
11139 self.intrinsics.i64_ty,
11140 self.intrinsics.i8_ty,
11141 memarg,
11142 AtomicRMWBinOp::Or,
11143 Some(ExtraInfo::arithmetic_f64()),
11144 )?,
11145 Operator::I64AtomicRmw16OrU { ref memarg } => self.translate_atomic_rmw(
11146 self.intrinsics.i64_ty,
11147 self.intrinsics.i16_ty,
11148 memarg,
11149 AtomicRMWBinOp::Or,
11150 Some(ExtraInfo::arithmetic_f64()),
11151 )?,
11152 Operator::I64AtomicRmw32OrU { ref memarg } => self.translate_atomic_rmw(
11153 self.intrinsics.i64_ty,
11154 self.intrinsics.i32_ty,
11155 memarg,
11156 AtomicRMWBinOp::Or,
11157 Some(ExtraInfo::arithmetic_f64()),
11158 )?,
11159 Operator::I64AtomicRmwOr { ref memarg } => self.translate_atomic_rmw(
11160 self.intrinsics.i64_ty,
11161 self.intrinsics.i64_ty,
11162 memarg,
11163 AtomicRMWBinOp::Or,
11164 None,
11165 )?,
11166 Operator::I32AtomicRmw8XorU { ref memarg } => self.translate_atomic_rmw(
11167 self.intrinsics.i32_ty,
11168 self.intrinsics.i8_ty,
11169 memarg,
11170 AtomicRMWBinOp::Xor,
11171 Some(ExtraInfo::arithmetic_f32()),
11172 )?,
11173 Operator::I32AtomicRmw16XorU { ref memarg } => self.translate_atomic_rmw(
11174 self.intrinsics.i32_ty,
11175 self.intrinsics.i16_ty,
11176 memarg,
11177 AtomicRMWBinOp::Xor,
11178 Some(ExtraInfo::arithmetic_f32()),
11179 )?,
11180 Operator::I32AtomicRmwXor { ref memarg } => self.translate_atomic_rmw(
11181 self.intrinsics.i32_ty,
11182 self.intrinsics.i32_ty,
11183 memarg,
11184 AtomicRMWBinOp::Xor,
11185 None,
11186 )?,
11187 Operator::I64AtomicRmw8XorU { ref memarg } => self.translate_atomic_rmw(
11188 self.intrinsics.i64_ty,
11189 self.intrinsics.i8_ty,
11190 memarg,
11191 AtomicRMWBinOp::Xor,
11192 Some(ExtraInfo::arithmetic_f64()),
11193 )?,
11194 Operator::I64AtomicRmw16XorU { ref memarg } => self.translate_atomic_rmw(
11195 self.intrinsics.i64_ty,
11196 self.intrinsics.i16_ty,
11197 memarg,
11198 AtomicRMWBinOp::Xor,
11199 Some(ExtraInfo::arithmetic_f64()),
11200 )?,
11201 Operator::I64AtomicRmw32XorU { ref memarg } => self.translate_atomic_rmw(
11202 self.intrinsics.i64_ty,
11203 self.intrinsics.i32_ty,
11204 memarg,
11205 AtomicRMWBinOp::Xor,
11206 Some(ExtraInfo::arithmetic_f64()),
11207 )?,
11208 Operator::I64AtomicRmwXor { ref memarg } => self.translate_atomic_rmw(
11209 self.intrinsics.i64_ty,
11210 self.intrinsics.i64_ty,
11211 memarg,
11212 AtomicRMWBinOp::Xor,
11213 None,
11214 )?,
11215 Operator::I32AtomicRmw8XchgU { ref memarg } => self.translate_atomic_rmw(
11216 self.intrinsics.i32_ty,
11217 self.intrinsics.i8_ty,
11218 memarg,
11219 AtomicRMWBinOp::Xchg,
11220 Some(ExtraInfo::arithmetic_f32()),
11221 )?,
11222 Operator::I32AtomicRmw16XchgU { ref memarg } => self.translate_atomic_rmw(
11223 self.intrinsics.i32_ty,
11224 self.intrinsics.i16_ty,
11225 memarg,
11226 AtomicRMWBinOp::Xchg,
11227 Some(ExtraInfo::arithmetic_f32()),
11228 )?,
11229 Operator::I32AtomicRmwXchg { ref memarg } => self.translate_atomic_rmw(
11230 self.intrinsics.i32_ty,
11231 self.intrinsics.i32_ty,
11232 memarg,
11233 AtomicRMWBinOp::Xchg,
11234 None,
11235 )?,
11236 Operator::I64AtomicRmw8XchgU { ref memarg } => self.translate_atomic_rmw(
11237 self.intrinsics.i64_ty,
11238 self.intrinsics.i8_ty,
11239 memarg,
11240 AtomicRMWBinOp::Xchg,
11241 Some(ExtraInfo::arithmetic_f64()),
11242 )?,
11243 Operator::I64AtomicRmw16XchgU { ref memarg } => self.translate_atomic_rmw(
11244 self.intrinsics.i64_ty,
11245 self.intrinsics.i16_ty,
11246 memarg,
11247 AtomicRMWBinOp::Xchg,
11248 Some(ExtraInfo::arithmetic_f64()),
11249 )?,
11250 Operator::I64AtomicRmw32XchgU { ref memarg } => self.translate_atomic_rmw(
11251 self.intrinsics.i64_ty,
11252 self.intrinsics.i32_ty,
11253 memarg,
11254 AtomicRMWBinOp::Xchg,
11255 Some(ExtraInfo::arithmetic_f64()),
11256 )?,
11257 Operator::I64AtomicRmwXchg { ref memarg } => self.translate_atomic_rmw(
11258 self.intrinsics.i64_ty,
11259 self.intrinsics.i64_ty,
11260 memarg,
11261 AtomicRMWBinOp::Xchg,
11262 None,
11263 )?,
11264 Operator::I32AtomicRmw8CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11265 self.intrinsics.i32_ty,
11266 self.intrinsics.i8_ty,
11267 memarg,
11268 Some(ExtraInfo::arithmetic_f32()),
11269 )?,
11270 Operator::I32AtomicRmw16CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11271 self.intrinsics.i32_ty,
11272 self.intrinsics.i16_ty,
11273 memarg,
11274 Some(ExtraInfo::arithmetic_f32()),
11275 )?,
11276 Operator::I32AtomicRmwCmpxchg { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11277 self.intrinsics.i32_ty,
11278 self.intrinsics.i32_ty,
11279 memarg,
11280 None,
11281 )?,
11282 Operator::I64AtomicRmw8CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11283 self.intrinsics.i64_ty,
11284 self.intrinsics.i8_ty,
11285 memarg,
11286 Some(ExtraInfo::arithmetic_f64()),
11287 )?,
11288 Operator::I64AtomicRmw16CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11289 self.intrinsics.i64_ty,
11290 self.intrinsics.i16_ty,
11291 memarg,
11292 Some(ExtraInfo::arithmetic_f64()),
11293 )?,
11294 Operator::I64AtomicRmw32CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11295 self.intrinsics.i64_ty,
11296 self.intrinsics.i32_ty,
11297 memarg,
11298 Some(ExtraInfo::arithmetic_f64()),
11299 )?,
11300 Operator::I64AtomicRmwCmpxchg { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11301 self.intrinsics.i64_ty,
11302 self.intrinsics.i64_ty,
11303 memarg,
11304 None,
11305 )?,
11306 Operator::MemoryAtomicWait32 { memarg } => {
11307 let memory_index = MemoryIndex::from_u32(memarg.memory);
11308 let index_arg = self
11309 .wasm_module
11310 .local_memory_index(memory_index)
11311 .map_or(memarg.memory, |index| index.as_u32());
11312 let (dst, val, timeout) = self.state.pop3()?;
11313 let dst = self.fold_atomic_mem_addr(dst, &memarg)?;
11314 let wait32_fn_ptr = self.ctx.memory_wait32(memory_index, self.intrinsics)?;
11315 let ret = err!(
11316 self.builder.build_indirect_call(
11317 self.intrinsics.memory_wait32_ty,
11318 wait32_fn_ptr,
11319 &[
11320 vmctx.as_basic_value_enum().into(),
11321 self.intrinsics
11322 .i32_ty
11323 .const_int(index_arg as u64, false)
11324 .into(),
11325 dst.into(),
11326 val.into(),
11327 timeout.into(),
11328 ],
11329 "",
11330 )
11331 );
11332 self.state.push1(ret.try_as_basic_value().unwrap_basic());
11333 }
11334 Operator::MemoryAtomicWait64 { memarg } => {
11335 let memory_index = MemoryIndex::from_u32(memarg.memory);
11336 let index_arg = self
11337 .wasm_module
11338 .local_memory_index(memory_index)
11339 .map_or(memarg.memory, |index| index.as_u32());
11340 let (dst, val, timeout) = self.state.pop3()?;
11341 let dst = self.fold_atomic_mem_addr(dst, &memarg)?;
11342 let wait64_fn_ptr = self.ctx.memory_wait64(memory_index, self.intrinsics)?;
11343 let ret = err!(
11344 self.builder.build_indirect_call(
11345 self.intrinsics.memory_wait64_ty,
11346 wait64_fn_ptr,
11347 &[
11348 vmctx.as_basic_value_enum().into(),
11349 self.intrinsics
11350 .i32_ty
11351 .const_int(index_arg as u64, false)
11352 .into(),
11353 dst.into(),
11354 val.into(),
11355 timeout.into(),
11356 ],
11357 "",
11358 )
11359 );
11360 self.state.push1(ret.try_as_basic_value().unwrap_basic());
11361 }
11362 Operator::MemoryAtomicNotify { memarg } => {
11363 let memory_index = MemoryIndex::from_u32(memarg.memory);
11364 let index_arg = self
11365 .wasm_module
11366 .local_memory_index(memory_index)
11367 .map_or(memarg.memory, |index| index.as_u32());
11368 let (dst, count) = self.state.pop2()?;
11369 let dst = self.fold_atomic_mem_addr(dst, &memarg)?;
11370 let notify_fn_ptr = self.ctx.memory_notify(memory_index, self.intrinsics)?;
11371 let cnt = err!(
11372 self.builder.build_indirect_call(
11373 self.intrinsics.memory_notify_ty,
11374 notify_fn_ptr,
11375 &[
11376 vmctx.as_basic_value_enum().into(),
11377 self.intrinsics
11378 .i32_ty
11379 .const_int(index_arg as u64, false)
11380 .into(),
11381 dst.into(),
11382 count.into(),
11383 ],
11384 "",
11385 )
11386 );
11387 self.state.push1(cnt.try_as_basic_value().unwrap_basic());
11388 }
11389 _ => unreachable!(),
11390 }
11391 Ok(())
11392 }
11393
11394 fn translate_reference_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11397 match op {
11398 Operator::RefNull { hty } => {
11399 let ty = err!(wpheaptype_to_type(hty));
11400 let ty = type_to_llvm(self.intrinsics, ty)?;
11401 self.state.push1(ty.const_zero());
11402 }
11403 Operator::RefIsNull => {
11404 let value = self.state.pop1()?;
11405 let is_null = match value {
11406 BasicValueEnum::IntValue(value) => err!(self.builder.build_int_compare(
11407 IntPredicate::EQ,
11408 value,
11409 value.get_type().const_zero(),
11410 "",
11411 )),
11412 BasicValueEnum::PointerValue(value) => {
11413 err!(self.builder.build_is_null(value, ""))
11414 }
11415 _ => unreachable!("ref.is_null only accepts reference types"),
11416 };
11417 let is_null = err!(self.builder.build_int_z_extend(
11418 is_null,
11419 self.intrinsics.i32_ty,
11420 ""
11421 ));
11422 self.state.push1(is_null);
11423 }
11424 Operator::RefFunc { function_index } => {
11425 let index = self
11426 .intrinsics
11427 .i32_ty
11428 .const_int(function_index.into(), false);
11429 let value = self
11430 .build_call_with_param_attributes(
11431 self.intrinsics.func_ref,
11432 &[self.ctx.basic().into(), index.into()],
11433 "",
11434 )?
11435 .try_as_basic_value()
11436 .unwrap_basic();
11437 self.state.push1(value);
11438 }
11439 _ => unreachable!(),
11440 }
11441 Ok(())
11442 }
11443
11444 fn translate_table_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11446 match op {
11447 Operator::TableGet { table } => {
11448 let elem = self.state.pop1()?;
11449 let (table_get, table_index) = if let Some(local_table_index) = self
11450 .wasm_module
11451 .local_table_index(TableIndex::from_u32(table))
11452 {
11453 (self.intrinsics.table_get, local_table_index.as_u32())
11454 } else {
11455 (self.intrinsics.imported_table_get, table)
11456 };
11457 let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11458 let value = self
11459 .build_call_with_param_attributes(
11460 table_get,
11461 &[self.ctx.basic().into(), table_index.into(), elem.into()],
11462 "",
11463 )?
11464 .try_as_basic_value()
11465 .unwrap_basic();
11466 let value = err!(
11467 self.builder.build_bit_cast(
11468 value,
11469 type_to_llvm(
11470 self.intrinsics,
11471 self.wasm_module
11472 .tables
11473 .get(TableIndex::from_u32(table))
11474 .unwrap()
11475 .ty,
11476 )?,
11477 "",
11478 )
11479 );
11480 self.state.push1(value);
11481 }
11482 Operator::TableSet { table } => {
11483 let (elem, value) = self.state.pop2()?;
11484 let value = err!(
11485 self.builder
11486 .build_bit_cast(value, self.intrinsics.ptr_ty, "")
11487 );
11488 let (table_set, table_index) = if let Some(local_table_index) = self
11489 .wasm_module
11490 .local_table_index(TableIndex::from_u32(table))
11491 {
11492 (self.intrinsics.table_set, local_table_index.as_u32())
11493 } else {
11494 (self.intrinsics.imported_table_set, table)
11495 };
11496 let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11497 self.build_call_with_param_attributes(
11498 table_set,
11499 &[
11500 self.ctx.basic().into(),
11501 table_index.into(),
11502 elem.into(),
11503 value.into(),
11504 ],
11505 "",
11506 )?;
11507 }
11508 Operator::TableCopy {
11509 dst_table,
11510 src_table,
11511 } => {
11512 let (dst, src, len) = self.state.pop3()?;
11513 let dst_table = self.intrinsics.i32_ty.const_int(dst_table as u64, false);
11514 let src_table = self.intrinsics.i32_ty.const_int(src_table as u64, false);
11515 self.build_call_with_param_attributes(
11516 self.intrinsics.table_copy,
11517 &[
11518 self.ctx.basic().into(),
11519 dst_table.into(),
11520 src_table.into(),
11521 dst.into(),
11522 src.into(),
11523 len.into(),
11524 ],
11525 "",
11526 )?;
11527 }
11528 Operator::TableInit { elem_index, table } => {
11529 let (dst, src, len) = self.state.pop3()?;
11530 let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
11531 let table = self.intrinsics.i32_ty.const_int(table as u64, false);
11532 self.build_call_with_param_attributes(
11533 self.intrinsics.table_init,
11534 &[
11535 self.ctx.basic().into(),
11536 table.into(),
11537 segment.into(),
11538 dst.into(),
11539 src.into(),
11540 len.into(),
11541 ],
11542 "",
11543 )?;
11544 }
11545 Operator::ElemDrop { elem_index } => {
11546 let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
11547 self.build_call_with_param_attributes(
11548 self.intrinsics.elem_drop,
11549 &[self.ctx.basic().into(), segment.into()],
11550 "",
11551 )?;
11552 }
11553 Operator::TableFill { table } => {
11554 let table = self.intrinsics.i32_ty.const_int(table as u64, false);
11555 let (start, elem, len) = self.state.pop3()?;
11556 let elem = err!(
11557 self.builder
11558 .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
11559 );
11560 self.build_call_with_param_attributes(
11561 self.intrinsics.table_fill,
11562 &[
11563 self.ctx.basic().into(),
11564 table.into(),
11565 start.into(),
11566 elem.into(),
11567 len.into(),
11568 ],
11569 "",
11570 )?;
11571 }
11572 Operator::TableGrow { table } => {
11573 let (elem, delta) = self.state.pop2()?;
11574 let elem = err!(
11575 self.builder
11576 .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
11577 );
11578 let (table_grow, table_index) = if let Some(local_table_index) = self
11579 .wasm_module
11580 .local_table_index(TableIndex::from_u32(table))
11581 {
11582 (self.intrinsics.table_grow, local_table_index.as_u32())
11583 } else {
11584 (self.intrinsics.imported_table_grow, table)
11585 };
11586 let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11587 let size = self
11588 .build_call_with_param_attributes(
11589 table_grow,
11590 &[
11591 self.ctx.basic().into(),
11592 elem.into(),
11593 delta.into(),
11594 table_index.into(),
11595 ],
11596 "",
11597 )?
11598 .try_as_basic_value()
11599 .unwrap_basic();
11600 self.state.push1(size);
11601 }
11602 Operator::TableSize { table } => {
11603 let (table_size, table_index) = if let Some(local_table_index) = self
11604 .wasm_module
11605 .local_table_index(TableIndex::from_u32(table))
11606 {
11607 (self.intrinsics.table_size, local_table_index.as_u32())
11608 } else {
11609 (self.intrinsics.imported_table_size, table)
11610 };
11611 let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11612 let size = self
11613 .build_call_with_param_attributes(
11614 table_size,
11615 &[self.ctx.basic().into(), table_index.into()],
11616 "",
11617 )?
11618 .try_as_basic_value()
11619 .unwrap_basic();
11620 self.state.push1(size);
11621 }
11622 _ => unreachable!(),
11623 }
11624 Ok(())
11625 }
11626
11627 fn translate_eh_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11630 match op {
11631 Operator::TryTable { try_table } => {
11632 let current_block = self
11633 .builder
11634 .get_insert_block()
11635 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
11636
11637 self.builder.position_at_end(current_block);
11638
11639 let end_block = self.context.append_basic_block(self.function, "try_end");
11640
11641 let end_phis = {
11642 self.builder.position_at_end(end_block);
11643
11644 let phis = self
11645 .module_translation
11646 .blocktype_params_results(&try_table.ty)?
11647 .1
11648 .iter()
11649 .map(|&wp_ty| {
11650 err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
11651 type_to_llvm(self.intrinsics, wasm_ty)
11652 .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
11653 })
11654 })
11655 .collect::<Result<_, _>>()?;
11656
11657 self.builder.position_at_end(current_block);
11658 phis
11659 };
11660
11661 let catches: Vec<_> = try_table
11665 .catches
11666 .into_iter()
11667 .unique_by(|v| match v {
11668 Catch::One { tag, .. } | Catch::OneRef { tag, .. } => *tag as i32,
11669 Catch::All { .. } | Catch::AllRef { .. } => CATCH_ALL_TAG_VALUE,
11670 })
11671 .collect();
11672
11673 let null = self.intrinsics.ptr_ty.const_zero();
11675
11676 let mut catch_tag_values = vec![];
11677 let mut lpad_clauses: Vec<BasicValueEnum<'ctx>> = catches
11678 .iter()
11679 .map(|catch| match catch {
11680 Catch::All { .. } | Catch::AllRef { .. } => {
11681 catch_tag_values.push(CATCH_ALL_TAG_VALUE as u32);
11682 Ok(null.into())
11683 }
11684 Catch::One { tag, .. } | Catch::OneRef { tag, .. } => {
11685 catch_tag_values.push(*tag);
11686 Ok(self.get_or_insert_tag_type_info_global(*tag as i32))
11687 }
11688 })
11689 .collect::<Result<Vec<BasicValueEnum<'ctx>>, CompileError>>()?;
11690
11691 let mut outer_catch_blocks = vec![];
11695 for outer_landingpad in self.state.landingpads.iter().rev() {
11696 for catch_info @ TagCatchInfo { tag, .. } in &outer_landingpad.tags {
11697 if !catch_tag_values.contains(tag) {
11698 catch_tag_values.push(*tag);
11699 lpad_clauses.push(if *tag as i32 == CATCH_ALL_TAG_VALUE {
11700 null.into()
11701 } else {
11702 *self.tags_cache.get(&(*tag as i32)).expect(
11703 "If a previous try_table encountered a tag, \
11704 it should be in the cache",
11705 )
11706 });
11707 outer_catch_blocks.push(*catch_info);
11708 }
11709 }
11710 }
11711
11712 let mut maybe_lpad_block = None;
11716 let mut catch_blocks = vec![];
11717 if !lpad_clauses.is_empty() {
11718 let lpad_block = self.context.append_basic_block(self.function, "catch");
11719 let catch_all_block =
11720 self.context.append_basic_block(self.function, "catch_all");
11721 let catch_specific_block = self
11722 .context
11723 .append_basic_block(self.function, "catch_specific");
11724 let catch_end_block =
11725 self.context.append_basic_block(self.function, "catch_end");
11726 let rethrow_block = self.context.append_basic_block(self.function, "rethrow");
11727
11728 self.builder.position_at_end(lpad_block);
11729
11730 let res = err!(self.builder.build_landing_pad(
11731 self.intrinsics.lpad_exception_ty,
11732 self.intrinsics.personality,
11733 &lpad_clauses,
11734 false,
11735 "exc_struct",
11736 ));
11737
11738 let res = res.into_struct_value();
11739
11740 let uw_exc = err!(self.builder.build_extract_value(res, 0, "exc_ptr"));
11741 let pre_selector =
11742 err!(self.builder.build_extract_value(res, 1, "pre_selector"));
11743
11744 let pre_selector_is_zero = err!(self.builder.build_int_compare(
11747 IntPredicate::EQ,
11748 pre_selector.into_int_value(),
11749 self.intrinsics.i32_zero,
11750 "pre_selector_is_zero"
11751 ));
11752 err!(self.builder.build_conditional_branch(
11753 pre_selector_is_zero,
11754 catch_all_block,
11755 catch_specific_block
11756 ));
11757
11758 self.builder.position_at_end(catch_all_block);
11759 err!(self.builder.build_unconditional_branch(catch_end_block));
11760
11761 self.builder.position_at_end(catch_specific_block);
11762 let selector_value = self.build_call_with_param_attributes(
11763 self.intrinsics.personality2,
11764 &[self.ctx.basic().into(), uw_exc.into()],
11765 "selector",
11766 )?;
11767 err!(self.builder.build_unconditional_branch(catch_end_block));
11768
11769 self.builder.position_at_end(catch_end_block);
11770 let selector = err!(self.builder.build_phi(self.intrinsics.i32_ty, "selector"));
11771 selector.add_incoming(&[
11772 (
11773 &self
11774 .intrinsics
11775 .i32_ty
11776 .const_int(CATCH_ALL_TAG_VALUE as u64, false),
11777 catch_all_block,
11778 ),
11779 (
11780 &selector_value
11781 .try_as_basic_value()
11782 .unwrap_basic()
11783 .into_int_value(),
11784 catch_specific_block,
11785 ),
11786 ]);
11787
11788 let uw_exc = uw_exc.into_pointer_value();
11833 let exnref = self.build_call_with_param_attributes(
11834 self.intrinsics.exception_into_exnref,
11835 &[uw_exc.into()],
11836 "exnref",
11837 )?;
11838
11839 let exnref = exnref.try_as_basic_value().unwrap_basic().into_int_value();
11840 let selector = selector.as_basic_value().into_int_value();
11841
11842 for catch in catches.iter() {
11843 match catch {
11844 Catch::All { label } => {
11845 let b = self
11846 .context
11847 .append_basic_block(self.function, "catch_all_clause");
11848 self.builder.position_at_end(b);
11849 let frame = self.state.frame_at_depth(*label)?;
11850
11851 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11852
11853 self.builder.position_at_end(catch_end_block);
11854 catch_blocks.push((b, None));
11855 }
11856 Catch::One { tag, label } => {
11857 let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
11858 let signature = &self.wasm_module.signatures[tag_idx];
11859 let params = signature.params();
11860
11861 let b = self.context.append_basic_block(
11862 self.function,
11863 format!("catch_one_clause_{tag}").as_str(),
11864 );
11865 self.builder.position_at_end(b);
11866
11867 let exnref_phi = err!(
11868 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11869 );
11870 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11871
11872 let exn_payload_ptr = err!(self.builder.build_direct_call(
11874 self.intrinsics.read_exnref,
11875 &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
11876 "exn_ptr",
11877 ));
11878 let exn_payload_ptr = exn_payload_ptr
11879 .try_as_basic_value()
11880 .unwrap_basic()
11881 .into_pointer_value();
11882
11883 let values = params
11885 .iter()
11886 .enumerate()
11887 .map(|(i, v)| {
11888 let name = format!("value_{i}");
11889 let ptr = err!(unsafe {
11890 self.builder.build_gep(
11891 self.intrinsics.i128_ty,
11892 exn_payload_ptr,
11893 &[self
11894 .intrinsics
11895 .i32_ty
11896 .const_int(i as u64, false)],
11897 format!("{name}_ptr").as_str(),
11898 )
11899 });
11900 err_nt!(self.builder.build_load(
11901 type_to_llvm(self.intrinsics, *v)?,
11902 ptr,
11903 &name,
11904 ))
11905 })
11906 .collect::<Result<Vec<_>, CompileError>>()?;
11907
11908 let frame = self.state.frame_at_depth(*label)?;
11909
11910 for (phi, value) in frame.phis().iter().zip(values.iter()) {
11911 phi.add_incoming(&[(value, b)])
11912 }
11913
11914 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11915
11916 self.builder.position_at_end(catch_end_block);
11917 catch_blocks.push((b, Some(exnref_phi)));
11918 }
11919 Catch::OneRef { label, tag } => {
11920 let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
11921 let signature = &self.wasm_module.signatures[tag_idx];
11922 let params = signature.params();
11923
11924 let b = self.context.append_basic_block(
11925 self.function,
11926 format!("catch_one_ref_clause_{tag}").as_str(),
11927 );
11928 self.builder.position_at_end(b);
11929
11930 let exnref_phi = err!(
11931 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11932 );
11933 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11934
11935 let exn_payload_ptr = err!(self.builder.build_direct_call(
11937 self.intrinsics.read_exnref,
11938 &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
11939 "exn_ptr",
11940 ));
11941 let exn_payload_ptr = exn_payload_ptr
11942 .try_as_basic_value()
11943 .unwrap_basic()
11944 .into_pointer_value();
11945
11946 let mut values = params
11948 .iter()
11949 .enumerate()
11950 .map(|(i, v)| {
11951 let name = format!("value_{i}");
11952 let ptr = err!(unsafe {
11953 self.builder.build_gep(
11954 self.intrinsics.i128_ty,
11955 exn_payload_ptr,
11956 &[self
11957 .intrinsics
11958 .i32_ty
11959 .const_int(i as u64, false)],
11960 format!("{name}_ptr").as_str(),
11961 )
11962 });
11963 err_nt!(self.builder.build_load(
11964 type_to_llvm(self.intrinsics, *v)?,
11965 ptr,
11966 &name,
11967 ))
11968 })
11969 .collect::<Result<Vec<_>, CompileError>>()?;
11970
11971 values.push(exnref_phi.as_basic_value());
11972
11973 let frame = self.state.frame_at_depth(*label)?;
11974
11975 for (phi, value) in frame.phis().iter().zip(values.iter()) {
11976 phi.add_incoming(&[(value, b)])
11977 }
11978
11979 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11980
11981 self.builder.position_at_end(catch_end_block);
11982 catch_blocks.push((b, Some(exnref_phi)));
11983 }
11984 Catch::AllRef { label } => {
11985 let b = self
11986 .context
11987 .append_basic_block(self.function, "catch_all_ref_clause");
11988 self.builder.position_at_end(b);
11989
11990 let exnref_phi = err!(
11991 self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11992 );
11993 exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11994
11995 let frame = self.state.frame_at_depth(*label)?;
11996
11997 let phis = frame.phis();
11998
11999 assert_eq!(phis.len(), 1);
12000 phis[0].add_incoming(&[(&exnref_phi.as_basic_value(), b)]);
12001
12002 err!(self.builder.build_unconditional_branch(*frame.br_dest()));
12003
12004 self.builder.position_at_end(catch_end_block);
12005 catch_blocks.push((b, Some(exnref_phi)));
12006 }
12007 }
12008 }
12009
12010 for catch_info in &outer_catch_blocks {
12011 if let Some(phi) = catch_info.exnref_phi {
12012 phi.add_incoming(&[(&exnref, catch_end_block)]);
12013 }
12014 }
12015
12016 err!(
12017 self.builder.build_switch(
12018 selector,
12019 rethrow_block,
12020 catch_blocks
12021 .iter()
12022 .enumerate()
12023 .map(|(i, v)| (
12024 self.intrinsics
12025 .i32_ty
12026 .const_int(catch_tag_values[i] as _, false),
12027 v.0
12028 ))
12029 .chain(outer_catch_blocks.iter().map(|catch_info| (
12030 self.intrinsics.i32_ty.const_int(catch_info.tag as _, false),
12031 catch_info.catch_block
12032 )))
12033 .collect::<Vec<_>>()
12034 .as_slice()
12035 )
12036 );
12037
12038 self.builder.position_at_end(rethrow_block);
12042
12043 self.build_call_with_param_attributes(
12044 self.intrinsics.throw,
12045 &[self.ctx.basic().into(), exnref.into()],
12046 "rethrow",
12047 )?;
12048 err!(self.builder.build_unreachable());
12050
12051 maybe_lpad_block = Some(lpad_block);
12052 }
12053
12054 self.builder.position_at_end(current_block);
12056
12057 let catch_tags_and_blocks = catch_tag_values
12060 .into_iter()
12061 .zip(catch_blocks)
12062 .map(|(tag, (block, exnref_phi))| TagCatchInfo {
12063 tag,
12064 catch_block: block,
12065 exnref_phi,
12066 })
12067 .collect::<Vec<_>>();
12068 self.state.push_landingpad(
12069 maybe_lpad_block,
12070 end_block,
12071 end_phis,
12072 &catch_tags_and_blocks,
12073 self.module_translation
12074 .blocktype_params_results(&try_table.ty)?
12075 .0
12076 .len(),
12077 );
12078 }
12079 Operator::Throw { tag_index } => {
12080 let current_block = self
12081 .builder
12082 .get_insert_block()
12083 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
12084
12085 let sig_index = self.wasm_module.tags[TagIndex::from_u32(tag_index)];
12086 let signature = &self.wasm_module.signatures[sig_index];
12087 let params = signature.params();
12088 let values = self.state.popn_save_extra(params.len())?;
12089
12090 values.iter().enumerate().try_for_each(|(i, (v, _))| {
12091 let t = type_to_llvm(self.intrinsics, params[i])?;
12092 if t != v.get_type() {
12093 return Err(CompileError::Codegen(format!(
12094 "Incompatible types: {:?} != {:?}",
12095 t,
12096 v.get_type()
12097 )));
12098 }
12099
12100 Ok(())
12101 })?;
12102
12103 let exnref = err!(
12105 self.builder.build_direct_call(
12106 self.intrinsics.alloc_exception,
12107 &[
12108 self.ctx.basic().into(),
12109 self.intrinsics
12110 .i32_ty
12111 .const_int(tag_index as _, false)
12112 .into()
12113 ],
12114 "exnref",
12115 )
12116 );
12117 let exnref = exnref.try_as_basic_value().unwrap_basic();
12118
12119 let exn_payload_ptr = err!(self.builder.build_direct_call(
12120 self.intrinsics.read_exnref,
12121 &[self.ctx.basic().into(), exnref.into()],
12122 "exn_ptr",
12123 ));
12124 let exn_payload_ptr = exn_payload_ptr
12125 .try_as_basic_value()
12126 .unwrap_basic()
12127 .into_pointer_value();
12128
12129 for (i, value) in values.into_iter().enumerate() {
12130 let ptr = err!(unsafe {
12131 self.builder.build_gep(
12132 self.intrinsics.i128_ty,
12133 exn_payload_ptr,
12134 &[self.intrinsics.i32_ty.const_int(i as u64, false)],
12135 format!("value_{i}_ptr").as_str(),
12136 )
12137 });
12138 err!(self.builder.build_store(ptr, value.0));
12139 }
12140
12141 if let Some(pad) = self.state.get_innermost_landingpad() {
12142 let unreachable_block = self
12143 .context
12144 .append_basic_block(self.function, "_throw_unreachable");
12145
12146 err!(self.builder.build_invoke(
12147 self.intrinsics.throw,
12148 &[self.ctx.basic(), exnref],
12149 unreachable_block,
12150 pad,
12151 "throw",
12152 ));
12153
12154 self.builder.position_at_end(unreachable_block);
12155 err!(self.builder.build_unreachable());
12157
12158 self.builder.position_at_end(current_block);
12159 } else {
12160 self.build_call_with_param_attributes(
12161 self.intrinsics.throw,
12162 &[self.ctx.basic().into(), exnref.into()],
12163 "throw",
12164 )?;
12165 err!(self.builder.build_unreachable());
12167 }
12168
12169 self.state.reachable = false;
12170 }
12171 Operator::ThrowRef => {
12172 let current_block = self
12173 .builder
12174 .get_insert_block()
12175 .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
12176
12177 let exnref = self.state.pop1()?;
12178
12179 if let Some(pad) = self.state.get_innermost_landingpad() {
12180 let unreachable_block = self
12181 .context
12182 .append_basic_block(self.function, "_rethrow_unreachable");
12183
12184 err!(self.builder.build_invoke(
12185 self.intrinsics.throw,
12186 &[self.ctx.basic(), exnref],
12187 unreachable_block,
12188 pad,
12189 "throw",
12190 ));
12191
12192 self.builder.position_at_end(unreachable_block);
12193 err!(self.builder.build_unreachable());
12195
12196 self.builder.position_at_end(current_block);
12197 } else {
12198 self.build_call_with_param_attributes(
12199 self.intrinsics.throw,
12200 &[self.ctx.basic().into(), exnref.into()],
12201 "throw",
12202 )?;
12203 err!(self.builder.build_unreachable());
12205 }
12206
12207 self.state.reachable = false;
12208 }
12209 _ => unreachable!(),
12210 }
12211 Ok(())
12212 }
12213
12214 fn translate_operator(&mut self, op: Operator, _source_loc: u32) -> Result<(), CompileError> {
12215 if !self.state.reachable {
12218 match op {
12219 Operator::Block { blockty: _ }
12220 | Operator::Loop { blockty: _ }
12221 | Operator::If { blockty: _ }
12222 | Operator::TryTable { .. } => {
12223 self.unreachable_depth += 1;
12224 return Ok(());
12225 }
12226 Operator::Else => {
12227 if self.unreachable_depth != 0 {
12228 return Ok(());
12229 }
12230 }
12231 Operator::End => {
12232 if self.unreachable_depth != 0 {
12233 self.unreachable_depth -= 1;
12234 return Ok(());
12235 }
12236 }
12237 _ => {
12238 return Ok(());
12239 }
12240 }
12241 }
12242
12243 match op {
12244 Operator::Block { .. }
12245 | Operator::Loop { .. }
12246 | Operator::Br { .. }
12247 | Operator::BrIf { .. }
12248 | Operator::BrTable { .. }
12249 | Operator::If { .. }
12250 | Operator::Else
12251 | Operator::End
12252 | Operator::Return
12253 | Operator::Unreachable => {
12254 self.translate_control_flow_operator(op)?;
12255 }
12256 Operator::Nop
12257 | Operator::Drop
12258 | Operator::I32Const { .. }
12259 | Operator::I64Const { .. }
12260 | Operator::F32Const { .. }
12261 | Operator::F64Const { .. }
12262 | Operator::V128Const { .. }
12263 | Operator::I8x16Splat
12264 | Operator::I16x8Splat
12265 | Operator::I32x4Splat
12266 | Operator::I64x2Splat
12267 | Operator::F32x4Splat
12268 | Operator::F64x2Splat
12269 | Operator::LocalGet { .. }
12270 | Operator::LocalSet { .. }
12271 | Operator::LocalTee { .. }
12272 | Operator::GlobalGet { .. }
12273 | Operator::GlobalSet { .. }
12274 | Operator::Call { .. }
12275 | Operator::ReturnCall { .. }
12276 | Operator::CallIndirect { .. }
12277 | Operator::ReturnCallIndirect { .. }
12278 | Operator::TypedSelect { .. }
12279 | Operator::Select => {
12280 self.translate_basic_operator(op)?;
12281 }
12282 Operator::I32Add
12283 | Operator::I64Add
12284 | Operator::I8x16Add
12285 | Operator::I16x8Add
12286 | Operator::I16x8ExtAddPairwiseI8x16S
12287 | Operator::I16x8ExtAddPairwiseI8x16U
12288 | Operator::I32x4Add
12289 | Operator::I32x4ExtAddPairwiseI16x8S
12290 | Operator::I32x4ExtAddPairwiseI16x8U
12291 | Operator::I64x2Add
12292 | Operator::I8x16AddSatS
12293 | Operator::I16x8AddSatS
12294 | Operator::I8x16AddSatU
12295 | Operator::I16x8AddSatU
12296 | Operator::I32Sub
12297 | Operator::I64Sub
12298 | Operator::I8x16Sub
12299 | Operator::I16x8Sub
12300 | Operator::I32x4Sub
12301 | Operator::I64x2Sub
12302 | Operator::I8x16SubSatS
12303 | Operator::I16x8SubSatS
12304 | Operator::I8x16SubSatU
12305 | Operator::I16x8SubSatU
12306 | Operator::I32Mul
12307 | Operator::I64Mul
12308 | Operator::I16x8Mul
12309 | Operator::I32x4Mul
12310 | Operator::I64x2Mul
12311 | Operator::I16x8RelaxedQ15mulrS
12312 | Operator::I16x8Q15MulrSatS
12313 | Operator::I16x8ExtMulLowI8x16S
12314 | Operator::I16x8ExtMulLowI8x16U
12315 | Operator::I16x8ExtMulHighI8x16S
12316 | Operator::I16x8ExtMulHighI8x16U
12317 | Operator::I32x4ExtMulLowI16x8S
12318 | Operator::I32x4ExtMulLowI16x8U
12319 | Operator::I32x4ExtMulHighI16x8S
12320 | Operator::I32x4ExtMulHighI16x8U
12321 | Operator::I64x2ExtMulLowI32x4S
12322 | Operator::I64x2ExtMulLowI32x4U
12323 | Operator::I64x2ExtMulHighI32x4S
12324 | Operator::I64x2ExtMulHighI32x4U
12325 | Operator::I32x4DotI16x8S
12326 | Operator::I16x8RelaxedDotI8x16I7x16S
12327 | Operator::I32x4RelaxedDotI8x16I7x16AddS
12328 | Operator::I32DivS
12329 | Operator::I64DivS
12330 | Operator::I32DivU
12331 | Operator::I64DivU
12332 | Operator::I32RemS
12333 | Operator::I64RemS
12334 | Operator::I32RemU
12335 | Operator::I64RemU
12336 | Operator::I32And
12337 | Operator::I64And
12338 | Operator::V128And
12339 | Operator::I32Or
12340 | Operator::I64Or
12341 | Operator::V128Or
12342 | Operator::I32Xor
12343 | Operator::I64Xor
12344 | Operator::V128Xor
12345 | Operator::V128AndNot
12346 | Operator::I8x16RelaxedLaneselect
12347 | Operator::I16x8RelaxedLaneselect
12348 | Operator::I32x4RelaxedLaneselect
12349 | Operator::I64x2RelaxedLaneselect
12350 | Operator::V128Bitselect
12351 | Operator::I8x16Bitmask
12352 | Operator::I16x8Bitmask
12353 | Operator::I32x4Bitmask
12354 | Operator::I64x2Bitmask
12355 | Operator::I32Shl
12356 | Operator::I64Shl
12357 | Operator::I8x16Shl
12358 | Operator::I16x8Shl
12359 | Operator::I32x4Shl
12360 | Operator::I64x2Shl
12361 | Operator::I32ShrS
12362 | Operator::I64ShrS
12363 | Operator::I8x16ShrS
12364 | Operator::I16x8ShrS
12365 | Operator::I32x4ShrS
12366 | Operator::I64x2ShrS
12367 | Operator::I32ShrU
12368 | Operator::I64ShrU
12369 | Operator::I8x16ShrU
12370 | Operator::I16x8ShrU
12371 | Operator::I32x4ShrU
12372 | Operator::I64x2ShrU
12373 | Operator::I32Rotl
12374 | Operator::I64Rotl
12375 | Operator::I32Rotr
12376 | Operator::I64Rotr
12377 | Operator::I32Clz
12378 | Operator::I64Clz
12379 | Operator::I32Ctz
12380 | Operator::I64Ctz
12381 | Operator::I8x16Popcnt
12382 | Operator::I32Popcnt
12383 | Operator::I64Popcnt
12384 | Operator::I32Eqz
12385 | Operator::I64Eqz
12386 | Operator::I8x16Abs
12387 | Operator::I16x8Abs
12388 | Operator::I32x4Abs
12389 | Operator::I64x2Abs
12390 | Operator::I8x16MinS
12391 | Operator::I8x16MinU
12392 | Operator::I8x16MaxS
12393 | Operator::I8x16MaxU
12394 | Operator::I16x8MinS
12395 | Operator::I16x8MinU
12396 | Operator::I16x8MaxS
12397 | Operator::I16x8MaxU
12398 | Operator::I32x4MinS
12399 | Operator::I32x4MinU
12400 | Operator::I32x4MaxS
12401 | Operator::I32x4MaxU
12402 | Operator::I8x16AvgrU
12403 | Operator::I16x8AvgrU
12404 | Operator::I64Add128
12405 | Operator::I64Sub128
12406 | Operator::I64MulWideS
12407 | Operator::I64MulWideU => self.translate_integer_arithmetic_operator(op)?,
12408 Operator::F32Add
12409 | Operator::F64Add
12410 | Operator::F32x4Add
12411 | Operator::F64x2Add
12412 | Operator::F32Sub
12413 | Operator::F64Sub
12414 | Operator::F32x4Sub
12415 | Operator::F64x2Sub
12416 | Operator::F32Mul
12417 | Operator::F64Mul
12418 | Operator::F32x4Mul
12419 | Operator::F32x4RelaxedMadd
12420 | Operator::F32x4RelaxedNmadd
12421 | Operator::F64x2Mul
12422 | Operator::F64x2RelaxedMadd
12423 | Operator::F64x2RelaxedNmadd
12424 | Operator::F32Div
12425 | Operator::F64Div
12426 | Operator::F32x4Div
12427 | Operator::F64x2Div
12428 | Operator::F32Sqrt
12429 | Operator::F64Sqrt
12430 | Operator::F32x4Sqrt
12431 | Operator::F64x2Sqrt
12432 | Operator::F32Min
12433 | Operator::F64Min
12434 | Operator::F32x4RelaxedMin
12435 | Operator::F32x4Min
12436 | Operator::F32x4PMin
12437 | Operator::F64x2RelaxedMin
12438 | Operator::F64x2Min
12439 | Operator::F64x2PMin
12440 | Operator::F32Max
12441 | Operator::F64Max
12442 | Operator::F32x4RelaxedMax
12443 | Operator::F32x4Max
12444 | Operator::F32x4PMax
12445 | Operator::F64x2RelaxedMax
12446 | Operator::F64x2Max
12447 | Operator::F64x2PMax
12448 | Operator::F32Ceil
12449 | Operator::F32x4Ceil
12450 | Operator::F64Ceil
12451 | Operator::F64x2Ceil
12452 | Operator::F32Floor
12453 | Operator::F32x4Floor
12454 | Operator::F64Floor
12455 | Operator::F64x2Floor
12456 | Operator::F32Trunc
12457 | Operator::F32x4Trunc
12458 | Operator::F64Trunc
12459 | Operator::F64x2Trunc
12460 | Operator::F32Nearest
12461 | Operator::F32x4Nearest
12462 | Operator::F64Nearest
12463 | Operator::F64x2Nearest
12464 | Operator::F32Abs
12465 | Operator::F64Abs
12466 | Operator::F32x4Abs
12467 | Operator::F64x2Abs
12468 | Operator::F32x4Neg
12469 | Operator::F64x2Neg
12470 | Operator::F32Neg
12471 | Operator::F64Neg
12472 | Operator::F32Copysign
12473 | Operator::F64Copysign => self.translate_floating_point_arithmetic_operator(op)?,
12474 Operator::I32Eq
12475 | Operator::I64Eq
12476 | Operator::I8x16Eq
12477 | Operator::I16x8Eq
12478 | Operator::I32x4Eq
12479 | Operator::I64x2Eq
12480 | Operator::I32Ne
12481 | Operator::I64Ne
12482 | Operator::I8x16Ne
12483 | Operator::I16x8Ne
12484 | Operator::I32x4Ne
12485 | Operator::I64x2Ne
12486 | Operator::I32LtS
12487 | Operator::I64LtS
12488 | Operator::I8x16LtS
12489 | Operator::I16x8LtS
12490 | Operator::I32x4LtS
12491 | Operator::I64x2LtS
12492 | Operator::I32LtU
12493 | Operator::I64LtU
12494 | Operator::I8x16LtU
12495 | Operator::I16x8LtU
12496 | Operator::I32x4LtU
12497 | Operator::I32LeS
12498 | Operator::I64LeS
12499 | Operator::I8x16LeS
12500 | Operator::I16x8LeS
12501 | Operator::I32x4LeS
12502 | Operator::I64x2LeS
12503 | Operator::I32LeU
12504 | Operator::I64LeU
12505 | Operator::I8x16LeU
12506 | Operator::I16x8LeU
12507 | Operator::I32x4LeU
12508 | Operator::I32GtS
12509 | Operator::I64GtS
12510 | Operator::I8x16GtS
12511 | Operator::I16x8GtS
12512 | Operator::I32x4GtS
12513 | Operator::I64x2GtS
12514 | Operator::I32GtU
12515 | Operator::I64GtU
12516 | Operator::I8x16GtU
12517 | Operator::I16x8GtU
12518 | Operator::I32x4GtU
12519 | Operator::I32GeS
12520 | Operator::I64GeS
12521 | Operator::I8x16GeS
12522 | Operator::I16x8GeS
12523 | Operator::I32x4GeS
12524 | Operator::I64x2GeS
12525 | Operator::I32GeU
12526 | Operator::I64GeU
12527 | Operator::I8x16GeU
12528 | Operator::I16x8GeU
12529 | Operator::I32x4GeU => self.translate_integer_comparison_operator(op)?,
12530 Operator::F32Eq
12531 | Operator::F64Eq
12532 | Operator::F32x4Eq
12533 | Operator::F64x2Eq
12534 | Operator::F32Ne
12535 | Operator::F64Ne
12536 | Operator::F32x4Ne
12537 | Operator::F64x2Ne
12538 | Operator::F32Lt
12539 | Operator::F64Lt
12540 | Operator::F32x4Lt
12541 | Operator::F64x2Lt
12542 | Operator::F32Le
12543 | Operator::F64Le
12544 | Operator::F32x4Le
12545 | Operator::F64x2Le
12546 | Operator::F32Gt
12547 | Operator::F64Gt
12548 | Operator::F32x4Gt
12549 | Operator::F64x2Gt
12550 | Operator::F32Ge
12551 | Operator::F64Ge
12552 | Operator::F32x4Ge
12553 | Operator::F64x2Ge => self.translate_floating_point_comparison_operator(op)?,
12554 Operator::I32WrapI64
12555 | Operator::I64ExtendI32S
12556 | Operator::I64ExtendI32U
12557 | Operator::I16x8ExtendLowI8x16S
12558 | Operator::I16x8ExtendHighI8x16S
12559 | Operator::I16x8ExtendLowI8x16U
12560 | Operator::I16x8ExtendHighI8x16U
12561 | Operator::I32x4ExtendLowI16x8S
12562 | Operator::I32x4ExtendHighI16x8S
12563 | Operator::I32x4ExtendLowI16x8U
12564 | Operator::I32x4ExtendHighI16x8U
12565 | Operator::I64x2ExtendLowI32x4U
12566 | Operator::I64x2ExtendLowI32x4S
12567 | Operator::I64x2ExtendHighI32x4U
12568 | Operator::I64x2ExtendHighI32x4S
12569 | Operator::I8x16NarrowI16x8S
12570 | Operator::I8x16NarrowI16x8U
12571 | Operator::I16x8NarrowI32x4S
12572 | Operator::I16x8NarrowI32x4U
12573 | Operator::I32x4RelaxedTruncF32x4S
12574 | Operator::I32x4TruncSatF32x4S
12575 | Operator::I32x4RelaxedTruncF32x4U
12576 | Operator::I32x4TruncSatF32x4U
12577 | Operator::I32x4RelaxedTruncF64x2SZero
12578 | Operator::I32x4RelaxedTruncF64x2UZero
12579 | Operator::I32x4TruncSatF64x2SZero
12580 | Operator::I32x4TruncSatF64x2UZero
12581 | Operator::I32TruncF32S
12582 | Operator::I32TruncF64S
12583 | Operator::I32TruncSatF32S
12584 | Operator::I32TruncSatF64S
12585 | Operator::I64TruncF32S
12586 | Operator::I64TruncF64S
12587 | Operator::I64TruncSatF32S
12588 | Operator::I64TruncSatF64S
12589 | Operator::I32TruncF32U
12590 | Operator::I32TruncF64U
12591 | Operator::I32TruncSatF32U
12592 | Operator::I32TruncSatF64U
12593 | Operator::I64TruncF32U
12594 | Operator::I64TruncF64U
12595 | Operator::I64TruncSatF32U
12596 | Operator::I64TruncSatF64U
12597 | Operator::F32DemoteF64
12598 | Operator::F64PromoteF32
12599 | Operator::F32ConvertI32S
12600 | Operator::F32ConvertI64S
12601 | Operator::F64ConvertI32S
12602 | Operator::F64ConvertI64S
12603 | Operator::F32ConvertI32U
12604 | Operator::F32ConvertI64U
12605 | Operator::F64ConvertI32U
12606 | Operator::F64ConvertI64U
12607 | Operator::F32x4ConvertI32x4S
12608 | Operator::F32x4ConvertI32x4U
12609 | Operator::F64x2ConvertLowI32x4S
12610 | Operator::F64x2ConvertLowI32x4U
12611 | Operator::F64x2PromoteLowF32x4
12612 | Operator::F32x4DemoteF64x2Zero
12613 | Operator::I32ReinterpretF32
12614 | Operator::I64ReinterpretF64
12615 | Operator::F32ReinterpretI32
12616 | Operator::F64ReinterpretI64 => self.translate_conversion_operator(op)?,
12617 Operator::I32Extend8S
12618 | Operator::I32Extend16S
12619 | Operator::I64Extend8S
12620 | Operator::I64Extend16S
12621 | Operator::I64Extend32S => self.translate_sign_extension_operator(op)?,
12622 Operator::I32Load { .. }
12623 | Operator::I64Load { .. }
12624 | Operator::F32Load { .. }
12625 | Operator::F64Load { .. }
12626 | Operator::V128Load { .. }
12627 | Operator::V128Load8Lane { .. }
12628 | Operator::V128Load16Lane { .. }
12629 | Operator::V128Load32Lane { .. }
12630 | Operator::V128Load64Lane { .. }
12631 | Operator::I32Store { .. }
12632 | Operator::I64Store { .. }
12633 | Operator::F32Store { .. }
12634 | Operator::F64Store { .. }
12635 | Operator::V128Store { .. }
12636 | Operator::V128Store8Lane { .. }
12637 | Operator::V128Store16Lane { .. }
12638 | Operator::V128Store32Lane { .. }
12639 | Operator::V128Store64Lane { .. }
12640 | Operator::I32Load8S { .. }
12641 | Operator::I32Load16S { .. }
12642 | Operator::I64Load8S { .. }
12643 | Operator::I64Load16S { .. }
12644 | Operator::I64Load32S { .. }
12645 | Operator::I32Load8U { .. }
12646 | Operator::I32Load16U { .. }
12647 | Operator::I64Load8U { .. }
12648 | Operator::I64Load16U { .. }
12649 | Operator::I64Load32U { .. }
12650 | Operator::I32Store8 { .. }
12651 | Operator::I64Store8 { .. }
12652 | Operator::I32Store16 { .. }
12653 | Operator::I64Store16 { .. }
12654 | Operator::I64Store32 { .. }
12655 | Operator::I8x16Neg
12656 | Operator::I16x8Neg
12657 | Operator::I32x4Neg
12658 | Operator::I64x2Neg
12659 | Operator::V128Not
12660 | Operator::V128AnyTrue
12661 | Operator::I8x16AllTrue
12662 | Operator::I16x8AllTrue
12663 | Operator::I32x4AllTrue
12664 | Operator::I64x2AllTrue
12665 | Operator::I8x16ExtractLaneS { .. }
12666 | Operator::I8x16ExtractLaneU { .. }
12667 | Operator::I16x8ExtractLaneS { .. }
12668 | Operator::I16x8ExtractLaneU { .. }
12669 | Operator::I32x4ExtractLane { .. }
12670 | Operator::I64x2ExtractLane { .. }
12671 | Operator::F32x4ExtractLane { .. }
12672 | Operator::F64x2ExtractLane { .. }
12673 | Operator::I8x16ReplaceLane { .. }
12674 | Operator::I16x8ReplaceLane { .. }
12675 | Operator::I32x4ReplaceLane { .. }
12676 | Operator::I64x2ReplaceLane { .. }
12677 | Operator::F32x4ReplaceLane { .. }
12678 | Operator::F64x2ReplaceLane { .. }
12679 | Operator::I8x16RelaxedSwizzle
12680 | Operator::I8x16Swizzle
12681 | Operator::I8x16Shuffle { .. }
12682 | Operator::V128Load8x8S { .. }
12683 | Operator::V128Load8x8U { .. }
12684 | Operator::V128Load16x4S { .. }
12685 | Operator::V128Load16x4U { .. }
12686 | Operator::V128Load32x2S { .. }
12687 | Operator::V128Load32x2U { .. }
12688 | Operator::V128Load32Zero { .. }
12689 | Operator::V128Load64Zero { .. }
12690 | Operator::V128Load8Splat { .. }
12691 | Operator::V128Load16Splat { .. }
12692 | Operator::V128Load32Splat { .. }
12693 | Operator::V128Load64Splat { .. }
12694 | Operator::MemoryGrow { .. }
12695 | Operator::MemorySize { .. }
12696 | Operator::MemoryInit { .. }
12697 | Operator::DataDrop { .. }
12698 | Operator::MemoryCopy { .. }
12699 | Operator::MemoryFill { .. } => self.translate_memory_operator(op)?,
12700 Operator::AtomicFence { .. }
12701 | Operator::I32AtomicLoad { .. }
12702 | Operator::I64AtomicLoad { .. }
12703 | Operator::I32AtomicLoad8U { .. }
12704 | Operator::I32AtomicLoad16U { .. }
12705 | Operator::I64AtomicLoad8U { .. }
12706 | Operator::I64AtomicLoad16U { .. }
12707 | Operator::I64AtomicLoad32U { .. }
12708 | Operator::I32AtomicStore { .. }
12709 | Operator::I64AtomicStore { .. }
12710 | Operator::I32AtomicStore8 { .. }
12711 | Operator::I64AtomicStore8 { .. }
12712 | Operator::I32AtomicStore16 { .. }
12713 | Operator::I64AtomicStore16 { .. }
12714 | Operator::I64AtomicStore32 { .. }
12715 | Operator::I32AtomicRmw8AddU { .. }
12716 | Operator::I32AtomicRmw16AddU { .. }
12717 | Operator::I32AtomicRmwAdd { .. }
12718 | Operator::I64AtomicRmw8AddU { .. }
12719 | Operator::I64AtomicRmw16AddU { .. }
12720 | Operator::I64AtomicRmw32AddU { .. }
12721 | Operator::I64AtomicRmwAdd { .. }
12722 | Operator::I32AtomicRmw8SubU { .. }
12723 | Operator::I32AtomicRmw16SubU { .. }
12724 | Operator::I32AtomicRmwSub { .. }
12725 | Operator::I64AtomicRmw8SubU { .. }
12726 | Operator::I64AtomicRmw16SubU { .. }
12727 | Operator::I64AtomicRmw32SubU { .. }
12728 | Operator::I64AtomicRmwSub { .. }
12729 | Operator::I32AtomicRmw8AndU { .. }
12730 | Operator::I32AtomicRmw16AndU { .. }
12731 | Operator::I32AtomicRmwAnd { .. }
12732 | Operator::I64AtomicRmw8AndU { .. }
12733 | Operator::I64AtomicRmw16AndU { .. }
12734 | Operator::I64AtomicRmw32AndU { .. }
12735 | Operator::I64AtomicRmwAnd { .. }
12736 | Operator::I32AtomicRmw8OrU { .. }
12737 | Operator::I32AtomicRmw16OrU { .. }
12738 | Operator::I32AtomicRmwOr { .. }
12739 | Operator::I64AtomicRmw8OrU { .. }
12740 | Operator::I64AtomicRmw16OrU { .. }
12741 | Operator::I64AtomicRmw32OrU { .. }
12742 | Operator::I64AtomicRmwOr { .. }
12743 | Operator::I32AtomicRmw8XorU { .. }
12744 | Operator::I32AtomicRmw16XorU { .. }
12745 | Operator::I32AtomicRmwXor { .. }
12746 | Operator::I64AtomicRmw8XorU { .. }
12747 | Operator::I64AtomicRmw16XorU { .. }
12748 | Operator::I64AtomicRmw32XorU { .. }
12749 | Operator::I64AtomicRmwXor { .. }
12750 | Operator::I32AtomicRmw8XchgU { .. }
12751 | Operator::I32AtomicRmw16XchgU { .. }
12752 | Operator::I32AtomicRmwXchg { .. }
12753 | Operator::I64AtomicRmw8XchgU { .. }
12754 | Operator::I64AtomicRmw16XchgU { .. }
12755 | Operator::I64AtomicRmw32XchgU { .. }
12756 | Operator::I64AtomicRmwXchg { .. }
12757 | Operator::I32AtomicRmw8CmpxchgU { .. }
12758 | Operator::I32AtomicRmw16CmpxchgU { .. }
12759 | Operator::I32AtomicRmwCmpxchg { .. }
12760 | Operator::I64AtomicRmw8CmpxchgU { .. }
12761 | Operator::I64AtomicRmw16CmpxchgU { .. }
12762 | Operator::I64AtomicRmw32CmpxchgU { .. }
12763 | Operator::I64AtomicRmwCmpxchg { .. }
12764 | Operator::MemoryAtomicWait32 { .. }
12765 | Operator::MemoryAtomicWait64 { .. }
12766 | Operator::MemoryAtomicNotify { .. } => self.translate_atomic_memory_operator(op)?,
12767 Operator::RefNull { .. } | Operator::RefIsNull | Operator::RefFunc { .. } => {
12768 self.translate_reference_operator(op)?;
12769 }
12770 Operator::TableGet { .. }
12771 | Operator::TableSet { .. }
12772 | Operator::TableCopy { .. }
12773 | Operator::TableInit { .. }
12774 | Operator::ElemDrop { .. }
12775 | Operator::TableFill { .. }
12776 | Operator::TableGrow { .. }
12777 | Operator::TableSize { .. } => self.translate_table_operator(op)?,
12778 Operator::TryTable { .. } | Operator::Throw { .. } | Operator::ThrowRef => {
12779 self.translate_eh_operator(op)?;
12780 }
12781 _ => {
12782 return Err(CompileError::Codegen(format!(
12783 "Operator {op:?} unimplemented",
12784 )));
12785 }
12786 }
12787
12788 Ok(())
12789 }
12790
12791 fn build_call_with_param_attributes(
12792 &self,
12793 function: FunctionValue<'ctx>,
12794 args: &[BasicMetadataValueEnum<'ctx>],
12795 name: &str,
12796 ) -> Result<CallSiteValue<'ctx>, CompileError> {
12797 let call = self
12798 .builder
12799 .build_call(function, args, name)
12800 .map_err(|e| CompileError::Codegen(e.to_string()))?;
12801
12802 if matches!(self.target_triple.architecture, Architecture::Riscv64(..)) {
12807 let param_types = function.get_type().get_param_types();
12808 for (i, ty) in param_types.into_iter().enumerate() {
12809 if ty == self.context.i32_type().into() {
12810 call.add_attribute(
12811 AttributeLoc::Param(i as u32),
12812 self.context
12813 .create_enum_attribute(Attribute::get_named_enum_kind_id("signext"), 0),
12814 );
12815 call.add_attribute(
12816 AttributeLoc::Param(i as u32),
12817 self.context
12818 .create_enum_attribute(Attribute::get_named_enum_kind_id("noundef"), 0),
12819 );
12820 }
12821 }
12822 }
12823
12824 Ok(call)
12825 }
12826}
12827
12828fn is_f32_arithmetic(bits: u32) -> bool {
12829 let bits = bits & 0x7FFF_FFFF;
12831 bits < 0x7FC0_0000
12832}
12833
12834fn is_f64_arithmetic(bits: u64) -> bool {
12835 let bits = bits & 0x7FFF_FFFF_FFFF_FFFF;
12837 bits < 0x7FF8_0000_0000_0000
12838}