Skip to main content

wasmer_compiler_llvm/translator/
code.rs

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    // stackmap::{StackmapEntry, StackmapEntryKind, StackmapRegistry, ValueSemantic},
9    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
68// Since we want to use module-local tag numbers for landing pads,
69// the catch-all tag can't be zero; we instead use i32::MAX, which
70// is hopefully large enough to not conflict with any real tag.
71// If you have 2 billion tags in a single module, you deserve what you get.
72// ( Arshia: that comment above is AI-generated... AI is savage XD )
73const 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        // The function type, used for the callbacks.
146        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        // We can pass and use the heap pointer (memory #0) only and only if the memory static, that means
151        // the allocated heap is never moved to a different location.
152        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(&section));
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        // Uncomment to print, at the start of the function, the function name.
350        // (poor man's debugger!)
351        //let func_name_str =
352        //    err!(alloca_builder.build_global_string_ptr(&function_name, "function_name"));
353        //
354        //_ = alloca_builder.build_call(
355        //    intrinsics.debug_str,
356        //    &[
357        //        func_name_str.as_pointer_value().into(),
358        //        intrinsics
359        //            .i32_ty
360        //            .const_int(function_name.len() as _, false)
361        //            .into(),
362        //    ],
363        //    "",
364        //);
365
366        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                        // TODO: try caching the lexical scopes (might be a space saver)
453                        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                // Apparently, the default<Os> could be much slower compared to -O1.
493                passes.push("default<O1>");
494            }
495            OptimizationStyle::ForSpeed => {
496                passes.push("sccp");
497                passes.push("early-cse");
498                //passes.push("deadargelim");
499                passes.push("adce");
500                passes.push("sroa");
501                passes.push("aggressive-instcombine");
502                passes.push("jump-threading");
503                //passes.push("ipsccp");
504                passes.push("simplifycfg");
505                passes.push("reassociate");
506                passes.push("loop-rotate");
507                passes.push("indvars");
508                //passes.push("lcssa");
509                //passes.push("licm");
510                //passes.push("instcombine");
511                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("instcombine");
519                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            // `__wasm_apply_data_relocs` can become a very large function made up
557            // mostly of loads and stores, and even `-O1` can spend significant
558            // time optimizing it.
559            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    // Create a vector where each lane contains the same value.
628    fn splat_vector(
629        &self,
630        value: BasicValueEnum<'ctx>,
631        vec_ty: VectorType<'ctx>,
632    ) -> Result<VectorValue<'ctx>, CompileError> {
633        // Use insert_element to insert the element into an undef vector, then use
634        // shuffle vector to copy that lane to all lanes.
635        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    // Convert floating point vector to integer and saturate when out of range.
654    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
655    #[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, // Exclusive (least representable value)
661        upper_bound: u64, // Exclusive (greatest representable value)
662        int_min_value: u64,
663        int_max_value: u64,
664        value: IntValue<'ctx>,
665    ) -> Result<VectorValue<'ctx>, CompileError> {
666        // a) Compare vector with itself to identify NaN lanes.
667        // b) Compare vector with splat of inttofp(upper_bound) to identify
668        //    lanes that need to saturate to max.
669        // c) Compare vector with splat of inttofp(lower_bound) to identify
670        //    lanes that need to saturate to min.
671        // d) Use vector select (not shuffle) to pick from either the
672        //    splat vector or the input vector depending on whether the
673        //    comparison indicates that we have an unrepresentable value. Replace
674        //    unrepresentable values with zero.
675        // e) Now that the value is safe, fpto[su]i it.
676        // f) Use our previous comparison results to replace certain zeros with
677        //    int_min or int_max.
678
679        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    // Convert floating point vector to integer and saturate when out of range.
779    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
780    #[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, // Exclusive (least representable value)
786        upper_bound: u64, // Exclusive (greatest representable value)
787        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    // Convert floating point vector to integer and saturate when out of range.
808    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
809    fn trunc_sat_scalar(
810        &self,
811        int_ty: IntType<'ctx>,
812        lower_bound: u64, // Exclusive (least representable value)
813        upper_bound: u64, // Exclusive (greatest representable value)
814        int_min_value: u64,
815        int_max_value: u64,
816        value: FloatValue<'ctx>,
817    ) -> Result<IntValue<'ctx>, CompileError> {
818        // TODO: this is a scalarized version of the process in trunc_sat. Either
819        // we should merge with trunc_sat, or we should simplify this function.
820
821        // a) Compare value with itself to identify NaN.
822        // b) Compare value inttofp(upper_bound) to identify values that need to
823        //    saturate to max.
824        // c) Compare value with inttofp(lower_bound) to identify values that need
825        //    to saturate to min.
826        // d) Use select to pick from either zero or the input vector depending on
827        //    whether the comparison indicates that we have an unrepresentable
828        //    value.
829        // e) Now that the value is safe, fpto[su]i it.
830        // f) Use our previous comparison results to replace certain zeros with
831        //    int_min or int_max.
832
833        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, // Inclusive (not a trapping value)
928        upper_bound: u64, // Inclusive (not a trapping value)
929        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        // The 'U' in the float predicate is short for "unordered" which means that
952        // the comparison will compare true if either operand is a NaN. Thus, NaNs
953        // are out of bounds.
954        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    // If the value is pending a 64-bit canonicalization, do it now.
1201    // Return a f32x4 vector.
1202    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    // If the value is pending a 32-bit canonicalization, do it now.
1228    // Return a f64x2 vector.
1229    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    // Replaces any NaN with the canonical QNaN, otherwise leaves the value alone.
1297    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 this memory access must trap when out of bounds (i.e. it is a memory
1358            // access written in the user program as opposed to one used by our VM)
1359            // then mark that it can't be deleted.
1360            if let MemoryCache::Static { base_ptr: _ } = self.ctx.memory(
1361                memory_index,
1362                self.intrinsics,
1363                self.module,
1364                self.memory_styles,
1365            )? {
1366                // The best we've got is `volatile`.
1367                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        // Build a dead load (if non-volatile memory operations are disabled) to preserve
1483        // artifacts from partial store operations.
1484        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        // Note the alignment is checked at the libcall side.
1771        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        // Compute the offset into the storage.
1788        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        // Look up the memory base (as pointer) and bounds (as unsigned integer).
1793        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                    // Bounds check it.
1805                    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                        // When the offset is constant, if it's below the minimum
1809                        // memory size, we've statically shown that it's safe.
1810                        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                        // LLVM may have folded this into 'i1 true' in which case we know
1863                        // the pointer is in bounds. LLVM may also have folded it into a
1864                        // constant expression, not known to be either true or false yet.
1865                        // If it's false, unknown-but-constant, or not-a-constant, emit a
1866                        // runtime bounds check. LLVM may yet succeed at optimizing it away.
1867                        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    // Generates a global constant with the tag's module-local index, which can be used
2041    // as the "type info" of a catch clause.
2042    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        // Why set this to a specific section? On macOS it would land on a specific read only data
2064        // section. GOT-based relocations will probably be generated with a non-zero addend, making
2065        // some EH-related intricacies not working.
2066        //
2067        // The general idea is that each tag has its own section, so the GOT-based relocation can
2068        // have a zero addend, i.e. the data of the tag is the first (and only) value in a specific
2069        // section we can target in relocations.
2070        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        // This is an unintuitive spec corner case: a tail call must bypass all enclosing
2086        // try_table blocks in the function. See https://github.com/WebAssembly/exception-handling/issues/249.
2087        //
2088        // The LLVM MustTail is more restrictive than the one defined in the WebAssembly spec.
2089        // WebAssembly types alone are not enough here: the lowered ABI can add hidden arguments
2090        // like `m0` and `sret`, so we must compare the actual LLVM function types instead.
2091        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    // Return sret pointer if the functions needs the hidden argument for multiple return values.
2113    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            //let current_block = self.builder.get_insert_block().unwrap();
2194            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                &params,
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                    &params,
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                &params,
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                &params,
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            &params,
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        // Apply pending canonicalization.
2357        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        // This is an unintuitive spec corner case: a tail call must bypass all enclosing
2418        // try_table blocks in the function. See https://github.com/WebAssembly/exception-handling/issues/249.
2419        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>)>, // Contains params and locals
2463    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    // Control Flow instructions.
2721    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#control-flow-instructions
2722    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                // Pop the loop parameters and canonicalize them in
2787                // pre_loop_block (before the terminator is emitted) so that the
2788                // select instruction dominates the phi uses.
2789                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 each result of the block we're branching to,
2829                // pop a value off the value stack and load it into
2830                // the corresponding phi.
2831                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                // Build else_phis in if_else_block and then_phis in if_then_block.
2978                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                // Pop the condition.
2990                let cond = self.state.pop1()?;
2991
2992                // Pop the block parameters and canonicalize them in current_block
2993                // (before the terminator is emitted) so that the select instruction
2994                // dominates the phi uses.
2995                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                    // Push our own 'else' phi nodes to the stack.
3066                    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                // Push each phi value to the value stack.
3112                for phi in frame.phis() {
3113                    if phi.count_incoming() != 0 {
3114                        self.state.push1(phi.as_basic_value());
3115                    } else {
3116                        // TODO if there are no incoming phi values, it means
3117                        // this block has no predecessors, and we can skip it
3118                        // altogether. However, fixing this is non-trivial as
3119                        // some places in the code rely on code getting generated
3120                        // for unreachable end blocks. For now, we let LLVM remove
3121                        // the block during dead code elimination instead.
3122                        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    // Basic instructions.
3164    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#basic-instructions
3165    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                // Do nothing.
3171            }
3172            Operator::Drop => {
3173                self.state.pop1()?;
3174            }
3175
3176            // Generate const values.
3177            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                // The spec is unclear, we interpret splat as preserving NaN
3307                // payload bits.
3308                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                // The spec is unclear, we interpret splat as preserving NaN
3318                // payload bits.
3319                self.state.push1_extra(res, i);
3320            }
3321
3322            // Operate on self.locals.
3323            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            // `TypedSelect` must be used for extern refs so ref counting should
3415            // be done with TypedSelect. But otherwise they're the same.
3416            Operator::TypedSelect { .. } | Operator::Select => {
3417                let ((v1, i1), (v2, i2), (cond, _)) = self.state.pop3_extra()?;
3418                // We don't bother canonicalizing 'cond' here because we only
3419                // compare it to zero, and that's invariant under
3420                // canonicalization.
3421
3422                // If the pending bits of v1 and v2 are the same, we can pass
3423                // them along to the result. Otherwise, apply pending
3424                // canonicalization now.
3425                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                /*
3491                let func_ptr = self.llvm.functions.borrow_mut()[&func_index];
3492
3493                (params, func_ptr.as_global_value().as_pointer_value())
3494                */
3495                let params = self.state.popn_save_extra(func_type.params().len())?;
3496
3497                // Apply pending canonicalization.
3498                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                    /* For imported functions, we must be careful about when to include `g0_param`:
3521                    imports from another Wasm module expect it, while host-function imports do not.
3522                    We intentionally not leverage tail-calls for such function calls. */
3523                    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                // First, check if the index is outside of the table bounds.
3710                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                    // We assume the table has the `funcref` (pointer to `anyfunc`)
3769                    // element type.
3770                    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                    // a funcref (pointer to `anyfunc`)
3786                    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                        // trap if we're trying to call a null funcref
3795                        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                // Load things from the anyfunc data structure.
3826                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                // Next, check if the table element is initialized.
3858
3859                // TODO: we may not need this check anymore
3860                let elem_initialized = err!(self.builder.build_is_not_null(func_ptr, ""));
3861
3862                // Next, check if the signature id is correct.
3863
3864                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                // Tell llvm that the expected and found signature hashes should match.
3878                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    // Integer Arithmetic instructions.
3975    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-arithmetic-instructions
3976    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                // magic number specified by the spec
4402                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                // PMADDUBSW computes pairwise u8*i8 with i16 saturation, which
4780                // is one of the valid relaxed dot-product behaviors.
4781                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                // "Overflow also leads to undefined behavior; this is a rare
4968                // case, but can occur, for example, by taking the remainder of
4969                // a 32-bit division of -2147483648 by -1. (The remainder
4970                // doesn’t actually overflow, but this rule lets srem be
4971                // implemented using instructions that return both the result
4972                // of the division and the remainder.)"
4973                //   -- https://llvm.org/docs/LangRef.html#srem-instruction
4974                //
4975                // In Wasm, the i32.rem_s i32.const -2147483648 i32.const -1 is
4976                // i32.const 0. We implement this by swapping out the left value
4977                // for 0 in this case.
4978                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                // This approach is faster on x86-64 when the PAVG[BW]
5912                // instructions are available. On other platforms, an alternative
5913                // implementation appears likely to outperform, described here:
5914                //   %a = or %v1, %v2
5915                //   %b = and %a, 1
5916                //   %v1 = lshr %v1, 1
5917                //   %v2 = lshr %v2, 1
5918                //   %sum = add %v1, %v2
5919                //   %res = add %sum, %b
5920
5921                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                // This approach is faster on x86-64 when the PAVG[BW]
5949                // instructions are available. On other platforms, an alternative
5950                // implementation appears likely to outperform, described here:
5951                //   %a = or %v1, %v2
5952                //   %b = and %a, 1
5953                //   %v1 = lshr %v1, 1
5954                //   %v2 = lshr %v2, 1
5955                //   %sum = add %v1, %v2
5956                //   %res = add %sum, %b
5957
5958                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    // Floating-Point Arithmetic instructions.
6090    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-arithmetic-instructions
6091    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                // Pseudo-min: b < a ? b : a
6765                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                // Pseudo-min: b < a ? b : a
6827                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                // Pseudo-max: a < b ? b : a
6935                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                // Pseudo-max: a < b ? b : a
6998                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                // The exact NaN returned by F32Abs is fully defined. Do not
7252                // adjust.
7253                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                // The exact NaN returned by F64Abs is fully defined. Do not
7265                // adjust.
7266                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                // The exact NaN returned by F32x4Abs is fully defined. Do not
7285                // adjust.
7286                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                // The exact NaN returned by F32x4Abs is fully defined. Do not
7305                // adjust.
7306                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                // The exact NaN returned by F32x4Neg is fully defined. Do not
7324                // adjust.
7325                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                // The exact NaN returned by F64x2Neg is fully defined. Do not
7343                // adjust.
7344                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                // The exact NaN returned by F32Neg and F64Neg are fully defined.
7353                // Do not adjust.
7354                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                // The exact NaN returned by F32Copysign is fully defined.
7369                // Do not adjust.
7370                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                // The exact NaN returned by F32Copysign is fully defined.
7385                // Do not adjust.
7386                self.state.push1_extra(res, mag_info.strip_pending());
7387            }
7388            _ => unreachable!(),
7389        }
7390        Ok(())
7391    }
7392
7393    // Integer Comparison instructions.
7394    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-comparison-instructions
7395    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    // Floating-Point Comparison instructions.
8195    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-comparison-instructions
8196    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    // Conversion instructions.
8519    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#conversion-instructions
8520    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::I64x2TruncSatF64x2S => {
9249            //     let (v, i) = self.state.pop1_extra()?;
9250            //     let v = self.apply_pending_canonicalization(v, i)?;
9251            //     let v = v.into_int_value();
9252            //     let res = self.trunc_sat_into_int(
9253            //         self.intrinsics.f64x2_ty,
9254            //         self.intrinsics.i64x2_ty,
9255            //         i64::MIN as u64,
9256            //         i64::MAX as u64,
9257            //         i64::MIN as u64,
9258            //         i64::MAX as u64,
9259            //         v,
9260            //     )?;
9261            //     self.state.push1(res);
9262            // }
9263            // Operator::I64x2TruncSatF64x2U => {
9264            //     let (v, i) = self.state.pop1_extra()?;
9265            //     let v = self.apply_pending_canonicalization(v, i)?;
9266            //     let v = v.into_int_value();
9267            //     let res = self.trunc_sat_into_int(
9268            //         self.intrinsics.f64x2_ty,
9269            //         self.intrinsics.i64x2_ty,
9270            //         u64::MIN,
9271            //         u64::MAX,
9272            //         u64::MIN,
9273            //         u64::MAX,
9274            //         v,
9275            //     )?;
9276            //     self.state.push1(res);
9277            // }
9278            Operator::I32TruncF32S => {
9279                let v1 = self.state.pop1()?.into_float_value();
9280                self.trap_if_not_representable_as_int(
9281                    0xcf000000, // -2147483600.0
9282                    0x4effffff, // 2147483500.0
9283                    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, // -2147483648.9999995
9296                    0x41dfffffffffffff, // 2147483647.9999998
9297                    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, // -9223372000000000000.0
9338                    0x5effffff, // 9223371500000000000.0
9339                    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, // -9223372036854776000.0
9352                    0x43dfffffffffffff, // 9223372036854775000.0
9353                    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, // -0.99999994
9394                    0x4f7fffff, // 4294967000.0
9395                    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, // -0.9999999999999999
9408                    0x41efffffffffffff, // 4294967295.9999995
9409                    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, // -0.99999994
9450                    0x5f7fffff, // 18446743000000000000.0
9451                    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, // -0.9999999999999999
9464                    0x43efffffffffffff, // 18446744073709550000.0
9465                    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::F64x2ConvertI64x2S => {
9685            //     let v = self.state.pop1()?;
9686            //     let v = self
9687            //         .builder
9688            //         .build_bit_cast(v, self.intrinsics.i64x2_ty, "")
9689            //         .into_vector_value();
9690            //     let res = self
9691            //         .builder
9692            //         .build_signed_int_to_float(v, self.intrinsics.f64x2_ty, "");
9693            //     let res = check_err!(self.builder.build_bit_cast(res, self.intrinsics.i128_ty, ""));
9694            //     self.state.push1(res);
9695            // }
9696            // Operator::F64x2ConvertI64x2U => {
9697            //     let v = self.state.pop1()?;
9698            //     let v = self
9699            //         .builder
9700            //         .build_bit_cast(v, self.intrinsics.i64x2_ty, "")
9701            //         .into_vector_value();
9702            //     let res = self
9703            //         .builder
9704            //         .build_unsigned_int_to_float(v, self.intrinsics.f64x2_ty, "");
9705            //     let res = check_err!(self.builder.build_bit_cast(res, self.intrinsics.i128_ty, ""));
9706            //     self.state.push1(res);
9707            // }
9708            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    // Sign-extension operators.
9736    // https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md
9737    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    // Load and Store instructions.
9815    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#load-and-store-instructions
9816    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                // | Operator::I64x2AnyTrue
10175                // Skip canonicalization, it never changes non-zero values to zero or vice versa.
10176                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                //size.add_attribute(AttributeLoc::Function, self.intrinsics.readonly);
10757                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    // Atomic memory operations.
10831    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                // Fence is a nop.
10837                //
10838                // Fence was added to preserve information about fences from
10839                // source languages. If in the future Wasm extends the memory
10840                // model, and if we hadn't recorded what fences used to be there,
10841                // it would lead to data races that weren't present in the
10842                // original source language.
10843            }
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    // Reference types.
11395    // https://github.com/WebAssembly/reference-types/blob/master/proposals/reference-types/Overview.md
11396    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    // Table operators.
11445    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    // Exception handling.
11628    // https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md
11629    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                // Collect unique catches. It is not a "hard" error on the wasm side,
11662                // but LLVM will definitely complain about having the same identifier
11663                // match two different branches in the switch below.
11664                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                // Build the landing pad.
11674                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                // Since jumping between landingpads is not possible, we need to collect
11692                // all tags from outer try_tables as well to build a clause for *every*
11693                // possible tag that might be caught.
11694                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                // If there are no catch clauses, we have to skip everything, since
11713                // an lpad without catch clauses is invalid (and won't ever be jumped
11714                // to anyway)
11715                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                    // The pre-selector can be either 0 (for catch-all) or 1 (for a
11745                    // specific, but as-yet-unknown tag).
11746                    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                    // Now we're done looking at the exception, it's time to deallocate and get
11789                    // the exnref out of it. When an exception is caught, "rethrowing" simply
11790                    // means starting another unwind by calling _Unwind_RaiseException with the
11791                    // same exception bits. Instead of keeping the same exception around, we
11792                    // deallocate the exception once it's caught, and if we need to rethrow, we
11793                    // just re-allocate a new exception.
11794                    //
11795                    // Note that this is different from how it's done in C++ land, where the
11796                    // exception object is kept around for rethrowing; this discrepancy exists
11797                    // because in C++, exception handling is lexical (i.e. there's an implicit
11798                    // "current exception" in catch blocks) whereas in WASM, you rethrow with
11799                    // an exnref that may very well have come from somewhere else; consider this
11800                    // (badly implemented and erroneous) pseudo-module:
11801                    //
11802                    // (module
11803                    //   (global $e (mut exnref) (ref.null exn))
11804                    //   ;; Store the given exnref, return the previous one
11805                    //   (func $delay_exnref (param exnref) (result exnref)
11806                    //     (global.get $e)
11807                    //     (local.get 0)
11808                    //     (global.set $e)
11809                    //   )
11810                    //   (func foo
11811                    //     (block $catch (result exnref)
11812                    //       (try_table (catch_all_ref $catch)
11813                    //         ...
11814                    //       )
11815                    //     )
11816                    //     (call $delay_exnref) ;; store the exnref caught above
11817                    //     throw_ref ;; throw the previous exnref
11818                    //   )
11819                    // )
11820                    //
11821                    // Here, it's impossible to reuse the same exception object since the
11822                    // exnref given to throw_ref is a different one than the one we caught
11823                    // with the try_table.
11824                    //
11825                    // Another difference is that C++ exceptions may well carry lots of data
11826                    // around; a WASM exception is just an exnref, backed by a u32, which is
11827                    // just 4 bytes, and is cheap to reallocate. C++ exceptions may also carry
11828                    // things with dtors around; another thing that doesn't exist in WASM.
11829                    //
11830                    // All of this is to say that putting exception deallocation and exnref
11831                    // retrieval in the same function has been a very deliberate choice.
11832                    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                                // Get the payload pointer.
11873                                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                                // Read each value from the data ptr.
11884                                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                                // Get the payload pointer.
11936                                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                                // Read each value from the data ptr.
11947                                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                    // -- end
12039
12040                    // -- The rethrow block
12041                    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                    // can't reach after an explicit throw!
12049                    err!(self.builder.build_unreachable());
12050
12051                    maybe_lpad_block = Some(lpad_block);
12052                }
12053
12054                // Move back to current block
12055                self.builder.position_at_end(current_block);
12056
12057                // Note: catch_tag_values also contains outer tags, but zipping with
12058                // catch_blocks will let us ignore the extra ones.
12059                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                // Allocate the necessary bytes for the exception.
12104                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                    // can't reach after an explicit throw!
12156                    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                    // can't reach after an explicit throw!
12166                    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                    // can't reach after an explicit throw!
12194                    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                    // can't reach after an explicit throw!
12204                    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        //let opcode_offset: Option<usize> = None;
12216
12217        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        // https://five-embeddev.com/riscv-user-isa-manual/Priv-v1.12/rv64.html
12803        // > The compiler and calling convention maintain an invariant that all 32-bit values are held in a sign-extended format in 64-bit registers.
12804        // > Even 32-bit unsigned integers extend bit 31 into bits 63 through 32. Consequently, conversion between unsigned and signed 32-bit integers
12805        // > is a no-op, as is conversion from a signed 32-bit integer to a signed 64-bit integer.
12806        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    // Mask off sign bit.
12830    let bits = bits & 0x7FFF_FFFF;
12831    bits < 0x7FC0_0000
12832}
12833
12834fn is_f64_arithmetic(bits: u64) -> bool {
12835    // Mask off sign bit.
12836    let bits = bits & 0x7FFF_FFFF_FFFF_FFFF;
12837    bits < 0x7FF8_0000_0000_0000
12838}