wasmer_compiler_llvm/translator/
code.rs

1use std::num::NonZero;
2use std::{collections::HashMap, path::Path};
3
4use super::{
5    intrinsics::{
6        CtxType, FunctionCache, GlobalCache, Intrinsics, MemoryCache, tbaa_label, type_to_llvm,
7    },
8    // 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::{Abi, get_abi},
38    config::LLVM,
39    error::{err, err_nt},
40    object_file::load_object_file,
41};
42use wasmer_compiler::{
43    CANONICAL_NAN_F32, CANONICAL_NAN_F64, FunctionBinaryReader, FunctionBodyData,
44    GEF32_LEQ_I32_MAX, GEF32_LEQ_I64_MAX, GEF32_LEQ_U32_MAX, GEF32_LEQ_U64_MAX, GEF64_LEQ_I32_MAX,
45    GEF64_LEQ_I64_MAX, GEF64_LEQ_U32_MAX, GEF64_LEQ_U64_MAX, LEF32_GEQ_I32_MIN, LEF32_GEQ_I64_MIN,
46    LEF32_GEQ_U32_MIN, LEF32_GEQ_U64_MIN, LEF64_GEQ_I32_MIN, LEF64_GEQ_I64_MIN, LEF64_GEQ_U32_MIN,
47    LEF64_GEQ_U64_MIN, MiddlewareBinaryReader, ModuleMiddlewareChain, ModuleTranslationState,
48    from_binaryreadererror_wasmerror,
49    misc::{CompiledFunctionExt, CompiledKind},
50    types::{
51        relocation::RelocationTarget,
52        symbols::{Symbol, SymbolRegistry},
53    },
54    wasmparser::{Catch, MemArg, Operator},
55    wpheaptype_to_type, wptype_to_type,
56};
57use wasmer_types::{
58    CompileError, FunctionIndex, FunctionType, GlobalIndex, LocalFunctionIndex, MemoryIndex,
59    ModuleInfo, SignatureHash, SignatureIndex, TableIndex, Type, target::CpuFeature,
60};
61use wasmer_types::{TagIndex, entity::PrimaryMap};
62use wasmer_vm::{MemoryStyle, TableStyle, VMOffsets};
63
64const FUNCTION_SECTION_ELF: &str = "__TEXT,wasmer_function";
65const FUNCTION_SECTION_MACHO: &str = "__TEXT";
66const FUNCTION_SEGMENT_MACHO: &str = "wasmer_function";
67
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: Box<dyn Abi>,
80    binary_fmt: BinaryFormat,
81    func_section: String,
82    pointer_width: u8,
83    cpu_features: EnumSet<CpuFeature>,
84    non_volatile_memory_ops: bool,
85    wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
86}
87
88impl wasmer_compiler::FuncTranslator for FuncTranslator {}
89
90impl FuncTranslator {
91    pub fn new(
92        target_triple: Triple,
93        target_machines: HashMap<OptimizationStyle, TargetMachine>,
94        binary_fmt: BinaryFormat,
95        pointer_width: u8,
96        cpu_features: EnumSet<CpuFeature>,
97        non_volatile_memory_ops: bool,
98        wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
99    ) -> Result<Self, CompileError> {
100        let abi_source_tm = target_machines
101            .get(&OptimizationStyle::ForSpeed)
102            .expect("target_machines must contain OptimizationStyle::ForSpeed");
103        let abi = get_abi(abi_source_tm);
104        Ok(Self {
105            ctx: Context::create(),
106            target_triple,
107            target_machines,
108            abi,
109            func_section: match binary_fmt {
110                BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
111                BinaryFormat::Macho => FUNCTION_SEGMENT_MACHO.to_string(),
112                _ => {
113                    return Err(CompileError::UnsupportedTarget(format!(
114                        "Unsupported binary format: {binary_fmt:?}"
115                    )));
116                }
117            },
118            binary_fmt,
119            pointer_width,
120            cpu_features,
121            non_volatile_memory_ops,
122            wasm_apply_data_relocs_fn_index,
123        })
124    }
125
126    #[allow(clippy::too_many_arguments)]
127    pub fn translate_to_module(
128        &self,
129        wasm_module: &ModuleInfo,
130        module_translation: &ModuleTranslationState,
131        signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
132        local_func_index: &LocalFunctionIndex,
133        function_body: &FunctionBodyData,
134        config: &LLVM,
135        memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
136        _table_styles: &PrimaryMap<TableIndex, TableStyle>,
137        symbol_registry: &dyn SymbolRegistry,
138        target: &Triple,
139        opt_style: OptimizationStyle,
140    ) -> Result<Module<'_>, CompileError> {
141        // The function type, used for the callbacks.
142        let func_index = wasm_module.func_index(*local_func_index);
143        let function =
144            CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
145
146        // We can pass and use the heap pointer (memory #0) only and only if the memory static, that means
147        // the allocated heap is never moved to a different location.
148        let m0_is_enabled = memory_styles
149            .get(MemoryIndex::from_u32(0))
150            .is_some_and(|memory| matches!(memory, MemoryStyle::Static { .. }));
151
152        let (function_name, module_name) = if cfg!(feature = "experimental-artifact") {
153            (function.linkage_name(), String::new())
154        } else {
155            let function_name =
156                symbol_registry.symbol_to_name(Symbol::LocalFunction(*local_func_index));
157            let module_name = match wasm_module.name.as_ref() {
158                None => format!("<anonymous module> function {function_name}"),
159                Some(module_name) => format!("module {module_name} function {function_name}"),
160            };
161            (function_name, module_name)
162        };
163
164        let module = self.ctx.create_module(module_name.as_str());
165
166        let target_machine = &self.target_machines.values().next().unwrap();
167        let target_triple = target_machine.get_triple();
168        let target_data = target_machine.get_target_data();
169        module.set_triple(&target_triple);
170        module.set_data_layout(&target_data.get_data_layout());
171        let wasm_fn_type = wasm_module
172            .signatures
173            .get(wasm_module.functions[func_index])
174            .unwrap();
175
176        let offsets = VMOffsets::new(self.pointer_width, wasm_module);
177        let intrinsics = Intrinsics::declare(
178            &module,
179            &self.ctx,
180            &target_data,
181            &self.target_triple,
182            &self.binary_fmt,
183        );
184        let (func_type, func_attrs) = self.abi.func_type_to_llvm(
185            &self.ctx,
186            &intrinsics,
187            Some(&offsets),
188            wasm_fn_type,
189            m0_is_enabled,
190        )?;
191
192        let func = module.add_function(&function_name, func_type, Some(Linkage::External));
193        let debug_info = if cfg!(feature = "experimental-artifact") {
194            let debug_metadata_version = self
195                .ctx
196                .i32_type()
197                .const_int(inkwell::debug_info::debug_metadata_version().into(), false);
198            module.add_basic_value_flag(
199                "Debug Info Version",
200                FlagBehavior::Warning,
201                debug_metadata_version,
202            );
203            module.add_basic_value_flag(
204                "Dwarf Version",
205                FlagBehavior::Warning,
206                self.ctx.i32_type().const_int(4, false),
207            );
208
209            let (dibuilder, compile_unit) = module.create_debug_info_builder(
210                true,
211                DWARFSourceLanguage::C,
212                &wasm_module.name(),
213                ".",
214                "wasmer",
215                true,
216                "",
217                0,
218                "",
219                DWARFEmissionKind::Full,
220                0,
221                false,
222                false,
223                "",
224                "",
225            );
226            let subroutine_type = dibuilder.create_subroutine_type(
227                compile_unit.get_file(),
228                None,
229                &[],
230                DIFlags::PUBLIC,
231            );
232            let function_name = wasm_module.get_function_name(func_index);
233            let start_line = (function_body.module_offset as u32).saturating_add(1);
234            let subprogram = dibuilder.create_function(
235                compile_unit.as_debug_info_scope(),
236                &function_name,
237                None,
238                compile_unit.get_file(),
239                start_line,
240                subroutine_type,
241                false,
242                true,
243                start_line,
244                DIFlags::PUBLIC,
245                true,
246            );
247            func.set_subprogram(subprogram);
248            Some((dibuilder, subprogram))
249        } else {
250            None
251        };
252        for (attr, attr_loc) in &func_attrs {
253            func.add_attribute(*attr_loc, *attr);
254        }
255
256        if !matches!(target.operating_system, OperatingSystem::Windows) {
257            func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe);
258        }
259
260        func.add_attribute(AttributeLoc::Function, intrinsics.uwtable);
261        func.add_attribute(AttributeLoc::Function, intrinsics.frame_pointer);
262
263        let section = match self.binary_fmt {
264            BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
265            BinaryFormat::Macho => {
266                format!("{FUNCTION_SECTION_MACHO},{FUNCTION_SEGMENT_MACHO}")
267            }
268            _ => {
269                return Err(CompileError::UnsupportedTarget(format!(
270                    "Unsupported binary format: {:?}",
271                    self.binary_fmt
272                )));
273            }
274        };
275
276        func.set_personality_function(intrinsics.personality);
277        if !cfg!(feature = "experimental-artifact") {
278            func.as_global_value().set_section(Some(&section));
279        }
280
281        func.set_linkage(Linkage::DLLExport);
282        func.as_global_value()
283            .set_dll_storage_class(DLLStorageClass::Export);
284
285        let entry = self.ctx.append_basic_block(func, "entry");
286        let start_of_code = self.ctx.append_basic_block(func, "start_of_code");
287        let return_ = self.ctx.append_basic_block(func, "return");
288        let alloca_builder = self.ctx.create_builder();
289        let cache_builder = self.ctx.create_builder();
290        let builder = self.ctx.create_builder();
291        cache_builder.position_at_end(entry);
292        let br = err!(cache_builder.build_unconditional_branch(start_of_code));
293        alloca_builder.position_before(&br);
294        cache_builder.position_before(&br);
295        builder.position_at_end(start_of_code);
296
297        let mut state = State::new();
298        builder.position_at_end(return_);
299        let phis: SmallVec<[PhiValue; 1]> = wasm_fn_type
300            .results()
301            .iter()
302            .map(|&wasm_ty| {
303                type_to_llvm(&intrinsics, wasm_ty).map(|ty| builder.build_phi(ty, "").unwrap())
304            })
305            .collect::<Result<_, _>>()?;
306        state.push_block(return_, phis, 0);
307        builder.position_at_end(start_of_code);
308
309        let mut reader = MiddlewareBinaryReader::new_with_offset(
310            function_body.data,
311            function_body.module_offset,
312        );
313        reader.set_middleware_chain(
314            config
315                .middlewares
316                .generate_function_middleware_chain(*local_func_index),
317        );
318
319        let mut params = vec![];
320        let first_param =
321            if func_type.get_return_type().is_none() && wasm_fn_type.results().len() > 1 {
322                if m0_is_enabled { 3 } else { 2 }
323            } else if m0_is_enabled {
324                2
325            } else {
326                1
327            };
328        let mut is_first_alloca = true;
329        let mut insert_alloca = |ty, name: String| -> Result<PointerValue, CompileError> {
330            let alloca = err!(alloca_builder.build_alloca(ty, &name));
331            if is_first_alloca {
332                alloca_builder.position_at(entry, &alloca.as_instruction_value().unwrap());
333                is_first_alloca = false;
334            }
335            Ok(alloca)
336        };
337
338        // Uncomment to print, at the start of the function, the function name.
339        // (poor man's debugger!)
340        //let func_name_str =
341        //    err!(alloca_builder.build_global_string_ptr(&function_name, "function_name"));
342        //
343        //_ = alloca_builder.build_call(
344        //    intrinsics.debug_str,
345        //    &[
346        //        func_name_str.as_pointer_value().into(),
347        //        intrinsics
348        //            .i32_ty
349        //            .const_int(function_name.len() as _, false)
350        //            .into(),
351        //    ],
352        //    "",
353        //);
354
355        for idx in 0..wasm_fn_type.params().len() {
356            let ty = wasm_fn_type.params()[idx];
357            let ty = type_to_llvm(&intrinsics, ty)?;
358            let value = func
359                .get_nth_param((idx as u32).checked_add(first_param).unwrap())
360                .unwrap();
361            let alloca = insert_alloca(ty, format!("param_{idx}"))?;
362            err!(cache_builder.build_store(alloca, value));
363            params.push((ty, alloca));
364        }
365
366        let mut locals = vec![];
367        let num_locals = reader.read_local_count()?;
368        for idx in 0..num_locals {
369            let (count, ty) = reader.read_local_decl()?;
370            let ty = err!(wptype_to_type(ty));
371            let ty = type_to_llvm(&intrinsics, ty)?;
372            for _ in 0..count {
373                let alloca = insert_alloca(ty, format!("local_{idx}"))?;
374                err!(cache_builder.build_store(alloca, ty.const_zero()));
375                locals.push((ty, alloca));
376            }
377        }
378
379        let mut params_locals = params.clone();
380        params_locals.extend(locals.iter().cloned());
381
382        let mut m0_param = None;
383
384        if m0_is_enabled {
385            let m0 = self.abi.get_m0_ptr_param(&func);
386            m0.set_name("m0_base_ptr");
387            m0_param = Some(m0);
388        }
389
390        let mut fcg = LLVMFunctionCodeGenerator {
391            m0_param,
392            context: &self.ctx,
393            builder,
394            alloca_builder,
395            intrinsics: &intrinsics,
396            target_data: &target_data,
397            state,
398            function: func,
399            locals: params_locals,
400            ctx: CtxType::new(
401                wasm_module,
402                &func,
403                &cache_builder,
404                &*self.abi,
405                self.pointer_width,
406                m0_param,
407            ),
408            unreachable_depth: 0,
409            memory_styles,
410            _table_styles,
411            module: &module,
412            module_translation,
413            signature_hashes,
414            wasm_module,
415            symbol_registry,
416            abi: &*self.abi,
417            config,
418            target_triple: self.target_triple.clone(),
419            tags_cache: HashMap::new(),
420            binary_fmt: self.binary_fmt,
421            cpu_features: self.cpu_features,
422            non_volatile_memory_ops: self.non_volatile_memory_ops,
423        };
424
425        fcg.ctx.add_func(
426            func_index,
427            func.as_global_value().as_pointer_value(),
428            func_type,
429            fcg.ctx.basic(),
430            &func_attrs,
431        );
432
433        while fcg.state.has_control_frames() {
434            let pos = reader.current_position() as u32;
435            let original_pos = reader.original_position() as u32;
436            let op = reader.read_operator()?;
437            if let Some((dibuilder, subprogram)) = debug_info.as_ref() {
438                let line = original_pos.saturating_add(1);
439                let loc = dibuilder.create_debug_location(
440                    &self.ctx,
441                    line,
442                    1,
443                    subprogram.as_debug_info_scope(),
444                    None,
445                );
446                fcg.builder.set_current_debug_location(loc);
447            }
448            fcg.translate_operator(op, pos)?;
449        }
450
451        fcg.finalize(wasm_fn_type)?;
452        if let Some((dibuilder, _)) = debug_info {
453            dibuilder.finalize();
454        }
455
456        if let Some(ref callbacks) = config.callbacks {
457            callbacks.preopt_ir(&function, &wasm_module.hash_string(), &module);
458        }
459
460        let mut passes = vec![];
461        if config.enable_verifier {
462            passes.push("verify");
463        }
464
465        match opt_style {
466            OptimizationStyle::Disabled => {
467                passes.push("default<O0>");
468            }
469            OptimizationStyle::ForSize => {
470                // Apparently, the default<Os> could be much slower compared to -O1.
471                passes.push("default<O1>");
472            }
473            OptimizationStyle::ForSpeed => {
474                passes.push("sccp");
475                passes.push("early-cse");
476                //passes.push("deadargelim");
477                passes.push("adce");
478                passes.push("sroa");
479                passes.push("aggressive-instcombine");
480                passes.push("jump-threading");
481                //passes.push("ipsccp");
482                passes.push("simplifycfg");
483                passes.push("reassociate");
484                passes.push("loop-rotate");
485                passes.push("indvars");
486                //passes.push("lcssa");
487                //passes.push("licm");
488                //passes.push("instcombine");
489                passes.push("sccp");
490                passes.push("reassociate");
491                passes.push("simplifycfg");
492                passes.push("gvn");
493                passes.push("memcpyopt");
494                passes.push("dse");
495                passes.push("dce");
496                //passes.push("instcombine");
497                passes.push("reassociate");
498                passes.push("simplifycfg");
499                passes.push("mem2reg");
500            }
501        }
502
503        module
504            .run_passes(
505                &passes.join(","),
506                target_machine,
507                PassBuilderOptions::create(),
508            )
509            .unwrap();
510
511        if let Some(ref callbacks) = config.callbacks {
512            callbacks.postopt_ir(&function, &wasm_module.hash_string(), &module);
513        }
514
515        Ok(module)
516    }
517
518    #[allow(clippy::too_many_arguments)]
519    pub fn translate(
520        &self,
521        wasm_module: &ModuleInfo,
522        module_translation: &ModuleTranslationState,
523        signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
524        local_func_index: &LocalFunctionIndex,
525        function_body: &FunctionBodyData,
526        config: &LLVM,
527        memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
528        table_styles: &PrimaryMap<TableIndex, TableStyle>,
529        symbol_registry: &ModuleBasedSymbolRegistry,
530        target: &Triple,
531        build_directory: &Path,
532    ) -> Result<CompiledFunction, CompileError> {
533        let func_index = wasm_module.func_index(*local_func_index);
534        let opt_style = if Some(func_index) == self.wasm_apply_data_relocs_fn_index {
535            // `__wasm_apply_data_relocs` can become a very large function made up
536            // mostly of loads and stores, and even `-O1` can spend significant
537            // time optimizing it.
538            OptimizationStyle::Disabled
539        } else if function_body.data.len() as u64 > WASM_LARGE_FUNCTION_THRESHOLD {
540            OptimizationStyle::ForSize
541        } else {
542            OptimizationStyle::ForSpeed
543        };
544        let module = self.translate_to_module(
545            wasm_module,
546            module_translation,
547            signature_hashes,
548            local_func_index,
549            function_body,
550            config,
551            memory_styles,
552            table_styles,
553            symbol_registry,
554            target,
555            opt_style,
556        )?;
557        let function =
558            CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
559
560        let target_machine = self.target_machines.get(&opt_style).unwrap();
561        let memory_buffer = target_machine
562            .write_to_memory_buffer(&module, FileType::Object)
563            .unwrap();
564
565        if let Some(ref callbacks) = config.callbacks {
566            let module_hash = wasm_module.hash().map(|m| m.to_string());
567            callbacks.obj_memory_buffer(&function, &module_hash, &memory_buffer);
568            let asm_buffer = target_machine
569                .write_to_memory_buffer(&module, FileType::Assembly)
570                .unwrap();
571            callbacks.asm_memory_buffer(&function, &module_hash, &asm_buffer)
572        }
573
574        if cfg!(feature = "experimental-artifact") {
575            let object_path = build_directory
576                .to_path_buf()
577                .join(function.object_filename());
578            std::fs::write(&object_path, memory_buffer.as_slice())
579                .map_err(|e| CompileError::Codegen(format!("Cannot save LLVM object file: {e}")))?;
580            Ok(CompiledFunction::Elf(object_path))
581        } else {
582            Ok(CompiledFunction::Rkyv(Box::new(load_object_file(
583                memory_buffer.as_slice(),
584                &self.func_section,
585                RelocationTarget::LocalFunc(*local_func_index),
586                |name: &str| {
587                    Ok({
588                        let name = if matches!(self.binary_fmt, BinaryFormat::Macho) {
589                            name.strip_prefix("_").unwrap_or(name)
590                        } else {
591                            name
592                        }
593                        .to_string();
594                        if let Some(Symbol::LocalFunction(local_func_index)) =
595                            symbol_registry.name_to_symbol(&name)
596                        {
597                            Some(RelocationTarget::LocalFunc(local_func_index))
598                        } else {
599                            None
600                        }
601                    })
602                },
603                self.binary_fmt,
604                &self.target_triple,
605            )?)))
606        }
607    }
608}
609
610impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
611    // Create a vector where each lane contains the same value.
612    fn splat_vector(
613        &self,
614        value: BasicValueEnum<'ctx>,
615        vec_ty: VectorType<'ctx>,
616    ) -> Result<VectorValue<'ctx>, CompileError> {
617        // Use insert_element to insert the element into an undef vector, then use
618        // shuffle vector to copy that lane to all lanes.
619        err_nt!(
620            self.builder.build_shuffle_vector(
621                err!(self.builder.build_insert_element(
622                    vec_ty.get_undef(),
623                    value,
624                    self.intrinsics.i32_zero,
625                    "",
626                )),
627                vec_ty.get_undef(),
628                self.intrinsics
629                    .i32_ty
630                    .vec_type(vec_ty.get_size())
631                    .const_zero(),
632                "",
633            )
634        )
635    }
636
637    // Convert floating point vector to integer and saturate when out of range.
638    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
639    #[allow(clippy::too_many_arguments)]
640    fn trunc_sat<T: FloatMathType<'ctx>>(
641        &self,
642        fvec_ty: T,
643        ivec_ty: T::MathConvType,
644        lower_bound: u64, // Exclusive (least representable value)
645        upper_bound: u64, // Exclusive (greatest representable value)
646        int_min_value: u64,
647        int_max_value: u64,
648        value: IntValue<'ctx>,
649    ) -> Result<VectorValue<'ctx>, CompileError> {
650        // a) Compare vector with itself to identify NaN lanes.
651        // b) Compare vector with splat of inttofp(upper_bound) to identify
652        //    lanes that need to saturate to max.
653        // c) Compare vector with splat of inttofp(lower_bound) to identify
654        //    lanes that need to saturate to min.
655        // d) Use vector select (not shuffle) to pick from either the
656        //    splat vector or the input vector depending on whether the
657        //    comparison indicates that we have an unrepresentable value. Replace
658        //    unrepresentable values with zero.
659        // e) Now that the value is safe, fpto[su]i it.
660        // f) Use our previous comparison results to replace certain zeros with
661        //    int_min or int_max.
662
663        let fvec_ty = fvec_ty.as_basic_type_enum().into_vector_type();
664        let ivec_ty = ivec_ty.as_basic_type_enum().into_vector_type();
665        let fvec_element_ty = fvec_ty.get_element_type().into_float_type();
666        let ivec_element_ty = ivec_ty.get_element_type().into_int_type();
667
668        let is_signed = int_min_value != 0;
669        let int_min_value = self.splat_vector(
670            ivec_element_ty
671                .const_int(int_min_value, is_signed)
672                .as_basic_value_enum(),
673            ivec_ty,
674        )?;
675        let int_max_value = self.splat_vector(
676            ivec_element_ty
677                .const_int(int_max_value, is_signed)
678                .as_basic_value_enum(),
679            ivec_ty,
680        )?;
681        let lower_bound = if is_signed {
682            err!(self.builder.build_signed_int_to_float(
683                ivec_element_ty.const_int(lower_bound, is_signed),
684                fvec_element_ty,
685                "",
686            ))
687        } else {
688            err!(self.builder.build_unsigned_int_to_float(
689                ivec_element_ty.const_int(lower_bound, is_signed),
690                fvec_element_ty,
691                "",
692            ))
693        };
694        let upper_bound = if is_signed {
695            err!(self.builder.build_signed_int_to_float(
696                ivec_element_ty.const_int(upper_bound, is_signed),
697                fvec_element_ty,
698                "",
699            ))
700        } else {
701            err!(self.builder.build_unsigned_int_to_float(
702                ivec_element_ty.const_int(upper_bound, is_signed),
703                fvec_element_ty,
704                "",
705            ))
706        };
707
708        let value = err!(self.builder.build_bit_cast(value, fvec_ty, "")).into_vector_value();
709        let zero = fvec_ty.const_zero();
710        let lower_bound = self.splat_vector(lower_bound.as_basic_value_enum(), fvec_ty)?;
711        let upper_bound = self.splat_vector(upper_bound.as_basic_value_enum(), fvec_ty)?;
712        let nan_cmp =
713            err!(
714                self.builder
715                    .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
716            );
717        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
718            FloatPredicate::OGT,
719            value,
720            upper_bound,
721            "above_upper_bound",
722        ));
723        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
724            FloatPredicate::OLT,
725            value,
726            lower_bound,
727            "below_lower_bound",
728        ));
729        let not_representable = err!(self.builder.build_or(
730            err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
731            below_lower_bound_cmp,
732            "not_representable_as_int",
733        ));
734        let value =
735            err!(
736                self.builder
737                    .build_select(not_representable, zero, value, "safe_to_convert")
738            )
739            .into_vector_value();
740        let value = if is_signed {
741            self.builder
742                .build_float_to_signed_int(value, ivec_ty, "as_int")
743        } else {
744            self.builder
745                .build_float_to_unsigned_int(value, ivec_ty, "as_int")
746        };
747
748        let value = err!(value);
749        let value =
750            err!(
751                self.builder
752                    .build_select(above_upper_bound_cmp, int_max_value, value, "")
753            )
754            .into_vector_value();
755        err_nt!(
756            self.builder
757                .build_select(below_lower_bound_cmp, int_min_value, value, "")
758                .map(|v| v.into_vector_value())
759        )
760    }
761
762    // Convert floating point vector to integer and saturate when out of range.
763    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
764    #[allow(clippy::too_many_arguments)]
765    fn trunc_sat_into_int<T: FloatMathType<'ctx>>(
766        &self,
767        fvec_ty: T,
768        ivec_ty: T::MathConvType,
769        lower_bound: u64, // Exclusive (least representable value)
770        upper_bound: u64, // Exclusive (greatest representable value)
771        int_min_value: u64,
772        int_max_value: u64,
773        value: IntValue<'ctx>,
774    ) -> Result<IntValue<'ctx>, CompileError> {
775        let res = self.trunc_sat(
776            fvec_ty,
777            ivec_ty,
778            lower_bound,
779            upper_bound,
780            int_min_value,
781            int_max_value,
782            value,
783        )?;
784        err_nt!(
785            self.builder
786                .build_bit_cast(res, self.intrinsics.i128_ty, "")
787                .map(|v| v.into_int_value())
788        )
789    }
790
791    // Convert floating point vector to integer and saturate when out of range.
792    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
793    fn trunc_sat_scalar(
794        &self,
795        int_ty: IntType<'ctx>,
796        lower_bound: u64, // Exclusive (least representable value)
797        upper_bound: u64, // Exclusive (greatest representable value)
798        int_min_value: u64,
799        int_max_value: u64,
800        value: FloatValue<'ctx>,
801    ) -> Result<IntValue<'ctx>, CompileError> {
802        // TODO: this is a scalarized version of the process in trunc_sat. Either
803        // we should merge with trunc_sat, or we should simplify this function.
804
805        // a) Compare value with itself to identify NaN.
806        // b) Compare value inttofp(upper_bound) to identify values that need to
807        //    saturate to max.
808        // c) Compare value with inttofp(lower_bound) to identify values that need
809        //    to saturate to min.
810        // d) Use select to pick from either zero or the input vector depending on
811        //    whether the comparison indicates that we have an unrepresentable
812        //    value.
813        // e) Now that the value is safe, fpto[su]i it.
814        // f) Use our previous comparison results to replace certain zeros with
815        //    int_min or int_max.
816
817        let is_signed = int_min_value != 0;
818        let int_min_value = int_ty.const_int(int_min_value, is_signed);
819        let int_max_value = int_ty.const_int(int_max_value, is_signed);
820
821        let lower_bound = if is_signed {
822            err!(self.builder.build_signed_int_to_float(
823                int_ty.const_int(lower_bound, is_signed),
824                value.get_type(),
825                "",
826            ))
827        } else {
828            err!(self.builder.build_unsigned_int_to_float(
829                int_ty.const_int(lower_bound, is_signed),
830                value.get_type(),
831                "",
832            ))
833        };
834        let upper_bound = if is_signed {
835            err!(self.builder.build_signed_int_to_float(
836                int_ty.const_int(upper_bound, is_signed),
837                value.get_type(),
838                "",
839            ))
840        } else {
841            err!(self.builder.build_unsigned_int_to_float(
842                int_ty.const_int(upper_bound, is_signed),
843                value.get_type(),
844                "",
845            ))
846        };
847
848        let zero = value.get_type().const_zero();
849
850        let nan_cmp =
851            err!(
852                self.builder
853                    .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
854            );
855        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
856            FloatPredicate::OGT,
857            value,
858            upper_bound,
859            "above_upper_bound",
860        ));
861        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
862            FloatPredicate::OLT,
863            value,
864            lower_bound,
865            "below_lower_bound",
866        ));
867        let not_representable = err!(self.builder.build_or(
868            err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
869            below_lower_bound_cmp,
870            "not_representable_as_int",
871        ));
872        let value =
873            err!(
874                self.builder
875                    .build_select(not_representable, zero, value, "safe_to_convert")
876            )
877            .into_float_value();
878        let value = if is_signed {
879            err!(
880                self.builder
881                    .build_float_to_signed_int(value, int_ty, "as_int")
882            )
883        } else {
884            err!(
885                self.builder
886                    .build_float_to_unsigned_int(value, int_ty, "as_int")
887            )
888        };
889        let value =
890            err!(
891                self.builder
892                    .build_select(above_upper_bound_cmp, int_max_value, value, "")
893            )
894            .into_int_value();
895        let value =
896            err!(
897                self.builder
898                    .build_select(below_lower_bound_cmp, int_min_value, value, "")
899            )
900            .into_int_value();
901
902        err_nt!(
903            self.builder
904                .build_bit_cast(value, int_ty, "")
905                .map(|v| v.into_int_value())
906        )
907    }
908
909    fn trap_if_not_representable_as_int(
910        &self,
911        lower_bound: u64, // Inclusive (not a trapping value)
912        upper_bound: u64, // Inclusive (not a trapping value)
913        value: FloatValue<'ctx>,
914    ) -> Result<(), CompileError> {
915        let float_ty = value.get_type();
916        let int_ty = if float_ty == self.intrinsics.f32_ty {
917            self.intrinsics.i32_ty
918        } else {
919            self.intrinsics.i64_ty
920        };
921
922        let lower_bound = err!(self.builder.build_bit_cast(
923            int_ty.const_int(lower_bound, false),
924            float_ty,
925            ""
926        ))
927        .into_float_value();
928        let upper_bound = err!(self.builder.build_bit_cast(
929            int_ty.const_int(upper_bound, false),
930            float_ty,
931            ""
932        ))
933        .into_float_value();
934
935        // The 'U' in the float predicate is short for "unordered" which means that
936        // the comparison will compare true if either operand is a NaN. Thus, NaNs
937        // are out of bounds.
938        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
939            FloatPredicate::UGT,
940            value,
941            upper_bound,
942            "above_upper_bound",
943        ));
944        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
945            FloatPredicate::ULT,
946            value,
947            lower_bound,
948            "below_lower_bound",
949        ));
950        let out_of_bounds = err!(self.builder.build_or(
951            above_upper_bound_cmp,
952            below_lower_bound_cmp,
953            "out_of_bounds",
954        ));
955
956        let failure_block = self
957            .context
958            .append_basic_block(self.function, "conversion_failure_block");
959        let continue_block = self
960            .context
961            .append_basic_block(self.function, "conversion_success_block");
962
963        err!(
964            self.builder
965                .build_conditional_branch(out_of_bounds, failure_block, continue_block)
966        );
967        self.builder.position_at_end(failure_block);
968        let is_nan =
969            err!(
970                self.builder
971                    .build_float_compare(FloatPredicate::UNO, value, value, "is_nan")
972            );
973        let trap_code = err!(self.builder.build_select(
974            is_nan,
975            self.intrinsics.trap_bad_conversion_to_integer,
976            self.intrinsics.trap_illegal_arithmetic,
977            "",
978        ));
979        self.build_call_with_param_attributes(
980            self.intrinsics.throw_trap,
981            &[trap_code.into()],
982            "throw",
983        )?;
984        err!(self.builder.build_unreachable());
985        self.builder.position_at_end(continue_block);
986
987        Ok(())
988    }
989
990    fn trap_if_zero_or_overflow(
991        &self,
992        left: IntValue<'ctx>,
993        right: IntValue<'ctx>,
994    ) -> Result<(), CompileError> {
995        let int_type = left.get_type();
996
997        let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
998            let min_value = int_type.const_int(i32::MIN as u64, false);
999            let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
1000            (min_value, neg_one_value)
1001        } else if int_type == self.intrinsics.i64_ty {
1002            let min_value = int_type.const_int(i64::MIN as u64, false);
1003            let neg_one_value = int_type.const_int(-1i64 as u64, false);
1004            (min_value, neg_one_value)
1005        } else {
1006            unreachable!()
1007        };
1008
1009        let divisor_is_zero = err!(self.builder.build_int_compare(
1010            IntPredicate::EQ,
1011            right,
1012            int_type.const_zero(),
1013            "divisor_is_zero",
1014        ));
1015        let should_trap = err!(self.builder.build_or(
1016            divisor_is_zero,
1017            err!(self.builder.build_and(
1018                err!(self.builder.build_int_compare(
1019                    IntPredicate::EQ,
1020                    left,
1021                    min_value,
1022                    "left_is_min"
1023                )),
1024                err!(self.builder.build_int_compare(
1025                    IntPredicate::EQ,
1026                    right,
1027                    neg_one_value,
1028                    "right_is_neg_one",
1029                )),
1030                "div_will_overflow",
1031            )),
1032            "div_should_trap",
1033        ));
1034
1035        let should_trap = self
1036            .build_call_with_param_attributes(
1037                self.intrinsics.expect_i1,
1038                &[
1039                    should_trap.into(),
1040                    self.intrinsics.i1_ty.const_zero().into(),
1041                ],
1042                "should_trap_expect",
1043            )?
1044            .try_as_basic_value()
1045            .unwrap_basic()
1046            .into_int_value();
1047
1048        let shouldnt_trap_block = self
1049            .context
1050            .append_basic_block(self.function, "shouldnt_trap_block");
1051        let should_trap_block = self
1052            .context
1053            .append_basic_block(self.function, "should_trap_block");
1054        err!(self.builder.build_conditional_branch(
1055            should_trap,
1056            should_trap_block,
1057            shouldnt_trap_block
1058        ));
1059        self.builder.position_at_end(should_trap_block);
1060        let trap_code = err!(self.builder.build_select(
1061            divisor_is_zero,
1062            self.intrinsics.trap_integer_division_by_zero,
1063            self.intrinsics.trap_illegal_arithmetic,
1064            "",
1065        ));
1066        err!(
1067            self.builder
1068                .build_call(self.intrinsics.throw_trap, &[trap_code.into()], "throw")
1069        );
1070        err!(self.builder.build_unreachable());
1071        self.builder.position_at_end(shouldnt_trap_block);
1072
1073        Ok(())
1074    }
1075
1076    fn trap_if_zero(&self, value: IntValue<'ctx>) -> Result<(), CompileError> {
1077        let int_type = value.get_type();
1078        let should_trap = err!(self.builder.build_int_compare(
1079            IntPredicate::EQ,
1080            value,
1081            int_type.const_zero(),
1082            "divisor_is_zero",
1083        ));
1084
1085        let should_trap = self
1086            .build_call_with_param_attributes(
1087                self.intrinsics.expect_i1,
1088                &[
1089                    should_trap.into(),
1090                    self.intrinsics.i1_ty.const_zero().into(),
1091                ],
1092                "should_trap_expect",
1093            )?
1094            .try_as_basic_value()
1095            .unwrap_basic()
1096            .into_int_value();
1097
1098        let shouldnt_trap_block = self
1099            .context
1100            .append_basic_block(self.function, "shouldnt_trap_block");
1101        let should_trap_block = self
1102            .context
1103            .append_basic_block(self.function, "should_trap_block");
1104        err!(self.builder.build_conditional_branch(
1105            should_trap,
1106            should_trap_block,
1107            shouldnt_trap_block
1108        ));
1109        self.builder.position_at_end(should_trap_block);
1110        self.build_call_with_param_attributes(
1111            self.intrinsics.throw_trap,
1112            &[self.intrinsics.trap_integer_division_by_zero.into()],
1113            "throw",
1114        )?;
1115        err!(self.builder.build_unreachable());
1116        self.builder.position_at_end(shouldnt_trap_block);
1117
1118        Ok(())
1119    }
1120
1121    fn v128_into_int_vec(
1122        &self,
1123        value: BasicValueEnum<'ctx>,
1124        info: ExtraInfo,
1125        int_vec_ty: VectorType<'ctx>,
1126    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1127        let (value, info) = if self.config.enable_nan_canonicalization {
1128            if info.has_pending_f32_nan() {
1129                let value = err!(
1130                    self.builder
1131                        .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1132                );
1133                (self.canonicalize_nans(value)?, info.strip_pending())
1134            } else if info.has_pending_f64_nan() {
1135                let value = err!(
1136                    self.builder
1137                        .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1138                );
1139                (self.canonicalize_nans(value)?, info.strip_pending())
1140            } else {
1141                (value, info)
1142            }
1143        } else {
1144            (value, info)
1145        };
1146        Ok((
1147            err!(self.builder.build_bit_cast(value, int_vec_ty, "")).into_vector_value(),
1148            info,
1149        ))
1150    }
1151
1152    fn v128_into_i8x16(
1153        &self,
1154        value: BasicValueEnum<'ctx>,
1155        info: ExtraInfo,
1156    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1157        self.v128_into_int_vec(value, info, self.intrinsics.i8x16_ty)
1158    }
1159
1160    fn v128_into_i16x8(
1161        &self,
1162        value: BasicValueEnum<'ctx>,
1163        info: ExtraInfo,
1164    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1165        self.v128_into_int_vec(value, info, self.intrinsics.i16x8_ty)
1166    }
1167
1168    fn v128_into_i32x4(
1169        &self,
1170        value: BasicValueEnum<'ctx>,
1171        info: ExtraInfo,
1172    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1173        self.v128_into_int_vec(value, info, self.intrinsics.i32x4_ty)
1174    }
1175
1176    fn v128_into_i64x2(
1177        &self,
1178        value: BasicValueEnum<'ctx>,
1179        info: ExtraInfo,
1180    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1181        self.v128_into_int_vec(value, info, self.intrinsics.i64x2_ty)
1182    }
1183
1184    // If the value is pending a 64-bit canonicalization, do it now.
1185    // Return a f32x4 vector.
1186    fn v128_into_f32x4(
1187        &self,
1188        value: BasicValueEnum<'ctx>,
1189        info: ExtraInfo,
1190    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1191        let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f64_nan()
1192        {
1193            let value = err!(
1194                self.builder
1195                    .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1196            );
1197            (self.canonicalize_nans(value)?, info.strip_pending())
1198        } else {
1199            (value, info)
1200        };
1201        Ok((
1202            err!(
1203                self.builder
1204                    .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1205            )
1206            .into_vector_value(),
1207            info,
1208        ))
1209    }
1210
1211    // If the value is pending a 32-bit canonicalization, do it now.
1212    // Return a f64x2 vector.
1213    fn v128_into_f64x2(
1214        &self,
1215        value: BasicValueEnum<'ctx>,
1216        info: ExtraInfo,
1217    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1218        let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f32_nan()
1219        {
1220            let value = err!(
1221                self.builder
1222                    .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1223            );
1224            (self.canonicalize_nans(value)?, info.strip_pending())
1225        } else {
1226            (value, info)
1227        };
1228        Ok((
1229            err!(
1230                self.builder
1231                    .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1232            )
1233            .into_vector_value(),
1234            info,
1235        ))
1236    }
1237
1238    fn apply_pending_canonicalization(
1239        &self,
1240        value: BasicValueEnum<'ctx>,
1241        info: ExtraInfo,
1242    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1243        if !self.config.enable_nan_canonicalization {
1244            return Ok(value);
1245        }
1246
1247        if info.has_pending_f32_nan() {
1248            if value.get_type().is_vector_type()
1249                || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1250            {
1251                let ty = value.get_type();
1252                let value = err!(
1253                    self.builder
1254                        .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1255                );
1256                let value = self.canonicalize_nans(value)?;
1257                err_nt!(self.builder.build_bit_cast(value, ty, ""))
1258            } else {
1259                self.canonicalize_nans(value)
1260            }
1261        } else if info.has_pending_f64_nan() {
1262            if value.get_type().is_vector_type()
1263                || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1264            {
1265                let ty = value.get_type();
1266                let value = err!(
1267                    self.builder
1268                        .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1269                );
1270                let value = self.canonicalize_nans(value)?;
1271                err_nt!(self.builder.build_bit_cast(value, ty, ""))
1272            } else {
1273                self.canonicalize_nans(value)
1274            }
1275        } else {
1276            Ok(value)
1277        }
1278    }
1279
1280    // Replaces any NaN with the canonical QNaN, otherwise leaves the value alone.
1281    fn canonicalize_nans(
1282        &self,
1283        value: BasicValueEnum<'ctx>,
1284    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1285        if !self.config.enable_nan_canonicalization {
1286            return Ok(value);
1287        }
1288
1289        let f_ty = value.get_type();
1290        if f_ty.is_vector_type() {
1291            let value = value.into_vector_value();
1292            let f_ty = f_ty.into_vector_type();
1293            let zero = f_ty.const_zero();
1294            let nan_cmp =
1295                err!(
1296                    self.builder
1297                        .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1298                );
1299            let canonical_qnan = f_ty
1300                .get_element_type()
1301                .into_float_type()
1302                .const_float(f64::NAN);
1303            let canonical_qnan = self.splat_vector(canonical_qnan.as_basic_value_enum(), f_ty)?;
1304            err_nt!(
1305                self.builder
1306                    .build_select(nan_cmp, canonical_qnan, value, "")
1307                    .map(|v| v.as_basic_value_enum())
1308            )
1309        } else {
1310            let value = value.into_float_value();
1311            let f_ty = f_ty.into_float_type();
1312            let zero = f_ty.const_zero();
1313            let nan_cmp =
1314                err!(
1315                    self.builder
1316                        .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1317                );
1318            let canonical_qnan = f_ty.const_float(f64::NAN);
1319            err_nt!(
1320                self.builder
1321                    .build_select(nan_cmp, canonical_qnan, value, "")
1322                    .map(|v| v.as_basic_value_enum())
1323            )
1324        }
1325    }
1326
1327    fn annotate_user_memaccess(
1328        &mut self,
1329        memory_index: MemoryIndex,
1330        _memarg: &MemArg,
1331        alignment: u32,
1332        memaccess: InstructionValue<'ctx>,
1333    ) -> Result<(), CompileError> {
1334        match memaccess.get_opcode() {
1335            InstructionOpcode::Load | InstructionOpcode::Store => {
1336                memaccess.set_alignment(alignment).unwrap();
1337            }
1338            _ => {}
1339        };
1340        if !self.non_volatile_memory_ops {
1341            // If this memory access must trap when out of bounds (i.e. it is a memory
1342            // access written in the user program as opposed to one used by our VM)
1343            // then mark that it can't be deleted.
1344            if let MemoryCache::Static { base_ptr: _ } = self.ctx.memory(
1345                memory_index,
1346                self.intrinsics,
1347                self.module,
1348                self.memory_styles,
1349            )? {
1350                // The best we've got is `volatile`.
1351                memaccess.set_volatile(true).map_err(|err| {
1352                    CompileError::Codegen(format!(
1353                        "could not set volatile on memory operation: {err}"
1354                    ))
1355                })?;
1356            }
1357        }
1358        tbaa_label(
1359            self.module,
1360            self.intrinsics,
1361            format!("memory {}", memory_index.as_u32()),
1362            memaccess,
1363        );
1364        Ok(())
1365    }
1366
1367    fn build_annotated_load<T: BasicType<'ctx>>(
1368        &mut self,
1369        pointee_ty: T,
1370        offset: IntValue<'ctx>,
1371        memarg: &MemArg,
1372        alignment: u32,
1373    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1374        let memory_index = MemoryIndex::from_u32(memarg.memory);
1375        let pointee_size = usize::try_from(self.target_data.get_store_size(&pointee_ty))
1376            .map_err(|_| CompileError::Codegen("pointee type size does not fit in usize".into()))?;
1377        let effective_address = self.resolve_memory_ptr(
1378            memory_index,
1379            memarg,
1380            self.intrinsics.ptr_ty,
1381            offset,
1382            pointee_size,
1383        )?;
1384        let result = err!(self.builder.build_load(pointee_ty, effective_address, ""));
1385        self.annotate_user_memaccess(
1386            MemoryIndex::from_u32(memarg.memory),
1387            memarg,
1388            alignment,
1389            result.as_instruction_value().unwrap(),
1390        )?;
1391        Ok(result)
1392    }
1393
1394    fn build_annotated_atomic_load(
1395        &mut self,
1396        outer_ty: IntType<'ctx>,
1397        inner_ty: IntType<'ctx>,
1398        offset: IntValue<'ctx>,
1399        memarg: &MemArg,
1400    ) -> Result<IntValue<'ctx>, CompileError> {
1401        let alignment = 2u32.pow(memarg.align as u32);
1402        let memory_index = MemoryIndex::from_u32(memarg.memory);
1403        let inner_size =
1404            usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1405                CompileError::Codegen("atomic inner type size does not fit in usize".into())
1406            })?;
1407        let outer_size =
1408            usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1409                CompileError::Codegen("atomic outer type size does not fit in usize".into())
1410            })?;
1411
1412        let effective_address = self.resolve_memory_ptr(
1413            memory_index,
1414            memarg,
1415            self.intrinsics.ptr_ty,
1416            offset,
1417            inner_size,
1418        )?;
1419        self.trap_if_misaligned(
1420            memarg,
1421            effective_address,
1422            u8::try_from(inner_size).map_err(|_| {
1423                CompileError::Codegen("atomic inner type size does not fit in u8".into())
1424            })?,
1425        )?;
1426
1427        let result = err!(
1428            self.builder
1429                .build_load(inner_ty, effective_address, "atomic_load")
1430        );
1431        let load = result.into_int_value();
1432        let load_inst = load.as_instruction_value().unwrap();
1433        self.annotate_user_memaccess(memory_index, memarg, alignment, load_inst)?;
1434        load_inst
1435            .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
1436            .unwrap();
1437
1438        if inner_size < outer_size {
1439            Ok(err_nt!(
1440                self.builder.build_int_z_extend(load, outer_ty, "")
1441            )?)
1442        } else {
1443            Ok(load)
1444        }
1445    }
1446
1447    fn build_annotated_store<T: BasicType<'ctx>>(
1448        &mut self,
1449        pointee_ty: T,
1450        offset: IntValue<'ctx>,
1451        value: BasicValueEnum<'ctx>,
1452        memarg: &MemArg,
1453        alignment: u32,
1454    ) -> Result<(), CompileError> {
1455        let memory_index = MemoryIndex::from_u32(memarg.memory);
1456        let pointee_size = usize::try_from(self.target_data.get_store_size(&pointee_ty))
1457            .map_err(|_| CompileError::Codegen("pointee type size does not fit in usize".into()))?;
1458        let effective_address = self.resolve_memory_ptr(
1459            memory_index,
1460            memarg,
1461            self.intrinsics.ptr_ty,
1462            offset,
1463            pointee_size,
1464        )?;
1465
1466        // Build a dead load (if non-volatile memory operations are disabled) to preserve
1467        // artifacts from partial store operations.
1468        if !self.non_volatile_memory_ops {
1469            self.build_annotated_load(pointee_ty, offset, memarg, alignment)?;
1470        }
1471
1472        let store = err!(self.builder.build_store(effective_address, value));
1473        self.annotate_user_memaccess(memory_index, memarg, alignment, store)
1474    }
1475
1476    fn build_annotated_atomic_store(
1477        &mut self,
1478        outer_ty: IntType<'ctx>,
1479        inner_ty: IntType<'ctx>,
1480        offset: IntValue<'ctx>,
1481        value: IntValue<'ctx>,
1482        memarg: &MemArg,
1483    ) -> Result<(), CompileError> {
1484        let alignment = 2u32.pow(memarg.align as u32);
1485        let memory_index = MemoryIndex::from_u32(memarg.memory);
1486        let inner_size =
1487            usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1488                CompileError::Codegen("atomic inner type size does not fit in usize".into())
1489            })?;
1490        let outer_size =
1491            usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1492                CompileError::Codegen("atomic outer type size does not fit in usize".into())
1493            })?;
1494
1495        let effective_address = self.resolve_memory_ptr(
1496            memory_index,
1497            memarg,
1498            self.intrinsics.ptr_ty,
1499            offset,
1500            inner_size,
1501        )?;
1502        self.trap_if_misaligned(
1503            memarg,
1504            effective_address,
1505            u8::try_from(inner_size).map_err(|_| {
1506                CompileError::Codegen("atomic inner type size does not fit in u8".into())
1507            })?,
1508        )?;
1509
1510        let value = if inner_size < outer_size {
1511            err!(self.builder.build_int_truncate(value, inner_ty, ""))
1512        } else {
1513            value
1514        };
1515        let store = err!(self.builder.build_store(effective_address, value));
1516        self.annotate_user_memaccess(memory_index, memarg, alignment, store)?;
1517        store
1518            .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
1519            .unwrap();
1520        Ok(())
1521    }
1522
1523    fn build_annotated_atomic_rmw(
1524        &mut self,
1525        outer_ty: IntType<'ctx>,
1526        inner_ty: IntType<'ctx>,
1527        offset: IntValue<'ctx>,
1528        value: IntValue<'ctx>,
1529        memarg: &MemArg,
1530        op: AtomicRMWBinOp,
1531    ) -> Result<IntValue<'ctx>, CompileError> {
1532        let alignment = 2u32.pow(memarg.align as u32);
1533        let memory_index = MemoryIndex::from_u32(memarg.memory);
1534        let inner_size =
1535            usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1536                CompileError::Codegen("atomic inner type size does not fit in usize".into())
1537            })?;
1538        let outer_size =
1539            usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1540                CompileError::Codegen("atomic outer type size does not fit in usize".into())
1541            })?;
1542
1543        let effective_address = self.resolve_memory_ptr(
1544            memory_index,
1545            memarg,
1546            self.intrinsics.ptr_ty,
1547            offset,
1548            inner_size,
1549        )?;
1550        self.trap_if_misaligned(
1551            memarg,
1552            effective_address,
1553            u8::try_from(inner_size).map_err(|_| {
1554                CompileError::Codegen("atomic inner type size does not fit in u8".into())
1555            })?,
1556        )?;
1557        let value = if inner_size < outer_size {
1558            err!(self.builder.build_int_truncate(value, inner_ty, ""))
1559        } else {
1560            value
1561        };
1562        let old = self
1563            .builder
1564            .build_atomicrmw(
1565                op,
1566                effective_address,
1567                value,
1568                AtomicOrdering::SequentiallyConsistent,
1569            )
1570            .unwrap();
1571        self.annotate_user_memaccess(
1572            memory_index,
1573            memarg,
1574            alignment,
1575            old.as_instruction_value().unwrap(),
1576        )?;
1577
1578        let value = if inner_size < outer_size {
1579            err!(self.builder.build_int_z_extend(old, outer_ty, ""))
1580        } else {
1581            old
1582        };
1583        Ok(value)
1584    }
1585
1586    fn build_annotated_atomic_rmw_cmpxchg(
1587        &mut self,
1588        outer_ty: IntType<'ctx>,
1589        inner_ty: IntType<'ctx>,
1590        offset: IntValue<'ctx>,
1591        cmp: IntValue<'ctx>,
1592        new: IntValue<'ctx>,
1593        memarg: &MemArg,
1594    ) -> Result<IntValue<'ctx>, CompileError> {
1595        let alignment = 2u32.pow(memarg.align as u32);
1596        let memory_index = MemoryIndex::from_u32(memarg.memory);
1597        let inner_size =
1598            usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1599                CompileError::Codegen("atomic inner type size does not fit in usize".into())
1600            })?;
1601        let outer_size =
1602            usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1603                CompileError::Codegen("atomic outer type size does not fit in usize".into())
1604            })?;
1605
1606        let effective_address = self.resolve_memory_ptr(
1607            memory_index,
1608            memarg,
1609            self.intrinsics.ptr_ty,
1610            offset,
1611            inner_size,
1612        )?;
1613        self.trap_if_misaligned(
1614            memarg,
1615            effective_address,
1616            u8::try_from(inner_size).map_err(|_| {
1617                CompileError::Codegen("atomic inner type size does not fit in u8".into())
1618            })?,
1619        )?;
1620        let (cmp, new) = if inner_size < outer_size {
1621            (
1622                err!(self.builder.build_int_truncate(cmp, inner_ty, "")),
1623                err!(self.builder.build_int_truncate(new, inner_ty, "")),
1624            )
1625        } else {
1626            (cmp, new)
1627        };
1628        let old = self
1629            .builder
1630            .build_cmpxchg(
1631                effective_address,
1632                cmp,
1633                new,
1634                AtomicOrdering::SequentiallyConsistent,
1635                AtomicOrdering::SequentiallyConsistent,
1636            )
1637            .unwrap();
1638        self.annotate_user_memaccess(
1639            memory_index,
1640            memarg,
1641            alignment,
1642            old.as_instruction_value().unwrap(),
1643        )?;
1644        let old = self
1645            .builder
1646            .build_extract_value(old, 0, "")
1647            .unwrap()
1648            .into_int_value();
1649
1650        let value = if inner_size < outer_size {
1651            err!(self.builder.build_int_z_extend(old, outer_ty, ""))
1652        } else {
1653            old
1654        };
1655        Ok(value)
1656    }
1657
1658    fn translate_atomic_rmw(
1659        &mut self,
1660        outer_ty: IntType<'ctx>,
1661        inner_ty: IntType<'ctx>,
1662        memarg: &MemArg,
1663        op: AtomicRMWBinOp,
1664        extra_info: Option<ExtraInfo>,
1665    ) -> Result<(), CompileError> {
1666        let value = self.state.pop1()?.into_int_value();
1667        let offset = self.state.pop1()?.into_int_value();
1668        let old = self.build_annotated_atomic_rmw(outer_ty, inner_ty, offset, value, memarg, op)?;
1669        if let Some(extra_info) = extra_info {
1670            self.state.push1_extra(old, extra_info);
1671        } else {
1672            self.state.push1(old);
1673        }
1674        Ok(())
1675    }
1676
1677    fn translate_atomic_rmw_cmpxchg(
1678        &mut self,
1679        outer_ty: IntType<'ctx>,
1680        inner_ty: IntType<'ctx>,
1681        memarg: &MemArg,
1682        extra_info: Option<ExtraInfo>,
1683    ) -> Result<(), CompileError> {
1684        let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
1685        let cmp = self
1686            .apply_pending_canonicalization(cmp, cmp_info)?
1687            .into_int_value();
1688        let new = self
1689            .apply_pending_canonicalization(new, new_info)?
1690            .into_int_value();
1691        let offset = self.state.pop1()?.into_int_value();
1692        let old =
1693            self.build_annotated_atomic_rmw_cmpxchg(outer_ty, inner_ty, offset, cmp, new, memarg)?;
1694        if let Some(extra_info) = extra_info {
1695            self.state.push1_extra(old, extra_info);
1696        } else {
1697            self.state.push1(old);
1698        }
1699        Ok(())
1700    }
1701
1702    fn resolve_memory_ptr(
1703        &mut self,
1704        memory_index: MemoryIndex,
1705        memarg: &MemArg,
1706        ptr_ty: PointerType<'ctx>,
1707        var_offset: IntValue<'ctx>,
1708        value_size: usize,
1709    ) -> Result<PointerValue<'ctx>, CompileError> {
1710        let builder = &self.builder;
1711        let intrinsics = &self.intrinsics;
1712        let context = &self.context;
1713        let function = &self.function;
1714
1715        // Compute the offset into the storage.
1716        let imm_offset = intrinsics.i64_ty.const_int(memarg.offset, false);
1717        let var_offset = err!(builder.build_int_z_extend(var_offset, intrinsics.i64_ty, ""));
1718        let offset = err!(builder.build_int_add(var_offset, imm_offset, ""));
1719
1720        // Look up the memory base (as pointer) and bounds (as unsigned integer).
1721        let base_ptr = if let Some(m0) = self.m0_param {
1722            m0
1723        } else {
1724            match self
1725                .ctx
1726                .memory(memory_index, intrinsics, self.module, self.memory_styles)?
1727            {
1728                MemoryCache::Dynamic {
1729                    ptr_to_base_ptr,
1730                    ptr_to_current_length,
1731                } => {
1732                    // Bounds check it.
1733                    let minimum = self.wasm_module.memories[memory_index].minimum;
1734                    let value_size_v = intrinsics.i64_ty.const_int(value_size as u64, false);
1735                    let ptr_in_bounds = if offset.is_const() {
1736                        // When the offset is constant, if it's below the minimum
1737                        // memory size, we've statically shown that it's safe.
1738                        let load_offset_end =
1739                            offset.const_add(value_size_v).get_zero_extended_constant();
1740                        if load_offset_end.is_some_and(|load_offset_end| {
1741                            load_offset_end <= minimum.bytes().0 as u64
1742                        }) {
1743                            Some(intrinsics.i64_ty.const_int(1, false))
1744                        } else {
1745                            None
1746                        }
1747                    } else {
1748                        None
1749                    };
1750
1751                    let ptr_in_bounds = match ptr_in_bounds {
1752                        Some(ptr) => ptr,
1753                        None => {
1754                            let load_offset_end = err!(builder.build_int_add(
1755                                offset,
1756                                value_size_v,
1757                                "load_offset_end"
1758                            ));
1759
1760                            let current_length = err!(builder.build_load(
1761                                self.intrinsics.i32_ty,
1762                                ptr_to_current_length,
1763                                "current_length"
1764                            ))
1765                            .into_int_value();
1766                            tbaa_label(
1767                                self.module,
1768                                self.intrinsics,
1769                                format!("memory {} length", memory_index.as_u32()),
1770                                current_length.as_instruction_value().unwrap(),
1771                            );
1772                            let current_length = err!(builder.build_int_z_extend(
1773                                current_length,
1774                                intrinsics.i64_ty,
1775                                "current_length_zextd"
1776                            ));
1777
1778                            err!(builder.build_int_compare(
1779                                IntPredicate::ULE,
1780                                load_offset_end,
1781                                current_length,
1782                                "ptr_in_bounds",
1783                            ))
1784                        }
1785                    };
1786
1787                    if !ptr_in_bounds.is_constant_int()
1788                        || ptr_in_bounds.get_zero_extended_constant().unwrap() != 1
1789                    {
1790                        // LLVM may have folded this into 'i1 true' in which case we know
1791                        // the pointer is in bounds. LLVM may also have folded it into a
1792                        // constant expression, not known to be either true or false yet.
1793                        // If it's false, unknown-but-constant, or not-a-constant, emit a
1794                        // runtime bounds check. LLVM may yet succeed at optimizing it away.
1795                        let ptr_in_bounds = err!(self.build_call_with_param_attributes(
1796                            intrinsics.expect_i1,
1797                            &[
1798                                ptr_in_bounds.into(),
1799                                intrinsics.i1_ty.const_int(1, true).into(),
1800                            ],
1801                            "ptr_in_bounds_expect",
1802                        ))
1803                        .try_as_basic_value()
1804                        .unwrap_basic()
1805                        .into_int_value();
1806
1807                        let in_bounds_continue_block =
1808                            context.append_basic_block(*function, "in_bounds_continue_block");
1809                        let not_in_bounds_block =
1810                            context.append_basic_block(*function, "not_in_bounds_block");
1811                        err!(builder.build_conditional_branch(
1812                            ptr_in_bounds,
1813                            in_bounds_continue_block,
1814                            not_in_bounds_block,
1815                        ));
1816                        builder.position_at_end(not_in_bounds_block);
1817                        err!(self.build_call_with_param_attributes(
1818                            intrinsics.throw_trap,
1819                            &[intrinsics.trap_memory_oob.into()],
1820                            "throw",
1821                        ));
1822                        err!(builder.build_unreachable());
1823                        builder.position_at_end(in_bounds_continue_block);
1824                    }
1825                    let ptr_to_base =
1826                        err!(builder.build_load(intrinsics.ptr_ty, ptr_to_base_ptr, "ptr_to_base"))
1827                            .into_pointer_value();
1828                    tbaa_label(
1829                        self.module,
1830                        self.intrinsics,
1831                        format!("memory base_ptr {}", memory_index.as_u32()),
1832                        ptr_to_base.as_instruction_value().unwrap(),
1833                    );
1834                    ptr_to_base
1835                }
1836                MemoryCache::Static { base_ptr } => base_ptr,
1837            }
1838        };
1839        let value_ptr = unsafe {
1840            err!(builder.build_gep(self.intrinsics.i8_ty, base_ptr, &[offset], "mem_value_ptr"))
1841        };
1842        err_nt!(
1843            builder
1844                .build_bit_cast(value_ptr, ptr_ty, "mem_value")
1845                .map(|v| v.into_pointer_value())
1846        )
1847    }
1848
1849    fn trap_if_misaligned(
1850        &self,
1851        _memarg: &MemArg,
1852        ptr: PointerValue<'ctx>,
1853        align: u8,
1854    ) -> Result<(), CompileError> {
1855        if align <= 1 {
1856            return Ok(());
1857        }
1858        let value = err!(self.builder.build_ptr_to_int(
1859            ptr,
1860            self.intrinsics.i64_ty,
1861            "mischeck_value"
1862        ));
1863        let and = err!(self.builder.build_and(
1864            value,
1865            self.intrinsics.i64_ty.const_int((align - 1).into(), false),
1866            "misaligncheck",
1867        ));
1868        let aligned = err!(self.builder.build_int_compare(
1869            IntPredicate::EQ,
1870            and,
1871            self.intrinsics.i64_zero,
1872            "is_aligned"
1873        ));
1874        let aligned = self
1875            .build_call_with_param_attributes(
1876                self.intrinsics.expect_i1,
1877                &[
1878                    aligned.into(),
1879                    self.intrinsics.i1_ty.const_int(1, false).into(),
1880                ],
1881                "is_aligned_expect",
1882            )?
1883            .try_as_basic_value()
1884            .unwrap_basic()
1885            .into_int_value();
1886
1887        let continue_block = self
1888            .context
1889            .append_basic_block(self.function, "aligned_access_continue_block");
1890        let not_aligned_block = self
1891            .context
1892            .append_basic_block(self.function, "misaligned_trap_block");
1893        err!(
1894            self.builder
1895                .build_conditional_branch(aligned, continue_block, not_aligned_block)
1896        );
1897
1898        self.builder.position_at_end(not_aligned_block);
1899        self.build_call_with_param_attributes(
1900            self.intrinsics.throw_trap,
1901            &[self.intrinsics.trap_unaligned_atomic.into()],
1902            "throw",
1903        )?;
1904        err!(self.builder.build_unreachable());
1905
1906        self.builder.position_at_end(continue_block);
1907        Ok(())
1908    }
1909
1910    fn finalize(&mut self, wasm_fn_type: &FunctionType) -> Result<(), CompileError> {
1911        let func_type = self.function.get_type();
1912
1913        let results = self.state.popn_save_extra(wasm_fn_type.results().len())?;
1914        let results = err!(
1915            results
1916                .into_iter()
1917                .map(|(v, i)| self.apply_pending_canonicalization(v, i))
1918                .collect::<Result<Vec<_>, _>>()
1919        );
1920
1921        if wasm_fn_type.results().is_empty() {
1922            err!(self.builder.build_return(None));
1923        } else if self.abi.is_sret(wasm_fn_type)? {
1924            let sret = self
1925                .function
1926                .get_first_param()
1927                .unwrap()
1928                .into_pointer_value();
1929            let llvm_params: Vec<_> = wasm_fn_type
1930                .results()
1931                .iter()
1932                .map(|x| type_to_llvm(self.intrinsics, *x).unwrap())
1933                .collect();
1934            let mut struct_value = self
1935                .context
1936                .struct_type(llvm_params.as_slice(), false)
1937                .get_undef();
1938            for (idx, value) in results.into_iter().enumerate() {
1939                let value = err!(self.builder.build_bit_cast(
1940                    value,
1941                    type_to_llvm(self.intrinsics, wasm_fn_type.results()[idx])?,
1942                    "",
1943                ));
1944                struct_value =
1945                    err!(
1946                        self.builder
1947                            .build_insert_value(struct_value, value, idx as u32, "")
1948                    )
1949                    .into_struct_value();
1950            }
1951            err!(self.builder.build_store(sret, struct_value));
1952            err!(self.builder.build_return(None));
1953        } else {
1954            err!(
1955                self.builder
1956                    .build_return(Some(&self.abi.pack_values_for_register_return(
1957                        self.intrinsics,
1958                        &self.builder,
1959                        &results,
1960                        &func_type,
1961                    )?))
1962            );
1963        }
1964        Ok(())
1965    }
1966
1967    // Generates a global constant with the tag's module-local index, which can be used
1968    // as the "type info" of a catch clause.
1969    fn get_or_insert_tag_type_info_global(&mut self, tag: i32) -> BasicValueEnum<'ctx> {
1970        if let Some(tag) = self.tags_cache.get(&tag) {
1971            return *tag;
1972        }
1973
1974        let tag_ty = self
1975            .context
1976            .struct_type(&[self.intrinsics.i32_ty.into()], false);
1977        let tag_glbl = self.module.add_global(
1978            tag_ty,
1979            Some(AddressSpace::default()),
1980            &format!("__wasmer_eh_type_info_{tag}"),
1981        );
1982        tag_glbl.set_initializer(
1983            &tag_ty
1984                .const_named_struct(&[self.intrinsics.i32_ty.const_int(tag as _, false).into()])
1985                .as_basic_value_enum(),
1986        );
1987
1988        tag_glbl.set_linkage(Linkage::LinkOnceODR);
1989        tag_glbl.set_constant(true);
1990        // Why set this to a specific section? On macOS it would land on a specific read only data
1991        // section. GOT-based relocations will probably be generated with a non-zero addend, making
1992        // some EH-related intricacies not working.
1993        //
1994        // The general idea is that each tag has its own section, so the GOT-based relocation can
1995        // have a zero addend, i.e. the data of the tag is the first (and only) value in a specific
1996        // section we can target in relocations.
1997        if matches!(self.binary_fmt, target_lexicon::BinaryFormat::Macho) {
1998            tag_glbl.set_section(Some(&format!("{FUNCTION_SECTION_MACHO},_eh_ti_{tag}")));
1999        }
2000
2001        let tag_glbl = tag_glbl.as_basic_value_enum();
2002
2003        self.tags_cache.insert(tag, tag_glbl);
2004        tag_glbl
2005    }
2006
2007    fn emit_return_call(
2008        &mut self,
2009        call_site: CallSiteValue<'ctx>,
2010        callee_llvm_func_type: inkwell::types::FunctionType<'ctx>,
2011    ) -> Result<(), CompileError> {
2012        // This is an unintuitive spec corner case: a tail call must bypass all enclosing
2013        // try_table blocks in the function. See https://github.com/WebAssembly/exception-handling/issues/249.
2014        //
2015        // The LLVM MustTail is more restrictive than the one defined in the WebAssembly spec.
2016        // WebAssembly types alone are not enough here: the lowered ABI can add hidden arguments
2017        // like `m0` and `sret`, so we must compare the actual LLVM function types instead.
2018        let tail_call_kind = if self.function.get_type() == callee_llvm_func_type {
2019            LLVMTailCallKind::LLVMTailCallKindMustTail
2020        } else {
2021            LLVMTailCallKind::LLVMTailCallKindTail
2022        };
2023        call_site.set_tail_call_kind(tail_call_kind);
2024
2025        if self.function.get_type().get_return_type().is_none() {
2026            err!(self.builder.build_return(None));
2027        } else {
2028            let ret = call_site.try_as_basic_value();
2029            if ret.is_instruction() {
2030                return Err(CompileError::Codegen(
2031                    "return_call expected a non-void call result".to_string(),
2032                ));
2033            }
2034            err!(self.builder.build_return(Some(&ret.unwrap_basic())));
2035        }
2036        Ok(())
2037    }
2038
2039    // Return sret pointer if the functions needs the hidden argument for multiple return values.
2040    fn current_sret_ptr(&self, func_type: &FunctionType) -> Option<PointerValue<'ctx>> {
2041        self.abi.is_sret(func_type).ok().map(|_| {
2042            self.function
2043                .get_first_param()
2044                .unwrap()
2045                .into_pointer_value()
2046        })
2047    }
2048
2049    fn build_m0_indirect_call(
2050        &mut self,
2051        table_index: u32,
2052        ctx_ptr: PointerValue<'ctx>,
2053        func_type: &FunctionType,
2054        func_ptr: PointerValue<'ctx>,
2055        func_index: IntValue<'ctx>,
2056        is_return_call: bool,
2057    ) -> Result<(), CompileError> {
2058        let Some(m0) = self.m0_param else {
2059            return Err(CompileError::Codegen(
2060                "Call to build_m0_indirect_call without m0 parameter!".to_string(),
2061            ));
2062        };
2063
2064        let params = self.state.popn_save_extra(func_type.params().len())?;
2065
2066        let mut local_func_indices = vec![];
2067        let mut foreign_func_indices = vec![];
2068
2069        for t in &self.wasm_module.table_initializers {
2070            if t.table_index.as_u32() == table_index {
2071                for (func_in_table_idx, func_idx) in t.elements.iter().enumerate() {
2072                    if self.wasm_module.local_func_index(*func_idx).is_some() {
2073                        local_func_indices.push(func_in_table_idx)
2074                    } else {
2075                        foreign_func_indices.push(func_in_table_idx)
2076                    }
2077                }
2078                break;
2079            }
2080        }
2081
2082        let needs_switch = self.m0_param.is_some()
2083            && !local_func_indices.is_empty()
2084            && !foreign_func_indices.is_empty();
2085
2086        if needs_switch {
2087            let foreign_idx_block = self
2088                .context
2089                .append_basic_block(self.function, "foreign_call_block");
2090            let local_idx_block = self
2091                .context
2092                .append_basic_block(self.function, "local_call_block");
2093            let unreachable_indirect_call_branch_block = self
2094                .context
2095                .append_basic_block(self.function, "unreachable_indirect_call_branch");
2096
2097            let cont =
2098                (!is_return_call).then(|| self.context.append_basic_block(self.function, "cont"));
2099
2100            err!(
2101                self.builder.build_switch(
2102                    func_index,
2103                    unreachable_indirect_call_branch_block,
2104                    &local_func_indices
2105                        .into_iter()
2106                        .map(|v| (
2107                            self.intrinsics.i32_ty.const_int(v as _, false),
2108                            local_idx_block
2109                        ))
2110                        .chain(foreign_func_indices.into_iter().map(|v| (
2111                            self.intrinsics.i32_ty.const_int(v as _, false),
2112                            foreign_idx_block
2113                        )))
2114                        .collect::<Vec<_>>()
2115                )
2116            );
2117
2118            self.builder
2119                .position_at_end(unreachable_indirect_call_branch_block);
2120            err!(self.builder.build_unreachable());
2121
2122            //let current_block = self.builder.get_insert_block().unwrap();
2123            self.builder.position_at_end(local_idx_block);
2124            let (local_call_site, local_llvm_func_type) = self.build_indirect_call_with_params(
2125                ctx_ptr,
2126                func_type,
2127                func_ptr,
2128                Some(m0),
2129                is_return_call,
2130                &params,
2131            )?;
2132
2133            let local_rets = if is_return_call {
2134                self.emit_return_call(local_call_site, local_llvm_func_type)?;
2135                Vec::new()
2136            } else {
2137                let rets = self.abi.rets_from_call(
2138                    &self.builder,
2139                    self.intrinsics,
2140                    local_call_site,
2141                    func_type,
2142                )?;
2143                err!(
2144                    self.builder
2145                        .build_unconditional_branch(cont.expect("non-return call requires cont"))
2146                );
2147                rets
2148            };
2149
2150            self.builder.position_at_end(foreign_idx_block);
2151            let (foreign_call_site, foreign_llvm_func_type) = self
2152                .build_indirect_call_with_params(
2153                    ctx_ptr,
2154                    func_type,
2155                    func_ptr,
2156                    None,
2157                    is_return_call,
2158                    &params,
2159                )?;
2160
2161            let foreign_rets = if is_return_call {
2162                self.emit_return_call(foreign_call_site, foreign_llvm_func_type)?;
2163                Vec::new()
2164            } else {
2165                let rets = self.abi.rets_from_call(
2166                    &self.builder,
2167                    self.intrinsics,
2168                    foreign_call_site,
2169                    func_type,
2170                )?;
2171                err!(
2172                    self.builder
2173                        .build_unconditional_branch(cont.expect("non-return call requires cont"))
2174                );
2175                rets
2176            };
2177
2178            if is_return_call {
2179                return Ok(());
2180            }
2181
2182            self.builder
2183                .position_at_end(cont.expect("non-return call requires cont"));
2184
2185            for i in 0..foreign_rets.len() {
2186                let f_i = foreign_rets[i];
2187                let l_i = local_rets[i];
2188                let ty = f_i.get_type();
2189                let v = err!(self.builder.build_phi(ty, ""));
2190                v.add_incoming(&[(&f_i, foreign_idx_block), (&l_i, local_idx_block)]);
2191                self.state.push1(v.as_basic_value());
2192            }
2193        } else if foreign_func_indices.is_empty() {
2194            let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
2195                ctx_ptr,
2196                func_type,
2197                func_ptr,
2198                Some(m0),
2199                is_return_call,
2200                &params,
2201            )?;
2202
2203            if is_return_call {
2204                self.emit_return_call(call_site, llvm_func_type)?;
2205            } else {
2206                self.abi
2207                    .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2208                    .iter()
2209                    .for_each(|ret| self.state.push1(*ret));
2210            }
2211        } else {
2212            let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
2213                ctx_ptr,
2214                func_type,
2215                func_ptr,
2216                None,
2217                is_return_call,
2218                &params,
2219            )?;
2220            if is_return_call {
2221                self.emit_return_call(call_site, llvm_func_type)?;
2222            } else {
2223                self.abi
2224                    .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2225                    .iter()
2226                    .for_each(|ret| self.state.push1(*ret));
2227            }
2228        }
2229
2230        Ok(())
2231    }
2232
2233    fn build_indirect_call(
2234        &mut self,
2235        ctx_ptr: PointerValue<'ctx>,
2236        func_type: &FunctionType,
2237        func_ptr: PointerValue<'ctx>,
2238        m0_param: Option<PointerValue<'ctx>>,
2239        is_return_call: bool,
2240    ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
2241        let params = self.state.popn_save_extra(func_type.params().len())?;
2242        self.build_indirect_call_with_params(
2243            ctx_ptr,
2244            func_type,
2245            func_ptr,
2246            m0_param,
2247            is_return_call,
2248            &params,
2249        )
2250    }
2251
2252    fn build_indirect_call_with_params(
2253        &mut self,
2254        ctx_ptr: PointerValue<'ctx>,
2255        func_type: &FunctionType,
2256        func_ptr: PointerValue<'ctx>,
2257        m0_param: Option<PointerValue<'ctx>>,
2258        is_return_call: bool,
2259        params: &[(BasicValueEnum<'ctx>, ExtraInfo)],
2260    ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
2261        let (llvm_func_type, llvm_func_attrs) = self.abi.func_type_to_llvm(
2262            self.context,
2263            self.intrinsics,
2264            Some(self.ctx.get_offsets()),
2265            func_type,
2266            m0_param.is_some(),
2267        )?;
2268
2269        // Apply pending canonicalization.
2270        let params = params
2271            .iter()
2272            .zip(func_type.params().iter())
2273            .map(|((v, info), wasm_ty)| match wasm_ty {
2274                Type::F32 => err_nt!(self.builder.build_bit_cast(
2275                    self.apply_pending_canonicalization(*v, *info)?,
2276                    self.intrinsics.f32_ty,
2277                    "",
2278                )),
2279                Type::F64 => err_nt!(self.builder.build_bit_cast(
2280                    self.apply_pending_canonicalization(*v, *info)?,
2281                    self.intrinsics.f64_ty,
2282                    "",
2283                )),
2284                Type::V128 => self.apply_pending_canonicalization(*v, *info),
2285                _ => Ok(*v),
2286            })
2287            .collect::<Result<Vec<_>, _>>()?;
2288
2289        let params = self.abi.args_to_call(
2290            &self.alloca_builder,
2291            func_type,
2292            &llvm_func_type,
2293            ctx_ptr,
2294            params.as_slice(),
2295            self.intrinsics,
2296            m0_param,
2297            is_return_call
2298                .then(|| self.current_sret_ptr(func_type))
2299                .flatten(),
2300        )?;
2301
2302        let typed_func_ptr = err!(self.builder.build_pointer_cast(
2303            func_ptr,
2304            self.context.ptr_type(AddressSpace::default()),
2305            "typed_func_ptr",
2306        ));
2307
2308        let call_site_local = self.build_indirect_call_or_invoke(
2309            llvm_func_type,
2310            typed_func_ptr,
2311            params.as_slice(),
2312            "then_block",
2313            is_return_call,
2314        )?;
2315        for (attr, attr_loc) in llvm_func_attrs {
2316            call_site_local.add_attribute(attr_loc, attr);
2317        }
2318
2319        Ok((call_site_local, llvm_func_type))
2320    }
2321
2322    fn build_indirect_call_or_invoke(
2323        &mut self,
2324        llvm_func_type: inkwell::types::FunctionType<'ctx>,
2325        func_ptr: PointerValue<'ctx>,
2326        params: &[BasicValueEnum<'ctx>],
2327        then_block_name: &str,
2328        is_return_call: bool,
2329    ) -> Result<CallSiteValue<'ctx>, CompileError> {
2330        // This is an unintuitive spec corner case: a tail call must bypass all enclosing
2331        // try_table blocks in the function. See https://github.com/WebAssembly/exception-handling/issues/249.
2332        if let Some(lpad) = self.state.get_innermost_landingpad()
2333            && !is_return_call
2334        {
2335            let then_block = self
2336                .context
2337                .append_basic_block(self.function, then_block_name);
2338
2339            let ret = err!(self.builder.build_indirect_invoke(
2340                llvm_func_type,
2341                func_ptr,
2342                params,
2343                then_block,
2344                lpad,
2345                "",
2346            ));
2347
2348            self.builder.position_at_end(then_block);
2349            Ok(ret)
2350        } else {
2351            let call_params = params
2352                .iter()
2353                .copied()
2354                .map(Into::into)
2355                .collect::<Vec<BasicMetadataValueEnum>>();
2356            Ok(err!(self.builder.build_indirect_call(
2357                llvm_func_type,
2358                func_ptr,
2359                call_params.as_slice(),
2360                ""
2361            )))
2362        }
2363    }
2364}
2365
2366pub struct LLVMFunctionCodeGenerator<'ctx, 'a> {
2367    m0_param: Option<PointerValue<'ctx>>,
2368    context: &'ctx Context,
2369    builder: Builder<'ctx>,
2370    alloca_builder: Builder<'ctx>,
2371    intrinsics: &'a Intrinsics<'ctx>,
2372    target_data: &'a TargetData,
2373    state: State<'ctx>,
2374    function: FunctionValue<'ctx>,
2375    locals: Vec<(BasicTypeEnum<'ctx>, PointerValue<'ctx>)>, // Contains params and locals
2376    ctx: CtxType<'ctx, 'a>,
2377    unreachable_depth: usize,
2378    memory_styles: &'a PrimaryMap<MemoryIndex, MemoryStyle>,
2379    _table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
2380    module: &'a Module<'ctx>,
2381    module_translation: &'a ModuleTranslationState,
2382    signature_hashes: &'a PrimaryMap<SignatureIndex, SignatureHash>,
2383    wasm_module: &'a ModuleInfo,
2384    #[allow(dead_code)]
2385    symbol_registry: &'a dyn SymbolRegistry,
2386    abi: &'a dyn Abi,
2387    config: &'a LLVM,
2388    target_triple: Triple,
2389    tags_cache: HashMap<i32, BasicValueEnum<'ctx>>,
2390    binary_fmt: target_lexicon::BinaryFormat,
2391    cpu_features: EnumSet<CpuFeature>,
2392    non_volatile_memory_ops: bool,
2393}
2394
2395impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
2396    fn quiet_nan(&self, value: BasicValueEnum<'ctx>) -> Result<BasicValueEnum<'ctx>, CompileError> {
2397        let intrinsic = if value
2398            .get_type()
2399            .eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2400        {
2401            Some(self.intrinsics.add_f32)
2402        } else if value
2403            .get_type()
2404            .eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2405        {
2406            Some(self.intrinsics.add_f64)
2407        } else if value
2408            .get_type()
2409            .eq(&self.intrinsics.f32x4_ty.as_basic_type_enum())
2410        {
2411            Some(self.intrinsics.add_f32x4)
2412        } else if value
2413            .get_type()
2414            .eq(&self.intrinsics.f64x2_ty.as_basic_type_enum())
2415        {
2416            Some(self.intrinsics.add_f64x2)
2417        } else {
2418            None
2419        };
2420
2421        match intrinsic {
2422            Some(intrinsic) => err_nt!(
2423                self.builder
2424                    .build_call(
2425                        intrinsic,
2426                        &[
2427                            value.into(),
2428                            value.get_type().const_zero().into(),
2429                            self.intrinsics.fp_rounding_md,
2430                            self.intrinsics.fp_exception_md,
2431                        ],
2432                        "",
2433                    )
2434                    .map(|v| v.try_as_basic_value().unwrap_basic())
2435            ),
2436            None => Ok(value),
2437        }
2438    }
2439
2440    fn finalize_minmax_result(
2441        &self,
2442        value: BasicValueEnum<'ctx>,
2443    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
2444        let ty = value.get_type();
2445        if ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2446            || ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2447        {
2448            let value = value.into_float_value();
2449            let is_nan = err!(self.builder.build_float_compare(
2450                FloatPredicate::UNO,
2451                value,
2452                value,
2453                "res_is_nan"
2454            ));
2455            let quiet = self.quiet_nan(value.as_basic_value_enum())?;
2456            let result =
2457                err!(
2458                    self.builder
2459                        .build_select(is_nan, quiet, value.as_basic_value_enum(), "")
2460                );
2461            Ok(result.as_basic_value_enum())
2462        } else if ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum()) {
2463            let value = value.into_vector_value();
2464            let is_nan = self
2465                .build_call_with_param_attributes(
2466                    self.intrinsics.cmp_f32x4,
2467                    &[
2468                        value.into(),
2469                        value.into(),
2470                        self.intrinsics.fp_uno_md,
2471                        self.intrinsics.fp_exception_md,
2472                    ],
2473                    "",
2474                )?
2475                .try_as_basic_value()
2476                .unwrap_basic()
2477                .into_vector_value();
2478            let quiet = self
2479                .quiet_nan(value.as_basic_value_enum())?
2480                .into_vector_value();
2481            let result = err!(self.builder.build_select(
2482                is_nan,
2483                quiet.as_basic_value_enum(),
2484                value.as_basic_value_enum(),
2485                "",
2486            ));
2487            Ok(result.as_basic_value_enum())
2488        } else if ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum()) {
2489            let value = value.into_vector_value();
2490            let is_nan = self
2491                .build_call_with_param_attributes(
2492                    self.intrinsics.cmp_f64x2,
2493                    &[
2494                        value.into(),
2495                        value.into(),
2496                        self.intrinsics.fp_uno_md,
2497                        self.intrinsics.fp_exception_md,
2498                    ],
2499                    "",
2500                )?
2501                .try_as_basic_value()
2502                .unwrap_basic()
2503                .into_vector_value();
2504            let quiet = self
2505                .quiet_nan(value.as_basic_value_enum())?
2506                .into_vector_value();
2507            let result = err!(self.builder.build_select(
2508                is_nan,
2509                quiet.as_basic_value_enum(),
2510                value.as_basic_value_enum(),
2511                "",
2512            ));
2513            Ok(result.as_basic_value_enum())
2514        } else {
2515            Ok(value)
2516        }
2517    }
2518
2519    fn finalize_rounding_result(
2520        &self,
2521        value: BasicValueEnum<'ctx>,
2522        info: ExtraInfo,
2523    ) -> Result<(BasicValueEnum<'ctx>, ExtraInfo), CompileError> {
2524        let ty = value.get_type();
2525        let is_f32 = ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum());
2526        let is_f64 = ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum());
2527        let is_f32x4 = ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum());
2528        let is_f64x2 = ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum());
2529        debug_assert!(is_f32 || is_f64 || is_f32x4 || is_f64x2);
2530
2531        if matches!(
2532            self.target_triple.architecture,
2533            Architecture::Riscv32(..) | Architecture::Riscv64(..)
2534        ) {
2535            if is_f32 || is_f64 {
2536                let input = value.into_float_value();
2537                let is_nan = err!(self.builder.build_float_compare(
2538                    FloatPredicate::UNO,
2539                    input,
2540                    input,
2541                    "res_is_nan",
2542                ));
2543                let canonical_nan_bits = if is_f32 {
2544                    self.intrinsics
2545                        .i32_ty
2546                        .const_int(CANONICAL_NAN_F32 as _, false)
2547                } else {
2548                    self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false)
2549                };
2550                let canonical_nan = err!(self.builder.build_bit_cast(
2551                    canonical_nan_bits,
2552                    ty,
2553                    "canonical_nan",
2554                ));
2555                let res =
2556                    err!(
2557                        self.builder
2558                            .build_select(is_nan, canonical_nan, value, "canonical_nan",)
2559                    );
2560                Ok((res, info))
2561            } else if is_f32x4 {
2562                let value = value.into_vector_value();
2563                let is_nan = err!(self.builder.build_call(
2564                    self.intrinsics.cmp_f32x4,
2565                    &[
2566                        value.into(),
2567                        value.into(),
2568                        self.intrinsics.fp_uno_md,
2569                        self.intrinsics.fp_exception_md,
2570                    ],
2571                    "",
2572                ))
2573                .try_as_basic_value()
2574                .unwrap_basic()
2575                .into_vector_value();
2576                let canonical_nan_bits = self
2577                    .intrinsics
2578                    .i32_ty
2579                    .const_int(CANONICAL_NAN_F32 as _, false);
2580                let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 4]);
2581                let canonical_nan = err!(self.builder.build_bit_cast(
2582                    canonical_nan_bits,
2583                    self.intrinsics.f32x4_ty,
2584                    "canonical_nan",
2585                ));
2586                let res = err!(self.builder.build_select(
2587                    is_nan,
2588                    canonical_nan.as_basic_value_enum(),
2589                    value.as_basic_value_enum(),
2590                    "canonical_nan",
2591                ));
2592                Ok((res, info))
2593            } else {
2594                let value = value.into_vector_value();
2595                let is_nan = err!(self.builder.build_call(
2596                    self.intrinsics.cmp_f64x2,
2597                    &[
2598                        value.into(),
2599                        value.into(),
2600                        self.intrinsics.fp_uno_md,
2601                        self.intrinsics.fp_exception_md,
2602                    ],
2603                    "",
2604                ))
2605                .try_as_basic_value()
2606                .unwrap_basic()
2607                .into_vector_value();
2608                let canonical_nan_bits = self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false);
2609                let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 2]);
2610                let canonical_nan = err!(self.builder.build_bit_cast(
2611                    canonical_nan_bits,
2612                    self.intrinsics.f64x2_ty,
2613                    "canonical_nan",
2614                ));
2615                let res = err!(self.builder.build_select(
2616                    is_nan,
2617                    canonical_nan.as_basic_value_enum(),
2618                    value.as_basic_value_enum(),
2619                    "canonical_nan",
2620                ));
2621                Ok((res, info))
2622            }
2623        } else {
2624            Ok((
2625                value,
2626                (info
2627                    | if is_f32 || is_f32x4 {
2628                        ExtraInfo::pending_f32_nan()
2629                    } else {
2630                        ExtraInfo::pending_f64_nan()
2631                    })?,
2632            ))
2633        }
2634    }
2635
2636    // Control Flow instructions.
2637    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#control-flow-instructions
2638    fn translate_control_flow_operator(&mut self, op: Operator) -> Result<(), CompileError> {
2639        match op {
2640            Operator::Block { blockty } => {
2641                let current_block = self
2642                    .builder
2643                    .get_insert_block()
2644                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2645
2646                let end_block = self.context.append_basic_block(self.function, "end");
2647                self.builder.position_at_end(end_block);
2648
2649                let phis: SmallVec<[PhiValue<'ctx>; 1]> = self
2650                    .module_translation
2651                    .blocktype_params_results(&blockty)?
2652                    .1
2653                    .iter()
2654                    .map(|&wp_ty| {
2655                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2656                            type_to_llvm(self.intrinsics, wasm_ty)
2657                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2658                        })
2659                    })
2660                    .collect::<Result<_, _>>()?;
2661
2662                self.state.push_block(
2663                    end_block,
2664                    phis,
2665                    self.module_translation
2666                        .blocktype_params_results(&blockty)?
2667                        .0
2668                        .len(),
2669                );
2670                self.builder.position_at_end(current_block);
2671            }
2672            Operator::Loop { blockty } => {
2673                let loop_body = self.context.append_basic_block(self.function, "loop_body");
2674                let loop_next = self.context.append_basic_block(self.function, "loop_outer");
2675                let pre_loop_block = self.builder.get_insert_block().unwrap();
2676
2677                let blocktypes = self.module_translation.blocktype_params_results(&blockty)?;
2678
2679                self.builder.position_at_end(loop_next);
2680                let phis = blocktypes
2681                    .1
2682                    .iter()
2683                    .map(|&wp_ty| {
2684                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2685                            type_to_llvm(self.intrinsics, wasm_ty)
2686                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2687                        })
2688                    })
2689                    .collect::<Result<_, _>>()?;
2690                self.builder.position_at_end(loop_body);
2691                let loop_phis: SmallVec<[PhiValue<'ctx>; 1]> = blocktypes
2692                    .0
2693                    .iter()
2694                    .map(|&wp_ty| {
2695                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2696                            type_to_llvm(self.intrinsics, wasm_ty)
2697                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2698                        })
2699                    })
2700                    .collect::<Result<_, _>>()?;
2701
2702                // Pop the loop parameters and canonicalize them in
2703                // pre_loop_block (before the terminator is emitted) so that the
2704                // select instruction dominates the phi uses.
2705                self.builder.position_at_end(pre_loop_block);
2706                for phi in loop_phis.iter().rev() {
2707                    let (value, info) = self.state.pop1_extra()?;
2708                    let value = self.apply_pending_canonicalization(value, info)?;
2709                    phi.add_incoming(&[(&value, pre_loop_block)]);
2710                }
2711
2712                err!(self.builder.build_unconditional_branch(loop_body));
2713
2714                self.builder.position_at_end(loop_body);
2715                for phi in &loop_phis {
2716                    self.state.push1(phi.as_basic_value());
2717                }
2718
2719                let num_inputs = loop_phis.len();
2720                self.state
2721                    .push_loop(loop_body, loop_next, loop_phis, phis, num_inputs);
2722            }
2723            Operator::Br { relative_depth } => {
2724                let frame = self.state.frame_at_depth(relative_depth)?;
2725
2726                let current_block = self
2727                    .builder
2728                    .get_insert_block()
2729                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2730
2731                let phis = if frame.is_loop() {
2732                    frame.loop_body_phis()
2733                } else {
2734                    frame.phis()
2735                };
2736
2737                let len = phis.len();
2738                let values = self.state.peekn_extra(len)?;
2739                let values = values
2740                    .iter()
2741                    .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2742                    .collect::<Result<Vec<_>, _>>()?;
2743
2744                // For each result of the block we're branching to,
2745                // pop a value off the value stack and load it into
2746                // the corresponding phi.
2747                for (phi, value) in phis.iter().zip(values) {
2748                    phi.add_incoming(&[(&value, current_block)]);
2749                }
2750
2751                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2752
2753                self.state.popn(len)?;
2754                self.state.reachable = false;
2755            }
2756            Operator::BrIf { relative_depth } => {
2757                let cond = self.state.pop1()?;
2758                let frame = self.state.frame_at_depth(relative_depth)?;
2759
2760                let current_block = self
2761                    .builder
2762                    .get_insert_block()
2763                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2764
2765                let phis = if frame.is_loop() {
2766                    frame.loop_body_phis()
2767                } else {
2768                    frame.phis()
2769                };
2770
2771                let param_stack = self.state.peekn_extra(phis.len())?;
2772                let param_stack = param_stack
2773                    .iter()
2774                    .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2775                    .collect::<Result<Vec<_>, _>>()?;
2776
2777                for (phi, value) in phis.iter().zip(param_stack) {
2778                    phi.add_incoming(&[(&value, current_block)]);
2779                }
2780
2781                let else_block = self.context.append_basic_block(self.function, "else");
2782
2783                let cond_value = err!(self.builder.build_int_compare(
2784                    IntPredicate::NE,
2785                    cond.into_int_value(),
2786                    self.intrinsics.i32_zero,
2787                    "",
2788                ));
2789                err!(self.builder.build_conditional_branch(
2790                    cond_value,
2791                    *frame.br_dest(),
2792                    else_block
2793                ));
2794                self.builder.position_at_end(else_block);
2795            }
2796            Operator::BrTable { ref targets } => {
2797                let current_block = self
2798                    .builder
2799                    .get_insert_block()
2800                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2801
2802                let index = self.state.pop1()?;
2803
2804                let default_frame = self.state.frame_at_depth(targets.default())?;
2805
2806                let phis = if default_frame.is_loop() {
2807                    default_frame.loop_body_phis()
2808                } else {
2809                    default_frame.phis()
2810                };
2811                let args = self.state.peekn(phis.len())?;
2812
2813                for (phi, value) in phis.iter().zip(args.iter()) {
2814                    phi.add_incoming(&[(value, current_block)]);
2815                }
2816
2817                let cases: Vec<_> = targets
2818                    .targets()
2819                    .enumerate()
2820                    .map(|(case_index, depth)| {
2821                        let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
2822                        let frame_result: Result<&ControlFrame, CompileError> =
2823                            self.state.frame_at_depth(depth);
2824                        let frame = match frame_result {
2825                            Ok(v) => v,
2826                            Err(e) => return Err(e),
2827                        };
2828                        let case_index_literal =
2829                            self.context.i32_type().const_int(case_index as u64, false);
2830                        let phis = if frame.is_loop() {
2831                            frame.loop_body_phis()
2832                        } else {
2833                            frame.phis()
2834                        };
2835                        for (phi, value) in phis.iter().zip(args.iter()) {
2836                            phi.add_incoming(&[(value, current_block)]);
2837                        }
2838
2839                        Ok((case_index_literal, *frame.br_dest()))
2840                    })
2841                    .collect::<Result<_, _>>()?;
2842
2843                err!(self.builder.build_switch(
2844                    index.into_int_value(),
2845                    *default_frame.br_dest(),
2846                    &cases[..],
2847                ));
2848
2849                let args_len = args.len();
2850                self.state.popn(args_len)?;
2851                self.state.reachable = false;
2852            }
2853            Operator::If { blockty } => {
2854                let current_block = self
2855                    .builder
2856                    .get_insert_block()
2857                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2858                let if_then_block = self.context.append_basic_block(self.function, "if_then");
2859                let if_else_block = self.context.append_basic_block(self.function, "if_else");
2860                let end_block = self.context.append_basic_block(self.function, "if_end");
2861
2862                let end_phis = {
2863                    self.builder.position_at_end(end_block);
2864
2865                    let phis = self
2866                        .module_translation
2867                        .blocktype_params_results(&blockty)?
2868                        .1
2869                        .iter()
2870                        .map(|&wp_ty| {
2871                            err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2872                                type_to_llvm(self.intrinsics, wasm_ty)
2873                                    .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2874                            })
2875                        })
2876                        .collect::<Result<_, _>>()?;
2877
2878                    self.builder.position_at_end(current_block);
2879                    phis
2880                };
2881
2882                let block_param_types = self
2883                    .module_translation
2884                    .blocktype_params_results(&blockty)?
2885                    .0
2886                    .iter()
2887                    .map(|&wp_ty| {
2888                        err_nt!(wptype_to_type(wp_ty))
2889                            .and_then(|wasm_ty| type_to_llvm(self.intrinsics, wasm_ty))
2890                    })
2891                    .collect::<Result<Vec<_>, _>>()?;
2892
2893                // Build else_phis in if_else_block and then_phis in if_then_block.
2894                self.builder.position_at_end(if_else_block);
2895                let else_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2896                    .iter()
2897                    .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2898                    .collect::<Result<SmallVec<_>, _>>()?;
2899                self.builder.position_at_end(if_then_block);
2900                let then_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2901                    .iter()
2902                    .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2903                    .collect::<Result<SmallVec<_>, _>>()?;
2904
2905                // Pop the condition.
2906                let cond = self.state.pop1()?;
2907
2908                // Pop the block parameters and canonicalize them in current_block
2909                // (before the terminator is emitted) so that the select instruction
2910                // dominates the phi uses.
2911                self.builder.position_at_end(current_block);
2912                for (else_phi, then_phi) in else_phis.iter().rev().zip(then_phis.iter().rev()) {
2913                    let (value, info) = self.state.pop1_extra()?;
2914                    let value = self.apply_pending_canonicalization(value, info)?;
2915                    else_phi.add_incoming(&[(&value, current_block)]);
2916                    then_phi.add_incoming(&[(&value, current_block)]);
2917                }
2918
2919                let cond_value = err!(self.builder.build_int_compare(
2920                    IntPredicate::NE,
2921                    cond.into_int_value(),
2922                    self.intrinsics.i32_zero,
2923                    "",
2924                ));
2925
2926                err!(self.builder.build_conditional_branch(
2927                    cond_value,
2928                    if_then_block,
2929                    if_else_block
2930                ));
2931
2932                self.builder.position_at_end(if_then_block);
2933                for phi in then_phis.iter() {
2934                    self.state.push1(phi.as_basic_value());
2935                }
2936
2937                self.state.push_if(
2938                    if_then_block,
2939                    if_else_block,
2940                    end_block,
2941                    then_phis,
2942                    else_phis,
2943                    end_phis,
2944                    block_param_types.len(),
2945                );
2946            }
2947            Operator::Else => {
2948                if self.state.reachable {
2949                    let frame = self.state.frame_at_depth(0)?;
2950                    let current_block = self.builder.get_insert_block().ok_or_else(|| {
2951                        CompileError::Codegen("not currently in a block".to_string())
2952                    })?;
2953
2954                    for phi in frame.phis().to_vec().iter().rev() {
2955                        let (value, info) = self.state.pop1_extra()?;
2956                        let value = self.apply_pending_canonicalization(value, info)?;
2957                        phi.add_incoming(&[(&value, current_block)])
2958                    }
2959
2960                    let frame = self.state.frame_at_depth(0)?;
2961                    err!(self.builder.build_unconditional_branch(*frame.code_after()));
2962                }
2963
2964                let (if_else_block, if_else_state) = if let ControlFrame::IfElse {
2965                    if_else,
2966                    if_else_state,
2967                    ..
2968                } = self.state.frame_at_depth_mut(0)?
2969                {
2970                    (if_else, if_else_state)
2971                } else {
2972                    unreachable!()
2973                };
2974
2975                *if_else_state = IfElseState::Else;
2976
2977                self.builder.position_at_end(*if_else_block);
2978                self.state.reachable = true;
2979
2980                if let ControlFrame::IfElse { else_phis, .. } = self.state.frame_at_depth(0)? {
2981                    // Push our own 'else' phi nodes to the stack.
2982                    for phi in else_phis.clone().iter() {
2983                        self.state.push1(phi.as_basic_value());
2984                    }
2985                };
2986            }
2987
2988            Operator::End => {
2989                let frame = self.state.pop_frame()?;
2990                let current_block = self
2991                    .builder
2992                    .get_insert_block()
2993                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2994
2995                if self.state.reachable {
2996                    for phi in frame.phis().iter().rev() {
2997                        let (value, info) = self.state.pop1_extra()?;
2998                        let value = self.apply_pending_canonicalization(value, info)?;
2999                        phi.add_incoming(&[(&value, current_block)]);
3000                    }
3001
3002                    err!(self.builder.build_unconditional_branch(*frame.code_after()));
3003                }
3004
3005                if let ControlFrame::IfElse {
3006                    if_else,
3007                    next,
3008                    if_else_state: IfElseState::If,
3009                    else_phis,
3010                    ..
3011                } = &frame
3012                {
3013                    for (phi, else_phi) in frame.phis().iter().zip(else_phis.iter()) {
3014                        phi.add_incoming(&[(&else_phi.as_basic_value(), *if_else)]);
3015                    }
3016                    self.builder.position_at_end(*if_else);
3017                    err!(self.builder.build_unconditional_branch(*next));
3018                } else if let ControlFrame::Landingpad { .. } = &frame {
3019                    self.state.pop_landingpad();
3020                };
3021
3022                self.builder.position_at_end(*frame.code_after());
3023                self.state.reset_stack(&frame);
3024
3025                self.state.reachable = true;
3026
3027                // Push each phi value to the value stack.
3028                for phi in frame.phis() {
3029                    if phi.count_incoming() != 0 {
3030                        self.state.push1(phi.as_basic_value());
3031                    } else {
3032                        // TODO if there are no incoming phi values, it means
3033                        // this block has no predecessors, and we can skip it
3034                        // altogether. However, fixing this is non-trivial as
3035                        // some places in the code rely on code getting generated
3036                        // for unreachable end blocks. For now, we let LLVM remove
3037                        // the block during dead code elimination instead.
3038                        let basic_ty = phi.as_basic_value().get_type();
3039                        let placeholder_value = basic_ty.const_zero();
3040                        self.state.push1(placeholder_value);
3041                        phi.as_instruction().erase_from_basic_block();
3042                    }
3043                }
3044            }
3045            Operator::Return => {
3046                let current_block = self
3047                    .builder
3048                    .get_insert_block()
3049                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
3050
3051                let frame = self.state.outermost_frame()?;
3052                for phi in frame.phis().to_vec().iter().rev() {
3053                    let (arg, info) = self.state.pop1_extra()?;
3054                    let arg = self.apply_pending_canonicalization(arg, info)?;
3055                    phi.add_incoming(&[(&arg, current_block)]);
3056                }
3057                let frame = self.state.outermost_frame()?;
3058                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
3059
3060                self.state.reachable = false;
3061            }
3062
3063            Operator::Unreachable => {
3064                self.build_call_with_param_attributes(
3065                    self.intrinsics.throw_trap,
3066                    &[self.intrinsics.trap_unreachable.into()],
3067                    "throw",
3068                )?;
3069                err!(self.builder.build_unreachable());
3070
3071                self.state.reachable = false;
3072            }
3073            _ => unreachable!(),
3074        }
3075
3076        Ok(())
3077    }
3078
3079    // Basic instructions.
3080    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#basic-instructions
3081    fn translate_basic_operator(&mut self, op: Operator) -> Result<(), CompileError> {
3082        let vmctx = &self.ctx.basic().into_pointer_value();
3083
3084        match op {
3085            Operator::Nop => {
3086                // Do nothing.
3087            }
3088            Operator::Drop => {
3089                self.state.pop1()?;
3090            }
3091
3092            // Generate const values.
3093            Operator::I32Const { value } => {
3094                let i = self.intrinsics.i32_ty.const_int(value as u64, false);
3095                let info = if is_f32_arithmetic(value as u32) {
3096                    ExtraInfo::arithmetic_f32()
3097                } else {
3098                    Default::default()
3099                };
3100                self.state.push1_extra(i, info);
3101            }
3102            Operator::I64Const { value } => {
3103                let i = self.intrinsics.i64_ty.const_int(value as u64, false);
3104                let info = if is_f64_arithmetic(value as u64) {
3105                    ExtraInfo::arithmetic_f64()
3106                } else {
3107                    Default::default()
3108                };
3109                self.state.push1_extra(i, info);
3110            }
3111            Operator::F32Const { value } => {
3112                let bits = self.intrinsics.i32_ty.const_int(value.bits() as u64, false);
3113                let info = if is_f32_arithmetic(value.bits()) {
3114                    ExtraInfo::arithmetic_f32()
3115                } else {
3116                    Default::default()
3117                };
3118                let f = err!(
3119                    self.builder
3120                        .build_bit_cast(bits, self.intrinsics.f32_ty, "f")
3121                );
3122                self.state.push1_extra(f, info);
3123            }
3124            Operator::F64Const { value } => {
3125                let bits = self.intrinsics.i64_ty.const_int(value.bits(), false);
3126                let info = if is_f64_arithmetic(value.bits()) {
3127                    ExtraInfo::arithmetic_f64()
3128                } else {
3129                    Default::default()
3130                };
3131                let f = err!(
3132                    self.builder
3133                        .build_bit_cast(bits, self.intrinsics.f64_ty, "f")
3134                );
3135                self.state.push1_extra(f, info);
3136            }
3137            Operator::V128Const { value } => {
3138                let mut hi: [u8; 8] = Default::default();
3139                let mut lo: [u8; 8] = Default::default();
3140                hi.copy_from_slice(&value.bytes()[0..8]);
3141                lo.copy_from_slice(&value.bytes()[8..16]);
3142                let packed = [u64::from_le_bytes(hi), u64::from_le_bytes(lo)];
3143                let i = self
3144                    .intrinsics
3145                    .i128_ty
3146                    .const_int_arbitrary_precision(&packed);
3147                let mut quad1: [u8; 4] = Default::default();
3148                let mut quad2: [u8; 4] = Default::default();
3149                let mut quad3: [u8; 4] = Default::default();
3150                let mut quad4: [u8; 4] = Default::default();
3151                quad1.copy_from_slice(&value.bytes()[0..4]);
3152                quad2.copy_from_slice(&value.bytes()[4..8]);
3153                quad3.copy_from_slice(&value.bytes()[8..12]);
3154                quad4.copy_from_slice(&value.bytes()[12..16]);
3155                let mut info: ExtraInfo = Default::default();
3156                if is_f32_arithmetic(u32::from_le_bytes(quad1))
3157                    && is_f32_arithmetic(u32::from_le_bytes(quad2))
3158                    && is_f32_arithmetic(u32::from_le_bytes(quad3))
3159                    && is_f32_arithmetic(u32::from_le_bytes(quad4))
3160                {
3161                    info |= ExtraInfo::arithmetic_f32();
3162                }
3163                if is_f64_arithmetic(packed[0]) && is_f64_arithmetic(packed[1]) {
3164                    info |= ExtraInfo::arithmetic_f64();
3165                }
3166                self.state.push1_extra(i, info);
3167            }
3168
3169            Operator::I8x16Splat => {
3170                let (v, i) = self.state.pop1_extra()?;
3171                let v = v.into_int_value();
3172                let v = err!(
3173                    self.builder
3174                        .build_int_truncate(v, self.intrinsics.i8_ty, "")
3175                );
3176                let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
3177                let res = err!(
3178                    self.builder
3179                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3180                );
3181                self.state.push1_extra(res, i);
3182            }
3183            Operator::I16x8Splat => {
3184                let (v, i) = self.state.pop1_extra()?;
3185                let v = v.into_int_value();
3186                let v = err!(
3187                    self.builder
3188                        .build_int_truncate(v, self.intrinsics.i16_ty, "")
3189                );
3190                let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
3191                let res = err!(
3192                    self.builder
3193                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3194                );
3195                self.state.push1_extra(res, i);
3196            }
3197            Operator::I32x4Splat => {
3198                let (v, i) = self.state.pop1_extra()?;
3199                let res = self.splat_vector(v, self.intrinsics.i32x4_ty)?;
3200                let res = err!(
3201                    self.builder
3202                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3203                );
3204                self.state.push1_extra(res, i);
3205            }
3206            Operator::I64x2Splat => {
3207                let (v, i) = self.state.pop1_extra()?;
3208                let res = self.splat_vector(v, self.intrinsics.i64x2_ty)?;
3209                let res = err!(
3210                    self.builder
3211                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3212                );
3213                self.state.push1_extra(res, i);
3214            }
3215            Operator::F32x4Splat => {
3216                let (v, i) = self.state.pop1_extra()?;
3217                let res = self.splat_vector(v, self.intrinsics.f32x4_ty)?;
3218                let res = err!(
3219                    self.builder
3220                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3221                );
3222                // The spec is unclear, we interpret splat as preserving NaN
3223                // payload bits.
3224                self.state.push1_extra(res, i);
3225            }
3226            Operator::F64x2Splat => {
3227                let (v, i) = self.state.pop1_extra()?;
3228                let res = self.splat_vector(v, self.intrinsics.f64x2_ty)?;
3229                let res = err!(
3230                    self.builder
3231                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3232                );
3233                // The spec is unclear, we interpret splat as preserving NaN
3234                // payload bits.
3235                self.state.push1_extra(res, i);
3236            }
3237
3238            // Operate on self.locals.
3239            Operator::LocalGet { local_index } => {
3240                let (type_value, pointer_value) = self.locals[local_index as usize];
3241                let v = err!(self.builder.build_load(
3242                    type_value,
3243                    pointer_value,
3244                    &format!("local_{local_index}_get")
3245                ));
3246                tbaa_label(
3247                    self.module,
3248                    self.intrinsics,
3249                    format!("local {local_index}"),
3250                    v.as_instruction_value().unwrap(),
3251                );
3252                self.state.push1(v);
3253            }
3254            Operator::LocalSet { local_index } => {
3255                let pointer_value = self.locals[local_index as usize].1;
3256                let (v, i) = self.state.pop1_extra()?;
3257                let v = self.apply_pending_canonicalization(v, i)?;
3258                let store = err!(self.builder.build_store(pointer_value, v));
3259                tbaa_label(
3260                    self.module,
3261                    self.intrinsics,
3262                    format!("local {local_index}"),
3263                    store,
3264                );
3265            }
3266            Operator::LocalTee { local_index } => {
3267                let pointer_value = self.locals[local_index as usize].1;
3268                let (v, i) = self.state.peek1_extra()?;
3269                let v = self.apply_pending_canonicalization(v, i)?;
3270                let store = err!(self.builder.build_store(pointer_value, v));
3271                tbaa_label(
3272                    self.module,
3273                    self.intrinsics,
3274                    format!("local {local_index}"),
3275                    store,
3276                );
3277            }
3278
3279            Operator::GlobalGet { global_index } => {
3280                let global_index = GlobalIndex::from_u32(global_index);
3281                match self
3282                    .ctx
3283                    .global(global_index, self.intrinsics, self.module)?
3284                {
3285                    GlobalCache::Const { value } => {
3286                        self.state.push1(*value);
3287                    }
3288                    GlobalCache::Mut {
3289                        ptr_to_value,
3290                        value_type,
3291                    } => {
3292                        let value = err!(self.builder.build_load(*value_type, *ptr_to_value, ""));
3293                        tbaa_label(
3294                            self.module,
3295                            self.intrinsics,
3296                            format!("global {}", global_index.as_u32()),
3297                            value.as_instruction_value().unwrap(),
3298                        );
3299                        self.state.push1(value);
3300                    }
3301                }
3302            }
3303            Operator::GlobalSet { global_index } => {
3304                let global_index = GlobalIndex::from_u32(global_index);
3305                match self
3306                    .ctx
3307                    .global(global_index, self.intrinsics, self.module)?
3308                {
3309                    GlobalCache::Const { value: _ } => {
3310                        return Err(CompileError::Codegen(format!(
3311                            "global.set on immutable global index {}",
3312                            global_index.as_u32()
3313                        )));
3314                    }
3315                    GlobalCache::Mut { ptr_to_value, .. } => {
3316                        let ptr_to_value = *ptr_to_value;
3317                        let (value, info) = self.state.pop1_extra()?;
3318                        let value = self.apply_pending_canonicalization(value, info)?;
3319                        let store = err!(self.builder.build_store(ptr_to_value, value));
3320                        tbaa_label(
3321                            self.module,
3322                            self.intrinsics,
3323                            format!("global {}", global_index.as_u32()),
3324                            store,
3325                        );
3326                    }
3327                }
3328            }
3329
3330            // `TypedSelect` must be used for extern refs so ref counting should
3331            // be done with TypedSelect. But otherwise they're the same.
3332            Operator::TypedSelect { .. } | Operator::Select => {
3333                let ((v1, i1), (v2, i2), (cond, _)) = self.state.pop3_extra()?;
3334                // We don't bother canonicalizing 'cond' here because we only
3335                // compare it to zero, and that's invariant under
3336                // canonicalization.
3337
3338                // If the pending bits of v1 and v2 are the same, we can pass
3339                // them along to the result. Otherwise, apply pending
3340                // canonicalization now.
3341                let (v1, i1, v2, i2) = if i1.has_pending_f32_nan() != i2.has_pending_f32_nan()
3342                    || i1.has_pending_f64_nan() != i2.has_pending_f64_nan()
3343                {
3344                    (
3345                        self.apply_pending_canonicalization(v1, i1)?,
3346                        i1.strip_pending(),
3347                        self.apply_pending_canonicalization(v2, i2)?,
3348                        i2.strip_pending(),
3349                    )
3350                } else {
3351                    (v1, i1, v2, i2)
3352                };
3353                let cond_value = err!(self.builder.build_int_compare(
3354                    IntPredicate::NE,
3355                    cond.into_int_value(),
3356                    self.intrinsics.i32_zero,
3357                    "",
3358                ));
3359                let res = err!(self.builder.build_select(cond_value, v1, v2, ""));
3360                let info = {
3361                    let mut info = (i1.strip_pending() & i2.strip_pending())?;
3362                    if i1.has_pending_f32_nan() {
3363                        debug_assert!(i2.has_pending_f32_nan());
3364                        info = (info | ExtraInfo::pending_f32_nan())?;
3365                    }
3366                    if i1.has_pending_f64_nan() {
3367                        debug_assert!(i2.has_pending_f64_nan());
3368                        info = (info | ExtraInfo::pending_f64_nan())?;
3369                    }
3370                    info
3371                };
3372                self.state.push1_extra(res, info);
3373            }
3374            Operator::Call { function_index } | Operator::ReturnCall { function_index } => {
3375                let is_return_call = matches!(op, Operator::ReturnCall { .. });
3376                let func_index = FunctionIndex::from_u32(function_index);
3377                let sigindex = &self.wasm_module.functions[func_index];
3378                let func_type = &self.wasm_module.signatures[*sigindex];
3379
3380                let FunctionCache {
3381                    func,
3382                    llvm_func_type,
3383                    vmctx: callee_vmctx,
3384                    imported_include_m0_param,
3385                    attrs,
3386                } = if let Some(local_func_index) = self.wasm_module.local_func_index(func_index) {
3387                    self.ctx.local_func(
3388                        local_func_index,
3389                        func_index,
3390                        self.intrinsics,
3391                        self.module,
3392                        self.context,
3393                        func_type,
3394                        &CompiledKind::Local(local_func_index, String::new()).linkage_name(),
3395                    )?
3396                } else {
3397                    self.ctx
3398                        .imported_func(func_index, self.intrinsics, self.context, func_type)?
3399                };
3400                let llvm_func_type = *llvm_func_type;
3401                let func = *func;
3402                let callee_vmctx = *callee_vmctx;
3403                let imported_include_m0_param = *imported_include_m0_param;
3404                let attrs = attrs.clone();
3405
3406                /*
3407                let func_ptr = self.llvm.functions.borrow_mut()[&func_index];
3408
3409                (params, func_ptr.as_global_value().as_pointer_value())
3410                */
3411                let params = self.state.popn_save_extra(func_type.params().len())?;
3412
3413                // Apply pending canonicalization.
3414                let params = params
3415                    .iter()
3416                    .zip(func_type.params().iter())
3417                    .map(|((v, info), wasm_ty)| match wasm_ty {
3418                        Type::F32 => err_nt!(self.builder.build_bit_cast(
3419                            self.apply_pending_canonicalization(*v, *info)?,
3420                            self.intrinsics.f32_ty,
3421                            "",
3422                        )),
3423                        Type::F64 => err_nt!(self.builder.build_bit_cast(
3424                            self.apply_pending_canonicalization(*v, *info)?,
3425                            self.intrinsics.f64_ty,
3426                            "",
3427                        )),
3428                        Type::V128 => self.apply_pending_canonicalization(*v, *info),
3429                        _ => Ok(*v),
3430                    })
3431                    .collect::<Result<Vec<_>, _>>()?;
3432
3433                if let (Some(m0_param), Some(include_m0_param)) =
3434                    (self.m0_param, imported_include_m0_param)
3435                {
3436                    /* For imported functions, we must be careful about when to include `g0_param`:
3437                    imports from another Wasm module expect it, while host-function imports do not.
3438                    We intentionally not leverage tail-calls for such function calls. */
3439                    let (llvm_func_type_no_m0, llvm_func_attrs_no_m0) =
3440                        self.abi.func_type_to_llvm(
3441                            self.context,
3442                            self.intrinsics,
3443                            Some(self.ctx.get_offsets()),
3444                            func_type,
3445                            false,
3446                        )?;
3447                    let params_with_m0 = self.abi.args_to_call(
3448                        &self.alloca_builder,
3449                        func_type,
3450                        &llvm_func_type,
3451                        callee_vmctx.into_pointer_value(),
3452                        params.as_slice(),
3453                        self.intrinsics,
3454                        Some(m0_param),
3455                        is_return_call
3456                            .then(|| self.current_sret_ptr(func_type))
3457                            .flatten(),
3458                    )?;
3459                    let params_no_m0 = self.abi.args_to_call(
3460                        &self.alloca_builder,
3461                        func_type,
3462                        &llvm_func_type_no_m0,
3463                        callee_vmctx.into_pointer_value(),
3464                        params.as_slice(),
3465                        self.intrinsics,
3466                        None,
3467                        is_return_call
3468                            .then(|| self.current_sret_ptr(func_type))
3469                            .flatten(),
3470                    )?;
3471
3472                    let include_m0_call_block = self
3473                        .context
3474                        .append_basic_block(self.function, "call_block_with_m0");
3475                    let skip_m0_call_block =
3476                        self.context.append_basic_block(self.function, "call_block");
3477                    let call_cont = self.context.append_basic_block(self.function, "call_cont");
3478                    err!(self.builder.build_conditional_branch(
3479                        include_m0_param,
3480                        include_m0_call_block,
3481                        skip_m0_call_block,
3482                    ));
3483
3484                    self.builder.position_at_end(include_m0_call_block);
3485                    let call_site_with_m0 = self.build_indirect_call_or_invoke(
3486                        llvm_func_type,
3487                        func,
3488                        params_with_m0.as_slice(),
3489                        "then_block_with_m0",
3490                        is_return_call,
3491                    )?;
3492                    for (attr, attr_loc) in &attrs {
3493                        call_site_with_m0.add_attribute(*attr_loc, *attr);
3494                    }
3495                    let rets_with_m0 = self.abi.rets_from_call(
3496                        &self.builder,
3497                        self.intrinsics,
3498                        call_site_with_m0,
3499                        func_type,
3500                    )?;
3501                    let with_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3502                        CompileError::Codegen(
3503                            "missing insertion block after call with m0".to_string(),
3504                        )
3505                    })?;
3506                    err!(self.builder.build_unconditional_branch(call_cont));
3507
3508                    self.builder.position_at_end(skip_m0_call_block);
3509                    let call_site_no_m0 = self.build_indirect_call_or_invoke(
3510                        llvm_func_type_no_m0,
3511                        func,
3512                        params_no_m0.as_slice(),
3513                        "then_block",
3514                        is_return_call,
3515                    )?;
3516                    for (attr, attr_loc) in &llvm_func_attrs_no_m0 {
3517                        call_site_no_m0.add_attribute(*attr_loc, *attr);
3518                    }
3519                    let rets_no_m0 = self.abi.rets_from_call(
3520                        &self.builder,
3521                        self.intrinsics,
3522                        call_site_no_m0,
3523                        func_type,
3524                    )?;
3525                    let no_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3526                        CompileError::Codegen(
3527                            "missing insertion block after call without m0".to_string(),
3528                        )
3529                    })?;
3530                    err!(self.builder.build_unconditional_branch(call_cont));
3531
3532                    self.builder.position_at_end(call_cont);
3533                    for i in 0..rets_with_m0.len() {
3534                        let with_m0 = rets_with_m0[i];
3535                        let no_m0 = rets_no_m0[i];
3536                        let phi = err!(self.builder.build_phi(with_m0.get_type(), ""));
3537                        phi.add_incoming(&[(&with_m0, with_m0_pred), (&no_m0, no_m0_pred)]);
3538                        self.state.push1(phi.as_basic_value());
3539                    }
3540                } else {
3541                    let params = self.abi.args_to_call(
3542                        &self.alloca_builder,
3543                        func_type,
3544                        &llvm_func_type,
3545                        callee_vmctx.into_pointer_value(),
3546                        params.as_slice(),
3547                        self.intrinsics,
3548                        self.m0_param,
3549                        if is_return_call {
3550                            self.current_sret_ptr(func_type)
3551                        } else {
3552                            None
3553                        },
3554                    )?;
3555
3556                    let call_site = self.build_indirect_call_or_invoke(
3557                        llvm_func_type,
3558                        func,
3559                        params.as_slice(),
3560                        "then_block",
3561                        is_return_call,
3562                    )?;
3563                    for (attr, attr_loc) in attrs {
3564                        call_site.add_attribute(attr_loc, attr);
3565                    }
3566
3567                    if is_return_call {
3568                        self.emit_return_call(call_site, llvm_func_type)?;
3569                        self.state.reachable = false;
3570                    } else {
3571                        self.abi
3572                            .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3573                            .iter()
3574                            .for_each(|ret| self.state.push1(*ret));
3575                    }
3576                }
3577            }
3578            Operator::CallIndirect {
3579                type_index,
3580                table_index,
3581            }
3582            | Operator::ReturnCallIndirect {
3583                type_index,
3584                table_index,
3585            } => {
3586                let is_return_call = matches!(op, Operator::ReturnCallIndirect { .. });
3587                let sigindex = SignatureIndex::from_u32(type_index);
3588                let table_index = TableIndex::from_u32(table_index);
3589                let func_type = &self.wasm_module.signatures[sigindex];
3590                let table = self.wasm_module.tables.get(table_index).unwrap();
3591                let local_fixed_funcref_table = self
3592                    .wasm_module
3593                    .local_table_index(table_index)
3594                    .filter(|_| table.is_fixed_funcref_table());
3595                let expected_signature_hash = self
3596                    .intrinsics
3597                    .i32_ty
3598                    .const_int(u64::from(self.signature_hashes[sigindex].as_u32()), false);
3599
3600                let func_index = self.state.pop1()?.into_int_value();
3601                let generic_table = if local_fixed_funcref_table.is_none() {
3602                    Some(self.ctx.table(
3603                        table_index,
3604                        self.intrinsics,
3605                        self.module,
3606                        &self.builder,
3607                    )?)
3608                } else {
3609                    None
3610                };
3611
3612                let table_bound = if local_fixed_funcref_table.is_some() {
3613                    self.intrinsics
3614                        .i32_ty
3615                        .const_int(table.minimum.into(), false)
3616                } else {
3617                    let (_, table_bound) = *generic_table.as_ref().unwrap();
3618                    err!(self.builder.build_int_truncate(
3619                        table_bound,
3620                        self.intrinsics.i32_ty,
3621                        "truncated_table_bounds",
3622                    ))
3623                };
3624
3625                // First, check if the index is outside of the table bounds.
3626                let index_in_bounds = err!(self.builder.build_int_compare(
3627                    IntPredicate::ULT,
3628                    func_index,
3629                    table_bound,
3630                    "index_in_bounds",
3631                ));
3632
3633                let index_in_bounds = self
3634                    .build_call_with_param_attributes(
3635                        self.intrinsics.expect_i1,
3636                        &[
3637                            index_in_bounds.into(),
3638                            self.intrinsics.i1_ty.const_int(1, false).into(),
3639                        ],
3640                        "index_in_bounds_expect",
3641                    )?
3642                    .try_as_basic_value()
3643                    .unwrap_basic()
3644                    .into_int_value();
3645
3646                let in_bounds_continue_block = self
3647                    .context
3648                    .append_basic_block(self.function, "in_bounds_continue_block");
3649                let not_in_bounds_block = self
3650                    .context
3651                    .append_basic_block(self.function, "not_in_bounds_block");
3652                err!(self.builder.build_conditional_branch(
3653                    index_in_bounds,
3654                    in_bounds_continue_block,
3655                    not_in_bounds_block,
3656                ));
3657                self.builder.position_at_end(not_in_bounds_block);
3658                self.build_call_with_param_attributes(
3659                    self.intrinsics.throw_trap,
3660                    &[self.intrinsics.trap_table_access_oob.into()],
3661                    "throw",
3662                )?;
3663                err!(self.builder.build_unreachable());
3664                self.builder.position_at_end(in_bounds_continue_block);
3665
3666                let anyfunc_struct_ptr = if let Some(local_table_index) = local_fixed_funcref_table
3667                {
3668                    let anyfuncs = self.ctx.fixed_funcref_table_anyfuncs(
3669                        local_table_index,
3670                        self.intrinsics,
3671                        &self.builder,
3672                    )?;
3673                    unsafe {
3674                        err!(self.builder.build_in_bounds_gep(
3675                            self.intrinsics.anyfunc_ty,
3676                            anyfuncs,
3677                            &[func_index],
3678                            "anyfunc_struct_ptr",
3679                        ))
3680                    }
3681                } else {
3682                    let (table_base, _) = *generic_table.as_ref().unwrap();
3683
3684                    // We assume the table has the `funcref` (pointer to `anyfunc`)
3685                    // element type.
3686                    let casted_table_base = err!(self.builder.build_pointer_cast(
3687                        table_base,
3688                        self.context.ptr_type(AddressSpace::default()),
3689                        "casted_table_base",
3690                    ));
3691
3692                    let funcref_ptr = unsafe {
3693                        err!(self.builder.build_in_bounds_gep(
3694                            self.intrinsics.ptr_ty,
3695                            casted_table_base,
3696                            &[func_index],
3697                            "funcref_ptr",
3698                        ))
3699                    };
3700
3701                    // a funcref (pointer to `anyfunc`)
3702                    let anyfunc_struct_ptr = err!(self.builder.build_load(
3703                        self.intrinsics.ptr_ty,
3704                        funcref_ptr,
3705                        "anyfunc_struct_ptr",
3706                    ))
3707                    .into_pointer_value();
3708
3709                    if !table.readonly {
3710                        // trap if we're trying to call a null funcref
3711                        let funcref_not_null = err!(
3712                            self.builder
3713                                .build_is_not_null(anyfunc_struct_ptr, "null_funcref_check")
3714                        );
3715
3716                        let funcref_continue_deref_block = self
3717                            .context
3718                            .append_basic_block(self.function, "funcref_continue_deref_block");
3719
3720                        let funcref_is_null_block = self
3721                            .context
3722                            .append_basic_block(self.function, "funcref_is_null_block");
3723                        err!(self.builder.build_conditional_branch(
3724                            funcref_not_null,
3725                            funcref_continue_deref_block,
3726                            funcref_is_null_block,
3727                        ));
3728                        self.builder.position_at_end(funcref_is_null_block);
3729                        self.build_call_with_param_attributes(
3730                            self.intrinsics.throw_trap,
3731                            &[self.intrinsics.trap_call_indirect_null.into()],
3732                            "throw",
3733                        )?;
3734                        err!(self.builder.build_unreachable());
3735                        self.builder.position_at_end(funcref_continue_deref_block);
3736                    }
3737
3738                    anyfunc_struct_ptr
3739                };
3740
3741                // Load things from the anyfunc data structure.
3742                let sig_hash_ptr = self
3743                    .builder
3744                    .build_struct_gep(
3745                        self.intrinsics.anyfunc_ty,
3746                        anyfunc_struct_ptr,
3747                        1,
3748                        "sig_hash_ptr",
3749                    )
3750                    .unwrap();
3751                let func_ptr_ptr = self
3752                    .builder
3753                    .build_struct_gep(
3754                        self.intrinsics.anyfunc_ty,
3755                        anyfunc_struct_ptr,
3756                        0,
3757                        "func_ptr_ptr",
3758                    )
3759                    .unwrap();
3760                let (func_ptr, found_signature_hash) = (
3761                    err!(
3762                        self.builder
3763                            .build_load(self.intrinsics.ptr_ty, func_ptr_ptr, "func_ptr")
3764                    )
3765                    .into_pointer_value(),
3766                    err!(
3767                        self.builder
3768                            .build_load(self.intrinsics.i32_ty, sig_hash_ptr, "sig_hash")
3769                    )
3770                    .into_int_value(),
3771                );
3772
3773                // Next, check if the table element is initialized.
3774
3775                // TODO: we may not need this check anymore
3776                let elem_initialized = err!(self.builder.build_is_not_null(func_ptr, ""));
3777
3778                // Next, check if the signature id is correct.
3779
3780                let sig_hashes_equal = err!(self.builder.build_int_compare(
3781                    IntPredicate::EQ,
3782                    expected_signature_hash,
3783                    found_signature_hash,
3784                    "sig_hashes_equal",
3785                ));
3786
3787                let initialized_and_sig_hashes_match = err!(self.builder.build_and(
3788                    elem_initialized,
3789                    sig_hashes_equal,
3790                    ""
3791                ));
3792
3793                // Tell llvm that the expected and found signature hashes should match.
3794                let initialized_and_sig_hashes_match = self
3795                    .build_call_with_param_attributes(
3796                        self.intrinsics.expect_i1,
3797                        &[
3798                            initialized_and_sig_hashes_match.into(),
3799                            self.intrinsics.i1_ty.const_int(1, false).into(),
3800                        ],
3801                        "initialized_and_sig_hashes_match_expect",
3802                    )?
3803                    .try_as_basic_value()
3804                    .unwrap_basic()
3805                    .into_int_value();
3806
3807                let continue_block = self
3808                    .context
3809                    .append_basic_block(self.function, "continue_block");
3810                let sighashes_notequal_block = self
3811                    .context
3812                    .append_basic_block(self.function, "sighashes_notequal_block");
3813                err!(self.builder.build_conditional_branch(
3814                    initialized_and_sig_hashes_match,
3815                    continue_block,
3816                    sighashes_notequal_block,
3817                ));
3818
3819                self.builder.position_at_end(sighashes_notequal_block);
3820                let trap_code = err!(self.builder.build_select(
3821                    elem_initialized,
3822                    self.intrinsics.trap_call_indirect_sig,
3823                    self.intrinsics.trap_call_indirect_null,
3824                    "",
3825                ));
3826                self.build_call_with_param_attributes(
3827                    self.intrinsics.throw_trap,
3828                    &[trap_code.into()],
3829                    "throw",
3830                )?;
3831                err!(self.builder.build_unreachable());
3832                self.builder.position_at_end(continue_block);
3833
3834                let callee_vmctx = if table.readonly {
3835                    *vmctx
3836                } else {
3837                    let ctx_ptr_ptr = self
3838                        .builder
3839                        .build_struct_gep(
3840                            self.intrinsics.anyfunc_ty,
3841                            anyfunc_struct_ptr,
3842                            2,
3843                            "ctx_ptr_ptr",
3844                        )
3845                        .unwrap();
3846                    err!(
3847                        self.builder
3848                            .build_load(self.intrinsics.ptr_ty, ctx_ptr_ptr, "ctx_ptr")
3849                    )
3850                    .into_pointer_value()
3851                };
3852
3853                if self.m0_param.is_some() {
3854                    self.build_m0_indirect_call(
3855                        table_index.as_u32(),
3856                        callee_vmctx,
3857                        func_type,
3858                        func_ptr,
3859                        func_index,
3860                        is_return_call,
3861                    )?;
3862                } else {
3863                    let (call_site, llvm_func_type) = self.build_indirect_call(
3864                        callee_vmctx,
3865                        func_type,
3866                        func_ptr,
3867                        None,
3868                        is_return_call,
3869                    )?;
3870
3871                    if is_return_call {
3872                        self.emit_return_call(call_site, llvm_func_type)?;
3873                    } else {
3874                        self.abi
3875                            .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3876                            .iter()
3877                            .for_each(|ret| self.state.push1(*ret));
3878                    }
3879                }
3880
3881                if is_return_call {
3882                    self.state.reachable = false;
3883                }
3884            }
3885            _ => unreachable!(),
3886        }
3887        Ok(())
3888    }
3889
3890    // Integer Arithmetic instructions.
3891    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-arithmetic-instructions
3892    fn translate_integer_arithmetic_operator(&mut self, op: Operator) -> Result<(), CompileError> {
3893        match op {
3894            Operator::I32Add | Operator::I64Add => {
3895                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3896                let v1 = self.apply_pending_canonicalization(v1, i1)?;
3897                let v2 = self.apply_pending_canonicalization(v2, i2)?;
3898                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3899                let res = err!(self.builder.build_int_add(v1, v2, ""));
3900                self.state.push1(res);
3901            }
3902            Operator::I8x16Add => {
3903                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3904                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3905                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3906                let res = err!(self.builder.build_int_add(v1, v2, ""));
3907                let res = err!(
3908                    self.builder
3909                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3910                );
3911                self.state.push1(res);
3912            }
3913            Operator::I16x8Add => {
3914                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3915                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3916                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3917                let res = err!(self.builder.build_int_add(v1, v2, ""));
3918                let res = err!(
3919                    self.builder
3920                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3921                );
3922                self.state.push1(res);
3923            }
3924            Operator::I16x8ExtAddPairwiseI8x16S | Operator::I16x8ExtAddPairwiseI8x16U => {
3925                let extend_op = match op {
3926                    Operator::I16x8ExtAddPairwiseI8x16S => {
3927                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, "")
3928                    }
3929                    Operator::I16x8ExtAddPairwiseI8x16U => {
3930                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, "")
3931                    }
3932                    _ => unreachable!("Unhandled internal variant"),
3933                };
3934                let (v, i) = self.state.pop1_extra()?;
3935                let (v, _) = self.v128_into_i8x16(v, i)?;
3936
3937                let left = err!(self.builder.build_shuffle_vector(
3938                    v,
3939                    v.get_type().get_undef(),
3940                    VectorType::const_vector(&[
3941                        self.intrinsics.i32_consts[0],
3942                        self.intrinsics.i32_consts[2],
3943                        self.intrinsics.i32_consts[4],
3944                        self.intrinsics.i32_consts[6],
3945                        self.intrinsics.i32_consts[8],
3946                        self.intrinsics.i32_consts[10],
3947                        self.intrinsics.i32_consts[12],
3948                        self.intrinsics.i32_consts[14],
3949                    ]),
3950                    "",
3951                ));
3952                let left = err!(extend_op(self, left));
3953                let right = err!(self.builder.build_shuffle_vector(
3954                    v,
3955                    v.get_type().get_undef(),
3956                    VectorType::const_vector(&[
3957                        self.intrinsics.i32_consts[1],
3958                        self.intrinsics.i32_consts[3],
3959                        self.intrinsics.i32_consts[5],
3960                        self.intrinsics.i32_consts[7],
3961                        self.intrinsics.i32_consts[9],
3962                        self.intrinsics.i32_consts[11],
3963                        self.intrinsics.i32_consts[13],
3964                        self.intrinsics.i32_consts[15],
3965                    ]),
3966                    "",
3967                ));
3968                let right = err!(extend_op(self, right));
3969
3970                let res = err!(self.builder.build_int_add(left, right, ""));
3971                let res = err!(
3972                    self.builder
3973                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3974                );
3975                self.state.push1(res);
3976            }
3977            Operator::I32x4Add => {
3978                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3979                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3980                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3981                let res = err!(self.builder.build_int_add(v1, v2, ""));
3982                let res = err!(
3983                    self.builder
3984                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3985                );
3986                self.state.push1(res);
3987            }
3988            Operator::I32x4ExtAddPairwiseI16x8S | Operator::I32x4ExtAddPairwiseI16x8U => {
3989                let extend_op = match op {
3990                    Operator::I32x4ExtAddPairwiseI16x8S => {
3991                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
3992                    }
3993                    Operator::I32x4ExtAddPairwiseI16x8U => {
3994                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
3995                    }
3996                    _ => unreachable!("Unhandled internal variant"),
3997                };
3998                let (v, i) = self.state.pop1_extra()?;
3999                let (v, _) = self.v128_into_i16x8(v, i)?;
4000
4001                let left = err!(self.builder.build_shuffle_vector(
4002                    v,
4003                    v.get_type().get_undef(),
4004                    VectorType::const_vector(&[
4005                        self.intrinsics.i32_consts[0],
4006                        self.intrinsics.i32_consts[2],
4007                        self.intrinsics.i32_consts[4],
4008                        self.intrinsics.i32_consts[6],
4009                    ]),
4010                    "",
4011                ));
4012                let left = err!(extend_op(self, left));
4013                let right = err!(self.builder.build_shuffle_vector(
4014                    v,
4015                    v.get_type().get_undef(),
4016                    VectorType::const_vector(&[
4017                        self.intrinsics.i32_consts[1],
4018                        self.intrinsics.i32_consts[3],
4019                        self.intrinsics.i32_consts[5],
4020                        self.intrinsics.i32_consts[7],
4021                    ]),
4022                    "",
4023                ));
4024                let right = err!(extend_op(self, right));
4025
4026                let res = err!(self.builder.build_int_add(left, right, ""));
4027                let res = err!(
4028                    self.builder
4029                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4030                );
4031                self.state.push1(res);
4032            }
4033            Operator::I64x2Add => {
4034                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4035                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4036                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4037                let res = err!(self.builder.build_int_add(v1, v2, ""));
4038                let res = err!(
4039                    self.builder
4040                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4041                );
4042                self.state.push1(res);
4043            }
4044            Operator::I8x16AddSatS => {
4045                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4046                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4047                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4048                let res = self
4049                    .build_call_with_param_attributes(
4050                        self.intrinsics.sadd_sat_i8x16,
4051                        &[v1.into(), v2.into()],
4052                        "",
4053                    )?
4054                    .try_as_basic_value()
4055                    .unwrap_basic();
4056                let res = err!(
4057                    self.builder
4058                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4059                );
4060                self.state.push1(res);
4061            }
4062            Operator::I16x8AddSatS => {
4063                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4064                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4065                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4066                let res = self
4067                    .build_call_with_param_attributes(
4068                        self.intrinsics.sadd_sat_i16x8,
4069                        &[v1.into(), v2.into()],
4070                        "",
4071                    )?
4072                    .try_as_basic_value()
4073                    .unwrap_basic();
4074                let res = err!(
4075                    self.builder
4076                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4077                );
4078                self.state.push1(res);
4079            }
4080            Operator::I8x16AddSatU => {
4081                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4082                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4083                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4084                let res = self
4085                    .build_call_with_param_attributes(
4086                        self.intrinsics.uadd_sat_i8x16,
4087                        &[v1.into(), v2.into()],
4088                        "",
4089                    )?
4090                    .try_as_basic_value()
4091                    .unwrap_basic();
4092                let res = err!(
4093                    self.builder
4094                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4095                );
4096                self.state.push1(res);
4097            }
4098            Operator::I16x8AddSatU => {
4099                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4100                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4101                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4102                let res = self
4103                    .build_call_with_param_attributes(
4104                        self.intrinsics.uadd_sat_i16x8,
4105                        &[v1.into(), v2.into()],
4106                        "",
4107                    )?
4108                    .try_as_basic_value()
4109                    .unwrap_basic();
4110                let res = err!(
4111                    self.builder
4112                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4113                );
4114                self.state.push1(res);
4115            }
4116            Operator::I32Sub | Operator::I64Sub => {
4117                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4118                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4119                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4120                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4121                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4122                self.state.push1(res);
4123            }
4124            Operator::I8x16Sub => {
4125                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4126                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4127                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4128                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4129                let res = err!(
4130                    self.builder
4131                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4132                );
4133                self.state.push1(res);
4134            }
4135            Operator::I16x8Sub => {
4136                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4137                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4138                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4139                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4140                let res = err!(
4141                    self.builder
4142                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4143                );
4144                self.state.push1(res);
4145            }
4146            Operator::I32x4Sub => {
4147                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4148                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4149                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4150                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4151                let res = err!(
4152                    self.builder
4153                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4154                );
4155                self.state.push1(res);
4156            }
4157            Operator::I64x2Sub => {
4158                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4159                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4160                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4161                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4162                let res = err!(
4163                    self.builder
4164                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4165                );
4166                self.state.push1(res);
4167            }
4168            Operator::I8x16SubSatS => {
4169                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4170                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4171                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4172                let res = self
4173                    .build_call_with_param_attributes(
4174                        self.intrinsics.ssub_sat_i8x16,
4175                        &[v1.into(), v2.into()],
4176                        "",
4177                    )?
4178                    .try_as_basic_value()
4179                    .unwrap_basic();
4180                let res = err!(
4181                    self.builder
4182                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4183                );
4184                self.state.push1(res);
4185            }
4186            Operator::I16x8SubSatS => {
4187                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4188                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4189                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4190                let res = self
4191                    .build_call_with_param_attributes(
4192                        self.intrinsics.ssub_sat_i16x8,
4193                        &[v1.into(), v2.into()],
4194                        "",
4195                    )?
4196                    .try_as_basic_value()
4197                    .unwrap_basic();
4198                let res = err!(
4199                    self.builder
4200                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4201                );
4202                self.state.push1(res);
4203            }
4204            Operator::I8x16SubSatU => {
4205                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4206                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4207                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4208                let res = self
4209                    .build_call_with_param_attributes(
4210                        self.intrinsics.usub_sat_i8x16,
4211                        &[v1.into(), v2.into()],
4212                        "",
4213                    )?
4214                    .try_as_basic_value()
4215                    .unwrap_basic();
4216                let res = err!(
4217                    self.builder
4218                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4219                );
4220                self.state.push1(res);
4221            }
4222            Operator::I16x8SubSatU => {
4223                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4224                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4225                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4226                let res = self
4227                    .build_call_with_param_attributes(
4228                        self.intrinsics.usub_sat_i16x8,
4229                        &[v1.into(), v2.into()],
4230                        "",
4231                    )?
4232                    .try_as_basic_value()
4233                    .unwrap_basic();
4234                let res = err!(
4235                    self.builder
4236                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4237                );
4238                self.state.push1(res);
4239            }
4240            Operator::I32Mul | Operator::I64Mul => {
4241                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4242                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4243                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4244                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4245                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4246                self.state.push1(res);
4247            }
4248            Operator::I16x8Mul => {
4249                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4250                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4251                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4252                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4253                let res = err!(
4254                    self.builder
4255                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4256                );
4257                self.state.push1(res);
4258            }
4259            Operator::I32x4Mul => {
4260                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4261                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4262                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4263                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4264                let res = err!(
4265                    self.builder
4266                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4267                );
4268                self.state.push1(res);
4269            }
4270            Operator::I64x2Mul => {
4271                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4272                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4273                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4274                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4275                let res = err!(
4276                    self.builder
4277                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4278                );
4279                self.state.push1(res);
4280            }
4281            Operator::I16x8RelaxedQ15mulrS if self.cpu_features.contains(CpuFeature::SSSE3) => {
4282                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4283                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4284                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4285                let res = self
4286                    .build_call_with_param_attributes(
4287                        self.intrinsics.x86_64.pmulhrsw128,
4288                        &[v1.into(), v2.into()],
4289                        "",
4290                    )?
4291                    .try_as_basic_value()
4292                    .unwrap_basic();
4293                let res = err!(
4294                    self.builder
4295                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4296                );
4297                self.state.push1(res);
4298            }
4299            Operator::I16x8Q15MulrSatS | Operator::I16x8RelaxedQ15mulrS => {
4300                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4301                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4302                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4303
4304                let max_value = self.intrinsics.i16_ty.const_int(i16::MAX as u64, false);
4305                let max_values = VectorType::const_vector(&[max_value; 8]);
4306
4307                let v1 = err!(
4308                    self.builder
4309                        .build_int_s_extend(v1, self.intrinsics.i32x8_ty, "")
4310                );
4311                let v2 = err!(
4312                    self.builder
4313                        .build_int_s_extend(v2, self.intrinsics.i32x8_ty, "")
4314                );
4315                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4316
4317                // magic number specified by the spec
4318                let bit = self.intrinsics.i32_ty.const_int(0x4000, false);
4319                let bits = VectorType::const_vector(&[bit; 8]);
4320
4321                let res = err!(self.builder.build_int_add(res, bits, ""));
4322
4323                let fifteen = self.intrinsics.i32_consts[15];
4324                let fifteens = VectorType::const_vector(&[fifteen; 8]);
4325
4326                let res = err!(self.builder.build_right_shift(res, fifteens, true, ""));
4327                let saturate_up = {
4328                    let max_values = err!(self.builder.build_int_s_extend(
4329                        max_values,
4330                        self.intrinsics.i32x8_ty,
4331                        ""
4332                    ));
4333                    err!(
4334                        self.builder
4335                            .build_int_compare(IntPredicate::SGT, res, max_values, "")
4336                    )
4337                };
4338
4339                let res = err!(
4340                    self.builder
4341                        .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
4342                );
4343
4344                let res = err!(self.builder.build_select(saturate_up, max_values, res, ""))
4345                    .into_vector_value();
4346                let res = err!(
4347                    self.builder
4348                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4349                );
4350                self.state.push1(res);
4351            }
4352            Operator::I16x8ExtMulLowI8x16S
4353            | Operator::I16x8ExtMulLowI8x16U
4354            | Operator::I16x8ExtMulHighI8x16S
4355            | Operator::I16x8ExtMulHighI8x16U => {
4356                let extend_op = match op {
4357                    Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulHighI8x16S => {
4358                        |s: &Self, v| -> Result<VectorValue, CompileError> {
4359                            err_nt!(s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, ""))
4360                        }
4361                    }
4362                    Operator::I16x8ExtMulLowI8x16U | Operator::I16x8ExtMulHighI8x16U => {
4363                        |s: &Self, v| -> Result<VectorValue, CompileError> {
4364                            err_nt!(s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, ""))
4365                        }
4366                    }
4367                    _ => unreachable!("Unhandled internal variant"),
4368                };
4369                let shuffle_array = match op {
4370                    Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulLowI8x16U => [
4371                        self.intrinsics.i32_consts[0],
4372                        self.intrinsics.i32_consts[1],
4373                        self.intrinsics.i32_consts[2],
4374                        self.intrinsics.i32_consts[3],
4375                        self.intrinsics.i32_consts[4],
4376                        self.intrinsics.i32_consts[5],
4377                        self.intrinsics.i32_consts[6],
4378                        self.intrinsics.i32_consts[7],
4379                    ],
4380                    Operator::I16x8ExtMulHighI8x16S | Operator::I16x8ExtMulHighI8x16U => [
4381                        self.intrinsics.i32_consts[8],
4382                        self.intrinsics.i32_consts[9],
4383                        self.intrinsics.i32_consts[10],
4384                        self.intrinsics.i32_consts[11],
4385                        self.intrinsics.i32_consts[12],
4386                        self.intrinsics.i32_consts[13],
4387                        self.intrinsics.i32_consts[14],
4388                        self.intrinsics.i32_consts[15],
4389                    ],
4390                    _ => unreachable!("Unhandled internal variant"),
4391                };
4392                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4393                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4394                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4395                let val1 = err!(self.builder.build_shuffle_vector(
4396                    v1,
4397                    v1.get_type().get_undef(),
4398                    VectorType::const_vector(&shuffle_array),
4399                    "",
4400                ));
4401                let val1 = err!(extend_op(self, val1));
4402                let val2 = err!(self.builder.build_shuffle_vector(
4403                    v2,
4404                    v2.get_type().get_undef(),
4405                    VectorType::const_vector(&shuffle_array),
4406                    "",
4407                ));
4408                let val2 = err!(extend_op(self, val2));
4409                let res = err!(self.builder.build_int_mul(val1, val2, ""));
4410                let res = err!(
4411                    self.builder
4412                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4413                );
4414                self.state.push1(res);
4415            }
4416            Operator::I32x4ExtMulLowI16x8S
4417            | Operator::I32x4ExtMulLowI16x8U
4418            | Operator::I32x4ExtMulHighI16x8S
4419            | Operator::I32x4ExtMulHighI16x8U => {
4420                let extend_op = match op {
4421                    Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulHighI16x8S => {
4422                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
4423                    }
4424                    Operator::I32x4ExtMulLowI16x8U | Operator::I32x4ExtMulHighI16x8U => {
4425                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
4426                    }
4427                    _ => unreachable!("Unhandled internal variant"),
4428                };
4429                let shuffle_array = match op {
4430                    Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulLowI16x8U => [
4431                        self.intrinsics.i32_consts[0],
4432                        self.intrinsics.i32_consts[1],
4433                        self.intrinsics.i32_consts[2],
4434                        self.intrinsics.i32_consts[3],
4435                    ],
4436                    Operator::I32x4ExtMulHighI16x8S | Operator::I32x4ExtMulHighI16x8U => [
4437                        self.intrinsics.i32_consts[4],
4438                        self.intrinsics.i32_consts[5],
4439                        self.intrinsics.i32_consts[6],
4440                        self.intrinsics.i32_consts[7],
4441                    ],
4442                    _ => unreachable!("Unhandled internal variant"),
4443                };
4444                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4445                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4446                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4447                let val1 = err!(self.builder.build_shuffle_vector(
4448                    v1,
4449                    v1.get_type().get_undef(),
4450                    VectorType::const_vector(&shuffle_array),
4451                    "",
4452                ));
4453                let val1 = err!(extend_op(self, val1));
4454                let val2 = err!(self.builder.build_shuffle_vector(
4455                    v2,
4456                    v2.get_type().get_undef(),
4457                    VectorType::const_vector(&shuffle_array),
4458                    "",
4459                ));
4460                let val2 = err!(extend_op(self, val2));
4461                let res = err!(self.builder.build_int_mul(val1, val2, ""));
4462                let res = err!(
4463                    self.builder
4464                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4465                );
4466                self.state.push1(res);
4467            }
4468            Operator::I64x2ExtMulLowI32x4S
4469            | Operator::I64x2ExtMulLowI32x4U
4470            | Operator::I64x2ExtMulHighI32x4S
4471            | Operator::I64x2ExtMulHighI32x4U => {
4472                let extend_op = match op {
4473                    Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulHighI32x4S => {
4474                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
4475                    }
4476                    Operator::I64x2ExtMulLowI32x4U | Operator::I64x2ExtMulHighI32x4U => {
4477                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
4478                    }
4479                    _ => unreachable!("Unhandled internal variant"),
4480                };
4481                let shuffle_array = match op {
4482                    Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulLowI32x4U => {
4483                        [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
4484                    }
4485                    Operator::I64x2ExtMulHighI32x4S | Operator::I64x2ExtMulHighI32x4U => {
4486                        [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
4487                    }
4488                    _ => unreachable!("Unhandled internal variant"),
4489                };
4490                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4491                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4492                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4493                let val1 = err!(self.builder.build_shuffle_vector(
4494                    v1,
4495                    v1.get_type().get_undef(),
4496                    VectorType::const_vector(&shuffle_array),
4497                    "",
4498                ));
4499                let val1 = err!(extend_op(self, val1));
4500                let val2 = err!(self.builder.build_shuffle_vector(
4501                    v2,
4502                    v2.get_type().get_undef(),
4503                    VectorType::const_vector(&shuffle_array),
4504                    "",
4505                ));
4506                let val2 = err!(extend_op(self, val2));
4507                let res = err!(self.builder.build_int_mul(val1, val2, ""));
4508                let res = err!(
4509                    self.builder
4510                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4511                );
4512                self.state.push1(res);
4513            }
4514            Operator::I32x4DotI16x8S => {
4515                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4516                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4517                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4518                let low_i16 = [
4519                    self.intrinsics.i32_consts[0],
4520                    self.intrinsics.i32_consts[2],
4521                    self.intrinsics.i32_consts[4],
4522                    self.intrinsics.i32_consts[6],
4523                ];
4524                let high_i16 = [
4525                    self.intrinsics.i32_consts[1],
4526                    self.intrinsics.i32_consts[3],
4527                    self.intrinsics.i32_consts[5],
4528                    self.intrinsics.i32_consts[7],
4529                ];
4530                let v1_low = err!(self.builder.build_shuffle_vector(
4531                    v1,
4532                    v1.get_type().get_undef(),
4533                    VectorType::const_vector(&low_i16),
4534                    "",
4535                ));
4536                let v1_low = err!(self.builder.build_int_s_extend(
4537                    v1_low,
4538                    self.intrinsics.i32x4_ty,
4539                    ""
4540                ));
4541                let v1_high = err!(self.builder.build_shuffle_vector(
4542                    v1,
4543                    v1.get_type().get_undef(),
4544                    VectorType::const_vector(&high_i16),
4545                    "",
4546                ));
4547                let v1_high = err!(self.builder.build_int_s_extend(
4548                    v1_high,
4549                    self.intrinsics.i32x4_ty,
4550                    ""
4551                ));
4552                let v2_low = err!(self.builder.build_shuffle_vector(
4553                    v2,
4554                    v2.get_type().get_undef(),
4555                    VectorType::const_vector(&low_i16),
4556                    "",
4557                ));
4558                let v2_low = err!(self.builder.build_int_s_extend(
4559                    v2_low,
4560                    self.intrinsics.i32x4_ty,
4561                    ""
4562                ));
4563                let v2_high = err!(self.builder.build_shuffle_vector(
4564                    v2,
4565                    v2.get_type().get_undef(),
4566                    VectorType::const_vector(&high_i16),
4567                    "",
4568                ));
4569                let v2_high = err!(self.builder.build_int_s_extend(
4570                    v2_high,
4571                    self.intrinsics.i32x4_ty,
4572                    ""
4573                ));
4574                let low_product = err!(self.builder.build_int_mul(v1_low, v2_low, ""));
4575                let high_product = err!(self.builder.build_int_mul(v1_high, v2_high, ""));
4576
4577                let res = err!(self.builder.build_int_add(low_product, high_product, ""));
4578                let res = err!(
4579                    self.builder
4580                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4581                );
4582                self.state.push1(res);
4583            }
4584            Operator::I16x8RelaxedDotI8x16I7x16S
4585                if self.cpu_features.contains(CpuFeature::SSSE3) =>
4586            {
4587                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4588                let (a, _) = self.v128_into_i8x16(v1, i1)?;
4589                let (b, _) = self.v128_into_i8x16(v2, i2)?;
4590
4591                let res = self
4592                    .build_call_with_param_attributes(
4593                        self.intrinsics.x86_64.pmaddubsw128,
4594                        &[b.into(), a.into()],
4595                        "",
4596                    )?
4597                    .try_as_basic_value()
4598                    .unwrap_basic()
4599                    .into_vector_value();
4600                let res = err!(
4601                    self.builder
4602                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4603                );
4604                self.state.push1(res);
4605            }
4606            Operator::I16x8RelaxedDotI8x16I7x16S => {
4607                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4608                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4609                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4610
4611                let left_indices = [
4612                    self.intrinsics.i32_consts[0],
4613                    self.intrinsics.i32_consts[2],
4614                    self.intrinsics.i32_consts[4],
4615                    self.intrinsics.i32_consts[6],
4616                    self.intrinsics.i32_consts[8],
4617                    self.intrinsics.i32_consts[10],
4618                    self.intrinsics.i32_consts[12],
4619                    self.intrinsics.i32_consts[14],
4620                ];
4621                let right_indices = [
4622                    self.intrinsics.i32_consts[1],
4623                    self.intrinsics.i32_consts[3],
4624                    self.intrinsics.i32_consts[5],
4625                    self.intrinsics.i32_consts[7],
4626                    self.intrinsics.i32_consts[9],
4627                    self.intrinsics.i32_consts[11],
4628                    self.intrinsics.i32_consts[13],
4629                    self.intrinsics.i32_consts[15],
4630                ];
4631
4632                let v1_left = err!(self.builder.build_shuffle_vector(
4633                    v1,
4634                    v1.get_type().get_undef(),
4635                    VectorType::const_vector(&left_indices),
4636                    "",
4637                ));
4638                let v1_left = err!(self.builder.build_int_s_extend(
4639                    v1_left,
4640                    self.intrinsics.i16x8_ty,
4641                    ""
4642                ));
4643                let v1_right = err!(self.builder.build_shuffle_vector(
4644                    v1,
4645                    v1.get_type().get_undef(),
4646                    VectorType::const_vector(&right_indices),
4647                    "",
4648                ));
4649                let v1_right = err!(self.builder.build_int_s_extend(
4650                    v1_right,
4651                    self.intrinsics.i16x8_ty,
4652                    ""
4653                ));
4654
4655                let v2_left = err!(self.builder.build_shuffle_vector(
4656                    v2,
4657                    v2.get_type().get_undef(),
4658                    VectorType::const_vector(&left_indices),
4659                    "",
4660                ));
4661                let v2_left = err!(self.builder.build_int_s_extend(
4662                    v2_left,
4663                    self.intrinsics.i16x8_ty,
4664                    ""
4665                ));
4666                let v2_right = err!(self.builder.build_shuffle_vector(
4667                    v2,
4668                    v2.get_type().get_undef(),
4669                    VectorType::const_vector(&right_indices),
4670                    "",
4671                ));
4672                let v2_right = err!(self.builder.build_int_s_extend(
4673                    v2_right,
4674                    self.intrinsics.i16x8_ty,
4675                    ""
4676                ));
4677
4678                let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4679                let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4680                let res = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4681                let res = err!(
4682                    self.builder
4683                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4684                );
4685                self.state.push1(res);
4686            }
4687            Operator::I32x4RelaxedDotI8x16I7x16AddS
4688                if self.cpu_features.contains(CpuFeature::SSSE3) =>
4689            {
4690                let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4691                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4692                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4693                let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4694
4695                // PMADDUBSW computes pairwise u8*i8 with i16 saturation, which
4696                // is one of the valid relaxed dot-product behaviors.
4697                let dot16 = self
4698                    .build_call_with_param_attributes(
4699                        self.intrinsics.x86_64.pmaddubsw128,
4700                        &[v2.into(), v1.into()],
4701                        "",
4702                    )?
4703                    .try_as_basic_value()
4704                    .unwrap_basic()
4705                    .into_vector_value();
4706                let ones =
4707                    VectorType::const_vector(&[self.intrinsics.i16_ty.const_int(1, false); 8]);
4708                let dot32 = self
4709                    .build_call_with_param_attributes(
4710                        self.intrinsics.x86_64.pmaddwd128,
4711                        &[dot16.into(), ones.into()],
4712                        "",
4713                    )?
4714                    .try_as_basic_value()
4715                    .unwrap_basic()
4716                    .into_vector_value();
4717                let res = err!(self.builder.build_int_add(dot32, acc, ""));
4718                let res = err!(
4719                    self.builder
4720                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4721                );
4722                self.state.push1(res);
4723            }
4724            Operator::I32x4RelaxedDotI8x16I7x16AddS => {
4725                let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4726                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4727                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4728                let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4729
4730                let left_indices = [
4731                    self.intrinsics.i32_consts[0],
4732                    self.intrinsics.i32_consts[2],
4733                    self.intrinsics.i32_consts[4],
4734                    self.intrinsics.i32_consts[6],
4735                    self.intrinsics.i32_consts[8],
4736                    self.intrinsics.i32_consts[10],
4737                    self.intrinsics.i32_consts[12],
4738                    self.intrinsics.i32_consts[14],
4739                ];
4740                let right_indices = [
4741                    self.intrinsics.i32_consts[1],
4742                    self.intrinsics.i32_consts[3],
4743                    self.intrinsics.i32_consts[5],
4744                    self.intrinsics.i32_consts[7],
4745                    self.intrinsics.i32_consts[9],
4746                    self.intrinsics.i32_consts[11],
4747                    self.intrinsics.i32_consts[13],
4748                    self.intrinsics.i32_consts[15],
4749                ];
4750
4751                let v1_left = err!(self.builder.build_shuffle_vector(
4752                    v1,
4753                    v1.get_type().get_undef(),
4754                    VectorType::const_vector(&left_indices),
4755                    "",
4756                ));
4757                let v1_left = err!(self.builder.build_int_s_extend(
4758                    v1_left,
4759                    self.intrinsics.i16x8_ty,
4760                    ""
4761                ));
4762                let v1_right = err!(self.builder.build_shuffle_vector(
4763                    v1,
4764                    v1.get_type().get_undef(),
4765                    VectorType::const_vector(&right_indices),
4766                    "",
4767                ));
4768                let v1_right = err!(self.builder.build_int_s_extend(
4769                    v1_right,
4770                    self.intrinsics.i16x8_ty,
4771                    ""
4772                ));
4773
4774                let v2_left = err!(self.builder.build_shuffle_vector(
4775                    v2,
4776                    v2.get_type().get_undef(),
4777                    VectorType::const_vector(&left_indices),
4778                    "",
4779                ));
4780                let v2_left = err!(self.builder.build_int_s_extend(
4781                    v2_left,
4782                    self.intrinsics.i16x8_ty,
4783                    ""
4784                ));
4785                let v2_right = err!(self.builder.build_shuffle_vector(
4786                    v2,
4787                    v2.get_type().get_undef(),
4788                    VectorType::const_vector(&right_indices),
4789                    "",
4790                ));
4791                let v2_right = err!(self.builder.build_int_s_extend(
4792                    v2_right,
4793                    self.intrinsics.i16x8_ty,
4794                    ""
4795                ));
4796
4797                let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4798                let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4799                let dot16 = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4800
4801                let pair_left = err!(self.builder.build_shuffle_vector(
4802                    dot16,
4803                    dot16.get_type().get_undef(),
4804                    VectorType::const_vector(&[
4805                        self.intrinsics.i32_consts[0],
4806                        self.intrinsics.i32_consts[2],
4807                        self.intrinsics.i32_consts[4],
4808                        self.intrinsics.i32_consts[6],
4809                    ]),
4810                    "",
4811                ));
4812                let pair_left = err!(self.builder.build_int_s_extend(
4813                    pair_left,
4814                    self.intrinsics.i32x4_ty,
4815                    ""
4816                ));
4817                let pair_right = err!(self.builder.build_shuffle_vector(
4818                    dot16,
4819                    dot16.get_type().get_undef(),
4820                    VectorType::const_vector(&[
4821                        self.intrinsics.i32_consts[1],
4822                        self.intrinsics.i32_consts[3],
4823                        self.intrinsics.i32_consts[5],
4824                        self.intrinsics.i32_consts[7],
4825                    ]),
4826                    "",
4827                ));
4828                let pair_right = err!(self.builder.build_int_s_extend(
4829                    pair_right,
4830                    self.intrinsics.i32x4_ty,
4831                    ""
4832                ));
4833                let dot32 = err!(self.builder.build_int_add(pair_left, pair_right, ""));
4834                let res = err!(self.builder.build_int_add(dot32, acc, ""));
4835                let res = err!(
4836                    self.builder
4837                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4838                );
4839                self.state.push1(res);
4840            }
4841            Operator::I32DivS | Operator::I64DivS => {
4842                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4843                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4844                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4845                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4846
4847                self.trap_if_zero_or_overflow(v1, v2)?;
4848
4849                let res = err!(self.builder.build_int_signed_div(v1, v2, ""));
4850                self.state.push1(res);
4851            }
4852            Operator::I32DivU | Operator::I64DivU => {
4853                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4854                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4855                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4856                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4857
4858                self.trap_if_zero(v2)?;
4859
4860                let res = err!(self.builder.build_int_unsigned_div(v1, v2, ""));
4861                self.state.push1(res);
4862            }
4863            Operator::I32RemS | Operator::I64RemS => {
4864                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4865                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4866                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4867                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4868                let int_type = v1.get_type();
4869                let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
4870                    let min_value = int_type.const_int(i32::MIN as u64, false);
4871                    let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
4872                    (min_value, neg_one_value)
4873                } else if int_type == self.intrinsics.i64_ty {
4874                    let min_value = int_type.const_int(i64::MIN as u64, false);
4875                    let neg_one_value = int_type.const_int(-1i64 as u64, false);
4876                    (min_value, neg_one_value)
4877                } else {
4878                    unreachable!()
4879                };
4880
4881                self.trap_if_zero(v2)?;
4882
4883                // "Overflow also leads to undefined behavior; this is a rare
4884                // case, but can occur, for example, by taking the remainder of
4885                // a 32-bit division of -2147483648 by -1. (The remainder
4886                // doesn’t actually overflow, but this rule lets srem be
4887                // implemented using instructions that return both the result
4888                // of the division and the remainder.)"
4889                //   -- https://llvm.org/docs/LangRef.html#srem-instruction
4890                //
4891                // In Wasm, the i32.rem_s i32.const -2147483648 i32.const -1 is
4892                // i32.const 0. We implement this by swapping out the left value
4893                // for 0 in this case.
4894                let will_overflow = err!(self.builder.build_and(
4895                    err!(self.builder.build_int_compare(
4896                        IntPredicate::EQ,
4897                        v1,
4898                        min_value,
4899                        "left_is_min"
4900                    )),
4901                    err!(self.builder.build_int_compare(
4902                        IntPredicate::EQ,
4903                        v2,
4904                        neg_one_value,
4905                        "right_is_neg_one",
4906                    )),
4907                    "srem_will_overflow",
4908                ));
4909                let v1 =
4910                    err!(
4911                        self.builder
4912                            .build_select(will_overflow, int_type.const_zero(), v1, "")
4913                    )
4914                    .into_int_value();
4915                let res = err!(self.builder.build_int_signed_rem(v1, v2, ""));
4916                self.state.push1(res);
4917            }
4918            Operator::I32RemU | Operator::I64RemU => {
4919                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4920                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4921                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4922                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4923
4924                self.trap_if_zero(v2)?;
4925
4926                let res = err!(self.builder.build_int_unsigned_rem(v1, v2, ""));
4927                self.state.push1(res);
4928            }
4929            Operator::I32And | Operator::I64And | Operator::V128And => {
4930                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4931                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4932                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4933                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4934                let res = err!(self.builder.build_and(v1, v2, ""));
4935                self.state.push1(res);
4936            }
4937            Operator::I32Or | Operator::I64Or | Operator::V128Or => {
4938                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4939                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4940                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4941                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4942                let res = err!(self.builder.build_or(v1, v2, ""));
4943                self.state.push1(res);
4944            }
4945            Operator::I32Xor | Operator::I64Xor | Operator::V128Xor => {
4946                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4947                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4948                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4949                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4950                let res = err!(self.builder.build_xor(v1, v2, ""));
4951                self.state.push1(res);
4952            }
4953            Operator::V128AndNot => {
4954                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4955                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4956                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4957                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4958                let v2 = err!(self.builder.build_not(v2, ""));
4959                let res = err!(self.builder.build_and(v1, v2, ""));
4960                self.state.push1(res);
4961            }
4962            Operator::I8x16RelaxedLaneselect
4963            | Operator::I16x8RelaxedLaneselect
4964            | Operator::I32x4RelaxedLaneselect
4965            | Operator::I64x2RelaxedLaneselect
4966                if self.cpu_features.contains(CpuFeature::SSE41) =>
4967            {
4968                let ((v1, i1), (v2, i2), (mask, mask_info)) = self.state.pop3_extra()?;
4969                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4970                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4971                let mask = self.apply_pending_canonicalization(mask, mask_info)?;
4972
4973                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4974                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4975                let (mask, _) = self.v128_into_i8x16(mask, mask_info)?;
4976                let res = self
4977                    .build_call_with_param_attributes(
4978                        self.intrinsics.x86_64.pblendvb,
4979                        &[v2.into(), v1.into(), mask.into()],
4980                        "",
4981                    )?
4982                    .try_as_basic_value()
4983                    .unwrap_basic();
4984                let res = err!(
4985                    self.builder
4986                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4987                );
4988                self.state.push1(res);
4989            }
4990            Operator::I8x16RelaxedLaneselect
4991            | Operator::I16x8RelaxedLaneselect
4992            | Operator::I32x4RelaxedLaneselect
4993            | Operator::I64x2RelaxedLaneselect
4994            | Operator::V128Bitselect => {
4995                let ((v1, i1), (v2, i2), (cond, cond_info)) = self.state.pop3_extra()?;
4996                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4997                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4998                let cond = self.apply_pending_canonicalization(cond, cond_info)?;
4999                let v1 = err!(
5000                    self.builder
5001                        .build_bit_cast(v1, self.intrinsics.i1x128_ty, "")
5002                )
5003                .into_vector_value();
5004                let v2 = err!(
5005                    self.builder
5006                        .build_bit_cast(v2, self.intrinsics.i1x128_ty, "")
5007                )
5008                .into_vector_value();
5009                let cond = err!(
5010                    self.builder
5011                        .build_bit_cast(cond, self.intrinsics.i1x128_ty, "")
5012                )
5013                .into_vector_value();
5014                let res = err!(self.builder.build_select(cond, v1, v2, ""));
5015                let res = err!(
5016                    self.builder
5017                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5018                );
5019                self.state.push1(res);
5020            }
5021            Operator::I8x16Bitmask => {
5022                let (v, i) = self.state.pop1_extra()?;
5023                let (v, _) = self.v128_into_i8x16(v, i)?;
5024
5025                let zeros = self.intrinsics.i8x16_ty.const_zero();
5026                let res = err!(
5027                    self.builder
5028                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
5029                );
5030                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i16_ty, ""))
5031                    .into_int_value();
5032                let res = err!(
5033                    self.builder
5034                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5035                );
5036                self.state.push1(res);
5037            }
5038            Operator::I16x8Bitmask => {
5039                let (v, i) = self.state.pop1_extra()?;
5040                let (v, _) = self.v128_into_i16x8(v, i)?;
5041
5042                let zeros = self.intrinsics.i16x8_ty.const_zero();
5043                let res = err!(
5044                    self.builder
5045                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
5046                );
5047                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i8_ty, ""))
5048                    .into_int_value();
5049                let res = err!(
5050                    self.builder
5051                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5052                );
5053                self.state.push1(res);
5054            }
5055            Operator::I32x4Bitmask => {
5056                let (v, i) = self.state.pop1_extra()?;
5057                let (v, _) = self.v128_into_i32x4(v, i)?;
5058
5059                let zeros = self.intrinsics.i32x4_ty.const_zero();
5060                let res = err!(
5061                    self.builder
5062                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
5063                );
5064                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i4_ty, ""))
5065                    .into_int_value();
5066                let res = err!(
5067                    self.builder
5068                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5069                );
5070                self.state.push1(res);
5071            }
5072            Operator::I64x2Bitmask => {
5073                let (v, i) = self.state.pop1_extra()?;
5074                let (v, _) = self.v128_into_i64x2(v, i)?;
5075
5076                let zeros = self.intrinsics.i64x2_ty.const_zero();
5077                let res = err!(
5078                    self.builder
5079                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
5080                );
5081                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i2_ty, ""))
5082                    .into_int_value();
5083                let res = err!(
5084                    self.builder
5085                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5086                );
5087                self.state.push1(res);
5088            }
5089            Operator::I32Shl => {
5090                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5091                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5092                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5093                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5094                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5095                let v2 = err!(self.builder.build_and(v2, mask, ""));
5096                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5097                self.state.push1(res);
5098            }
5099            Operator::I64Shl => {
5100                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5101                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5102                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5103                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5104                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5105                let v2 = err!(self.builder.build_and(v2, mask, ""));
5106                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5107                self.state.push1(res);
5108            }
5109            Operator::I8x16Shl => {
5110                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5111                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5112                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5113                let v2 = v2.into_int_value();
5114                let v2 = err!(
5115                    self.builder
5116                        .build_and(v2, self.intrinsics.i32_consts[7], "")
5117                );
5118                let v2 = err!(
5119                    self.builder
5120                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5121                );
5122                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5123                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5124                let res = err!(
5125                    self.builder
5126                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5127                );
5128                self.state.push1(res);
5129            }
5130            Operator::I16x8Shl => {
5131                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5132                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5133                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5134                let v2 = v2.into_int_value();
5135                let v2 = err!(
5136                    self.builder
5137                        .build_and(v2, self.intrinsics.i32_consts[15], "")
5138                );
5139                let v2 = err!(
5140                    self.builder
5141                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5142                );
5143                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5144                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5145                let res = err!(
5146                    self.builder
5147                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5148                );
5149                self.state.push1(res);
5150            }
5151            Operator::I32x4Shl => {
5152                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5153                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5154                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5155                let v2 = v2.into_int_value();
5156                let v2 = err!(self.builder.build_and(
5157                    v2,
5158                    self.intrinsics.i32_ty.const_int(31, false),
5159                    ""
5160                ));
5161                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5162                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5163                let res = err!(
5164                    self.builder
5165                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5166                );
5167                self.state.push1(res);
5168            }
5169            Operator::I64x2Shl => {
5170                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5171                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5172                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5173                let v2 = v2.into_int_value();
5174                let v2 = err!(self.builder.build_and(
5175                    v2,
5176                    self.intrinsics.i32_ty.const_int(63, false),
5177                    ""
5178                ));
5179                let v2 = err!(
5180                    self.builder
5181                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5182                );
5183                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5184                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5185                let res = err!(
5186                    self.builder
5187                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5188                );
5189                self.state.push1(res);
5190            }
5191            Operator::I32ShrS => {
5192                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5193                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5194                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5195                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5196                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5197                let v2 = err!(self.builder.build_and(v2, mask, ""));
5198                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5199                self.state.push1(res);
5200            }
5201            Operator::I64ShrS => {
5202                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5203                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5204                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5205                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5206                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5207                let v2 = err!(self.builder.build_and(v2, mask, ""));
5208                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5209                self.state.push1(res);
5210            }
5211            Operator::I8x16ShrS => {
5212                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5213                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5214                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5215                let v2 = v2.into_int_value();
5216                let v2 = err!(
5217                    self.builder
5218                        .build_and(v2, self.intrinsics.i32_consts[7], "")
5219                );
5220                let v2 = err!(
5221                    self.builder
5222                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5223                );
5224                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5225                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5226                let res = err!(
5227                    self.builder
5228                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5229                );
5230                self.state.push1(res);
5231            }
5232            Operator::I16x8ShrS => {
5233                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5234                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5235                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5236                let v2 = v2.into_int_value();
5237                let v2 = err!(
5238                    self.builder
5239                        .build_and(v2, self.intrinsics.i32_consts[15], "")
5240                );
5241                let v2 = err!(
5242                    self.builder
5243                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5244                );
5245                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5246                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5247                let res = err!(
5248                    self.builder
5249                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5250                );
5251                self.state.push1(res);
5252            }
5253            Operator::I32x4ShrS => {
5254                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5255                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5256                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5257                let v2 = v2.into_int_value();
5258                let v2 = err!(self.builder.build_and(
5259                    v2,
5260                    self.intrinsics.i32_ty.const_int(31, false),
5261                    ""
5262                ));
5263                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5264                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5265                let res = err!(
5266                    self.builder
5267                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5268                );
5269                self.state.push1(res);
5270            }
5271            Operator::I64x2ShrS => {
5272                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5273                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5274                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5275                let v2 = v2.into_int_value();
5276                let v2 = err!(self.builder.build_and(
5277                    v2,
5278                    self.intrinsics.i32_ty.const_int(63, false),
5279                    ""
5280                ));
5281                let v2 = err!(
5282                    self.builder
5283                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5284                );
5285                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5286                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5287                let res = err!(
5288                    self.builder
5289                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5290                );
5291                self.state.push1(res);
5292            }
5293            Operator::I32ShrU => {
5294                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5295                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5296                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5297                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5298                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5299                let v2 = err!(self.builder.build_and(v2, mask, ""));
5300                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5301                self.state.push1(res);
5302            }
5303            Operator::I64ShrU => {
5304                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5305                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5306                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5307                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5308                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5309                let v2 = err!(self.builder.build_and(v2, mask, ""));
5310                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5311                self.state.push1(res);
5312            }
5313            Operator::I8x16ShrU => {
5314                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5315                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5316                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5317                let v2 = v2.into_int_value();
5318                let v2 = err!(
5319                    self.builder
5320                        .build_and(v2, self.intrinsics.i32_consts[7], "")
5321                );
5322                let v2 = err!(
5323                    self.builder
5324                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5325                );
5326                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5327                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5328                let res = err!(
5329                    self.builder
5330                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5331                );
5332                self.state.push1(res);
5333            }
5334            Operator::I16x8ShrU => {
5335                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5336                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5337                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5338                let v2 = v2.into_int_value();
5339                let v2 = err!(
5340                    self.builder
5341                        .build_and(v2, self.intrinsics.i32_consts[15], "")
5342                );
5343                let v2 = err!(
5344                    self.builder
5345                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5346                );
5347                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5348                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5349                let res = err!(
5350                    self.builder
5351                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5352                );
5353                self.state.push1(res);
5354            }
5355            Operator::I32x4ShrU => {
5356                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5357                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5358                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5359                let v2 = v2.into_int_value();
5360                let v2 = err!(self.builder.build_and(
5361                    v2,
5362                    self.intrinsics.i32_ty.const_int(31, false),
5363                    ""
5364                ));
5365                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5366                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5367                let res = err!(
5368                    self.builder
5369                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5370                );
5371                self.state.push1(res);
5372            }
5373            Operator::I64x2ShrU => {
5374                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5375                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5376                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5377                let v2 = v2.into_int_value();
5378                let v2 = err!(self.builder.build_and(
5379                    v2,
5380                    self.intrinsics.i32_ty.const_int(63, false),
5381                    ""
5382                ));
5383                let v2 = err!(
5384                    self.builder
5385                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5386                );
5387                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5388                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5389                let res = err!(
5390                    self.builder
5391                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5392                );
5393                self.state.push1(res);
5394            }
5395            Operator::I32Rotl => {
5396                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5397                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5398                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5399                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5400                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5401                let v2 = err!(self.builder.build_and(v2, mask, ""));
5402                let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5403                let rhs = {
5404                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5405                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5406                    err!(self.builder.build_right_shift(v1, rhs, false, ""))
5407                };
5408                let res = err!(self.builder.build_or(lhs, rhs, ""));
5409                self.state.push1(res);
5410            }
5411            Operator::I64Rotl => {
5412                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5413                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5414                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5415                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5416                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5417                let v2 = err!(self.builder.build_and(v2, mask, ""));
5418                let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5419                let rhs = {
5420                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5421                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5422                    err!(self.builder.build_right_shift(v1, rhs, false, ""))
5423                };
5424                let res = err!(self.builder.build_or(lhs, rhs, ""));
5425                self.state.push1(res);
5426            }
5427            Operator::I32Rotr => {
5428                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5429                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5430                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5431                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5432                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5433                let v2 = err!(self.builder.build_and(v2, mask, ""));
5434                let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5435                let rhs = {
5436                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5437                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5438                    err!(self.builder.build_left_shift(v1, rhs, ""))
5439                };
5440                let res = err!(self.builder.build_or(lhs, rhs, ""));
5441                self.state.push1(res);
5442            }
5443            Operator::I64Rotr => {
5444                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5445                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5446                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5447                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5448                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5449                let v2 = err!(self.builder.build_and(v2, mask, ""));
5450                let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5451                let rhs = {
5452                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5453                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5454                    err!(self.builder.build_left_shift(v1, rhs, ""))
5455                };
5456                let res = err!(self.builder.build_or(lhs, rhs, ""));
5457                self.state.push1(res);
5458            }
5459            Operator::I32Clz => {
5460                let (input, info) = self.state.pop1_extra()?;
5461                let input = self.apply_pending_canonicalization(input, info)?;
5462                let is_zero_undef = self.intrinsics.i1_zero;
5463                let res = self
5464                    .build_call_with_param_attributes(
5465                        self.intrinsics.ctlz_i32,
5466                        &[input.into(), is_zero_undef.into()],
5467                        "",
5468                    )?
5469                    .try_as_basic_value()
5470                    .unwrap_basic();
5471                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5472            }
5473            Operator::I64Clz => {
5474                let (input, info) = self.state.pop1_extra()?;
5475                let input = self.apply_pending_canonicalization(input, info)?;
5476                let is_zero_undef = self.intrinsics.i1_zero;
5477                let res = self
5478                    .build_call_with_param_attributes(
5479                        self.intrinsics.ctlz_i64,
5480                        &[input.into(), is_zero_undef.into()],
5481                        "",
5482                    )?
5483                    .try_as_basic_value()
5484                    .unwrap_basic();
5485                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5486            }
5487            Operator::I32Ctz => {
5488                let (input, info) = self.state.pop1_extra()?;
5489                let input = self.apply_pending_canonicalization(input, info)?;
5490                let is_zero_undef = self.intrinsics.i1_zero;
5491                let res = self
5492                    .build_call_with_param_attributes(
5493                        self.intrinsics.cttz_i32,
5494                        &[input.into(), is_zero_undef.into()],
5495                        "",
5496                    )?
5497                    .try_as_basic_value()
5498                    .unwrap_basic();
5499                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5500            }
5501            Operator::I64Ctz => {
5502                let (input, info) = self.state.pop1_extra()?;
5503                let input = self.apply_pending_canonicalization(input, info)?;
5504                let is_zero_undef = self.intrinsics.i1_zero;
5505                let res = self
5506                    .build_call_with_param_attributes(
5507                        self.intrinsics.cttz_i64,
5508                        &[input.into(), is_zero_undef.into()],
5509                        "",
5510                    )?
5511                    .try_as_basic_value()
5512                    .unwrap_basic();
5513                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5514            }
5515            Operator::I8x16Popcnt => {
5516                let (v, i) = self.state.pop1_extra()?;
5517                let (v, _) = self.v128_into_i8x16(v, i)?;
5518                let res = self
5519                    .build_call_with_param_attributes(self.intrinsics.ctpop_i8x16, &[v.into()], "")?
5520                    .try_as_basic_value()
5521                    .unwrap_basic();
5522                let res = err!(
5523                    self.builder
5524                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5525                );
5526                self.state.push1(res);
5527            }
5528            Operator::I32Popcnt => {
5529                let (input, info) = self.state.pop1_extra()?;
5530                let input = self.apply_pending_canonicalization(input, info)?;
5531                let res = self
5532                    .build_call_with_param_attributes(
5533                        self.intrinsics.ctpop_i32,
5534                        &[input.into()],
5535                        "",
5536                    )?
5537                    .try_as_basic_value()
5538                    .unwrap_basic();
5539                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5540            }
5541            Operator::I64Popcnt => {
5542                let (input, info) = self.state.pop1_extra()?;
5543                let input = self.apply_pending_canonicalization(input, info)?;
5544                let res = self
5545                    .build_call_with_param_attributes(
5546                        self.intrinsics.ctpop_i64,
5547                        &[input.into()],
5548                        "",
5549                    )?
5550                    .try_as_basic_value()
5551                    .unwrap_basic();
5552                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5553            }
5554            Operator::I32Eqz => {
5555                let input = self.state.pop1()?.into_int_value();
5556                let cond = err!(self.builder.build_int_compare(
5557                    IntPredicate::EQ,
5558                    input,
5559                    self.intrinsics.i32_zero,
5560                    "",
5561                ));
5562                let res = err!(
5563                    self.builder
5564                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5565                );
5566                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5567            }
5568            Operator::I64Eqz => {
5569                let input = self.state.pop1()?.into_int_value();
5570                let cond = err!(self.builder.build_int_compare(
5571                    IntPredicate::EQ,
5572                    input,
5573                    self.intrinsics.i64_zero,
5574                    "",
5575                ));
5576                let res = err!(
5577                    self.builder
5578                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5579                );
5580                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5581            }
5582            Operator::I8x16Abs => {
5583                let (v, i) = self.state.pop1_extra()?;
5584                let (v, _) = self.v128_into_i8x16(v, i)?;
5585
5586                let seven = self.intrinsics.i8_ty.const_int(7, false);
5587                let seven = VectorType::const_vector(&[seven; 16]);
5588                let all_sign_bits = err!(self.builder.build_right_shift(v, seven, true, ""));
5589                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5590                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5591                let res = err!(
5592                    self.builder
5593                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5594                );
5595                self.state.push1(res);
5596            }
5597            Operator::I16x8Abs => {
5598                let (v, i) = self.state.pop1_extra()?;
5599                let (v, _) = self.v128_into_i16x8(v, i)?;
5600
5601                let fifteen = self.intrinsics.i16_ty.const_int(15, false);
5602                let fifteen = VectorType::const_vector(&[fifteen; 8]);
5603                let all_sign_bits = err!(self.builder.build_right_shift(v, fifteen, true, ""));
5604                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5605                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5606                let res = err!(
5607                    self.builder
5608                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5609                );
5610                self.state.push1(res);
5611            }
5612            Operator::I32x4Abs => {
5613                let (v, i) = self.state.pop1_extra()?;
5614                let (v, _) = self.v128_into_i32x4(v, i)?;
5615
5616                let thirtyone = self.intrinsics.i32_ty.const_int(31, false);
5617                let thirtyone = VectorType::const_vector(&[thirtyone; 4]);
5618                let all_sign_bits = err!(self.builder.build_right_shift(v, thirtyone, true, ""));
5619                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5620                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5621                let res = err!(
5622                    self.builder
5623                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5624                );
5625                self.state.push1(res);
5626            }
5627            Operator::I64x2Abs => {
5628                let (v, i) = self.state.pop1_extra()?;
5629                let (v, _) = self.v128_into_i64x2(v, i)?;
5630
5631                let sixtythree = self.intrinsics.i64_ty.const_int(63, false);
5632                let sixtythree = VectorType::const_vector(&[sixtythree; 2]);
5633                let all_sign_bits = err!(self.builder.build_right_shift(v, sixtythree, true, ""));
5634                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5635                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5636                let res = err!(
5637                    self.builder
5638                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5639                );
5640                self.state.push1(res);
5641            }
5642            Operator::I8x16MinS => {
5643                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5644                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5645                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5646                let cmp = err!(
5647                    self.builder
5648                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5649                );
5650                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5651                let res = err!(
5652                    self.builder
5653                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5654                );
5655                self.state.push1(res);
5656            }
5657            Operator::I8x16MinU => {
5658                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5659                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5660                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5661                let cmp = err!(
5662                    self.builder
5663                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5664                );
5665                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5666                let res = err!(
5667                    self.builder
5668                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5669                );
5670                self.state.push1(res);
5671            }
5672            Operator::I8x16MaxS => {
5673                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5674                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5675                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5676                let cmp = err!(
5677                    self.builder
5678                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5679                );
5680                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5681                let res = err!(
5682                    self.builder
5683                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5684                );
5685                self.state.push1(res);
5686            }
5687            Operator::I8x16MaxU => {
5688                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5689                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5690                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5691                let cmp = err!(
5692                    self.builder
5693                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5694                );
5695                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5696                let res = err!(
5697                    self.builder
5698                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5699                );
5700                self.state.push1(res);
5701            }
5702            Operator::I16x8MinS => {
5703                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5704                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5705                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5706                let cmp = err!(
5707                    self.builder
5708                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5709                );
5710                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5711                let res = err!(
5712                    self.builder
5713                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5714                );
5715                self.state.push1(res);
5716            }
5717            Operator::I16x8MinU => {
5718                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5719                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5720                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5721                let cmp = err!(
5722                    self.builder
5723                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5724                );
5725                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5726                let res = err!(
5727                    self.builder
5728                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5729                );
5730                self.state.push1(res);
5731            }
5732            Operator::I16x8MaxS => {
5733                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5734                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5735                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5736                let cmp = err!(
5737                    self.builder
5738                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5739                );
5740                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5741                let res = err!(
5742                    self.builder
5743                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5744                );
5745                self.state.push1(res);
5746            }
5747            Operator::I16x8MaxU => {
5748                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5749                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5750                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5751                let cmp = err!(
5752                    self.builder
5753                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5754                );
5755                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5756                let res = err!(
5757                    self.builder
5758                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5759                );
5760                self.state.push1(res);
5761            }
5762            Operator::I32x4MinS => {
5763                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5764                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5765                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5766                let cmp = err!(
5767                    self.builder
5768                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5769                );
5770                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5771                let res = err!(
5772                    self.builder
5773                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5774                );
5775                self.state.push1(res);
5776            }
5777            Operator::I32x4MinU => {
5778                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5779                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5780                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5781                let cmp = err!(
5782                    self.builder
5783                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5784                );
5785                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5786                let res = err!(
5787                    self.builder
5788                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5789                );
5790                self.state.push1(res);
5791            }
5792            Operator::I32x4MaxS => {
5793                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5794                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5795                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5796                let cmp = err!(
5797                    self.builder
5798                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5799                );
5800                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5801                let res = err!(
5802                    self.builder
5803                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5804                );
5805                self.state.push1(res);
5806            }
5807            Operator::I32x4MaxU => {
5808                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5809                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5810                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5811                let cmp = err!(
5812                    self.builder
5813                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5814                );
5815                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5816                let res = err!(
5817                    self.builder
5818                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5819                );
5820                self.state.push1(res);
5821            }
5822            Operator::I8x16AvgrU => {
5823                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5824                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5825                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5826
5827                // This approach is faster on x86-64 when the PAVG[BW]
5828                // instructions are available. On other platforms, an alternative
5829                // implementation appears likely to outperform, described here:
5830                //   %a = or %v1, %v2
5831                //   %b = and %a, 1
5832                //   %v1 = lshr %v1, 1
5833                //   %v2 = lshr %v2, 1
5834                //   %sum = add %v1, %v2
5835                //   %res = add %sum, %b
5836
5837                let ext_ty = self.intrinsics.i16_ty.vec_type(16);
5838                let one = self.intrinsics.i16_ty.const_int(1, false);
5839                let one = VectorType::const_vector(&[one; 16]);
5840
5841                let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5842                let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5843                let res = err!(self.builder.build_int_add(
5844                    err!(self.builder.build_int_add(one, v1, "")),
5845                    v2,
5846                    ""
5847                ));
5848                let res = err!(self.builder.build_right_shift(res, one, false, ""));
5849                let res = err!(
5850                    self.builder
5851                        .build_int_truncate(res, self.intrinsics.i8x16_ty, "")
5852                );
5853                let res = err!(
5854                    self.builder
5855                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5856                );
5857                self.state.push1(res);
5858            }
5859            Operator::I16x8AvgrU => {
5860                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5861                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5862                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5863
5864                // This approach is faster on x86-64 when the PAVG[BW]
5865                // instructions are available. On other platforms, an alternative
5866                // implementation appears likely to outperform, described here:
5867                //   %a = or %v1, %v2
5868                //   %b = and %a, 1
5869                //   %v1 = lshr %v1, 1
5870                //   %v2 = lshr %v2, 1
5871                //   %sum = add %v1, %v2
5872                //   %res = add %sum, %b
5873
5874                let ext_ty = self.intrinsics.i32_ty.vec_type(8);
5875                let one = self.intrinsics.i32_consts[1];
5876                let one = VectorType::const_vector(&[one; 8]);
5877
5878                let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5879                let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5880                let res = err!(self.builder.build_int_add(
5881                    err!(self.builder.build_int_add(one, v1, "")),
5882                    v2,
5883                    ""
5884                ));
5885                let res = err!(self.builder.build_right_shift(res, one, false, ""));
5886                let res = err!(
5887                    self.builder
5888                        .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
5889                );
5890                let res = err!(
5891                    self.builder
5892                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5893                );
5894                self.state.push1(res);
5895            }
5896            Operator::I64Add128 | Operator::I64Sub128 => {
5897                let (rhs_hi, rhs_hi_info) = self.state.pop1_extra()?;
5898                let (rhs_lo, rhs_lo_info) = self.state.pop1_extra()?;
5899                let (lhs_hi, lhs_hi_info) = self.state.pop1_extra()?;
5900                let (lhs_lo, lhs_lo_info) = self.state.pop1_extra()?;
5901
5902                let lhs_lo = self
5903                    .apply_pending_canonicalization(lhs_lo, lhs_lo_info)?
5904                    .into_int_value();
5905                let lhs_hi = self
5906                    .apply_pending_canonicalization(lhs_hi, lhs_hi_info)?
5907                    .into_int_value();
5908                let rhs_lo = self
5909                    .apply_pending_canonicalization(rhs_lo, rhs_lo_info)?
5910                    .into_int_value();
5911                let rhs_hi = self
5912                    .apply_pending_canonicalization(rhs_hi, rhs_hi_info)?
5913                    .into_int_value();
5914
5915                let idx0 = self.intrinsics.i32_ty.const_zero();
5916                let idx1 = self.intrinsics.i32_ty.const_int(1, false);
5917
5918                let lhs = self.intrinsics.i64x2_ty.get_undef();
5919                let lhs = err!(self.builder.build_insert_element(lhs, lhs_lo, idx0, ""));
5920                let lhs = err!(self.builder.build_insert_element(lhs, lhs_hi, idx1, ""));
5921                let lhs = err!(
5922                    self.builder
5923                        .build_bit_cast(lhs, self.intrinsics.i128_ty, "a")
5924                )
5925                .into_int_value();
5926
5927                let rhs = self.intrinsics.i64x2_ty.get_undef();
5928                let rhs = err!(self.builder.build_insert_element(rhs, rhs_lo, idx0, ""));
5929                let rhs = err!(self.builder.build_insert_element(rhs, rhs_hi, idx1, ""));
5930                let rhs = err!(
5931                    self.builder
5932                        .build_bit_cast(rhs, self.intrinsics.i128_ty, "b")
5933                )
5934                .into_int_value();
5935
5936                let result = err!(match op {
5937                    Operator::I64Add128 => self.builder.build_int_add(lhs, rhs, ""),
5938                    Operator::I64Sub128 => self.builder.build_int_sub(lhs, rhs, ""),
5939                    _ => unreachable!(),
5940                });
5941                let result = err!(self.builder.build_bit_cast(
5942                    result,
5943                    self.intrinsics.i64x2_ty,
5944                    ""
5945                ))
5946                .into_vector_value();
5947                let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
5948                let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
5949
5950                self.state.push1(result_lo);
5951                self.state.push1(result_hi);
5952            }
5953            Operator::I64MulWideS | Operator::I64MulWideU => {
5954                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
5955                let lhs = self
5956                    .apply_pending_canonicalization(lhs, lhs_info)?
5957                    .into_int_value();
5958                let rhs = self
5959                    .apply_pending_canonicalization(rhs, rhs_info)?
5960                    .into_int_value();
5961
5962                let lhs = err!(match op {
5963                    Operator::I64MulWideS => {
5964                        self.builder
5965                            .build_int_s_extend(lhs, self.intrinsics.i128_ty, "a")
5966                    }
5967                    Operator::I64MulWideU => {
5968                        self.builder
5969                            .build_int_z_extend(lhs, self.intrinsics.i128_ty, "a")
5970                    }
5971                    _ => unreachable!(),
5972                });
5973                let rhs = err!(match op {
5974                    Operator::I64MulWideS => {
5975                        self.builder
5976                            .build_int_s_extend(rhs, self.intrinsics.i128_ty, "b")
5977                    }
5978                    Operator::I64MulWideU => {
5979                        self.builder
5980                            .build_int_z_extend(rhs, self.intrinsics.i128_ty, "b")
5981                    }
5982                    _ => unreachable!(),
5983                });
5984
5985                let result = err!(self.builder.build_int_mul(lhs, rhs, ""));
5986                let result = err!(self.builder.build_bit_cast(
5987                    result,
5988                    self.intrinsics.i64x2_ty,
5989                    ""
5990                ))
5991                .into_vector_value();
5992                let idx0 = self.intrinsics.i32_ty.const_zero();
5993                let idx1 = self.intrinsics.i32_ty.const_int(1, false);
5994                let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
5995                let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
5996
5997                self.state.push1(result_lo);
5998                self.state.push1(result_hi);
5999            }
6000            _ => unreachable!(),
6001        }
6002        Ok(())
6003    }
6004
6005    // Floating-Point Arithmetic instructions.
6006    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-arithmetic-instructions
6007    fn translate_floating_point_arithmetic_operator(
6008        &mut self,
6009        op: Operator,
6010    ) -> Result<(), CompileError> {
6011        match op {
6012            Operator::F32Add => {
6013                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6014                let res = self
6015                    .build_call_with_param_attributes(
6016                        self.intrinsics.add_f32,
6017                        &[
6018                            v1.into(),
6019                            v2.into(),
6020                            self.intrinsics.fp_rounding_md,
6021                            self.intrinsics.fp_exception_md,
6022                        ],
6023                        "",
6024                    )?
6025                    .try_as_basic_value()
6026                    .unwrap_basic();
6027                self.state.push1_extra(
6028                    res,
6029                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6030                );
6031            }
6032            Operator::F64Add => {
6033                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6034                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6035                let res = self
6036                    .build_call_with_param_attributes(
6037                        self.intrinsics.add_f64,
6038                        &[
6039                            v1.into(),
6040                            v2.into(),
6041                            self.intrinsics.fp_rounding_md,
6042                            self.intrinsics.fp_exception_md,
6043                        ],
6044                        "",
6045                    )?
6046                    .try_as_basic_value()
6047                    .unwrap_basic();
6048                self.state.push1_extra(
6049                    res,
6050                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6051                );
6052            }
6053            Operator::F32x4Add => {
6054                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6055                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6056                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6057                let res = self
6058                    .build_call_with_param_attributes(
6059                        self.intrinsics.add_f32x4,
6060                        &[
6061                            v1.into(),
6062                            v2.into(),
6063                            self.intrinsics.fp_rounding_md,
6064                            self.intrinsics.fp_exception_md,
6065                        ],
6066                        "",
6067                    )?
6068                    .try_as_basic_value()
6069                    .unwrap_basic();
6070                let res = err!(
6071                    self.builder
6072                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6073                );
6074                self.state.push1_extra(
6075                    res,
6076                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6077                );
6078            }
6079            Operator::F64x2Add => {
6080                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6081                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6082                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6083                let res = self
6084                    .build_call_with_param_attributes(
6085                        self.intrinsics.add_f64x2,
6086                        &[
6087                            v1.into(),
6088                            v2.into(),
6089                            self.intrinsics.fp_rounding_md,
6090                            self.intrinsics.fp_exception_md,
6091                        ],
6092                        "",
6093                    )?
6094                    .try_as_basic_value()
6095                    .unwrap_basic();
6096                let res = err!(
6097                    self.builder
6098                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6099                );
6100                self.state.push1_extra(
6101                    res,
6102                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6103                );
6104            }
6105            Operator::F32Sub => {
6106                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6107                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6108                let res = self
6109                    .build_call_with_param_attributes(
6110                        self.intrinsics.sub_f32,
6111                        &[
6112                            v1.into(),
6113                            v2.into(),
6114                            self.intrinsics.fp_rounding_md,
6115                            self.intrinsics.fp_exception_md,
6116                        ],
6117                        "",
6118                    )?
6119                    .try_as_basic_value()
6120                    .unwrap_basic();
6121                self.state.push1_extra(
6122                    res,
6123                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6124                );
6125            }
6126            Operator::F64Sub => {
6127                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6128                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6129                let res = self
6130                    .build_call_with_param_attributes(
6131                        self.intrinsics.sub_f64,
6132                        &[
6133                            v1.into(),
6134                            v2.into(),
6135                            self.intrinsics.fp_rounding_md,
6136                            self.intrinsics.fp_exception_md,
6137                        ],
6138                        "",
6139                    )?
6140                    .try_as_basic_value()
6141                    .unwrap_basic();
6142                self.state.push1_extra(
6143                    res,
6144                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6145                );
6146            }
6147            Operator::F32x4Sub => {
6148                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6149                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6150                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6151                let res = self
6152                    .build_call_with_param_attributes(
6153                        self.intrinsics.sub_f32x4,
6154                        &[
6155                            v1.into(),
6156                            v2.into(),
6157                            self.intrinsics.fp_rounding_md,
6158                            self.intrinsics.fp_exception_md,
6159                        ],
6160                        "",
6161                    )?
6162                    .try_as_basic_value()
6163                    .unwrap_basic();
6164                let res = err!(
6165                    self.builder
6166                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6167                );
6168                self.state.push1_extra(
6169                    res,
6170                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6171                );
6172            }
6173            Operator::F64x2Sub => {
6174                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6175                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6176                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6177                let res = self
6178                    .build_call_with_param_attributes(
6179                        self.intrinsics.sub_f64x2,
6180                        &[
6181                            v1.into(),
6182                            v2.into(),
6183                            self.intrinsics.fp_rounding_md,
6184                            self.intrinsics.fp_exception_md,
6185                        ],
6186                        "",
6187                    )?
6188                    .try_as_basic_value()
6189                    .unwrap_basic();
6190                let res = err!(
6191                    self.builder
6192                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6193                );
6194                self.state.push1_extra(
6195                    res,
6196                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6197                );
6198            }
6199            Operator::F32Mul => {
6200                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6201                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6202                let res = self
6203                    .build_call_with_param_attributes(
6204                        self.intrinsics.mul_f32,
6205                        &[
6206                            v1.into(),
6207                            v2.into(),
6208                            self.intrinsics.fp_rounding_md,
6209                            self.intrinsics.fp_exception_md,
6210                        ],
6211                        "",
6212                    )?
6213                    .try_as_basic_value()
6214                    .unwrap_basic();
6215                self.state.push1_extra(
6216                    res,
6217                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6218                );
6219            }
6220            Operator::F64Mul => {
6221                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6222                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6223                let res = self
6224                    .build_call_with_param_attributes(
6225                        self.intrinsics.mul_f64,
6226                        &[
6227                            v1.into(),
6228                            v2.into(),
6229                            self.intrinsics.fp_rounding_md,
6230                            self.intrinsics.fp_exception_md,
6231                        ],
6232                        "",
6233                    )?
6234                    .try_as_basic_value()
6235                    .unwrap_basic();
6236                self.state.push1_extra(
6237                    res,
6238                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6239                );
6240            }
6241            Operator::F32x4Mul => {
6242                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6243                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6244                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6245                let res = self
6246                    .build_call_with_param_attributes(
6247                        self.intrinsics.mul_f32x4,
6248                        &[
6249                            v1.into(),
6250                            v2.into(),
6251                            self.intrinsics.fp_rounding_md,
6252                            self.intrinsics.fp_exception_md,
6253                        ],
6254                        "",
6255                    )?
6256                    .try_as_basic_value()
6257                    .unwrap_basic();
6258                let res = err!(
6259                    self.builder
6260                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6261                );
6262                self.state.push1_extra(
6263                    res,
6264                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6265                );
6266            }
6267            Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd
6268                if self.cpu_features.contains(CpuFeature::FMA) =>
6269            {
6270                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6271                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6272                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6273                let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
6274
6275                let v1 = match op {
6276                    Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6277                    _ => v1,
6278                };
6279                let res = self
6280                    .build_call_with_param_attributes(
6281                        self.intrinsics.muladd_f32x4,
6282                        &[
6283                            v1.into(),
6284                            v2.into(),
6285                            v3.into(),
6286                            self.intrinsics.fp_rounding_md,
6287                            self.intrinsics.fp_exception_md,
6288                        ],
6289                        "",
6290                    )?
6291                    .try_as_basic_value()
6292                    .unwrap_basic();
6293                let res = err!(
6294                    self.builder
6295                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6296                );
6297                let info = (i1.strip_pending() & i2.strip_pending())?;
6298                let info = (info & i3.strip_pending())?;
6299                let info = (info | ExtraInfo::pending_f32_nan())?;
6300                self.state.push1_extra(res, info);
6301            }
6302            Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd => {
6303                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6304                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6305                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6306                let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
6307
6308                let v1 = match op {
6309                    Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6310                    _ => v1,
6311                };
6312                let mul = self
6313                    .build_call_with_param_attributes(
6314                        self.intrinsics.mul_f32x4,
6315                        &[
6316                            v1.into(),
6317                            v2.into(),
6318                            self.intrinsics.fp_rounding_md,
6319                            self.intrinsics.fp_exception_md,
6320                        ],
6321                        "",
6322                    )?
6323                    .try_as_basic_value()
6324                    .unwrap_basic();
6325                let mul = mul.into_vector_value();
6326                let res = self
6327                    .build_call_with_param_attributes(
6328                        self.intrinsics.add_f32x4,
6329                        &[
6330                            mul.into(),
6331                            v3.into(),
6332                            self.intrinsics.fp_rounding_md,
6333                            self.intrinsics.fp_exception_md,
6334                        ],
6335                        "",
6336                    )?
6337                    .try_as_basic_value()
6338                    .unwrap_basic();
6339                let res = err!(
6340                    self.builder
6341                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6342                );
6343                let info = (i1.strip_pending() & i2.strip_pending())?;
6344                let info = (info & i3.strip_pending())?;
6345                let info = (info | ExtraInfo::pending_f32_nan())?;
6346                self.state.push1_extra(res, info);
6347            }
6348            Operator::F64x2Mul => {
6349                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6350                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6351                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6352                let res = self
6353                    .build_call_with_param_attributes(
6354                        self.intrinsics.mul_f64x2,
6355                        &[
6356                            v1.into(),
6357                            v2.into(),
6358                            self.intrinsics.fp_rounding_md,
6359                            self.intrinsics.fp_exception_md,
6360                        ],
6361                        "",
6362                    )?
6363                    .try_as_basic_value()
6364                    .unwrap_basic();
6365                let res = err!(
6366                    self.builder
6367                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6368                );
6369                self.state.push1_extra(
6370                    res,
6371                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6372                );
6373            }
6374            Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd
6375                if self.cpu_features.contains(CpuFeature::FMA) =>
6376            {
6377                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6378                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6379                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6380                let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
6381
6382                let v1 = match op {
6383                    Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6384                    _ => v1,
6385                };
6386                let res = self
6387                    .build_call_with_param_attributes(
6388                        self.intrinsics.muladd_f64x2,
6389                        &[
6390                            v1.into(),
6391                            v2.into(),
6392                            v3.into(),
6393                            self.intrinsics.fp_rounding_md,
6394                            self.intrinsics.fp_exception_md,
6395                        ],
6396                        "",
6397                    )?
6398                    .try_as_basic_value()
6399                    .unwrap_basic();
6400                let res = err!(
6401                    self.builder
6402                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6403                );
6404                let info = (i1.strip_pending() & i2.strip_pending())?;
6405                let info = (info & i3.strip_pending())?;
6406                let info = (info | ExtraInfo::pending_f64_nan())?;
6407                self.state.push1_extra(res, info);
6408            }
6409            Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd => {
6410                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6411                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6412                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6413                let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
6414
6415                let v1 = match op {
6416                    Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6417                    _ => v1,
6418                };
6419                let mul = self
6420                    .build_call_with_param_attributes(
6421                        self.intrinsics.mul_f64x2,
6422                        &[
6423                            v1.into(),
6424                            v2.into(),
6425                            self.intrinsics.fp_rounding_md,
6426                            self.intrinsics.fp_exception_md,
6427                        ],
6428                        "",
6429                    )?
6430                    .try_as_basic_value()
6431                    .unwrap_basic();
6432                let mul = mul.into_vector_value();
6433                let res = self
6434                    .build_call_with_param_attributes(
6435                        self.intrinsics.add_f64x2,
6436                        &[
6437                            mul.into(),
6438                            v3.into(),
6439                            self.intrinsics.fp_rounding_md,
6440                            self.intrinsics.fp_exception_md,
6441                        ],
6442                        "",
6443                    )?
6444                    .try_as_basic_value()
6445                    .unwrap_basic();
6446                let res = err!(
6447                    self.builder
6448                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6449                );
6450                let info = (i1.strip_pending() & i2.strip_pending())?;
6451                let info = (info & i3.strip_pending())?;
6452                let info = (info | ExtraInfo::pending_f64_nan())?;
6453                self.state.push1_extra(res, info);
6454            }
6455            Operator::F32Div => {
6456                let (v1, v2) = self.state.pop2()?;
6457                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6458                let res = self
6459                    .build_call_with_param_attributes(
6460                        self.intrinsics.div_f32,
6461                        &[
6462                            v1.into(),
6463                            v2.into(),
6464                            self.intrinsics.fp_rounding_md,
6465                            self.intrinsics.fp_exception_md,
6466                        ],
6467                        "",
6468                    )?
6469                    .try_as_basic_value()
6470                    .unwrap_basic();
6471                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6472            }
6473            Operator::F64Div => {
6474                let (v1, v2) = self.state.pop2()?;
6475                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6476                let res = self
6477                    .build_call_with_param_attributes(
6478                        self.intrinsics.div_f64,
6479                        &[
6480                            v1.into(),
6481                            v2.into(),
6482                            self.intrinsics.fp_rounding_md,
6483                            self.intrinsics.fp_exception_md,
6484                        ],
6485                        "",
6486                    )?
6487                    .try_as_basic_value()
6488                    .unwrap_basic();
6489                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6490            }
6491            Operator::F32x4Div => {
6492                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6493                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
6494                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
6495                let res = self
6496                    .build_call_with_param_attributes(
6497                        self.intrinsics.div_f32x4,
6498                        &[
6499                            v1.into(),
6500                            v2.into(),
6501                            self.intrinsics.fp_rounding_md,
6502                            self.intrinsics.fp_exception_md,
6503                        ],
6504                        "",
6505                    )?
6506                    .try_as_basic_value()
6507                    .unwrap_basic();
6508                let res = err!(
6509                    self.builder
6510                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6511                );
6512                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6513            }
6514            Operator::F64x2Div => {
6515                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6516                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
6517                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
6518                let res = self
6519                    .build_call_with_param_attributes(
6520                        self.intrinsics.div_f64x2,
6521                        &[
6522                            v1.into(),
6523                            v2.into(),
6524                            self.intrinsics.fp_rounding_md,
6525                            self.intrinsics.fp_exception_md,
6526                        ],
6527                        "",
6528                    )?
6529                    .try_as_basic_value()
6530                    .unwrap_basic();
6531                let res = err!(
6532                    self.builder
6533                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6534                );
6535                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6536            }
6537            Operator::F32Sqrt => {
6538                let input = self.state.pop1()?;
6539                let res = self
6540                    .build_call_with_param_attributes(
6541                        self.intrinsics.sqrt_f32,
6542                        &[input.into()],
6543                        "",
6544                    )?
6545                    .try_as_basic_value()
6546                    .unwrap_basic();
6547                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6548            }
6549            Operator::F64Sqrt => {
6550                let input = self.state.pop1()?;
6551                let res = self
6552                    .build_call_with_param_attributes(
6553                        self.intrinsics.sqrt_f64,
6554                        &[input.into()],
6555                        "",
6556                    )?
6557                    .try_as_basic_value()
6558                    .unwrap_basic();
6559                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6560            }
6561            Operator::F32x4Sqrt => {
6562                let (v, i) = self.state.pop1_extra()?;
6563                let (v, _) = self.v128_into_f32x4(v, i)?;
6564                let res = self
6565                    .build_call_with_param_attributes(self.intrinsics.sqrt_f32x4, &[v.into()], "")?
6566                    .try_as_basic_value()
6567                    .unwrap_basic();
6568                let bits = err!(
6569                    self.builder
6570                        .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6571                );
6572                self.state.push1_extra(bits, ExtraInfo::pending_f32_nan());
6573            }
6574            Operator::F64x2Sqrt => {
6575                let (v, i) = self.state.pop1_extra()?;
6576                let (v, _) = self.v128_into_f64x2(v, i)?;
6577                let res = self
6578                    .build_call_with_param_attributes(self.intrinsics.sqrt_f64x2, &[v.into()], "")?
6579                    .try_as_basic_value()
6580                    .unwrap_basic();
6581                let bits = err!(
6582                    self.builder
6583                        .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6584                );
6585                self.state.push1(bits);
6586            }
6587            Operator::F32Min => {
6588                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6589                let lhs = self
6590                    .apply_pending_canonicalization(lhs, lhs_info)?
6591                    .into_float_value();
6592                let rhs = self
6593                    .apply_pending_canonicalization(rhs, rhs_info)?
6594                    .into_float_value();
6595
6596                let res = self
6597                    .build_call_with_param_attributes(
6598                        self.intrinsics.minimum_f32,
6599                        &[lhs.into(), rhs.into()],
6600                        "",
6601                    )?
6602                    .try_as_basic_value()
6603                    .unwrap_basic();
6604
6605                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6606                let res = res.into_float_value();
6607
6608                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6609            }
6610            Operator::F64Min => {
6611                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6612                let lhs = self
6613                    .apply_pending_canonicalization(lhs, lhs_info)?
6614                    .into_float_value();
6615                let rhs = self
6616                    .apply_pending_canonicalization(rhs, rhs_info)?
6617                    .into_float_value();
6618
6619                let res = self
6620                    .build_call_with_param_attributes(
6621                        self.intrinsics.minimum_f64,
6622                        &[lhs.into(), rhs.into()],
6623                        "",
6624                    )?
6625                    .try_as_basic_value()
6626                    .unwrap_basic();
6627
6628                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6629                let res = res.into_float_value();
6630
6631                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6632            }
6633            Operator::F32x4RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6634                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6635                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6636                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6637                let res = self
6638                    .build_call_with_param_attributes(
6639                        self.intrinsics.x86_64.min_ps,
6640                        &[v1.into(), v2.into()],
6641                        "",
6642                    )?
6643                    .try_as_basic_value()
6644                    .unwrap_basic();
6645                let res = err!(
6646                    self.builder
6647                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6648                );
6649                self.state.push1_extra(
6650                    res,
6651                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6652                );
6653            }
6654            Operator::F32x4Min | Operator::F32x4RelaxedMin => {
6655                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6656                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6657                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6658                let res = self
6659                    .build_call_with_param_attributes(
6660                        self.intrinsics.minimum_f32x4,
6661                        &[v1.into(), v2.into()],
6662                        "",
6663                    )?
6664                    .try_as_basic_value()
6665                    .unwrap_basic();
6666
6667                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6668                let res = res.into_vector_value();
6669
6670                let res = err!(
6671                    self.builder
6672                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6673                );
6674                self.state.push1_extra(
6675                    res,
6676                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6677                );
6678            }
6679            Operator::F32x4PMin => {
6680                // Pseudo-min: b < a ? b : a
6681                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6682                let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6683                let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6684                let cmp = err!(
6685                    self.builder
6686                        .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6687                );
6688                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6689                let res = err!(
6690                    self.builder
6691                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6692                );
6693                self.state.push1(res);
6694            }
6695            Operator::F64x2RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6696                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6697                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6698                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6699                let res = self
6700                    .build_call_with_param_attributes(
6701                        self.intrinsics.x86_64.min_pd,
6702                        &[v1.into(), v2.into()],
6703                        "",
6704                    )?
6705                    .try_as_basic_value()
6706                    .unwrap_basic();
6707                let res = err!(
6708                    self.builder
6709                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6710                );
6711                self.state.push1_extra(
6712                    res,
6713                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6714                );
6715            }
6716            Operator::F64x2Min | Operator::F64x2RelaxedMin => {
6717                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6718                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6719                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6720                let res = self
6721                    .build_call_with_param_attributes(
6722                        self.intrinsics.minimum_f64x2,
6723                        &[v1.into(), v2.into()],
6724                        "",
6725                    )?
6726                    .try_as_basic_value()
6727                    .unwrap_basic();
6728
6729                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6730                let res = res.into_vector_value();
6731
6732                let res = err!(
6733                    self.builder
6734                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6735                );
6736                self.state.push1_extra(
6737                    res,
6738                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6739                );
6740            }
6741            Operator::F64x2PMin => {
6742                // Pseudo-min: b < a ? b : a
6743                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6744                let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6745                let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6746                let cmp = err!(
6747                    self.builder
6748                        .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6749                );
6750                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6751                let res = err!(
6752                    self.builder
6753                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6754                );
6755                self.state.push1(res);
6756            }
6757            Operator::F32Max => {
6758                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6759                let lhs = self
6760                    .apply_pending_canonicalization(lhs, lhs_info)?
6761                    .into_float_value();
6762                let rhs = self
6763                    .apply_pending_canonicalization(rhs, rhs_info)?
6764                    .into_float_value();
6765
6766                let res = self
6767                    .build_call_with_param_attributes(
6768                        self.intrinsics.maximum_f32,
6769                        &[lhs.into(), rhs.into()],
6770                        "",
6771                    )?
6772                    .try_as_basic_value()
6773                    .unwrap_basic();
6774
6775                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6776                let res = res.into_float_value();
6777
6778                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6779            }
6780            Operator::F64Max => {
6781                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6782                let lhs = self
6783                    .apply_pending_canonicalization(lhs, lhs_info)?
6784                    .into_float_value();
6785                let rhs = self
6786                    .apply_pending_canonicalization(rhs, rhs_info)?
6787                    .into_float_value();
6788
6789                let res = self
6790                    .build_call_with_param_attributes(
6791                        self.intrinsics.maximum_f64,
6792                        &[lhs.into(), rhs.into()],
6793                        "",
6794                    )?
6795                    .try_as_basic_value()
6796                    .unwrap_basic();
6797
6798                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6799                let res = res.into_float_value();
6800
6801                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6802            }
6803            Operator::F32x4RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6804                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6805                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6806                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6807                let res = self
6808                    .build_call_with_param_attributes(
6809                        self.intrinsics.x86_64.max_ps,
6810                        &[v1.into(), v2.into()],
6811                        "",
6812                    )?
6813                    .try_as_basic_value()
6814                    .unwrap_basic();
6815                let res = err!(
6816                    self.builder
6817                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6818                );
6819                self.state.push1_extra(
6820                    res,
6821                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6822                );
6823            }
6824            Operator::F32x4Max | Operator::F32x4RelaxedMax => {
6825                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6826                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6827                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6828                let res = self
6829                    .build_call_with_param_attributes(
6830                        self.intrinsics.maximum_f32x4,
6831                        &[v1.into(), v2.into()],
6832                        "",
6833                    )?
6834                    .try_as_basic_value()
6835                    .unwrap_basic();
6836
6837                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6838                let res = res.into_vector_value();
6839
6840                let res = err!(
6841                    self.builder
6842                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6843                );
6844                self.state.push1_extra(
6845                    res,
6846                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6847                );
6848            }
6849            Operator::F32x4PMax => {
6850                // Pseudo-max: a < b ? b : a
6851                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6852                let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6853                let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6854                let cmp = err!(
6855                    self.builder
6856                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6857                );
6858                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6859
6860                let res = err!(
6861                    self.builder
6862                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6863                );
6864                self.state.push1(res);
6865            }
6866            Operator::F64x2RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6867                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6868                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6869                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6870                let res = self
6871                    .build_call_with_param_attributes(
6872                        self.intrinsics.x86_64.max_pd,
6873                        &[v1.into(), v2.into()],
6874                        "",
6875                    )?
6876                    .try_as_basic_value()
6877                    .unwrap_basic();
6878                let res = err!(
6879                    self.builder
6880                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6881                );
6882                self.state.push1_extra(
6883                    res,
6884                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6885                );
6886            }
6887            Operator::F64x2Max | Operator::F64x2RelaxedMax => {
6888                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6889                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6890                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6891                let res = self
6892                    .build_call_with_param_attributes(
6893                        self.intrinsics.maximum_f64x2,
6894                        &[v1.into(), v2.into()],
6895                        "",
6896                    )?
6897                    .try_as_basic_value()
6898                    .unwrap_basic();
6899
6900                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6901                let res = res.into_vector_value();
6902
6903                let res = err!(
6904                    self.builder
6905                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6906                );
6907                self.state.push1_extra(
6908                    res,
6909                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6910                );
6911            }
6912            Operator::F64x2PMax => {
6913                // Pseudo-max: a < b ? b : a
6914                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6915                let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6916                let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6917                let cmp = err!(
6918                    self.builder
6919                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6920                );
6921                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6922                let res = err!(
6923                    self.builder
6924                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6925                );
6926                self.state.push1(res);
6927            }
6928            Operator::F32Ceil => {
6929                let (input, info) = self.state.pop1_extra()?;
6930                let res = err!(self.build_call_with_param_attributes(
6931                    self.intrinsics.ceil_f32,
6932                    &[input.into()],
6933                    ""
6934                ))
6935                .try_as_basic_value()
6936                .unwrap_basic();
6937                let (res, info) = self.finalize_rounding_result(res, info)?;
6938                self.state.push1_extra(res, info);
6939            }
6940            Operator::F32x4Ceil => {
6941                let (v, i) = self.state.pop1_extra()?;
6942                let (v, _) = self.v128_into_f32x4(v, i)?;
6943                let res = err!(self.build_call_with_param_attributes(
6944                    self.intrinsics.ceil_f32x4,
6945                    &[v.into()],
6946                    ""
6947                ))
6948                .try_as_basic_value()
6949                .unwrap_basic();
6950                let (res, info) = self.finalize_rounding_result(res, i)?;
6951                let res = err!(
6952                    self.builder
6953                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6954                );
6955                self.state.push1_extra(res, info);
6956            }
6957            Operator::F64Ceil => {
6958                let (input, info) = self.state.pop1_extra()?;
6959                let res = err!(self.build_call_with_param_attributes(
6960                    self.intrinsics.ceil_f64,
6961                    &[input.into()],
6962                    ""
6963                ))
6964                .try_as_basic_value()
6965                .unwrap_basic();
6966                let (res, info) = self.finalize_rounding_result(res, info)?;
6967                self.state.push1_extra(res, info);
6968            }
6969            Operator::F64x2Ceil => {
6970                let (v, i) = self.state.pop1_extra()?;
6971                let (v, _) = self.v128_into_f64x2(v, i)?;
6972                let res = err!(self.build_call_with_param_attributes(
6973                    self.intrinsics.ceil_f64x2,
6974                    &[v.into()],
6975                    ""
6976                ))
6977                .try_as_basic_value()
6978                .unwrap_basic();
6979                let (res, info) = self.finalize_rounding_result(res, i)?;
6980                let res = err!(
6981                    self.builder
6982                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6983                );
6984                self.state.push1_extra(res, info);
6985            }
6986            Operator::F32Floor => {
6987                let (input, info) = self.state.pop1_extra()?;
6988                let res = err!(self.build_call_with_param_attributes(
6989                    self.intrinsics.floor_f32,
6990                    &[input.into()],
6991                    ""
6992                ))
6993                .try_as_basic_value()
6994                .unwrap_basic();
6995                let (res, info) = self.finalize_rounding_result(res, info)?;
6996                self.state.push1_extra(res, info);
6997            }
6998            Operator::F32x4Floor => {
6999                let (v, i) = self.state.pop1_extra()?;
7000                let (v, _) = self.v128_into_f32x4(v, i)?;
7001                let res = err!(self.build_call_with_param_attributes(
7002                    self.intrinsics.floor_f32x4,
7003                    &[v.into()],
7004                    ""
7005                ))
7006                .try_as_basic_value()
7007                .unwrap_basic();
7008                let (res, info) = self.finalize_rounding_result(res, i)?;
7009                let res = err!(
7010                    self.builder
7011                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7012                );
7013                self.state.push1_extra(res, info);
7014            }
7015            Operator::F64Floor => {
7016                let (input, info) = self.state.pop1_extra()?;
7017                let res = err!(self.build_call_with_param_attributes(
7018                    self.intrinsics.floor_f64,
7019                    &[input.into()],
7020                    ""
7021                ))
7022                .try_as_basic_value()
7023                .unwrap_basic();
7024                let (res, info) = self.finalize_rounding_result(res, info)?;
7025                self.state.push1_extra(res, info);
7026            }
7027            Operator::F64x2Floor => {
7028                let (v, i) = self.state.pop1_extra()?;
7029                let (v, _) = self.v128_into_f64x2(v, i)?;
7030                let res = err!(self.build_call_with_param_attributes(
7031                    self.intrinsics.floor_f64x2,
7032                    &[v.into()],
7033                    ""
7034                ))
7035                .try_as_basic_value()
7036                .unwrap_basic();
7037                let (res, info) = self.finalize_rounding_result(res, i)?;
7038                let res = err!(
7039                    self.builder
7040                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7041                );
7042                self.state.push1_extra(res, info);
7043            }
7044            Operator::F32Trunc => {
7045                let (v, info) = self.state.pop1_extra()?;
7046                let res = err!(
7047                    self.builder
7048                        .build_call(self.intrinsics.trunc_f32, &[v.into()], "")
7049                )
7050                .try_as_basic_value()
7051                .unwrap_basic();
7052                let (res, info) = self.finalize_rounding_result(res, info)?;
7053                self.state.push1_extra(res, info);
7054            }
7055            Operator::F32x4Trunc => {
7056                let (v, i) = self.state.pop1_extra()?;
7057                let (v, _) = self.v128_into_f32x4(v, i)?;
7058                let res = err!(self.build_call_with_param_attributes(
7059                    self.intrinsics.trunc_f32x4,
7060                    &[v.into()],
7061                    ""
7062                ))
7063                .try_as_basic_value()
7064                .unwrap_basic();
7065                let (res, info) = self.finalize_rounding_result(res, i)?;
7066                let res = err!(
7067                    self.builder
7068                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7069                );
7070                self.state.push1_extra(res, info);
7071            }
7072            Operator::F64Trunc => {
7073                let (v, info) = self.state.pop1_extra()?;
7074                let res = err!(
7075                    self.builder
7076                        .build_call(self.intrinsics.trunc_f64, &[v.into()], "")
7077                )
7078                .try_as_basic_value()
7079                .unwrap_basic();
7080                let (res, info) = self.finalize_rounding_result(res, info)?;
7081                self.state.push1_extra(res, info);
7082            }
7083            Operator::F64x2Trunc => {
7084                let (v, i) = self.state.pop1_extra()?;
7085                let (v, _) = self.v128_into_f64x2(v, i)?;
7086                let res = err!(self.build_call_with_param_attributes(
7087                    self.intrinsics.trunc_f64x2,
7088                    &[v.into()],
7089                    ""
7090                ))
7091                .try_as_basic_value()
7092                .unwrap_basic();
7093                let (res, info) = self.finalize_rounding_result(res, i)?;
7094                let res = err!(
7095                    self.builder
7096                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7097                );
7098                self.state.push1_extra(res, info);
7099            }
7100            Operator::F32Nearest => {
7101                let (v, info) = self.state.pop1_extra()?;
7102                let res = err!(self.build_call_with_param_attributes(
7103                    self.intrinsics.nearbyint_f32,
7104                    &[v.into()],
7105                    ""
7106                ))
7107                .try_as_basic_value()
7108                .unwrap_basic();
7109                let (res, info) = self.finalize_rounding_result(res, info)?;
7110                self.state.push1_extra(res, info);
7111            }
7112            Operator::F32x4Nearest => {
7113                let (v, i) = self.state.pop1_extra()?;
7114                let (v, _) = self.v128_into_f32x4(v, i)?;
7115                let res = err!(self.build_call_with_param_attributes(
7116                    self.intrinsics.nearbyint_f32x4,
7117                    &[v.into()],
7118                    ""
7119                ))
7120                .try_as_basic_value()
7121                .unwrap_basic();
7122                let (res, info) = self.finalize_rounding_result(res, i)?;
7123                let res = err!(
7124                    self.builder
7125                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7126                );
7127                self.state.push1_extra(res, info);
7128            }
7129            Operator::F64Nearest => {
7130                let (v, info) = self.state.pop1_extra()?;
7131                let res = err!(self.build_call_with_param_attributes(
7132                    self.intrinsics.nearbyint_f64,
7133                    &[v.into()],
7134                    ""
7135                ))
7136                .try_as_basic_value()
7137                .unwrap_basic();
7138                let (res, info) = self.finalize_rounding_result(res, info)?;
7139                self.state.push1_extra(res, info);
7140            }
7141            Operator::F64x2Nearest => {
7142                let (v, i) = self.state.pop1_extra()?;
7143                let (v, _) = self.v128_into_f64x2(v, i)?;
7144                let res = err!(self.build_call_with_param_attributes(
7145                    self.intrinsics.nearbyint_f64x2,
7146                    &[v.into()],
7147                    ""
7148                ))
7149                .try_as_basic_value()
7150                .unwrap_basic();
7151                let (res, info) = self.finalize_rounding_result(res, i)?;
7152                let res = err!(
7153                    self.builder
7154                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7155                );
7156                self.state.push1_extra(res, info);
7157            }
7158            Operator::F32Abs => {
7159                let (v, i) = self.state.pop1_extra()?;
7160                let v = self.apply_pending_canonicalization(v, i)?;
7161                let res = err!(
7162                    self.builder
7163                        .build_call(self.intrinsics.fabs_f32, &[v.into()], "")
7164                )
7165                .try_as_basic_value()
7166                .unwrap_basic();
7167                // The exact NaN returned by F32Abs is fully defined. Do not
7168                // adjust.
7169                self.state.push1_extra(res, i.strip_pending());
7170            }
7171            Operator::F64Abs => {
7172                let (v, i) = self.state.pop1_extra()?;
7173                let v = self.apply_pending_canonicalization(v, i)?;
7174                let res = err!(
7175                    self.builder
7176                        .build_call(self.intrinsics.fabs_f64, &[v.into()], "")
7177                )
7178                .try_as_basic_value()
7179                .unwrap_basic();
7180                // The exact NaN returned by F64Abs is fully defined. Do not
7181                // adjust.
7182                self.state.push1_extra(res, i.strip_pending());
7183            }
7184            Operator::F32x4Abs => {
7185                let (v, i) = self.state.pop1_extra()?;
7186                let v = err!(self.builder.build_bit_cast(
7187                    v.into_int_value(),
7188                    self.intrinsics.f32x4_ty,
7189                    ""
7190                ));
7191                let v = self.apply_pending_canonicalization(v, i)?;
7192                let res = self
7193                    .build_call_with_param_attributes(self.intrinsics.fabs_f32x4, &[v.into()], "")?
7194                    .try_as_basic_value()
7195                    .unwrap_basic();
7196                let res = err!(
7197                    self.builder
7198                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7199                );
7200                // The exact NaN returned by F32x4Abs is fully defined. Do not
7201                // adjust.
7202                self.state.push1_extra(res, i.strip_pending());
7203            }
7204            Operator::F64x2Abs => {
7205                let (v, i) = self.state.pop1_extra()?;
7206                let v = err!(self.builder.build_bit_cast(
7207                    v.into_int_value(),
7208                    self.intrinsics.f64x2_ty,
7209                    ""
7210                ));
7211                let v = self.apply_pending_canonicalization(v, i)?;
7212                let res = self
7213                    .build_call_with_param_attributes(self.intrinsics.fabs_f64x2, &[v.into()], "")?
7214                    .try_as_basic_value()
7215                    .unwrap_basic();
7216                let res = err!(
7217                    self.builder
7218                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7219                );
7220                // The exact NaN returned by F32x4Abs is fully defined. Do not
7221                // adjust.
7222                self.state.push1_extra(res, i.strip_pending());
7223            }
7224            Operator::F32x4Neg => {
7225                let (v, i) = self.state.pop1_extra()?;
7226                let v = err!(self.builder.build_bit_cast(
7227                    v.into_int_value(),
7228                    self.intrinsics.f32x4_ty,
7229                    ""
7230                ));
7231                let v = self
7232                    .apply_pending_canonicalization(v, i)?
7233                    .into_vector_value();
7234                let res = err!(self.builder.build_float_neg(v, ""));
7235                let res = err!(
7236                    self.builder
7237                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7238                );
7239                // The exact NaN returned by F32x4Neg is fully defined. Do not
7240                // adjust.
7241                self.state.push1_extra(res, i.strip_pending());
7242            }
7243            Operator::F64x2Neg => {
7244                let (v, i) = self.state.pop1_extra()?;
7245                let v = err!(self.builder.build_bit_cast(
7246                    v.into_int_value(),
7247                    self.intrinsics.f64x2_ty,
7248                    ""
7249                ));
7250                let v = self
7251                    .apply_pending_canonicalization(v, i)?
7252                    .into_vector_value();
7253                let res = err!(self.builder.build_float_neg(v, ""));
7254                let res = err!(
7255                    self.builder
7256                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7257                );
7258                // The exact NaN returned by F64x2Neg is fully defined. Do not
7259                // adjust.
7260                self.state.push1_extra(res, i.strip_pending());
7261            }
7262            Operator::F32Neg | Operator::F64Neg => {
7263                let (v, i) = self.state.pop1_extra()?;
7264                let v = self
7265                    .apply_pending_canonicalization(v, i)?
7266                    .into_float_value();
7267                let res = err!(self.builder.build_float_neg(v, ""));
7268                // The exact NaN returned by F32Neg and F64Neg are fully defined.
7269                // Do not adjust.
7270                self.state.push1_extra(res, i.strip_pending());
7271            }
7272            Operator::F32Copysign => {
7273                let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
7274                let mag = self.apply_pending_canonicalization(mag, mag_info)?;
7275                let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
7276                let res = self
7277                    .build_call_with_param_attributes(
7278                        self.intrinsics.copysign_f32,
7279                        &[mag.into(), sgn.into()],
7280                        "",
7281                    )?
7282                    .try_as_basic_value()
7283                    .unwrap_basic();
7284                // The exact NaN returned by F32Copysign is fully defined.
7285                // Do not adjust.
7286                self.state.push1_extra(res, mag_info.strip_pending());
7287            }
7288            Operator::F64Copysign => {
7289                let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
7290                let mag = self.apply_pending_canonicalization(mag, mag_info)?;
7291                let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
7292                let res = self
7293                    .build_call_with_param_attributes(
7294                        self.intrinsics.copysign_f64,
7295                        &[mag.into(), sgn.into()],
7296                        "",
7297                    )?
7298                    .try_as_basic_value()
7299                    .unwrap_basic();
7300                // The exact NaN returned by F32Copysign is fully defined.
7301                // Do not adjust.
7302                self.state.push1_extra(res, mag_info.strip_pending());
7303            }
7304            _ => unreachable!(),
7305        }
7306        Ok(())
7307    }
7308
7309    // Integer Comparison instructions.
7310    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-comparison-instructions
7311    fn translate_integer_comparison_operator(&mut self, op: Operator) -> Result<(), CompileError> {
7312        match op {
7313            Operator::I32Eq | Operator::I64Eq => {
7314                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7315                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7316                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7317                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7318                let cond = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7319                let res = err!(
7320                    self.builder
7321                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7322                );
7323                self.state.push1_extra(
7324                    res,
7325                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7326                );
7327            }
7328            Operator::I8x16Eq => {
7329                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7330                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7331                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7332                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7333                let res = err!(
7334                    self.builder
7335                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7336                );
7337                let res = err!(
7338                    self.builder
7339                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7340                );
7341                self.state.push1(res);
7342            }
7343            Operator::I16x8Eq => {
7344                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7345                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7346                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7347                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7348                let res = err!(
7349                    self.builder
7350                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7351                );
7352                let res = err!(
7353                    self.builder
7354                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7355                );
7356                self.state.push1(res);
7357            }
7358            Operator::I32x4Eq => {
7359                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7360                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7361                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7362                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7363                let res = err!(
7364                    self.builder
7365                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7366                );
7367                let res = err!(
7368                    self.builder
7369                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7370                );
7371                self.state.push1(res);
7372            }
7373            Operator::I64x2Eq => {
7374                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7375                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7376                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7377                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7378                let res = err!(
7379                    self.builder
7380                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7381                );
7382                let res = err!(
7383                    self.builder
7384                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7385                );
7386                self.state.push1(res);
7387            }
7388            Operator::I32Ne | Operator::I64Ne => {
7389                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7390                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7391                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7392                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7393                let cond = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7394                let res = err!(
7395                    self.builder
7396                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7397                );
7398                self.state.push1_extra(
7399                    res,
7400                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7401                );
7402            }
7403            Operator::I8x16Ne => {
7404                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7405                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7406                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7407                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7408                let res = err!(
7409                    self.builder
7410                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7411                );
7412                let res = err!(
7413                    self.builder
7414                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7415                );
7416                self.state.push1(res);
7417            }
7418            Operator::I16x8Ne => {
7419                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7420                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7421                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7422                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7423                let res = err!(
7424                    self.builder
7425                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7426                );
7427                let res = err!(
7428                    self.builder
7429                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7430                );
7431                self.state.push1(res);
7432            }
7433            Operator::I32x4Ne => {
7434                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7435                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7436                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7437                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7438                let res = err!(
7439                    self.builder
7440                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7441                );
7442                let res = err!(
7443                    self.builder
7444                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7445                );
7446                self.state.push1(res);
7447            }
7448            Operator::I64x2Ne => {
7449                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7450                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7451                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7452                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7453                let res = err!(
7454                    self.builder
7455                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7456                );
7457                let res = err!(
7458                    self.builder
7459                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7460                );
7461                self.state.push1(res);
7462            }
7463            Operator::I32LtS | Operator::I64LtS => {
7464                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7465                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7466                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7467                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7468                let cond = err!(
7469                    self.builder
7470                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7471                );
7472                let res = err!(
7473                    self.builder
7474                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7475                );
7476                self.state.push1_extra(
7477                    res,
7478                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7479                );
7480            }
7481            Operator::I8x16LtS => {
7482                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7483                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7484                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7485                let res = err!(
7486                    self.builder
7487                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7488                );
7489                let res = err!(
7490                    self.builder
7491                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7492                );
7493                let res = err!(
7494                    self.builder
7495                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7496                );
7497                self.state.push1(res);
7498            }
7499            Operator::I16x8LtS => {
7500                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7501                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7502                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7503                let res = err!(
7504                    self.builder
7505                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7506                );
7507                let res = err!(
7508                    self.builder
7509                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7510                );
7511                let res = err!(
7512                    self.builder
7513                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7514                );
7515                self.state.push1(res);
7516            }
7517            Operator::I32x4LtS => {
7518                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7519                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7520                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7521                let res = err!(
7522                    self.builder
7523                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7524                );
7525                let res = err!(
7526                    self.builder
7527                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7528                );
7529                let res = err!(
7530                    self.builder
7531                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7532                );
7533                self.state.push1(res);
7534            }
7535            Operator::I64x2LtS => {
7536                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7537                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7538                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7539                let res = err!(
7540                    self.builder
7541                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7542                );
7543                let res = err!(
7544                    self.builder
7545                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7546                );
7547                let res = err!(
7548                    self.builder
7549                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7550                );
7551                self.state.push1(res);
7552            }
7553            Operator::I32LtU | Operator::I64LtU => {
7554                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7555                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7556                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7557                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7558                let cond = err!(
7559                    self.builder
7560                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7561                );
7562                let res = err!(
7563                    self.builder
7564                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7565                );
7566                self.state.push1(res);
7567            }
7568            Operator::I8x16LtU => {
7569                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7570                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7571                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7572                let res = err!(
7573                    self.builder
7574                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7575                );
7576                let res = err!(
7577                    self.builder
7578                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7579                );
7580                let res = err!(
7581                    self.builder
7582                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7583                );
7584                self.state.push1(res);
7585            }
7586            Operator::I16x8LtU => {
7587                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7588                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7589                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7590                let res = err!(
7591                    self.builder
7592                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7593                );
7594                let res = err!(
7595                    self.builder
7596                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7597                );
7598                let res = err!(
7599                    self.builder
7600                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7601                );
7602                self.state.push1(res);
7603            }
7604            Operator::I32x4LtU => {
7605                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7606                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7607                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7608                let res = err!(
7609                    self.builder
7610                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7611                );
7612                let res = err!(
7613                    self.builder
7614                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7615                );
7616                let res = err!(
7617                    self.builder
7618                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7619                );
7620                self.state.push1(res);
7621            }
7622            Operator::I32LeS | Operator::I64LeS => {
7623                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7624                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7625                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7626                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7627                let cond = err!(
7628                    self.builder
7629                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7630                );
7631                let res = err!(
7632                    self.builder
7633                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7634                );
7635                self.state.push1_extra(
7636                    res,
7637                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7638                );
7639            }
7640            Operator::I8x16LeS => {
7641                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7642                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7643                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7644                let res = err!(
7645                    self.builder
7646                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7647                );
7648                let res = err!(
7649                    self.builder
7650                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7651                );
7652                let res = err!(
7653                    self.builder
7654                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7655                );
7656                self.state.push1(res);
7657            }
7658            Operator::I16x8LeS => {
7659                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7660                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7661                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7662                let res = err!(
7663                    self.builder
7664                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7665                );
7666                let res = err!(
7667                    self.builder
7668                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7669                );
7670                let res = err!(
7671                    self.builder
7672                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7673                );
7674                self.state.push1(res);
7675            }
7676            Operator::I32x4LeS => {
7677                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7678                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7679                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7680                let res = err!(
7681                    self.builder
7682                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7683                );
7684                let res = err!(
7685                    self.builder
7686                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7687                );
7688                let res = err!(
7689                    self.builder
7690                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7691                );
7692                self.state.push1(res);
7693            }
7694            Operator::I64x2LeS => {
7695                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7696                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7697                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7698                let res = err!(
7699                    self.builder
7700                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7701                );
7702                let res = err!(
7703                    self.builder
7704                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7705                );
7706                let res = err!(
7707                    self.builder
7708                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7709                );
7710                self.state.push1(res);
7711            }
7712            Operator::I32LeU | Operator::I64LeU => {
7713                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7714                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7715                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7716                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7717                let cond = err!(
7718                    self.builder
7719                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7720                );
7721                let res = err!(
7722                    self.builder
7723                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7724                );
7725                self.state.push1_extra(
7726                    res,
7727                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7728                );
7729            }
7730            Operator::I8x16LeU => {
7731                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7732                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7733                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7734                let res = err!(
7735                    self.builder
7736                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7737                );
7738                let res = err!(
7739                    self.builder
7740                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7741                );
7742                let res = err!(
7743                    self.builder
7744                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7745                );
7746                self.state.push1(res);
7747            }
7748            Operator::I16x8LeU => {
7749                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7750                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7751                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7752                let res = err!(
7753                    self.builder
7754                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7755                );
7756                let res = err!(
7757                    self.builder
7758                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7759                );
7760                let res = err!(
7761                    self.builder
7762                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7763                );
7764                self.state.push1(res);
7765            }
7766            Operator::I32x4LeU => {
7767                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7768                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7769                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7770                let res = err!(
7771                    self.builder
7772                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7773                );
7774                let res = err!(
7775                    self.builder
7776                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7777                );
7778                let res = err!(
7779                    self.builder
7780                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7781                );
7782                self.state.push1(res);
7783            }
7784            Operator::I32GtS | Operator::I64GtS => {
7785                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7786                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7787                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7788                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7789                let cond = err!(
7790                    self.builder
7791                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7792                );
7793                let res = err!(
7794                    self.builder
7795                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7796                );
7797                self.state.push1_extra(
7798                    res,
7799                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7800                );
7801            }
7802            Operator::I8x16GtS => {
7803                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7804                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7805                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7806                let res = err!(
7807                    self.builder
7808                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7809                );
7810                let res = err!(
7811                    self.builder
7812                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7813                );
7814                let res = err!(
7815                    self.builder
7816                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7817                );
7818                self.state.push1(res);
7819            }
7820            Operator::I16x8GtS => {
7821                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7822                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7823                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7824                let res = err!(
7825                    self.builder
7826                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7827                );
7828                let res = err!(
7829                    self.builder
7830                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7831                );
7832                let res = err!(
7833                    self.builder
7834                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7835                );
7836                self.state.push1(res);
7837            }
7838            Operator::I32x4GtS => {
7839                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7840                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7841                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7842                let res = err!(
7843                    self.builder
7844                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7845                );
7846                let res = err!(
7847                    self.builder
7848                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7849                );
7850                let res = err!(
7851                    self.builder
7852                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7853                );
7854                self.state.push1(res);
7855            }
7856            Operator::I64x2GtS => {
7857                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7858                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7859                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7860                let res = err!(
7861                    self.builder
7862                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7863                );
7864                let res = err!(
7865                    self.builder
7866                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7867                );
7868                let res = err!(
7869                    self.builder
7870                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7871                );
7872                self.state.push1(res);
7873            }
7874            Operator::I32GtU | Operator::I64GtU => {
7875                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7876                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7877                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7878                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7879                let cond = err!(
7880                    self.builder
7881                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
7882                );
7883                let res = err!(
7884                    self.builder
7885                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7886                );
7887                self.state.push1_extra(
7888                    res,
7889                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7890                );
7891            }
7892            Operator::I8x16GtU => {
7893                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7894                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7895                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7896                let res = err!(
7897                    self.builder
7898                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
7899                );
7900                let res = err!(
7901                    self.builder
7902                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7903                );
7904                let res = err!(
7905                    self.builder
7906                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7907                );
7908                self.state.push1(res);
7909            }
7910            Operator::I16x8GtU => {
7911                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7912                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7913                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7914                let res = err!(
7915                    self.builder
7916                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
7917                );
7918                let res = err!(
7919                    self.builder
7920                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7921                );
7922                let res = err!(
7923                    self.builder
7924                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7925                );
7926                self.state.push1(res);
7927            }
7928            Operator::I32x4GtU => {
7929                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7930                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7931                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7932                let res = err!(
7933                    self.builder
7934                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
7935                );
7936                let res = err!(
7937                    self.builder
7938                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7939                );
7940                let res = err!(
7941                    self.builder
7942                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7943                );
7944                self.state.push1(res);
7945            }
7946            Operator::I32GeS | Operator::I64GeS => {
7947                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7948                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7949                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7950                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7951                let cond = err!(
7952                    self.builder
7953                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7954                );
7955                let res = err!(
7956                    self.builder
7957                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7958                );
7959                self.state.push1(res);
7960            }
7961            Operator::I8x16GeS => {
7962                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7963                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7964                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7965                let res = err!(
7966                    self.builder
7967                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7968                );
7969                let res = err!(
7970                    self.builder
7971                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7972                );
7973                let res = err!(
7974                    self.builder
7975                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7976                );
7977                self.state.push1(res);
7978            }
7979            Operator::I16x8GeS => {
7980                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7981                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7982                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7983                let res = err!(
7984                    self.builder
7985                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7986                );
7987                let res = err!(
7988                    self.builder
7989                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7990                );
7991                let res = err!(
7992                    self.builder
7993                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7994                );
7995                self.state.push1(res);
7996            }
7997            Operator::I32x4GeS => {
7998                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7999                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8000                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8001                let res = err!(
8002                    self.builder
8003                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
8004                );
8005                let res = err!(
8006                    self.builder
8007                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8008                );
8009                let res = err!(
8010                    self.builder
8011                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8012                );
8013                self.state.push1(res);
8014            }
8015            Operator::I64x2GeS => {
8016                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8017                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
8018                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
8019                let res = err!(
8020                    self.builder
8021                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
8022                );
8023                let res = err!(
8024                    self.builder
8025                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8026                );
8027                let res = err!(
8028                    self.builder
8029                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8030                );
8031                self.state.push1(res);
8032            }
8033            Operator::I32GeU | Operator::I64GeU => {
8034                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8035                let v1 = self.apply_pending_canonicalization(v1, i1)?;
8036                let v2 = self.apply_pending_canonicalization(v2, i2)?;
8037                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
8038                let cond = err!(
8039                    self.builder
8040                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
8041                );
8042                let res = err!(
8043                    self.builder
8044                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8045                );
8046                self.state.push1_extra(
8047                    res,
8048                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8049                );
8050            }
8051            Operator::I8x16GeU => {
8052                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8053                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
8054                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
8055                let res = err!(
8056                    self.builder
8057                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
8058                );
8059                let res = err!(
8060                    self.builder
8061                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
8062                );
8063                let res = err!(
8064                    self.builder
8065                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8066                );
8067                self.state.push1(res);
8068            }
8069            Operator::I16x8GeU => {
8070                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8071                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8072                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8073                let res = err!(
8074                    self.builder
8075                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
8076                );
8077                let res = err!(
8078                    self.builder
8079                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
8080                );
8081                let res = err!(
8082                    self.builder
8083                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8084                );
8085                self.state.push1(res);
8086            }
8087            Operator::I32x4GeU => {
8088                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8089                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8090                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8091                let res = err!(
8092                    self.builder
8093                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
8094                );
8095                let res = err!(
8096                    self.builder
8097                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8098                );
8099                let res = err!(
8100                    self.builder
8101                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8102                );
8103                self.state.push1(res);
8104            }
8105            _ => unreachable!(),
8106        }
8107        Ok(())
8108    }
8109
8110    // Floating-Point Comparison instructions.
8111    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-comparison-instructions
8112    fn translate_floating_point_comparison_operator(
8113        &mut self,
8114        op: Operator,
8115    ) -> Result<(), CompileError> {
8116        match op {
8117            Operator::F32Eq | Operator::F64Eq => {
8118                let (v1, v2) = self.state.pop2()?;
8119                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8120                let cond = err!(
8121                    self.builder
8122                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8123                );
8124                let res = err!(
8125                    self.builder
8126                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8127                );
8128                self.state.push1_extra(
8129                    res,
8130                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8131                );
8132            }
8133            Operator::F32x4Eq => {
8134                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8135                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8136                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8137                let res = err!(
8138                    self.builder
8139                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8140                );
8141                let res = err!(
8142                    self.builder
8143                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8144                );
8145                let res = err!(
8146                    self.builder
8147                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8148                );
8149                self.state.push1(res);
8150            }
8151            Operator::F64x2Eq => {
8152                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8153                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8154                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8155                let res = err!(
8156                    self.builder
8157                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8158                );
8159                let res = err!(
8160                    self.builder
8161                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8162                );
8163                let res = err!(
8164                    self.builder
8165                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8166                );
8167                self.state.push1(res);
8168            }
8169            Operator::F32Ne | Operator::F64Ne => {
8170                let (v1, v2) = self.state.pop2()?;
8171                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8172                let cond = err!(
8173                    self.builder
8174                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8175                );
8176                let res = err!(
8177                    self.builder
8178                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8179                );
8180                self.state.push1_extra(
8181                    res,
8182                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8183                );
8184            }
8185            Operator::F32x4Ne => {
8186                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8187                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8188                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8189                let res = err!(
8190                    self.builder
8191                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8192                );
8193                let res = err!(
8194                    self.builder
8195                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8196                );
8197                let res = err!(
8198                    self.builder
8199                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8200                );
8201                self.state.push1(res);
8202            }
8203            Operator::F64x2Ne => {
8204                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8205                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8206                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8207                let res = err!(
8208                    self.builder
8209                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8210                );
8211                let res = err!(
8212                    self.builder
8213                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8214                );
8215                let res = err!(
8216                    self.builder
8217                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8218                );
8219                self.state.push1(res);
8220            }
8221            Operator::F32Lt | Operator::F64Lt => {
8222                let (v1, v2) = self.state.pop2()?;
8223                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8224                let cond = err!(
8225                    self.builder
8226                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8227                );
8228                let res = err!(
8229                    self.builder
8230                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8231                );
8232                self.state.push1_extra(
8233                    res,
8234                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8235                );
8236            }
8237            Operator::F32x4Lt => {
8238                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8239                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8240                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8241                let res = err!(
8242                    self.builder
8243                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8244                );
8245                let res = err!(
8246                    self.builder
8247                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8248                );
8249                let res = err!(
8250                    self.builder
8251                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8252                );
8253                self.state.push1(res);
8254            }
8255            Operator::F64x2Lt => {
8256                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8257                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8258                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8259                let res = err!(
8260                    self.builder
8261                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8262                );
8263                let res = err!(
8264                    self.builder
8265                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8266                );
8267                let res = err!(
8268                    self.builder
8269                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8270                );
8271                self.state.push1(res);
8272            }
8273            Operator::F32Le | Operator::F64Le => {
8274                let (v1, v2) = self.state.pop2()?;
8275                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8276                let cond = err!(
8277                    self.builder
8278                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8279                );
8280                let res = err!(
8281                    self.builder
8282                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8283                );
8284                self.state.push1_extra(
8285                    res,
8286                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8287                );
8288            }
8289            Operator::F32x4Le => {
8290                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8291                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8292                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8293                let res = err!(
8294                    self.builder
8295                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8296                );
8297                let res = err!(
8298                    self.builder
8299                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8300                );
8301                let res = err!(
8302                    self.builder
8303                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8304                );
8305                self.state.push1(res);
8306            }
8307            Operator::F64x2Le => {
8308                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8309                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8310                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8311                let res = err!(
8312                    self.builder
8313                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8314                );
8315                let res = err!(
8316                    self.builder
8317                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8318                );
8319                let res = err!(
8320                    self.builder
8321                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8322                );
8323                self.state.push1(res);
8324            }
8325            Operator::F32Gt | Operator::F64Gt => {
8326                let (v1, v2) = self.state.pop2()?;
8327                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8328                let cond = err!(
8329                    self.builder
8330                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8331                );
8332                let res = err!(
8333                    self.builder
8334                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8335                );
8336                self.state.push1_extra(
8337                    res,
8338                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8339                );
8340            }
8341            Operator::F32x4Gt => {
8342                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8343                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8344                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8345                let res = err!(
8346                    self.builder
8347                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8348                );
8349                let res = err!(
8350                    self.builder
8351                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8352                );
8353                let res = err!(
8354                    self.builder
8355                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8356                );
8357                self.state.push1(res);
8358            }
8359            Operator::F64x2Gt => {
8360                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8361                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8362                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8363                let res = err!(
8364                    self.builder
8365                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8366                );
8367                let res = err!(
8368                    self.builder
8369                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8370                );
8371                let res = err!(
8372                    self.builder
8373                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8374                );
8375                self.state.push1(res);
8376            }
8377            Operator::F32Ge | Operator::F64Ge => {
8378                let (v1, v2) = self.state.pop2()?;
8379                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8380                let cond = err!(
8381                    self.builder
8382                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8383                );
8384                let res = err!(
8385                    self.builder
8386                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8387                );
8388                self.state.push1_extra(
8389                    res,
8390                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8391                );
8392            }
8393            Operator::F32x4Ge => {
8394                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8395                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8396                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8397                let res = err!(
8398                    self.builder
8399                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8400                );
8401                let res = err!(
8402                    self.builder
8403                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8404                );
8405                let res = err!(
8406                    self.builder
8407                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8408                );
8409                self.state.push1(res);
8410            }
8411            Operator::F64x2Ge => {
8412                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8413                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8414                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8415                let res = err!(
8416                    self.builder
8417                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8418                );
8419                let res = err!(
8420                    self.builder
8421                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8422                );
8423                let res = err!(
8424                    self.builder
8425                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8426                );
8427                self.state.push1(res);
8428            }
8429            _ => unreachable!(),
8430        }
8431        Ok(())
8432    }
8433
8434    // Conversion instructions.
8435    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#conversion-instructions
8436    fn translate_conversion_operator(&mut self, op: Operator) -> Result<(), CompileError> {
8437        match op {
8438            Operator::I32WrapI64 => {
8439                let (v, i) = self.state.pop1_extra()?;
8440                let v = self.apply_pending_canonicalization(v, i)?;
8441                let v = v.into_int_value();
8442                let res = err!(
8443                    self.builder
8444                        .build_int_truncate(v, self.intrinsics.i32_ty, "")
8445                );
8446                self.state.push1(res);
8447            }
8448            Operator::I64ExtendI32S => {
8449                let (v, i) = self.state.pop1_extra()?;
8450                let v = self.apply_pending_canonicalization(v, i)?;
8451                let v = v.into_int_value();
8452                let res = err!(
8453                    self.builder
8454                        .build_int_s_extend(v, self.intrinsics.i64_ty, "")
8455                );
8456                self.state.push1(res);
8457            }
8458            Operator::I64ExtendI32U => {
8459                let (v, i) = self.state.pop1_extra()?;
8460                let v = self.apply_pending_canonicalization(v, i)?;
8461                let v = v.into_int_value();
8462                let res = err!(
8463                    self.builder
8464                        .build_int_z_extend(v, self.intrinsics.i64_ty, "")
8465                );
8466                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
8467            }
8468            Operator::I16x8ExtendLowI8x16S => {
8469                let (v, i) = self.state.pop1_extra()?;
8470                let (v, _) = self.v128_into_i8x16(v, i)?;
8471                let low = err!(self.builder.build_shuffle_vector(
8472                    v,
8473                    v.get_type().get_undef(),
8474                    VectorType::const_vector(&[
8475                        self.intrinsics.i32_consts[0],
8476                        self.intrinsics.i32_consts[1],
8477                        self.intrinsics.i32_consts[2],
8478                        self.intrinsics.i32_consts[3],
8479                        self.intrinsics.i32_consts[4],
8480                        self.intrinsics.i32_consts[5],
8481                        self.intrinsics.i32_consts[6],
8482                        self.intrinsics.i32_consts[7],
8483                    ]),
8484                    "",
8485                ));
8486                let res = err!(
8487                    self.builder
8488                        .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
8489                );
8490                let res = err!(
8491                    self.builder
8492                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8493                );
8494                self.state.push1(res);
8495            }
8496            Operator::I16x8ExtendHighI8x16S => {
8497                let (v, i) = self.state.pop1_extra()?;
8498                let (v, _) = self.v128_into_i8x16(v, i)?;
8499                let low = err!(self.builder.build_shuffle_vector(
8500                    v,
8501                    v.get_type().get_undef(),
8502                    VectorType::const_vector(&[
8503                        self.intrinsics.i32_consts[8],
8504                        self.intrinsics.i32_consts[9],
8505                        self.intrinsics.i32_consts[10],
8506                        self.intrinsics.i32_consts[11],
8507                        self.intrinsics.i32_consts[12],
8508                        self.intrinsics.i32_consts[13],
8509                        self.intrinsics.i32_consts[14],
8510                        self.intrinsics.i32_consts[15],
8511                    ]),
8512                    "",
8513                ));
8514                let res = err!(
8515                    self.builder
8516                        .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
8517                );
8518                let res = err!(
8519                    self.builder
8520                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8521                );
8522                self.state.push1(res);
8523            }
8524            Operator::I16x8ExtendLowI8x16U => {
8525                let (v, i) = self.state.pop1_extra()?;
8526                let (v, _) = self.v128_into_i8x16(v, i)?;
8527                let low = err!(self.builder.build_shuffle_vector(
8528                    v,
8529                    v.get_type().get_undef(),
8530                    VectorType::const_vector(&[
8531                        self.intrinsics.i32_consts[0],
8532                        self.intrinsics.i32_consts[1],
8533                        self.intrinsics.i32_consts[2],
8534                        self.intrinsics.i32_consts[3],
8535                        self.intrinsics.i32_consts[4],
8536                        self.intrinsics.i32_consts[5],
8537                        self.intrinsics.i32_consts[6],
8538                        self.intrinsics.i32_consts[7],
8539                    ]),
8540                    "",
8541                ));
8542                let res = err!(
8543                    self.builder
8544                        .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8545                );
8546                let res = err!(
8547                    self.builder
8548                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8549                );
8550                self.state.push1(res);
8551            }
8552            Operator::I16x8ExtendHighI8x16U => {
8553                let (v, i) = self.state.pop1_extra()?;
8554                let (v, _) = self.v128_into_i8x16(v, i)?;
8555                let low = err!(self.builder.build_shuffle_vector(
8556                    v,
8557                    v.get_type().get_undef(),
8558                    VectorType::const_vector(&[
8559                        self.intrinsics.i32_consts[8],
8560                        self.intrinsics.i32_consts[9],
8561                        self.intrinsics.i32_consts[10],
8562                        self.intrinsics.i32_consts[11],
8563                        self.intrinsics.i32_consts[12],
8564                        self.intrinsics.i32_consts[13],
8565                        self.intrinsics.i32_consts[14],
8566                        self.intrinsics.i32_consts[15],
8567                    ]),
8568                    "",
8569                ));
8570                let res = err!(
8571                    self.builder
8572                        .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8573                );
8574                let res = err!(
8575                    self.builder
8576                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8577                );
8578                self.state.push1(res);
8579            }
8580            Operator::I32x4ExtendLowI16x8S => {
8581                let (v, i) = self.state.pop1_extra()?;
8582                let (v, _) = self.v128_into_i16x8(v, i)?;
8583                let low = err!(self.builder.build_shuffle_vector(
8584                    v,
8585                    v.get_type().get_undef(),
8586                    VectorType::const_vector(&[
8587                        self.intrinsics.i32_consts[0],
8588                        self.intrinsics.i32_consts[1],
8589                        self.intrinsics.i32_consts[2],
8590                        self.intrinsics.i32_consts[3],
8591                    ]),
8592                    "",
8593                ));
8594                let res = err!(
8595                    self.builder
8596                        .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8597                );
8598                let res = err!(
8599                    self.builder
8600                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8601                );
8602                self.state.push1(res);
8603            }
8604            Operator::I32x4ExtendHighI16x8S => {
8605                let (v, i) = self.state.pop1_extra()?;
8606                let (v, _) = self.v128_into_i16x8(v, i)?;
8607                let low = err!(self.builder.build_shuffle_vector(
8608                    v,
8609                    v.get_type().get_undef(),
8610                    VectorType::const_vector(&[
8611                        self.intrinsics.i32_consts[4],
8612                        self.intrinsics.i32_consts[5],
8613                        self.intrinsics.i32_consts[6],
8614                        self.intrinsics.i32_consts[7],
8615                    ]),
8616                    "",
8617                ));
8618                let res = err!(
8619                    self.builder
8620                        .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8621                );
8622                let res = err!(
8623                    self.builder
8624                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8625                );
8626                self.state.push1(res);
8627            }
8628            Operator::I32x4ExtendLowI16x8U => {
8629                let (v, i) = self.state.pop1_extra()?;
8630                let (v, _) = self.v128_into_i16x8(v, i)?;
8631                let low = err!(self.builder.build_shuffle_vector(
8632                    v,
8633                    v.get_type().get_undef(),
8634                    VectorType::const_vector(&[
8635                        self.intrinsics.i32_consts[0],
8636                        self.intrinsics.i32_consts[1],
8637                        self.intrinsics.i32_consts[2],
8638                        self.intrinsics.i32_consts[3],
8639                    ]),
8640                    "",
8641                ));
8642                let res = err!(
8643                    self.builder
8644                        .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8645                );
8646                let res = err!(
8647                    self.builder
8648                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8649                );
8650                self.state.push1(res);
8651            }
8652            Operator::I32x4ExtendHighI16x8U => {
8653                let (v, i) = self.state.pop1_extra()?;
8654                let (v, _) = self.v128_into_i16x8(v, i)?;
8655                let low = err!(self.builder.build_shuffle_vector(
8656                    v,
8657                    v.get_type().get_undef(),
8658                    VectorType::const_vector(&[
8659                        self.intrinsics.i32_consts[4],
8660                        self.intrinsics.i32_consts[5],
8661                        self.intrinsics.i32_consts[6],
8662                        self.intrinsics.i32_consts[7],
8663                    ]),
8664                    "",
8665                ));
8666                let res = err!(
8667                    self.builder
8668                        .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8669                );
8670                let res = err!(
8671                    self.builder
8672                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8673                );
8674                self.state.push1(res);
8675            }
8676            Operator::I64x2ExtendLowI32x4U
8677            | Operator::I64x2ExtendLowI32x4S
8678            | Operator::I64x2ExtendHighI32x4U
8679            | Operator::I64x2ExtendHighI32x4S => {
8680                let extend = match op {
8681                    Operator::I64x2ExtendLowI32x4U | Operator::I64x2ExtendHighI32x4U => {
8682                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
8683                    }
8684                    Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendHighI32x4S => {
8685                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
8686                    }
8687                    _ => unreachable!("Unhandled inner case"),
8688                };
8689                let indices = match op {
8690                    Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendLowI32x4U => {
8691                        [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
8692                    }
8693                    Operator::I64x2ExtendHighI32x4S | Operator::I64x2ExtendHighI32x4U => {
8694                        [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
8695                    }
8696                    _ => unreachable!("Unhandled inner case"),
8697                };
8698                let (v, i) = self.state.pop1_extra()?;
8699                let (v, _) = self.v128_into_i32x4(v, i)?;
8700                let low = err!(self.builder.build_shuffle_vector(
8701                    v,
8702                    v.get_type().get_undef(),
8703                    VectorType::const_vector(&indices),
8704                    "",
8705                ));
8706                let res = err!(extend(self, low));
8707                let res = err!(
8708                    self.builder
8709                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8710                );
8711                self.state.push1(res);
8712            }
8713            Operator::I8x16NarrowI16x8S => {
8714                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8715                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8716                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8717                let min = self.intrinsics.i16_ty.const_int(0xff80, false);
8718                let max = self.intrinsics.i16_ty.const_int(0x007f, false);
8719                let min = VectorType::const_vector(&[min; 8]);
8720                let max = VectorType::const_vector(&[max; 8]);
8721                let apply_min_clamp_v1 =
8722                    err!(
8723                        self.builder
8724                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8725                    );
8726                let apply_max_clamp_v1 =
8727                    err!(
8728                        self.builder
8729                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8730                    );
8731                let apply_min_clamp_v2 =
8732                    err!(
8733                        self.builder
8734                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8735                    );
8736                let apply_max_clamp_v2 =
8737                    err!(
8738                        self.builder
8739                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8740                    );
8741                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8742                    .into_vector_value();
8743                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8744                    .into_vector_value();
8745                let v1 = err!(self.builder.build_int_truncate(
8746                    v1,
8747                    self.intrinsics.i8_ty.vec_type(8),
8748                    ""
8749                ));
8750                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8751                    .into_vector_value();
8752                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8753                    .into_vector_value();
8754                let v2 = err!(self.builder.build_int_truncate(
8755                    v2,
8756                    self.intrinsics.i8_ty.vec_type(8),
8757                    ""
8758                ));
8759                let res = err!(self.builder.build_shuffle_vector(
8760                    v1,
8761                    v2,
8762                    VectorType::const_vector(&[
8763                        self.intrinsics.i32_consts[0],
8764                        self.intrinsics.i32_consts[1],
8765                        self.intrinsics.i32_consts[2],
8766                        self.intrinsics.i32_consts[3],
8767                        self.intrinsics.i32_consts[4],
8768                        self.intrinsics.i32_consts[5],
8769                        self.intrinsics.i32_consts[6],
8770                        self.intrinsics.i32_consts[7],
8771                        self.intrinsics.i32_consts[8],
8772                        self.intrinsics.i32_consts[9],
8773                        self.intrinsics.i32_consts[10],
8774                        self.intrinsics.i32_consts[11],
8775                        self.intrinsics.i32_consts[12],
8776                        self.intrinsics.i32_consts[13],
8777                        self.intrinsics.i32_consts[14],
8778                        self.intrinsics.i32_consts[15],
8779                    ]),
8780                    "",
8781                ));
8782                let res = err!(
8783                    self.builder
8784                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8785                );
8786                self.state.push1(res);
8787            }
8788            Operator::I8x16NarrowI16x8U => {
8789                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8790                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8791                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8792                let min = self.intrinsics.i16x8_ty.const_zero();
8793                let max = self.intrinsics.i16_ty.const_int(0x00ff, false);
8794                let max = VectorType::const_vector(&[max; 8]);
8795                let apply_min_clamp_v1 =
8796                    err!(
8797                        self.builder
8798                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8799                    );
8800                let apply_max_clamp_v1 =
8801                    err!(
8802                        self.builder
8803                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8804                    );
8805                let apply_min_clamp_v2 =
8806                    err!(
8807                        self.builder
8808                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8809                    );
8810                let apply_max_clamp_v2 =
8811                    err!(
8812                        self.builder
8813                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8814                    );
8815                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8816                    .into_vector_value();
8817                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8818                    .into_vector_value();
8819                let v1 = err!(self.builder.build_int_truncate(
8820                    v1,
8821                    self.intrinsics.i8_ty.vec_type(8),
8822                    ""
8823                ));
8824                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8825                    .into_vector_value();
8826                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8827                    .into_vector_value();
8828                let v2 = err!(self.builder.build_int_truncate(
8829                    v2,
8830                    self.intrinsics.i8_ty.vec_type(8),
8831                    ""
8832                ));
8833                let res = err!(self.builder.build_shuffle_vector(
8834                    v1,
8835                    v2,
8836                    VectorType::const_vector(&[
8837                        self.intrinsics.i32_consts[0],
8838                        self.intrinsics.i32_consts[1],
8839                        self.intrinsics.i32_consts[2],
8840                        self.intrinsics.i32_consts[3],
8841                        self.intrinsics.i32_consts[4],
8842                        self.intrinsics.i32_consts[5],
8843                        self.intrinsics.i32_consts[6],
8844                        self.intrinsics.i32_consts[7],
8845                        self.intrinsics.i32_consts[8],
8846                        self.intrinsics.i32_consts[9],
8847                        self.intrinsics.i32_consts[10],
8848                        self.intrinsics.i32_consts[11],
8849                        self.intrinsics.i32_consts[12],
8850                        self.intrinsics.i32_consts[13],
8851                        self.intrinsics.i32_consts[14],
8852                        self.intrinsics.i32_consts[15],
8853                    ]),
8854                    "",
8855                ));
8856                let res = err!(
8857                    self.builder
8858                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8859                );
8860                self.state.push1(res);
8861            }
8862            Operator::I16x8NarrowI32x4S => {
8863                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8864                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8865                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8866                let min = self.intrinsics.i32_ty.const_int(0xffff8000, false);
8867                let max = self.intrinsics.i32_ty.const_int(0x00007fff, false);
8868                let min = VectorType::const_vector(&[min; 4]);
8869                let max = VectorType::const_vector(&[max; 4]);
8870                let apply_min_clamp_v1 =
8871                    err!(
8872                        self.builder
8873                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8874                    );
8875                let apply_max_clamp_v1 =
8876                    err!(
8877                        self.builder
8878                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8879                    );
8880                let apply_min_clamp_v2 =
8881                    err!(
8882                        self.builder
8883                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8884                    );
8885                let apply_max_clamp_v2 =
8886                    err!(
8887                        self.builder
8888                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8889                    );
8890                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8891                    .into_vector_value();
8892                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8893                    .into_vector_value();
8894                let v1 = err!(self.builder.build_int_truncate(
8895                    v1,
8896                    self.intrinsics.i16_ty.vec_type(4),
8897                    ""
8898                ));
8899                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8900                    .into_vector_value();
8901                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8902                    .into_vector_value();
8903                let v2 = err!(self.builder.build_int_truncate(
8904                    v2,
8905                    self.intrinsics.i16_ty.vec_type(4),
8906                    ""
8907                ));
8908                let res = err!(self.builder.build_shuffle_vector(
8909                    v1,
8910                    v2,
8911                    VectorType::const_vector(&[
8912                        self.intrinsics.i32_consts[0],
8913                        self.intrinsics.i32_consts[1],
8914                        self.intrinsics.i32_consts[2],
8915                        self.intrinsics.i32_consts[3],
8916                        self.intrinsics.i32_consts[4],
8917                        self.intrinsics.i32_consts[5],
8918                        self.intrinsics.i32_consts[6],
8919                        self.intrinsics.i32_consts[7],
8920                    ]),
8921                    "",
8922                ));
8923                let res = err!(
8924                    self.builder
8925                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8926                );
8927                self.state.push1(res);
8928            }
8929            Operator::I16x8NarrowI32x4U => {
8930                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8931                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8932                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8933                let min = self.intrinsics.i32x4_ty.const_zero();
8934                let max = self.intrinsics.i32_ty.const_int(0xffff, false);
8935                let max = VectorType::const_vector(&[max; 4]);
8936                let apply_min_clamp_v1 =
8937                    err!(
8938                        self.builder
8939                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8940                    );
8941                let apply_max_clamp_v1 =
8942                    err!(
8943                        self.builder
8944                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8945                    );
8946                let apply_min_clamp_v2 =
8947                    err!(
8948                        self.builder
8949                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8950                    );
8951                let apply_max_clamp_v2 =
8952                    err!(
8953                        self.builder
8954                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8955                    );
8956                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8957                    .into_vector_value();
8958                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8959                    .into_vector_value();
8960                let v1 = err!(self.builder.build_int_truncate(
8961                    v1,
8962                    self.intrinsics.i16_ty.vec_type(4),
8963                    ""
8964                ));
8965                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8966                    .into_vector_value();
8967                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8968                    .into_vector_value();
8969                let v2 = err!(self.builder.build_int_truncate(
8970                    v2,
8971                    self.intrinsics.i16_ty.vec_type(4),
8972                    ""
8973                ));
8974                let res = err!(self.builder.build_shuffle_vector(
8975                    v1,
8976                    v2,
8977                    VectorType::const_vector(&[
8978                        self.intrinsics.i32_consts[0],
8979                        self.intrinsics.i32_consts[1],
8980                        self.intrinsics.i32_consts[2],
8981                        self.intrinsics.i32_consts[3],
8982                        self.intrinsics.i32_consts[4],
8983                        self.intrinsics.i32_consts[5],
8984                        self.intrinsics.i32_consts[6],
8985                        self.intrinsics.i32_consts[7],
8986                    ]),
8987                    "",
8988                ));
8989                let res = err!(
8990                    self.builder
8991                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8992                );
8993                self.state.push1(res);
8994            }
8995            Operator::I32x4RelaxedTruncF32x4S if self.cpu_features.contains(CpuFeature::SSE2) => {
8996                let (v, i) = self.state.pop1_extra()?;
8997                let (v, _) = self.v128_into_f32x4(v, i)?;
8998                let res = self
8999                    .build_call_with_param_attributes(
9000                        self.intrinsics.x86_64.cvttps2dq,
9001                        &[v.into()],
9002                        "",
9003                    )?
9004                    .try_as_basic_value()
9005                    .unwrap_basic();
9006                let res = err!(
9007                    self.builder
9008                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9009                );
9010                self.state.push1(res);
9011            }
9012            Operator::I32x4TruncSatF32x4S | Operator::I32x4RelaxedTruncF32x4S => {
9013                let (v, i) = self.state.pop1_extra()?;
9014                let v = self.apply_pending_canonicalization(v, i)?;
9015                let v = v.into_int_value();
9016                let res = self.trunc_sat_into_int(
9017                    self.intrinsics.f32x4_ty,
9018                    self.intrinsics.i32x4_ty,
9019                    LEF32_GEQ_I32_MIN,
9020                    GEF32_LEQ_I32_MAX,
9021                    i32::MIN as u64,
9022                    i32::MAX as u64,
9023                    v,
9024                )?;
9025                self.state.push1(res);
9026            }
9027            Operator::I32x4RelaxedTruncF32x4U
9028                if self.cpu_features.contains(CpuFeature::AVX512F)
9029                    && self.cpu_features.contains(CpuFeature::AVX512VL) =>
9030            {
9031                let (v, i) = self.state.pop1_extra()?;
9032                let (v, _) = self.v128_into_f32x4(v, i)?;
9033                let res = self
9034                    .build_call_with_param_attributes(
9035                        self.intrinsics.x86_64.cvtps2udq128,
9036                        &[
9037                            v.into(),
9038                            self.intrinsics.i32x4_ty.const_zero().into(),
9039                            self.intrinsics.i8_ty.const_int(0xff, false).into(),
9040                        ],
9041                        "",
9042                    )?
9043                    .try_as_basic_value()
9044                    .unwrap_basic();
9045                let res = err!(
9046                    self.builder
9047                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9048                );
9049                self.state.push1(res);
9050            }
9051            Operator::I32x4TruncSatF32x4U | Operator::I32x4RelaxedTruncF32x4U => {
9052                let (v, i) = self.state.pop1_extra()?;
9053                let v = self.apply_pending_canonicalization(v, i)?;
9054                let v = v.into_int_value();
9055                let res = self.trunc_sat_into_int(
9056                    self.intrinsics.f32x4_ty,
9057                    self.intrinsics.i32x4_ty,
9058                    LEF32_GEQ_U32_MIN,
9059                    GEF32_LEQ_U32_MAX,
9060                    u32::MIN as u64,
9061                    u32::MAX as u64,
9062                    v,
9063                )?;
9064                self.state.push1(res);
9065            }
9066            Operator::I32x4RelaxedTruncF64x2SZero
9067                if self.cpu_features.contains(CpuFeature::SSE2) =>
9068            {
9069                let (v, i) = self.state.pop1_extra()?;
9070                let (v, _) = self.v128_into_f64x2(v, i)?;
9071                let res = self
9072                    .build_call_with_param_attributes(
9073                        self.intrinsics.x86_64.cvtpd2dq,
9074                        &[v.into()],
9075                        "",
9076                    )?
9077                    .try_as_basic_value()
9078                    .unwrap_basic();
9079                let res = err!(
9080                    self.builder
9081                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9082                );
9083                self.state.push1(res);
9084            }
9085            Operator::I32x4RelaxedTruncF64x2UZero
9086                if self.cpu_features.contains(CpuFeature::AVX512F)
9087                    && self.cpu_features.contains(CpuFeature::AVX512VL) =>
9088            {
9089                let (v, i) = self.state.pop1_extra()?;
9090                let (v, _) = self.v128_into_f64x2(v, i)?;
9091                let res = self
9092                    .build_call_with_param_attributes(
9093                        self.intrinsics.x86_64.cvtpd2udq128,
9094                        &[
9095                            v.into(),
9096                            self.intrinsics.i32x4_ty.const_zero().into(),
9097                            self.intrinsics.i8_ty.const_int(0xff, false).into(),
9098                        ],
9099                        "",
9100                    )?
9101                    .try_as_basic_value()
9102                    .unwrap_basic();
9103                let res = err!(
9104                    self.builder
9105                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9106                );
9107                self.state.push1(res);
9108            }
9109            Operator::I32x4TruncSatF64x2SZero
9110            | Operator::I32x4TruncSatF64x2UZero
9111            | Operator::I32x4RelaxedTruncF64x2SZero
9112            | Operator::I32x4RelaxedTruncF64x2UZero => {
9113                let ((min, max), (cmp_min, cmp_max)) = match op {
9114                    Operator::I32x4TruncSatF64x2SZero => (
9115                        (i32::MIN as u64, i32::MAX as u64),
9116                        (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
9117                    ),
9118                    Operator::I32x4TruncSatF64x2UZero => (
9119                        (u32::MIN as u64, u32::MAX as u64),
9120                        (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
9121                    ),
9122                    Operator::I32x4RelaxedTruncF64x2SZero => (
9123                        (i32::MIN as u64, i32::MAX as u64),
9124                        (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
9125                    ),
9126                    Operator::I32x4RelaxedTruncF64x2UZero => (
9127                        (u32::MIN as u64, u32::MAX as u64),
9128                        (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
9129                    ),
9130                    _ => unreachable!("Unhandled internal variant"),
9131                };
9132                let (v, i) = self.state.pop1_extra()?;
9133                let v = self.apply_pending_canonicalization(v, i)?;
9134                let v = v.into_int_value();
9135                let res = self.trunc_sat(
9136                    self.intrinsics.f64x2_ty,
9137                    self.intrinsics.i32_ty.vec_type(2),
9138                    cmp_min,
9139                    cmp_max,
9140                    min,
9141                    max,
9142                    v,
9143                )?;
9144
9145                let zero = self.intrinsics.i32_consts[0];
9146                let zeros = VectorType::const_vector(&[zero; 2]);
9147                let res = err!(self.builder.build_shuffle_vector(
9148                    res,
9149                    zeros,
9150                    VectorType::const_vector(&[
9151                        self.intrinsics.i32_consts[0],
9152                        self.intrinsics.i32_consts[1],
9153                        self.intrinsics.i32_consts[2],
9154                        self.intrinsics.i32_consts[3],
9155                    ]),
9156                    "",
9157                ));
9158                let res = err!(
9159                    self.builder
9160                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9161                );
9162                self.state.push1(res);
9163            }
9164            // Operator::I64x2TruncSatF64x2S => {
9165            //     let (v, i) = self.state.pop1_extra()?;
9166            //     let v = self.apply_pending_canonicalization(v, i)?;
9167            //     let v = v.into_int_value();
9168            //     let res = self.trunc_sat_into_int(
9169            //         self.intrinsics.f64x2_ty,
9170            //         self.intrinsics.i64x2_ty,
9171            //         i64::MIN as u64,
9172            //         i64::MAX as u64,
9173            //         i64::MIN as u64,
9174            //         i64::MAX as u64,
9175            //         v,
9176            //     )?;
9177            //     self.state.push1(res);
9178            // }
9179            // Operator::I64x2TruncSatF64x2U => {
9180            //     let (v, i) = self.state.pop1_extra()?;
9181            //     let v = self.apply_pending_canonicalization(v, i)?;
9182            //     let v = v.into_int_value();
9183            //     let res = self.trunc_sat_into_int(
9184            //         self.intrinsics.f64x2_ty,
9185            //         self.intrinsics.i64x2_ty,
9186            //         u64::MIN,
9187            //         u64::MAX,
9188            //         u64::MIN,
9189            //         u64::MAX,
9190            //         v,
9191            //     )?;
9192            //     self.state.push1(res);
9193            // }
9194            Operator::I32TruncF32S => {
9195                let v1 = self.state.pop1()?.into_float_value();
9196                self.trap_if_not_representable_as_int(
9197                    0xcf000000, // -2147483600.0
9198                    0x4effffff, // 2147483500.0
9199                    v1,
9200                )?;
9201                let res = err!(self.builder.build_float_to_signed_int(
9202                    v1,
9203                    self.intrinsics.i32_ty,
9204                    ""
9205                ));
9206                self.state.push1(res);
9207            }
9208            Operator::I32TruncF64S => {
9209                let v1 = self.state.pop1()?.into_float_value();
9210                self.trap_if_not_representable_as_int(
9211                    0xc1e00000001fffff, // -2147483648.9999995
9212                    0x41dfffffffffffff, // 2147483647.9999998
9213                    v1,
9214                )?;
9215                let res = err!(self.builder.build_float_to_signed_int(
9216                    v1,
9217                    self.intrinsics.i32_ty,
9218                    ""
9219                ));
9220                self.state.push1(res);
9221            }
9222            Operator::I32TruncSatF32S => {
9223                let (v, i) = self.state.pop1_extra()?;
9224                let v = self.apply_pending_canonicalization(v, i)?;
9225                let v = v.into_float_value();
9226                let res = self.trunc_sat_scalar(
9227                    self.intrinsics.i32_ty,
9228                    LEF32_GEQ_I32_MIN,
9229                    GEF32_LEQ_I32_MAX,
9230                    i32::MIN as u32 as u64,
9231                    i32::MAX as u32 as u64,
9232                    v,
9233                )?;
9234                self.state.push1(res);
9235            }
9236            Operator::I32TruncSatF64S => {
9237                let (v, i) = self.state.pop1_extra()?;
9238                let v = self.apply_pending_canonicalization(v, i)?;
9239                let v = v.into_float_value();
9240                let res = self.trunc_sat_scalar(
9241                    self.intrinsics.i32_ty,
9242                    LEF64_GEQ_I32_MIN,
9243                    GEF64_LEQ_I32_MAX,
9244                    i32::MIN as u64,
9245                    i32::MAX as u64,
9246                    v,
9247                )?;
9248                self.state.push1(res);
9249            }
9250            Operator::I64TruncF32S => {
9251                let v1 = self.state.pop1()?.into_float_value();
9252                self.trap_if_not_representable_as_int(
9253                    0xdf000000, // -9223372000000000000.0
9254                    0x5effffff, // 9223371500000000000.0
9255                    v1,
9256                )?;
9257                let res = err!(self.builder.build_float_to_signed_int(
9258                    v1,
9259                    self.intrinsics.i64_ty,
9260                    ""
9261                ));
9262                self.state.push1(res);
9263            }
9264            Operator::I64TruncF64S => {
9265                let v1 = self.state.pop1()?.into_float_value();
9266                self.trap_if_not_representable_as_int(
9267                    0xc3e0000000000000, // -9223372036854776000.0
9268                    0x43dfffffffffffff, // 9223372036854775000.0
9269                    v1,
9270                )?;
9271                let res = err!(self.builder.build_float_to_signed_int(
9272                    v1,
9273                    self.intrinsics.i64_ty,
9274                    ""
9275                ));
9276                self.state.push1(res);
9277            }
9278            Operator::I64TruncSatF32S => {
9279                let (v, i) = self.state.pop1_extra()?;
9280                let v = self.apply_pending_canonicalization(v, i)?;
9281                let v = v.into_float_value();
9282                let res = self.trunc_sat_scalar(
9283                    self.intrinsics.i64_ty,
9284                    LEF32_GEQ_I64_MIN,
9285                    GEF32_LEQ_I64_MAX,
9286                    i64::MIN as u64,
9287                    i64::MAX as u64,
9288                    v,
9289                )?;
9290                self.state.push1(res);
9291            }
9292            Operator::I64TruncSatF64S => {
9293                let (v, i) = self.state.pop1_extra()?;
9294                let v = self.apply_pending_canonicalization(v, i)?;
9295                let v = v.into_float_value();
9296                let res = self.trunc_sat_scalar(
9297                    self.intrinsics.i64_ty,
9298                    LEF64_GEQ_I64_MIN,
9299                    GEF64_LEQ_I64_MAX,
9300                    i64::MIN as u64,
9301                    i64::MAX as u64,
9302                    v,
9303                )?;
9304                self.state.push1(res);
9305            }
9306            Operator::I32TruncF32U => {
9307                let v1 = self.state.pop1()?.into_float_value();
9308                self.trap_if_not_representable_as_int(
9309                    0xbf7fffff, // -0.99999994
9310                    0x4f7fffff, // 4294967000.0
9311                    v1,
9312                )?;
9313                let res = err!(self.builder.build_float_to_unsigned_int(
9314                    v1,
9315                    self.intrinsics.i32_ty,
9316                    ""
9317                ));
9318                self.state.push1(res);
9319            }
9320            Operator::I32TruncF64U => {
9321                let v1 = self.state.pop1()?.into_float_value();
9322                self.trap_if_not_representable_as_int(
9323                    0xbfefffffffffffff, // -0.9999999999999999
9324                    0x41efffffffffffff, // 4294967295.9999995
9325                    v1,
9326                )?;
9327                let res = err!(self.builder.build_float_to_unsigned_int(
9328                    v1,
9329                    self.intrinsics.i32_ty,
9330                    ""
9331                ));
9332                self.state.push1(res);
9333            }
9334            Operator::I32TruncSatF32U => {
9335                let (v, i) = self.state.pop1_extra()?;
9336                let v = self.apply_pending_canonicalization(v, i)?;
9337                let v = v.into_float_value();
9338                let res = self.trunc_sat_scalar(
9339                    self.intrinsics.i32_ty,
9340                    LEF32_GEQ_U32_MIN,
9341                    GEF32_LEQ_U32_MAX,
9342                    u32::MIN as u64,
9343                    u32::MAX as u64,
9344                    v,
9345                )?;
9346                self.state.push1(res);
9347            }
9348            Operator::I32TruncSatF64U => {
9349                let (v, i) = self.state.pop1_extra()?;
9350                let v = self.apply_pending_canonicalization(v, i)?;
9351                let v = v.into_float_value();
9352                let res = self.trunc_sat_scalar(
9353                    self.intrinsics.i32_ty,
9354                    LEF64_GEQ_U32_MIN,
9355                    GEF64_LEQ_U32_MAX,
9356                    u32::MIN as u64,
9357                    u32::MAX as u64,
9358                    v,
9359                )?;
9360                self.state.push1(res);
9361            }
9362            Operator::I64TruncF32U => {
9363                let v1 = self.state.pop1()?.into_float_value();
9364                self.trap_if_not_representable_as_int(
9365                    0xbf7fffff, // -0.99999994
9366                    0x5f7fffff, // 18446743000000000000.0
9367                    v1,
9368                )?;
9369                let res = err!(self.builder.build_float_to_unsigned_int(
9370                    v1,
9371                    self.intrinsics.i64_ty,
9372                    ""
9373                ));
9374                self.state.push1(res);
9375            }
9376            Operator::I64TruncF64U => {
9377                let v1 = self.state.pop1()?.into_float_value();
9378                self.trap_if_not_representable_as_int(
9379                    0xbfefffffffffffff, // -0.9999999999999999
9380                    0x43efffffffffffff, // 18446744073709550000.0
9381                    v1,
9382                )?;
9383                let res = err!(self.builder.build_float_to_unsigned_int(
9384                    v1,
9385                    self.intrinsics.i64_ty,
9386                    ""
9387                ));
9388                self.state.push1(res);
9389            }
9390            Operator::I64TruncSatF32U => {
9391                let (v, i) = self.state.pop1_extra()?;
9392                let v = self.apply_pending_canonicalization(v, i)?;
9393                let v = v.into_float_value();
9394                let res = self.trunc_sat_scalar(
9395                    self.intrinsics.i64_ty,
9396                    LEF32_GEQ_U64_MIN,
9397                    GEF32_LEQ_U64_MAX,
9398                    u64::MIN,
9399                    u64::MAX,
9400                    v,
9401                )?;
9402                self.state.push1(res);
9403            }
9404            Operator::I64TruncSatF64U => {
9405                let (v, i) = self.state.pop1_extra()?;
9406                let v = self.apply_pending_canonicalization(v, i)?;
9407                let v = v.into_float_value();
9408                let res = self.trunc_sat_scalar(
9409                    self.intrinsics.i64_ty,
9410                    LEF64_GEQ_U64_MIN,
9411                    GEF64_LEQ_U64_MAX,
9412                    u64::MIN,
9413                    u64::MAX,
9414                    v,
9415                )?;
9416                self.state.push1(res);
9417            }
9418            Operator::F32DemoteF64 => {
9419                let v = self.state.pop1()?;
9420                let v = v.into_float_value();
9421                let res = self
9422                    .build_call_with_param_attributes(
9423                        self.intrinsics.fptrunc_f64,
9424                        &[
9425                            v.into(),
9426                            self.intrinsics.fp_rounding_md,
9427                            self.intrinsics.fp_exception_md,
9428                        ],
9429                        "",
9430                    )?
9431                    .try_as_basic_value()
9432                    .unwrap_basic();
9433                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9434            }
9435            Operator::F64PromoteF32 => {
9436                let v = self.state.pop1()?;
9437                let v = v.into_float_value();
9438                let res = self
9439                    .build_call_with_param_attributes(
9440                        self.intrinsics.fpext_f32,
9441                        &[v.into(), self.intrinsics.fp_exception_md],
9442                        "",
9443                    )?
9444                    .try_as_basic_value()
9445                    .unwrap_basic();
9446                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9447            }
9448            Operator::F32ConvertI32S | Operator::F32ConvertI64S => {
9449                let (v, i) = self.state.pop1_extra()?;
9450                let v = self.apply_pending_canonicalization(v, i)?;
9451                let v = v.into_int_value();
9452                let res = err!(self.builder.build_signed_int_to_float(
9453                    v,
9454                    self.intrinsics.f32_ty,
9455                    ""
9456                ));
9457                self.state.push1(res);
9458            }
9459            Operator::F64ConvertI32S | Operator::F64ConvertI64S => {
9460                let (v, i) = self.state.pop1_extra()?;
9461                let v = self.apply_pending_canonicalization(v, i)?;
9462                let v = v.into_int_value();
9463                let res = err!(self.builder.build_signed_int_to_float(
9464                    v,
9465                    self.intrinsics.f64_ty,
9466                    ""
9467                ));
9468                self.state.push1(res);
9469            }
9470            Operator::F32ConvertI32U | Operator::F32ConvertI64U => {
9471                let (v, i) = self.state.pop1_extra()?;
9472                let v = self.apply_pending_canonicalization(v, i)?;
9473                let v = v.into_int_value();
9474                let res = err!(self.builder.build_unsigned_int_to_float(
9475                    v,
9476                    self.intrinsics.f32_ty,
9477                    ""
9478                ));
9479                self.state.push1(res);
9480            }
9481            Operator::F64ConvertI32U | Operator::F64ConvertI64U => {
9482                let (v, i) = self.state.pop1_extra()?;
9483                let v = self.apply_pending_canonicalization(v, i)?;
9484                let v = v.into_int_value();
9485                let res = err!(self.builder.build_unsigned_int_to_float(
9486                    v,
9487                    self.intrinsics.f64_ty,
9488                    ""
9489                ));
9490                self.state.push1(res);
9491            }
9492            Operator::F32x4ConvertI32x4S => {
9493                let v = self.state.pop1()?;
9494                let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
9495                    .into_vector_value();
9496                let res = err!(self.builder.build_signed_int_to_float(
9497                    v,
9498                    self.intrinsics.f32x4_ty,
9499                    ""
9500                ));
9501                let res = err!(
9502                    self.builder
9503                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9504                );
9505                self.state.push1(res);
9506            }
9507            Operator::F32x4ConvertI32x4U => {
9508                let v = self.state.pop1()?;
9509                let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
9510                    .into_vector_value();
9511                let res = err!(self.builder.build_unsigned_int_to_float(
9512                    v,
9513                    self.intrinsics.f32x4_ty,
9514                    ""
9515                ));
9516                let res = err!(
9517                    self.builder
9518                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9519                );
9520                self.state.push1(res);
9521            }
9522            Operator::F64x2ConvertLowI32x4S | Operator::F64x2ConvertLowI32x4U => {
9523                let extend = match op {
9524                    Operator::F64x2ConvertLowI32x4U => {
9525                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
9526                    }
9527                    Operator::F64x2ConvertLowI32x4S => {
9528                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
9529                    }
9530                    _ => unreachable!("Unhandled inner case"),
9531                };
9532                let (v, i) = self.state.pop1_extra()?;
9533                let (v, _) = self.v128_into_i32x4(v, i)?;
9534                let low = err!(self.builder.build_shuffle_vector(
9535                    v,
9536                    v.get_type().get_undef(),
9537                    VectorType::const_vector(&[
9538                        self.intrinsics.i32_consts[0],
9539                        self.intrinsics.i32_consts[1],
9540                    ]),
9541                    "",
9542                ));
9543                let res = err!(extend(self, low));
9544                let res = err!(self.builder.build_signed_int_to_float(
9545                    res,
9546                    self.intrinsics.f64x2_ty,
9547                    ""
9548                ));
9549                let res = err!(
9550                    self.builder
9551                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9552                );
9553                self.state.push1(res);
9554            }
9555            Operator::F64x2PromoteLowF32x4 => {
9556                let (v, i) = self.state.pop1_extra()?;
9557                let (v, _) = self.v128_into_f32x4(v, i)?;
9558                let low = err!(self.builder.build_shuffle_vector(
9559                    v,
9560                    v.get_type().get_undef(),
9561                    VectorType::const_vector(&[
9562                        self.intrinsics.i32_consts[0],
9563                        self.intrinsics.i32_consts[1],
9564                    ]),
9565                    "",
9566                ));
9567                let res = err!(
9568                    self.builder
9569                        .build_float_ext(low, self.intrinsics.f64x2_ty, "")
9570                );
9571                let res = err!(
9572                    self.builder
9573                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9574                );
9575                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9576            }
9577            Operator::F32x4DemoteF64x2Zero => {
9578                let (v, i) = self.state.pop1_extra()?;
9579                let (v, _) = self.v128_into_f64x2(v, i)?;
9580                let f32x2_ty = self.intrinsics.f32_ty.vec_type(2);
9581                let res = err!(self.builder.build_float_trunc(v, f32x2_ty, ""));
9582                let zeros = f32x2_ty.const_zero();
9583                let res = err!(self.builder.build_shuffle_vector(
9584                    res,
9585                    zeros,
9586                    VectorType::const_vector(&[
9587                        self.intrinsics.i32_consts[0],
9588                        self.intrinsics.i32_consts[1],
9589                        self.intrinsics.i32_consts[2],
9590                        self.intrinsics.i32_consts[3],
9591                    ]),
9592                    "",
9593                ));
9594                let res = err!(
9595                    self.builder
9596                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9597                );
9598                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9599            }
9600            // Operator::F64x2ConvertI64x2S => {
9601            //     let v = self.state.pop1()?;
9602            //     let v = self
9603            //         .builder
9604            //         .build_bit_cast(v, self.intrinsics.i64x2_ty, "")
9605            //         .into_vector_value();
9606            //     let res = self
9607            //         .builder
9608            //         .build_signed_int_to_float(v, self.intrinsics.f64x2_ty, "");
9609            //     let res = check_err!(self.builder.build_bit_cast(res, self.intrinsics.i128_ty, ""));
9610            //     self.state.push1(res);
9611            // }
9612            // Operator::F64x2ConvertI64x2U => {
9613            //     let v = self.state.pop1()?;
9614            //     let v = self
9615            //         .builder
9616            //         .build_bit_cast(v, self.intrinsics.i64x2_ty, "")
9617            //         .into_vector_value();
9618            //     let res = self
9619            //         .builder
9620            //         .build_unsigned_int_to_float(v, self.intrinsics.f64x2_ty, "");
9621            //     let res = check_err!(self.builder.build_bit_cast(res, self.intrinsics.i128_ty, ""));
9622            //     self.state.push1(res);
9623            // }
9624            Operator::I32ReinterpretF32 => {
9625                let (v, i) = self.state.pop1_extra()?;
9626                let v = self.apply_pending_canonicalization(v, i)?;
9627                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i32_ty, ""));
9628                self.state.push1_extra(ret, ExtraInfo::arithmetic_f32());
9629            }
9630            Operator::I64ReinterpretF64 => {
9631                let (v, i) = self.state.pop1_extra()?;
9632                let v = self.apply_pending_canonicalization(v, i)?;
9633                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i64_ty, ""));
9634                self.state.push1_extra(ret, ExtraInfo::arithmetic_f64());
9635            }
9636            Operator::F32ReinterpretI32 => {
9637                let (v, i) = self.state.pop1_extra()?;
9638                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f32_ty, ""));
9639                self.state.push1_extra(ret, i);
9640            }
9641            Operator::F64ReinterpretI64 => {
9642                let (v, i) = self.state.pop1_extra()?;
9643                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f64_ty, ""));
9644                self.state.push1_extra(ret, i);
9645            }
9646            _ => unreachable!(),
9647        }
9648        Ok(())
9649    }
9650
9651    // Sign-extension operators.
9652    // https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md
9653    fn translate_sign_extension_operator(&mut self, op: Operator) -> Result<(), CompileError> {
9654        match op {
9655            Operator::I32Extend8S => {
9656                let value = self.state.pop1()?.into_int_value();
9657                let narrow_value = err!(self.builder.build_int_truncate(
9658                    value,
9659                    self.intrinsics.i8_ty,
9660                    ""
9661                ));
9662                let extended_value = err!(self.builder.build_int_s_extend(
9663                    narrow_value,
9664                    self.intrinsics.i32_ty,
9665                    ""
9666                ));
9667                self.state.push1(extended_value);
9668            }
9669            Operator::I32Extend16S => {
9670                let value = self.state.pop1()?.into_int_value();
9671                let narrow_value = err!(self.builder.build_int_truncate(
9672                    value,
9673                    self.intrinsics.i16_ty,
9674                    ""
9675                ));
9676                let extended_value = err!(self.builder.build_int_s_extend(
9677                    narrow_value,
9678                    self.intrinsics.i32_ty,
9679                    ""
9680                ));
9681                self.state.push1(extended_value);
9682            }
9683            Operator::I64Extend8S => {
9684                let value = self.state.pop1()?.into_int_value();
9685                let narrow_value = err!(self.builder.build_int_truncate(
9686                    value,
9687                    self.intrinsics.i8_ty,
9688                    ""
9689                ));
9690                let extended_value = err!(self.builder.build_int_s_extend(
9691                    narrow_value,
9692                    self.intrinsics.i64_ty,
9693                    ""
9694                ));
9695                self.state.push1(extended_value);
9696            }
9697            Operator::I64Extend16S => {
9698                let value = self.state.pop1()?.into_int_value();
9699                let narrow_value = err!(self.builder.build_int_truncate(
9700                    value,
9701                    self.intrinsics.i16_ty,
9702                    ""
9703                ));
9704                let extended_value = err!(self.builder.build_int_s_extend(
9705                    narrow_value,
9706                    self.intrinsics.i64_ty,
9707                    ""
9708                ));
9709                self.state.push1(extended_value);
9710            }
9711            Operator::I64Extend32S => {
9712                let value = self.state.pop1()?.into_int_value();
9713                let narrow_value = err!(self.builder.build_int_truncate(
9714                    value,
9715                    self.intrinsics.i32_ty,
9716                    ""
9717                ));
9718                let extended_value = err!(self.builder.build_int_s_extend(
9719                    narrow_value,
9720                    self.intrinsics.i64_ty,
9721                    ""
9722                ));
9723                self.state.push1(extended_value);
9724            }
9725            _ => unreachable!(),
9726        }
9727        Ok(())
9728    }
9729
9730    // Load and Store instructions.
9731    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#load-and-store-instructions
9732    fn translate_memory_operator(&mut self, op: Operator) -> Result<(), CompileError> {
9733        let vmctx = &self.ctx.basic().into_pointer_value();
9734
9735        match op {
9736            Operator::I32Load { ref memarg } => {
9737                let offset = self.state.pop1()?.into_int_value();
9738                let result =
9739                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9740                self.state.push1(result);
9741            }
9742            Operator::I64Load { ref memarg } => {
9743                let offset = self.state.pop1()?.into_int_value();
9744                let result =
9745                    self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
9746                self.state.push1(result);
9747            }
9748            Operator::F32Load { ref memarg } => {
9749                let offset = self.state.pop1()?.into_int_value();
9750                let result =
9751                    self.build_annotated_load(self.intrinsics.f32_ty, offset, memarg, 1)?;
9752                self.state.push1(result);
9753            }
9754            Operator::F64Load { ref memarg } => {
9755                let offset = self.state.pop1()?.into_int_value();
9756                let result =
9757                    self.build_annotated_load(self.intrinsics.f64_ty, offset, memarg, 1)?;
9758                self.state.push1(result);
9759            }
9760            Operator::V128Load { ref memarg } => {
9761                let offset = self.state.pop1()?.into_int_value();
9762                let result =
9763                    self.build_annotated_load(self.intrinsics.i128_ty, offset, memarg, 1)?;
9764                self.state.push1(result);
9765            }
9766            Operator::V128Load8Lane { ref memarg, lane } => {
9767                let (v, i) = self.state.pop1_extra()?;
9768                let (v, _i) = self.v128_into_i8x16(v, i)?;
9769                let offset = self.state.pop1()?.into_int_value();
9770                let element =
9771                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9772                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9773                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9774                let res = err!(
9775                    self.builder
9776                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9777                );
9778                self.state.push1(res);
9779            }
9780            Operator::V128Load16Lane { ref memarg, lane } => {
9781                let (v, i) = self.state.pop1_extra()?;
9782                let (v, i) = self.v128_into_i16x8(v, i)?;
9783                let offset = self.state.pop1()?.into_int_value();
9784                let element =
9785                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9786                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9787                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9788                let res = err!(
9789                    self.builder
9790                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9791                );
9792                self.state.push1_extra(res, i);
9793            }
9794            Operator::V128Load32Lane { ref memarg, lane } => {
9795                let (v, i) = self.state.pop1_extra()?;
9796                let (v, i) = self.v128_into_i32x4(v, i)?;
9797                let offset = self.state.pop1()?.into_int_value();
9798                let element =
9799                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9800                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9801                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9802                let res = err!(
9803                    self.builder
9804                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9805                );
9806                self.state.push1_extra(res, i);
9807            }
9808            Operator::V128Load64Lane { ref memarg, lane } => {
9809                let (v, i) = self.state.pop1_extra()?;
9810                let (v, i) = self.v128_into_i64x2(v, i)?;
9811                let offset = self.state.pop1()?.into_int_value();
9812                let element =
9813                    self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
9814                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9815                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9816                let res = err!(
9817                    self.builder
9818                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9819                );
9820                self.state.push1_extra(res, i);
9821            }
9822
9823            Operator::I32Store { ref memarg } => {
9824                let value = self.state.pop1()?;
9825                let offset = self.state.pop1()?.into_int_value();
9826                self.build_annotated_store(self.intrinsics.i32_ty, offset, value, memarg, 1)?;
9827            }
9828            Operator::I64Store { ref memarg } => {
9829                let value = self.state.pop1()?;
9830                let offset = self.state.pop1()?.into_int_value();
9831                self.build_annotated_store(self.intrinsics.i64_ty, offset, value, memarg, 1)?;
9832            }
9833            Operator::F32Store { ref memarg } => {
9834                let (v, i) = self.state.pop1_extra()?;
9835                let v = self.apply_pending_canonicalization(v, i)?;
9836                let offset = self.state.pop1()?.into_int_value();
9837                self.build_annotated_store(self.intrinsics.f32_ty, offset, v, memarg, 1)?;
9838            }
9839            Operator::F64Store { ref memarg } => {
9840                let (v, i) = self.state.pop1_extra()?;
9841                let v = self.apply_pending_canonicalization(v, i)?;
9842                let offset = self.state.pop1()?.into_int_value();
9843                self.build_annotated_store(self.intrinsics.f64_ty, offset, v, memarg, 1)?;
9844            }
9845            Operator::V128Store { ref memarg } => {
9846                let (v, i) = self.state.pop1_extra()?;
9847                let v = self.apply_pending_canonicalization(v, i)?;
9848                let offset = self.state.pop1()?.into_int_value();
9849                self.build_annotated_store(self.intrinsics.i128_ty, offset, v, memarg, 1)?;
9850            }
9851            Operator::V128Store8Lane { ref memarg, lane } => {
9852                let (v, i) = self.state.pop1_extra()?;
9853                let (v, _i) = self.v128_into_i8x16(v, i)?;
9854                let offset = self.state.pop1()?.into_int_value();
9855                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9856                let val = err!(self.builder.build_extract_element(v, idx, ""));
9857                self.build_annotated_store(self.intrinsics.i8_ty, offset, val, memarg, 1)?;
9858            }
9859            Operator::V128Store16Lane { ref memarg, lane } => {
9860                let (v, i) = self.state.pop1_extra()?;
9861                let (v, _i) = self.v128_into_i16x8(v, i)?;
9862                let offset = self.state.pop1()?.into_int_value();
9863                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9864                let val = err!(self.builder.build_extract_element(v, idx, ""));
9865                self.build_annotated_store(self.intrinsics.i16_ty, offset, val, memarg, 1)?;
9866            }
9867            Operator::V128Store32Lane { ref memarg, lane } => {
9868                let (v, i) = self.state.pop1_extra()?;
9869                let (v, _i) = self.v128_into_i32x4(v, i)?;
9870                let offset = self.state.pop1()?.into_int_value();
9871                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9872                let val = err!(self.builder.build_extract_element(v, idx, ""));
9873                self.build_annotated_store(self.intrinsics.i32_ty, offset, val, memarg, 1)?;
9874            }
9875            Operator::V128Store64Lane { ref memarg, lane } => {
9876                let (v, i) = self.state.pop1_extra()?;
9877                let (v, _i) = self.v128_into_i64x2(v, i)?;
9878                let offset = self.state.pop1()?.into_int_value();
9879                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9880                let val = err!(self.builder.build_extract_element(v, idx, ""));
9881                self.build_annotated_store(self.intrinsics.i64_ty, offset, val, memarg, 1)?;
9882            }
9883            Operator::I32Load8S { ref memarg } => {
9884                let offset = self.state.pop1()?.into_int_value();
9885                let narrow_result =
9886                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9887                let result = err!(self.builder.build_int_s_extend(
9888                    narrow_result.into_int_value(),
9889                    self.intrinsics.i32_ty,
9890                    "",
9891                ));
9892                self.state.push1(result);
9893            }
9894            Operator::I32Load16S { ref memarg } => {
9895                let offset = self.state.pop1()?.into_int_value();
9896                let narrow_result =
9897                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9898                let result = err!(self.builder.build_int_s_extend(
9899                    narrow_result.into_int_value(),
9900                    self.intrinsics.i32_ty,
9901                    "",
9902                ));
9903                self.state.push1(result);
9904            }
9905            Operator::I64Load8S { ref memarg } => {
9906                let offset = self.state.pop1()?.into_int_value();
9907                let narrow_result =
9908                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9909                let result = err!(self.builder.build_int_s_extend(
9910                    narrow_result.into_int_value(),
9911                    self.intrinsics.i64_ty,
9912                    ""
9913                ));
9914                self.state.push1(result);
9915            }
9916            Operator::I64Load16S { ref memarg } => {
9917                let offset = self.state.pop1()?.into_int_value();
9918                let narrow_result =
9919                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9920                let result = err!(self.builder.build_int_s_extend(
9921                    narrow_result.into_int_value(),
9922                    self.intrinsics.i64_ty,
9923                    ""
9924                ));
9925                self.state.push1(result);
9926            }
9927            Operator::I64Load32S { ref memarg } => {
9928                let offset = self.state.pop1()?.into_int_value();
9929                let narrow_result =
9930                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9931                let result = err!(self.builder.build_int_s_extend(
9932                    narrow_result.into_int_value(),
9933                    self.intrinsics.i64_ty,
9934                    "",
9935                ));
9936                self.state.push1(result);
9937            }
9938
9939            Operator::I32Load8U { ref memarg } => {
9940                let offset = self.state.pop1()?.into_int_value();
9941                let narrow_result =
9942                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9943                let result = err!(self.builder.build_int_z_extend(
9944                    narrow_result.into_int_value(),
9945                    self.intrinsics.i32_ty,
9946                    "",
9947                ));
9948                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9949            }
9950            Operator::I32Load16U { ref memarg } => {
9951                let offset = self.state.pop1()?.into_int_value();
9952                let narrow_result =
9953                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9954                let result = err!(self.builder.build_int_z_extend(
9955                    narrow_result.into_int_value(),
9956                    self.intrinsics.i32_ty,
9957                    "",
9958                ));
9959                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9960            }
9961            Operator::I64Load8U { ref memarg } => {
9962                let offset = self.state.pop1()?.into_int_value();
9963                let narrow_result =
9964                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9965                let result = err!(self.builder.build_int_z_extend(
9966                    narrow_result.into_int_value(),
9967                    self.intrinsics.i64_ty,
9968                    "",
9969                ));
9970                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9971            }
9972            Operator::I64Load16U { ref memarg } => {
9973                let offset = self.state.pop1()?.into_int_value();
9974                let narrow_result =
9975                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9976                let result = err!(self.builder.build_int_z_extend(
9977                    narrow_result.into_int_value(),
9978                    self.intrinsics.i64_ty,
9979                    "",
9980                ));
9981                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9982            }
9983            Operator::I64Load32U { ref memarg } => {
9984                let offset = self.state.pop1()?.into_int_value();
9985                let narrow_result =
9986                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9987                let result = err!(self.builder.build_int_z_extend(
9988                    narrow_result.into_int_value(),
9989                    self.intrinsics.i64_ty,
9990                    "",
9991                ));
9992                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9993            }
9994
9995            Operator::I32Store8 { ref memarg } | Operator::I64Store8 { ref memarg } => {
9996                let value = self.state.pop1()?.into_int_value();
9997                let offset = self.state.pop1()?.into_int_value();
9998                let narrow_value = err!(self.builder.build_int_truncate(
9999                    value,
10000                    self.intrinsics.i8_ty,
10001                    ""
10002                ));
10003                self.build_annotated_store(
10004                    self.intrinsics.i8_ty,
10005                    offset,
10006                    narrow_value.into(),
10007                    memarg,
10008                    1,
10009                )?;
10010            }
10011            Operator::I32Store16 { ref memarg } | Operator::I64Store16 { ref memarg } => {
10012                let value = self.state.pop1()?.into_int_value();
10013                let offset = self.state.pop1()?.into_int_value();
10014                let narrow_value = err!(self.builder.build_int_truncate(
10015                    value,
10016                    self.intrinsics.i16_ty,
10017                    ""
10018                ));
10019                self.build_annotated_store(
10020                    self.intrinsics.i16_ty,
10021                    offset,
10022                    narrow_value.into(),
10023                    memarg,
10024                    1,
10025                )?;
10026            }
10027            Operator::I64Store32 { ref memarg } => {
10028                let value = self.state.pop1()?.into_int_value();
10029                let offset = self.state.pop1()?.into_int_value();
10030                let narrow_value = err!(self.builder.build_int_truncate(
10031                    value,
10032                    self.intrinsics.i32_ty,
10033                    ""
10034                ));
10035                self.build_annotated_store(
10036                    self.intrinsics.i32_ty,
10037                    offset,
10038                    narrow_value.into(),
10039                    memarg,
10040                    1,
10041                )?;
10042            }
10043            Operator::I8x16Neg => {
10044                let (v, i) = self.state.pop1_extra()?;
10045                let (v, _) = self.v128_into_i8x16(v, i)?;
10046                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10047                let res = err!(
10048                    self.builder
10049                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10050                );
10051                self.state.push1(res);
10052            }
10053            Operator::I16x8Neg => {
10054                let (v, i) = self.state.pop1_extra()?;
10055                let (v, _) = self.v128_into_i16x8(v, i)?;
10056                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10057                let res = err!(
10058                    self.builder
10059                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10060                );
10061                self.state.push1(res);
10062            }
10063            Operator::I32x4Neg => {
10064                let (v, i) = self.state.pop1_extra()?;
10065                let (v, _) = self.v128_into_i32x4(v, i)?;
10066                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10067                let res = err!(
10068                    self.builder
10069                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10070                );
10071                self.state.push1(res);
10072            }
10073            Operator::I64x2Neg => {
10074                let (v, i) = self.state.pop1_extra()?;
10075                let (v, _) = self.v128_into_i64x2(v, i)?;
10076                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10077                let res = err!(
10078                    self.builder
10079                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10080                );
10081                self.state.push1(res);
10082            }
10083            Operator::V128Not => {
10084                let (v, i) = self.state.pop1_extra()?;
10085                let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10086                let res = err!(self.builder.build_not(v, ""));
10087                self.state.push1(res);
10088            }
10089            Operator::V128AnyTrue => {
10090                // | Operator::I64x2AnyTrue
10091                // Skip canonicalization, it never changes non-zero values to zero or vice versa.
10092                let v = self.state.pop1()?.into_int_value();
10093                let res = err!(self.builder.build_int_compare(
10094                    IntPredicate::NE,
10095                    v,
10096                    v.get_type().const_zero(),
10097                    "",
10098                ));
10099                let res = err!(
10100                    self.builder
10101                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10102                );
10103                self.state.push1_extra(
10104                    res,
10105                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10106                );
10107            }
10108            Operator::I8x16AllTrue
10109            | Operator::I16x8AllTrue
10110            | Operator::I32x4AllTrue
10111            | Operator::I64x2AllTrue => {
10112                let vec_ty = match op {
10113                    Operator::I8x16AllTrue => self.intrinsics.i8x16_ty,
10114                    Operator::I16x8AllTrue => self.intrinsics.i16x8_ty,
10115                    Operator::I32x4AllTrue => self.intrinsics.i32x4_ty,
10116                    Operator::I64x2AllTrue => self.intrinsics.i64x2_ty,
10117                    _ => unreachable!(),
10118                };
10119                let (v, i) = self.state.pop1_extra()?;
10120                let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10121                let lane_int_ty = self
10122                    .context
10123                    .custom_width_int_type(NonZero::new(vec_ty.get_size()).unwrap())
10124                    .unwrap();
10125                let vec = err!(self.builder.build_bit_cast(v, vec_ty, "vec")).into_vector_value();
10126                let mask = err!(self.builder.build_int_compare(
10127                    IntPredicate::NE,
10128                    vec,
10129                    vec_ty.const_zero(),
10130                    "mask",
10131                ));
10132                let cmask =
10133                    err!(self.builder.build_bit_cast(mask, lane_int_ty, "cmask")).into_int_value();
10134                let res = err!(self.builder.build_int_compare(
10135                    IntPredicate::EQ,
10136                    cmask,
10137                    lane_int_ty.const_int(u64::MAX, true),
10138                    "",
10139                ));
10140                let res = err!(
10141                    self.builder
10142                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10143                );
10144                self.state.push1_extra(
10145                    res,
10146                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10147                );
10148            }
10149            Operator::I8x16ExtractLaneS { lane } => {
10150                let (v, i) = self.state.pop1_extra()?;
10151                let (v, _) = self.v128_into_i8x16(v, i)?;
10152                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10153                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10154                let res = err!(
10155                    self.builder
10156                        .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10157                );
10158                self.state.push1(res);
10159            }
10160            Operator::I8x16ExtractLaneU { lane } => {
10161                let (v, i) = self.state.pop1_extra()?;
10162                let (v, _) = self.v128_into_i8x16(v, i)?;
10163                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10164                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10165                let res = err!(
10166                    self.builder
10167                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10168                );
10169                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10170            }
10171            Operator::I16x8ExtractLaneS { lane } => {
10172                let (v, i) = self.state.pop1_extra()?;
10173                let (v, _) = self.v128_into_i16x8(v, i)?;
10174                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10175                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10176                let res = err!(
10177                    self.builder
10178                        .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10179                );
10180                self.state.push1(res);
10181            }
10182            Operator::I16x8ExtractLaneU { lane } => {
10183                let (v, i) = self.state.pop1_extra()?;
10184                let (v, _) = self.v128_into_i16x8(v, i)?;
10185                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10186                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10187                let res = err!(
10188                    self.builder
10189                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10190                );
10191                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10192            }
10193            Operator::I32x4ExtractLane { lane } => {
10194                let (v, i) = self.state.pop1_extra()?;
10195                let (v, i) = self.v128_into_i32x4(v, i)?;
10196                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10197                let res = err!(self.builder.build_extract_element(v, idx, ""));
10198                self.state.push1_extra(res, i);
10199            }
10200            Operator::I64x2ExtractLane { lane } => {
10201                let (v, i) = self.state.pop1_extra()?;
10202                let (v, i) = self.v128_into_i64x2(v, i)?;
10203                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10204                let res = err!(self.builder.build_extract_element(v, idx, ""));
10205                self.state.push1_extra(res, i);
10206            }
10207            Operator::F32x4ExtractLane { lane } => {
10208                let (v, i) = self.state.pop1_extra()?;
10209                let (v, i) = self.v128_into_f32x4(v, i)?;
10210                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10211                let res = err!(self.builder.build_extract_element(v, idx, ""));
10212                self.state.push1_extra(res, i);
10213            }
10214            Operator::F64x2ExtractLane { lane } => {
10215                let (v, i) = self.state.pop1_extra()?;
10216                let (v, i) = self.v128_into_f64x2(v, i)?;
10217                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10218                let res = err!(self.builder.build_extract_element(v, idx, ""));
10219                self.state.push1_extra(res, i);
10220            }
10221            Operator::I8x16ReplaceLane { lane } => {
10222                let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10223                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10224                let v2 = v2.into_int_value();
10225                let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i8_ty, ""));
10226                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10227                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10228                let res = err!(
10229                    self.builder
10230                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10231                );
10232                self.state.push1(res);
10233            }
10234            Operator::I16x8ReplaceLane { lane } => {
10235                let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10236                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
10237                let v2 = v2.into_int_value();
10238                let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i16_ty, ""));
10239                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10240                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10241                let res = err!(
10242                    self.builder
10243                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10244                );
10245                self.state.push1(res);
10246            }
10247            Operator::I32x4ReplaceLane { lane } => {
10248                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10249                let (v1, i1) = self.v128_into_i32x4(v1, i1)?;
10250                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10251                let v2 = v2.into_int_value();
10252                let i2 = i2.strip_pending();
10253                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10254                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10255                let res = err!(
10256                    self.builder
10257                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10258                );
10259                self.state
10260                    .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f32())?);
10261            }
10262            Operator::I64x2ReplaceLane { lane } => {
10263                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10264                let (v1, i1) = self.v128_into_i64x2(v1, i1)?;
10265                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10266                let v2 = v2.into_int_value();
10267                let i2 = i2.strip_pending();
10268                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10269                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10270                let res = err!(
10271                    self.builder
10272                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10273                );
10274                self.state
10275                    .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f64())?);
10276            }
10277            Operator::F32x4ReplaceLane { lane } => {
10278                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10279                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
10280                let push_pending_f32_nan_to_result =
10281                    i1.has_pending_f32_nan() && i2.has_pending_f32_nan();
10282                let (v1, v2) = if !push_pending_f32_nan_to_result {
10283                    (
10284                        self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10285                            .into_vector_value(),
10286                        self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10287                            .into_float_value(),
10288                    )
10289                } else {
10290                    (v1, v2.into_float_value())
10291                };
10292                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10293                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10294                let res = err!(
10295                    self.builder
10296                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10297                );
10298                let info = if push_pending_f32_nan_to_result {
10299                    ExtraInfo::pending_f32_nan()
10300                } else {
10301                    (i1.strip_pending() & i2.strip_pending())?
10302                };
10303                self.state.push1_extra(res, info);
10304            }
10305            Operator::F64x2ReplaceLane { lane } => {
10306                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10307                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
10308                let push_pending_f64_nan_to_result =
10309                    i1.has_pending_f64_nan() && i2.has_pending_f64_nan();
10310                let (v1, v2) = if !push_pending_f64_nan_to_result {
10311                    (
10312                        self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10313                            .into_vector_value(),
10314                        self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10315                            .into_float_value(),
10316                    )
10317                } else {
10318                    (v1, v2.into_float_value())
10319                };
10320                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10321                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10322                let res = err!(
10323                    self.builder
10324                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10325                );
10326                let info = if push_pending_f64_nan_to_result {
10327                    ExtraInfo::pending_f64_nan()
10328                } else {
10329                    (i1.strip_pending() & i2.strip_pending())?
10330                };
10331                self.state.push1_extra(res, info);
10332            }
10333            Operator::I8x16RelaxedSwizzle if self.cpu_features.contains(CpuFeature::SSSE3) => {
10334                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10335                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10336                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10337
10338                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10339                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
10340                let res = self
10341                    .build_call_with_param_attributes(
10342                        self.intrinsics.x86_64.pshufb128,
10343                        &[v1.into(), v2.into()],
10344                        "",
10345                    )?
10346                    .try_as_basic_value()
10347                    .unwrap_basic();
10348                let res = err!(
10349                    self.builder
10350                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10351                );
10352                self.state.push1(res);
10353            }
10354            Operator::I8x16Swizzle | Operator::I8x16RelaxedSwizzle => {
10355                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10356                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10357                let v1 = err!(
10358                    self.builder
10359                        .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10360                )
10361                .into_vector_value();
10362                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10363                let v2 = err!(
10364                    self.builder
10365                        .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10366                )
10367                .into_vector_value();
10368                let lanes = self.intrinsics.i8_ty.const_int(16, false);
10369                let lanes =
10370                    self.splat_vector(lanes.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
10371                let mut res = self.intrinsics.i8x16_ty.get_undef();
10372                let idx_out_of_range = err!(self.builder.build_int_compare(
10373                    IntPredicate::UGE,
10374                    v2,
10375                    lanes,
10376                    "idx_out_of_range",
10377                ));
10378                let idx_clamped = err!(self.builder.build_select(
10379                    idx_out_of_range,
10380                    self.intrinsics.i8x16_ty.const_zero(),
10381                    v2,
10382                    "idx_clamped",
10383                ))
10384                .into_vector_value();
10385                for i in 0..16 {
10386                    let idx = err!(self.builder.build_extract_element(
10387                        idx_clamped,
10388                        self.intrinsics.i32_ty.const_int(i, false),
10389                        "idx",
10390                    ))
10391                    .into_int_value();
10392                    let replace_with_zero = err!(self.builder.build_extract_element(
10393                        idx_out_of_range,
10394                        self.intrinsics.i32_ty.const_int(i, false),
10395                        "replace_with_zero",
10396                    ))
10397                    .into_int_value();
10398                    let elem =
10399                        err!(self.builder.build_extract_element(v1, idx, "elem")).into_int_value();
10400                    let elem_or_zero = err!(self.builder.build_select(
10401                        replace_with_zero,
10402                        self.intrinsics.i8_zero,
10403                        elem,
10404                        "elem_or_zero",
10405                    ));
10406                    res = err!(self.builder.build_insert_element(
10407                        res,
10408                        elem_or_zero,
10409                        self.intrinsics.i32_ty.const_int(i, false),
10410                        "",
10411                    ));
10412                }
10413                let res = err!(
10414                    self.builder
10415                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10416                );
10417                self.state.push1(res);
10418            }
10419            Operator::I8x16Shuffle { lanes } => {
10420                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10421                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10422                let v1 = err!(
10423                    self.builder
10424                        .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10425                )
10426                .into_vector_value();
10427                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10428                let v2 = err!(
10429                    self.builder
10430                        .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10431                )
10432                .into_vector_value();
10433                let mask = VectorType::const_vector(
10434                    lanes
10435                        .iter()
10436                        .map(|l| self.intrinsics.i32_ty.const_int((*l).into(), false))
10437                        .collect::<Vec<IntValue>>()
10438                        .as_slice(),
10439                );
10440                let res = err!(self.builder.build_shuffle_vector(v1, v2, mask, ""));
10441                let res = err!(
10442                    self.builder
10443                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10444                );
10445                self.state.push1(res);
10446            }
10447            Operator::V128Load8x8S { ref memarg } => {
10448                let offset = self.state.pop1()?.into_int_value();
10449                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10450                let v = err!(
10451                    self.builder
10452                        .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10453                )
10454                .into_vector_value();
10455                let res = err!(
10456                    self.builder
10457                        .build_int_s_extend(v, self.intrinsics.i16x8_ty, "")
10458                );
10459                let res = err!(
10460                    self.builder
10461                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10462                );
10463                self.state.push1(res);
10464            }
10465            Operator::V128Load8x8U { ref memarg } => {
10466                let offset = self.state.pop1()?.into_int_value();
10467                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10468                let v = err!(
10469                    self.builder
10470                        .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10471                )
10472                .into_vector_value();
10473                let res = err!(
10474                    self.builder
10475                        .build_int_z_extend(v, self.intrinsics.i16x8_ty, "")
10476                );
10477                let res = err!(
10478                    self.builder
10479                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10480                );
10481                self.state.push1(res);
10482            }
10483            Operator::V128Load16x4S { ref memarg } => {
10484                let offset = self.state.pop1()?.into_int_value();
10485                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10486                let v = err!(self.builder.build_bit_cast(
10487                    v,
10488                    self.intrinsics.i16_ty.vec_type(4),
10489                    ""
10490                ))
10491                .into_vector_value();
10492                let res = err!(
10493                    self.builder
10494                        .build_int_s_extend(v, self.intrinsics.i32x4_ty, "")
10495                );
10496                let res = err!(
10497                    self.builder
10498                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10499                );
10500                self.state.push1(res);
10501            }
10502            Operator::V128Load16x4U { ref memarg } => {
10503                let offset = self.state.pop1()?.into_int_value();
10504                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10505                let v = err!(self.builder.build_bit_cast(
10506                    v,
10507                    self.intrinsics.i16_ty.vec_type(4),
10508                    ""
10509                ))
10510                .into_vector_value();
10511                let res = err!(
10512                    self.builder
10513                        .build_int_z_extend(v, self.intrinsics.i32x4_ty, "")
10514                );
10515                let res = err!(
10516                    self.builder
10517                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10518                );
10519                self.state.push1(res);
10520            }
10521            Operator::V128Load32x2S { ref memarg } => {
10522                let offset = self.state.pop1()?.into_int_value();
10523                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10524                let v = err!(self.builder.build_bit_cast(
10525                    v,
10526                    self.intrinsics.i32_ty.vec_type(2),
10527                    ""
10528                ))
10529                .into_vector_value();
10530                let res = err!(
10531                    self.builder
10532                        .build_int_s_extend(v, self.intrinsics.i64x2_ty, "")
10533                );
10534                let res = err!(
10535                    self.builder
10536                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10537                );
10538                self.state.push1(res);
10539            }
10540            Operator::V128Load32x2U { ref memarg } => {
10541                let offset = self.state.pop1()?.into_int_value();
10542                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10543                let v = err!(self.builder.build_bit_cast(
10544                    v,
10545                    self.intrinsics.i32_ty.vec_type(2),
10546                    ""
10547                ))
10548                .into_vector_value();
10549                let res = err!(
10550                    self.builder
10551                        .build_int_z_extend(v, self.intrinsics.i64x2_ty, "")
10552                );
10553                let res = err!(
10554                    self.builder
10555                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10556                );
10557                self.state.push1(res);
10558            }
10559            Operator::V128Load32Zero { ref memarg } => {
10560                let offset = self.state.pop1()?.into_int_value();
10561                let element =
10562                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10563                let res = err!(self.builder.build_int_z_extend(
10564                    element.into_int_value(),
10565                    self.intrinsics.i128_ty,
10566                    "",
10567                ));
10568                self.state.push1(res);
10569            }
10570            Operator::V128Load64Zero { ref memarg } => {
10571                let offset = self.state.pop1()?.into_int_value();
10572                let element =
10573                    self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10574                let res = err!(self.builder.build_int_z_extend(
10575                    element.into_int_value(),
10576                    self.intrinsics.i128_ty,
10577                    "",
10578                ));
10579                self.state.push1(res);
10580            }
10581            Operator::V128Load8Splat { ref memarg } => {
10582                let offset = self.state.pop1()?.into_int_value();
10583                let element =
10584                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
10585                let res = self.splat_vector(element, self.intrinsics.i8x16_ty)?;
10586                let res = err!(
10587                    self.builder
10588                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10589                );
10590                self.state.push1(res);
10591            }
10592            Operator::V128Load16Splat { ref memarg } => {
10593                let offset = self.state.pop1()?.into_int_value();
10594                let element =
10595                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10596                let res = self.splat_vector(element, self.intrinsics.i16x8_ty)?;
10597                let res = err!(
10598                    self.builder
10599                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10600                );
10601                self.state.push1(res);
10602            }
10603            Operator::V128Load32Splat { ref memarg } => {
10604                let offset = self.state.pop1()?.into_int_value();
10605                let element =
10606                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10607                let res = self.splat_vector(element, self.intrinsics.i32x4_ty)?;
10608                let res = err!(
10609                    self.builder
10610                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10611                );
10612                self.state.push1(res);
10613            }
10614            Operator::V128Load64Splat { ref memarg } => {
10615                let offset = self.state.pop1()?.into_int_value();
10616                let element =
10617                    self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10618                let res = self.splat_vector(element, self.intrinsics.i64x2_ty)?;
10619                let res = err!(
10620                    self.builder
10621                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10622                );
10623                self.state.push1(res);
10624            }
10625
10626            Operator::MemoryGrow { mem } => {
10627                let memory_index = MemoryIndex::from_u32(mem);
10628                let delta = self.state.pop1()?;
10629                let grow_fn_ptr = self.ctx.memory_grow(memory_index, self.intrinsics)?;
10630                let grow = err!(self.builder.build_indirect_call(
10631                    self.intrinsics.memory_grow_ty,
10632                    grow_fn_ptr,
10633                    &[
10634                        vmctx.as_basic_value_enum().into(),
10635                        delta.into(),
10636                        self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
10637                    ],
10638                    "",
10639                ));
10640                self.state.push1(grow.try_as_basic_value().unwrap_basic());
10641            }
10642            Operator::MemorySize { mem } => {
10643                let memory_index = MemoryIndex::from_u32(mem);
10644                let size_fn_ptr = self.ctx.memory_size(memory_index, self.intrinsics)?;
10645                let size = err!(self.builder.build_indirect_call(
10646                    self.intrinsics.memory_size_ty,
10647                    size_fn_ptr,
10648                    &[
10649                        vmctx.as_basic_value_enum().into(),
10650                        self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
10651                    ],
10652                    "",
10653                ));
10654                //size.add_attribute(AttributeLoc::Function, self.intrinsics.readonly);
10655                self.state.push1(size.try_as_basic_value().unwrap_basic());
10656            }
10657            Operator::MemoryInit { data_index, mem } => {
10658                let (dest, src, len) = self.state.pop3()?;
10659                let mem = self.intrinsics.i32_ty.const_int(mem.into(), false);
10660                let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
10661                self.build_call_with_param_attributes(
10662                    self.intrinsics.memory_init,
10663                    &[
10664                        vmctx.as_basic_value_enum().into(),
10665                        mem.into(),
10666                        segment.into(),
10667                        dest.into(),
10668                        src.into(),
10669                        len.into(),
10670                    ],
10671                    "",
10672                )?;
10673            }
10674            Operator::DataDrop { data_index } => {
10675                let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
10676                self.build_call_with_param_attributes(
10677                    self.intrinsics.data_drop,
10678                    &[vmctx.as_basic_value_enum().into(), segment.into()],
10679                    "",
10680                )?;
10681            }
10682            Operator::MemoryCopy { dst_mem, src_mem } => {
10683                // ignored until we support multiple memories
10684                let _dst = dst_mem;
10685                let (memory_copy, src) = if let Some(local_memory_index) = self
10686                    .wasm_module
10687                    .local_memory_index(MemoryIndex::from_u32(src_mem))
10688                {
10689                    (self.intrinsics.memory_copy, local_memory_index.as_u32())
10690                } else {
10691                    (self.intrinsics.imported_memory_copy, src_mem)
10692                };
10693
10694                let (dest_pos, src_pos, len) = self.state.pop3()?;
10695                let src_index = self.intrinsics.i32_ty.const_int(src.into(), false);
10696                self.build_call_with_param_attributes(
10697                    memory_copy,
10698                    &[
10699                        vmctx.as_basic_value_enum().into(),
10700                        src_index.into(),
10701                        dest_pos.into(),
10702                        src_pos.into(),
10703                        len.into(),
10704                    ],
10705                    "",
10706                )?;
10707            }
10708            Operator::MemoryFill { mem } => {
10709                let (memory_fill, mem) = if let Some(local_memory_index) = self
10710                    .wasm_module
10711                    .local_memory_index(MemoryIndex::from_u32(mem))
10712                {
10713                    (self.intrinsics.memory_fill, local_memory_index.as_u32())
10714                } else {
10715                    (self.intrinsics.imported_memory_fill, mem)
10716                };
10717
10718                let (dst, val, len) = self.state.pop3()?;
10719                let mem_index = self.intrinsics.i32_ty.const_int(mem.into(), false);
10720                self.build_call_with_param_attributes(
10721                    memory_fill,
10722                    &[
10723                        vmctx.as_basic_value_enum().into(),
10724                        mem_index.into(),
10725                        dst.into(),
10726                        val.into(),
10727                        len.into(),
10728                    ],
10729                    "",
10730                )?;
10731            }
10732            _ => unreachable!(),
10733        }
10734        Ok(())
10735    }
10736
10737    // Atomic memory operations.
10738    fn translate_atomic_memory_operator(&mut self, op: Operator) -> Result<(), CompileError> {
10739        let vmctx = &self.ctx.basic().into_pointer_value();
10740
10741        match op {
10742            Operator::AtomicFence => {
10743                // Fence is a nop.
10744                //
10745                // Fence was added to preserve information about fences from
10746                // source languages. If in the future Wasm extends the memory
10747                // model, and if we hadn't recorded what fences used to be there,
10748                // it would lead to data races that weren't present in the
10749                // original source language.
10750            }
10751            Operator::I32AtomicLoad { ref memarg } => {
10752                let offset = self.state.pop1()?.into_int_value();
10753                let result = self.build_annotated_atomic_load(
10754                    self.intrinsics.i32_ty,
10755                    self.intrinsics.i32_ty,
10756                    offset,
10757                    memarg,
10758                )?;
10759                self.state.push1(result);
10760            }
10761            Operator::I64AtomicLoad { ref memarg } => {
10762                let offset = self.state.pop1()?.into_int_value();
10763                let result = self.build_annotated_atomic_load(
10764                    self.intrinsics.i64_ty,
10765                    self.intrinsics.i64_ty,
10766                    offset,
10767                    memarg,
10768                )?;
10769                self.state.push1(result);
10770            }
10771            Operator::I32AtomicLoad8U { ref memarg } => {
10772                let offset = self.state.pop1()?.into_int_value();
10773                let result = self.build_annotated_atomic_load(
10774                    self.intrinsics.i32_ty,
10775                    self.intrinsics.i8_ty,
10776                    offset,
10777                    memarg,
10778                )?;
10779                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10780            }
10781            Operator::I32AtomicLoad16U { ref memarg } => {
10782                let offset = self.state.pop1()?.into_int_value();
10783                let result = self.build_annotated_atomic_load(
10784                    self.intrinsics.i32_ty,
10785                    self.intrinsics.i16_ty,
10786                    offset,
10787                    memarg,
10788                )?;
10789                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10790            }
10791            Operator::I64AtomicLoad8U { ref memarg } => {
10792                let offset = self.state.pop1()?.into_int_value();
10793                let result = self.build_annotated_atomic_load(
10794                    self.intrinsics.i64_ty,
10795                    self.intrinsics.i8_ty,
10796                    offset,
10797                    memarg,
10798                )?;
10799                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10800            }
10801            Operator::I64AtomicLoad16U { ref memarg } => {
10802                let offset = self.state.pop1()?.into_int_value();
10803                let result = self.build_annotated_atomic_load(
10804                    self.intrinsics.i64_ty,
10805                    self.intrinsics.i16_ty,
10806                    offset,
10807                    memarg,
10808                )?;
10809                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10810            }
10811            Operator::I64AtomicLoad32U { ref memarg } => {
10812                let offset = self.state.pop1()?.into_int_value();
10813                let result = self.build_annotated_atomic_load(
10814                    self.intrinsics.i64_ty,
10815                    self.intrinsics.i32_ty,
10816                    offset,
10817                    memarg,
10818                )?;
10819                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10820            }
10821            Operator::I32AtomicStore { ref memarg } => {
10822                let value = self.state.pop1()?.into_int_value();
10823                let offset = self.state.pop1()?.into_int_value();
10824                self.build_annotated_atomic_store(
10825                    self.intrinsics.i32_ty,
10826                    self.intrinsics.i32_ty,
10827                    offset,
10828                    value,
10829                    memarg,
10830                )?;
10831            }
10832            Operator::I64AtomicStore { ref memarg } => {
10833                let value = self.state.pop1()?.into_int_value();
10834                let offset = self.state.pop1()?.into_int_value();
10835                self.build_annotated_atomic_store(
10836                    self.intrinsics.i64_ty,
10837                    self.intrinsics.i64_ty,
10838                    offset,
10839                    value,
10840                    memarg,
10841                )?;
10842            }
10843            Operator::I32AtomicStore8 { ref memarg } | Operator::I64AtomicStore8 { ref memarg } => {
10844                let value = self.state.pop1()?.into_int_value();
10845                let offset = self.state.pop1()?.into_int_value();
10846                self.build_annotated_atomic_store(
10847                    value.get_type(),
10848                    self.intrinsics.i8_ty,
10849                    offset,
10850                    value,
10851                    memarg,
10852                )?;
10853            }
10854            Operator::I32AtomicStore16 { ref memarg }
10855            | Operator::I64AtomicStore16 { ref memarg } => {
10856                let value = self.state.pop1()?.into_int_value();
10857                let offset = self.state.pop1()?.into_int_value();
10858                self.build_annotated_atomic_store(
10859                    value.get_type(),
10860                    self.intrinsics.i16_ty,
10861                    offset,
10862                    value,
10863                    memarg,
10864                )?;
10865            }
10866            Operator::I64AtomicStore32 { ref memarg } => {
10867                let value = self.state.pop1()?.into_int_value();
10868                let offset = self.state.pop1()?.into_int_value();
10869                self.build_annotated_atomic_store(
10870                    self.intrinsics.i64_ty,
10871                    self.intrinsics.i32_ty,
10872                    offset,
10873                    value,
10874                    memarg,
10875                )?;
10876            }
10877            Operator::I32AtomicRmw8AddU { ref memarg } => self.translate_atomic_rmw(
10878                self.intrinsics.i32_ty,
10879                self.intrinsics.i8_ty,
10880                memarg,
10881                AtomicRMWBinOp::Add,
10882                Some(ExtraInfo::arithmetic_f32()),
10883            )?,
10884            Operator::I32AtomicRmw16AddU { ref memarg } => self.translate_atomic_rmw(
10885                self.intrinsics.i32_ty,
10886                self.intrinsics.i16_ty,
10887                memarg,
10888                AtomicRMWBinOp::Add,
10889                Some(ExtraInfo::arithmetic_f32()),
10890            )?,
10891            Operator::I32AtomicRmwAdd { ref memarg } => self.translate_atomic_rmw(
10892                self.intrinsics.i32_ty,
10893                self.intrinsics.i32_ty,
10894                memarg,
10895                AtomicRMWBinOp::Add,
10896                None,
10897            )?,
10898            Operator::I64AtomicRmw8AddU { ref memarg } => self.translate_atomic_rmw(
10899                self.intrinsics.i64_ty,
10900                self.intrinsics.i8_ty,
10901                memarg,
10902                AtomicRMWBinOp::Add,
10903                Some(ExtraInfo::arithmetic_f64()),
10904            )?,
10905            Operator::I64AtomicRmw16AddU { ref memarg } => self.translate_atomic_rmw(
10906                self.intrinsics.i64_ty,
10907                self.intrinsics.i16_ty,
10908                memarg,
10909                AtomicRMWBinOp::Add,
10910                Some(ExtraInfo::arithmetic_f64()),
10911            )?,
10912            Operator::I64AtomicRmw32AddU { ref memarg } => self.translate_atomic_rmw(
10913                self.intrinsics.i64_ty,
10914                self.intrinsics.i32_ty,
10915                memarg,
10916                AtomicRMWBinOp::Add,
10917                Some(ExtraInfo::arithmetic_f64()),
10918            )?,
10919            Operator::I64AtomicRmwAdd { ref memarg } => self.translate_atomic_rmw(
10920                self.intrinsics.i64_ty,
10921                self.intrinsics.i64_ty,
10922                memarg,
10923                AtomicRMWBinOp::Add,
10924                None,
10925            )?,
10926            Operator::I32AtomicRmw8SubU { ref memarg } => self.translate_atomic_rmw(
10927                self.intrinsics.i32_ty,
10928                self.intrinsics.i8_ty,
10929                memarg,
10930                AtomicRMWBinOp::Sub,
10931                Some(ExtraInfo::arithmetic_f32()),
10932            )?,
10933            Operator::I32AtomicRmw16SubU { ref memarg } => self.translate_atomic_rmw(
10934                self.intrinsics.i32_ty,
10935                self.intrinsics.i16_ty,
10936                memarg,
10937                AtomicRMWBinOp::Sub,
10938                Some(ExtraInfo::arithmetic_f32()),
10939            )?,
10940            Operator::I32AtomicRmwSub { ref memarg } => self.translate_atomic_rmw(
10941                self.intrinsics.i32_ty,
10942                self.intrinsics.i32_ty,
10943                memarg,
10944                AtomicRMWBinOp::Sub,
10945                None,
10946            )?,
10947            Operator::I64AtomicRmw8SubU { ref memarg } => self.translate_atomic_rmw(
10948                self.intrinsics.i64_ty,
10949                self.intrinsics.i8_ty,
10950                memarg,
10951                AtomicRMWBinOp::Sub,
10952                Some(ExtraInfo::arithmetic_f32()),
10953            )?,
10954            Operator::I64AtomicRmw16SubU { ref memarg } => self.translate_atomic_rmw(
10955                self.intrinsics.i64_ty,
10956                self.intrinsics.i16_ty,
10957                memarg,
10958                AtomicRMWBinOp::Sub,
10959                Some(ExtraInfo::arithmetic_f64()),
10960            )?,
10961            Operator::I64AtomicRmw32SubU { ref memarg } => self.translate_atomic_rmw(
10962                self.intrinsics.i64_ty,
10963                self.intrinsics.i32_ty,
10964                memarg,
10965                AtomicRMWBinOp::Sub,
10966                Some(ExtraInfo::arithmetic_f64()),
10967            )?,
10968            Operator::I64AtomicRmwSub { ref memarg } => self.translate_atomic_rmw(
10969                self.intrinsics.i64_ty,
10970                self.intrinsics.i64_ty,
10971                memarg,
10972                AtomicRMWBinOp::Sub,
10973                None,
10974            )?,
10975            Operator::I32AtomicRmw8AndU { ref memarg } => self.translate_atomic_rmw(
10976                self.intrinsics.i32_ty,
10977                self.intrinsics.i8_ty,
10978                memarg,
10979                AtomicRMWBinOp::And,
10980                Some(ExtraInfo::arithmetic_f32()),
10981            )?,
10982            Operator::I32AtomicRmw16AndU { ref memarg } => self.translate_atomic_rmw(
10983                self.intrinsics.i32_ty,
10984                self.intrinsics.i16_ty,
10985                memarg,
10986                AtomicRMWBinOp::And,
10987                Some(ExtraInfo::arithmetic_f32()),
10988            )?,
10989            Operator::I32AtomicRmwAnd { ref memarg } => self.translate_atomic_rmw(
10990                self.intrinsics.i32_ty,
10991                self.intrinsics.i32_ty,
10992                memarg,
10993                AtomicRMWBinOp::And,
10994                None,
10995            )?,
10996            Operator::I64AtomicRmw8AndU { ref memarg } => self.translate_atomic_rmw(
10997                self.intrinsics.i64_ty,
10998                self.intrinsics.i8_ty,
10999                memarg,
11000                AtomicRMWBinOp::And,
11001                Some(ExtraInfo::arithmetic_f64()),
11002            )?,
11003            Operator::I64AtomicRmw16AndU { ref memarg } => self.translate_atomic_rmw(
11004                self.intrinsics.i64_ty,
11005                self.intrinsics.i16_ty,
11006                memarg,
11007                AtomicRMWBinOp::And,
11008                Some(ExtraInfo::arithmetic_f64()),
11009            )?,
11010            Operator::I64AtomicRmw32AndU { ref memarg } => self.translate_atomic_rmw(
11011                self.intrinsics.i64_ty,
11012                self.intrinsics.i32_ty,
11013                memarg,
11014                AtomicRMWBinOp::And,
11015                Some(ExtraInfo::arithmetic_f64()),
11016            )?,
11017            Operator::I64AtomicRmwAnd { ref memarg } => self.translate_atomic_rmw(
11018                self.intrinsics.i64_ty,
11019                self.intrinsics.i64_ty,
11020                memarg,
11021                AtomicRMWBinOp::And,
11022                None,
11023            )?,
11024            Operator::I32AtomicRmw8OrU { ref memarg } => self.translate_atomic_rmw(
11025                self.intrinsics.i32_ty,
11026                self.intrinsics.i8_ty,
11027                memarg,
11028                AtomicRMWBinOp::Or,
11029                Some(ExtraInfo::arithmetic_f32()),
11030            )?,
11031            Operator::I32AtomicRmw16OrU { ref memarg } => self.translate_atomic_rmw(
11032                self.intrinsics.i32_ty,
11033                self.intrinsics.i16_ty,
11034                memarg,
11035                AtomicRMWBinOp::Or,
11036                Some(ExtraInfo::arithmetic_f32()),
11037            )?,
11038            Operator::I32AtomicRmwOr { ref memarg } => self.translate_atomic_rmw(
11039                self.intrinsics.i32_ty,
11040                self.intrinsics.i32_ty,
11041                memarg,
11042                AtomicRMWBinOp::Or,
11043                Some(ExtraInfo::arithmetic_f32()),
11044            )?,
11045            Operator::I64AtomicRmw8OrU { ref memarg } => self.translate_atomic_rmw(
11046                self.intrinsics.i64_ty,
11047                self.intrinsics.i8_ty,
11048                memarg,
11049                AtomicRMWBinOp::Or,
11050                Some(ExtraInfo::arithmetic_f64()),
11051            )?,
11052            Operator::I64AtomicRmw16OrU { ref memarg } => self.translate_atomic_rmw(
11053                self.intrinsics.i64_ty,
11054                self.intrinsics.i16_ty,
11055                memarg,
11056                AtomicRMWBinOp::Or,
11057                Some(ExtraInfo::arithmetic_f64()),
11058            )?,
11059            Operator::I64AtomicRmw32OrU { ref memarg } => self.translate_atomic_rmw(
11060                self.intrinsics.i64_ty,
11061                self.intrinsics.i32_ty,
11062                memarg,
11063                AtomicRMWBinOp::Or,
11064                Some(ExtraInfo::arithmetic_f64()),
11065            )?,
11066            Operator::I64AtomicRmwOr { ref memarg } => self.translate_atomic_rmw(
11067                self.intrinsics.i64_ty,
11068                self.intrinsics.i64_ty,
11069                memarg,
11070                AtomicRMWBinOp::Or,
11071                None,
11072            )?,
11073            Operator::I32AtomicRmw8XorU { ref memarg } => self.translate_atomic_rmw(
11074                self.intrinsics.i32_ty,
11075                self.intrinsics.i8_ty,
11076                memarg,
11077                AtomicRMWBinOp::Xor,
11078                Some(ExtraInfo::arithmetic_f32()),
11079            )?,
11080            Operator::I32AtomicRmw16XorU { ref memarg } => self.translate_atomic_rmw(
11081                self.intrinsics.i32_ty,
11082                self.intrinsics.i16_ty,
11083                memarg,
11084                AtomicRMWBinOp::Xor,
11085                Some(ExtraInfo::arithmetic_f32()),
11086            )?,
11087            Operator::I32AtomicRmwXor { ref memarg } => self.translate_atomic_rmw(
11088                self.intrinsics.i32_ty,
11089                self.intrinsics.i32_ty,
11090                memarg,
11091                AtomicRMWBinOp::Xor,
11092                None,
11093            )?,
11094            Operator::I64AtomicRmw8XorU { ref memarg } => self.translate_atomic_rmw(
11095                self.intrinsics.i64_ty,
11096                self.intrinsics.i8_ty,
11097                memarg,
11098                AtomicRMWBinOp::Xor,
11099                Some(ExtraInfo::arithmetic_f64()),
11100            )?,
11101            Operator::I64AtomicRmw16XorU { ref memarg } => self.translate_atomic_rmw(
11102                self.intrinsics.i64_ty,
11103                self.intrinsics.i16_ty,
11104                memarg,
11105                AtomicRMWBinOp::Xor,
11106                Some(ExtraInfo::arithmetic_f64()),
11107            )?,
11108            Operator::I64AtomicRmw32XorU { ref memarg } => self.translate_atomic_rmw(
11109                self.intrinsics.i64_ty,
11110                self.intrinsics.i32_ty,
11111                memarg,
11112                AtomicRMWBinOp::Xor,
11113                Some(ExtraInfo::arithmetic_f64()),
11114            )?,
11115            Operator::I64AtomicRmwXor { ref memarg } => self.translate_atomic_rmw(
11116                self.intrinsics.i64_ty,
11117                self.intrinsics.i64_ty,
11118                memarg,
11119                AtomicRMWBinOp::Xor,
11120                None,
11121            )?,
11122            Operator::I32AtomicRmw8XchgU { ref memarg } => self.translate_atomic_rmw(
11123                self.intrinsics.i32_ty,
11124                self.intrinsics.i8_ty,
11125                memarg,
11126                AtomicRMWBinOp::Xchg,
11127                Some(ExtraInfo::arithmetic_f32()),
11128            )?,
11129            Operator::I32AtomicRmw16XchgU { ref memarg } => self.translate_atomic_rmw(
11130                self.intrinsics.i32_ty,
11131                self.intrinsics.i16_ty,
11132                memarg,
11133                AtomicRMWBinOp::Xchg,
11134                Some(ExtraInfo::arithmetic_f32()),
11135            )?,
11136            Operator::I32AtomicRmwXchg { ref memarg } => self.translate_atomic_rmw(
11137                self.intrinsics.i32_ty,
11138                self.intrinsics.i32_ty,
11139                memarg,
11140                AtomicRMWBinOp::Xchg,
11141                None,
11142            )?,
11143            Operator::I64AtomicRmw8XchgU { ref memarg } => self.translate_atomic_rmw(
11144                self.intrinsics.i64_ty,
11145                self.intrinsics.i8_ty,
11146                memarg,
11147                AtomicRMWBinOp::Xchg,
11148                Some(ExtraInfo::arithmetic_f64()),
11149            )?,
11150            Operator::I64AtomicRmw16XchgU { ref memarg } => self.translate_atomic_rmw(
11151                self.intrinsics.i64_ty,
11152                self.intrinsics.i16_ty,
11153                memarg,
11154                AtomicRMWBinOp::Xchg,
11155                Some(ExtraInfo::arithmetic_f64()),
11156            )?,
11157            Operator::I64AtomicRmw32XchgU { ref memarg } => self.translate_atomic_rmw(
11158                self.intrinsics.i64_ty,
11159                self.intrinsics.i32_ty,
11160                memarg,
11161                AtomicRMWBinOp::Xchg,
11162                Some(ExtraInfo::arithmetic_f64()),
11163            )?,
11164            Operator::I64AtomicRmwXchg { ref memarg } => self.translate_atomic_rmw(
11165                self.intrinsics.i64_ty,
11166                self.intrinsics.i64_ty,
11167                memarg,
11168                AtomicRMWBinOp::Xchg,
11169                None,
11170            )?,
11171            Operator::I32AtomicRmw8CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11172                self.intrinsics.i32_ty,
11173                self.intrinsics.i8_ty,
11174                memarg,
11175                Some(ExtraInfo::arithmetic_f32()),
11176            )?,
11177            Operator::I32AtomicRmw16CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11178                self.intrinsics.i32_ty,
11179                self.intrinsics.i16_ty,
11180                memarg,
11181                Some(ExtraInfo::arithmetic_f32()),
11182            )?,
11183            Operator::I32AtomicRmwCmpxchg { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11184                self.intrinsics.i32_ty,
11185                self.intrinsics.i32_ty,
11186                memarg,
11187                None,
11188            )?,
11189            Operator::I64AtomicRmw8CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11190                self.intrinsics.i64_ty,
11191                self.intrinsics.i8_ty,
11192                memarg,
11193                Some(ExtraInfo::arithmetic_f64()),
11194            )?,
11195            Operator::I64AtomicRmw16CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11196                self.intrinsics.i64_ty,
11197                self.intrinsics.i16_ty,
11198                memarg,
11199                Some(ExtraInfo::arithmetic_f64()),
11200            )?,
11201            Operator::I64AtomicRmw32CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11202                self.intrinsics.i64_ty,
11203                self.intrinsics.i32_ty,
11204                memarg,
11205                Some(ExtraInfo::arithmetic_f64()),
11206            )?,
11207            Operator::I64AtomicRmwCmpxchg { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11208                self.intrinsics.i64_ty,
11209                self.intrinsics.i64_ty,
11210                memarg,
11211                None,
11212            )?,
11213            Operator::MemoryAtomicWait32 { memarg } => {
11214                let memory_index = MemoryIndex::from_u32(memarg.memory);
11215                let (dst, val, timeout) = self.state.pop3()?;
11216                let wait32_fn_ptr = self.ctx.memory_wait32(memory_index, self.intrinsics)?;
11217                let ret = err!(
11218                    self.builder.build_indirect_call(
11219                        self.intrinsics.memory_wait32_ty,
11220                        wait32_fn_ptr,
11221                        &[
11222                            vmctx.as_basic_value_enum().into(),
11223                            self.intrinsics
11224                                .i32_ty
11225                                .const_int(memarg.memory as u64, false)
11226                                .into(),
11227                            dst.into(),
11228                            val.into(),
11229                            timeout.into(),
11230                        ],
11231                        "",
11232                    )
11233                );
11234                self.state.push1(ret.try_as_basic_value().unwrap_basic());
11235            }
11236            Operator::MemoryAtomicWait64 { memarg } => {
11237                let memory_index = MemoryIndex::from_u32(memarg.memory);
11238                let (dst, val, timeout) = self.state.pop3()?;
11239                let wait64_fn_ptr = self.ctx.memory_wait64(memory_index, self.intrinsics)?;
11240                let ret = err!(
11241                    self.builder.build_indirect_call(
11242                        self.intrinsics.memory_wait64_ty,
11243                        wait64_fn_ptr,
11244                        &[
11245                            vmctx.as_basic_value_enum().into(),
11246                            self.intrinsics
11247                                .i32_ty
11248                                .const_int(memarg.memory as u64, false)
11249                                .into(),
11250                            dst.into(),
11251                            val.into(),
11252                            timeout.into(),
11253                        ],
11254                        "",
11255                    )
11256                );
11257                self.state.push1(ret.try_as_basic_value().unwrap_basic());
11258            }
11259            Operator::MemoryAtomicNotify { memarg } => {
11260                let memory_index = MemoryIndex::from_u32(memarg.memory);
11261                let (dst, count) = self.state.pop2()?;
11262                let notify_fn_ptr = self.ctx.memory_notify(memory_index, self.intrinsics)?;
11263                let cnt = err!(
11264                    self.builder.build_indirect_call(
11265                        self.intrinsics.memory_notify_ty,
11266                        notify_fn_ptr,
11267                        &[
11268                            vmctx.as_basic_value_enum().into(),
11269                            self.intrinsics
11270                                .i32_ty
11271                                .const_int(memarg.memory as u64, false)
11272                                .into(),
11273                            dst.into(),
11274                            count.into(),
11275                        ],
11276                        "",
11277                    )
11278                );
11279                self.state.push1(cnt.try_as_basic_value().unwrap_basic());
11280            }
11281            _ => unreachable!(),
11282        }
11283        Ok(())
11284    }
11285
11286    // Reference types.
11287    // https://github.com/WebAssembly/reference-types/blob/master/proposals/reference-types/Overview.md
11288    fn translate_reference_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11289        match op {
11290            Operator::RefNull { hty } => {
11291                let ty = err!(wpheaptype_to_type(hty));
11292                let ty = type_to_llvm(self.intrinsics, ty)?;
11293                self.state.push1(ty.const_zero());
11294            }
11295            Operator::RefIsNull => {
11296                let value = self.state.pop1()?;
11297                let is_null = match value {
11298                    BasicValueEnum::IntValue(value) => err!(self.builder.build_int_compare(
11299                        IntPredicate::EQ,
11300                        value,
11301                        value.get_type().const_zero(),
11302                        "",
11303                    )),
11304                    BasicValueEnum::PointerValue(value) => {
11305                        err!(self.builder.build_is_null(value, ""))
11306                    }
11307                    _ => unreachable!("ref.is_null only accepts reference types"),
11308                };
11309                let is_null = err!(self.builder.build_int_z_extend(
11310                    is_null,
11311                    self.intrinsics.i32_ty,
11312                    ""
11313                ));
11314                self.state.push1(is_null);
11315            }
11316            Operator::RefFunc { function_index } => {
11317                let index = self
11318                    .intrinsics
11319                    .i32_ty
11320                    .const_int(function_index.into(), false);
11321                let value = self
11322                    .build_call_with_param_attributes(
11323                        self.intrinsics.func_ref,
11324                        &[self.ctx.basic().into(), index.into()],
11325                        "",
11326                    )?
11327                    .try_as_basic_value()
11328                    .unwrap_basic();
11329                self.state.push1(value);
11330            }
11331            _ => unreachable!(),
11332        }
11333        Ok(())
11334    }
11335
11336    // Table operators.
11337    fn translate_table_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11338        match op {
11339            Operator::TableGet { table } => {
11340                let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
11341                let elem = self.state.pop1()?;
11342                let table_get = if self
11343                    .wasm_module
11344                    .local_table_index(TableIndex::from_u32(table))
11345                    .is_some()
11346                {
11347                    self.intrinsics.table_get
11348                } else {
11349                    self.intrinsics.imported_table_get
11350                };
11351                let value = self
11352                    .build_call_with_param_attributes(
11353                        table_get,
11354                        &[self.ctx.basic().into(), table_index.into(), elem.into()],
11355                        "",
11356                    )?
11357                    .try_as_basic_value()
11358                    .unwrap_basic();
11359                let value = err!(
11360                    self.builder.build_bit_cast(
11361                        value,
11362                        type_to_llvm(
11363                            self.intrinsics,
11364                            self.wasm_module
11365                                .tables
11366                                .get(TableIndex::from_u32(table))
11367                                .unwrap()
11368                                .ty,
11369                        )?,
11370                        "",
11371                    )
11372                );
11373                self.state.push1(value);
11374            }
11375            Operator::TableSet { table } => {
11376                let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
11377                let (elem, value) = self.state.pop2()?;
11378                let value = err!(
11379                    self.builder
11380                        .build_bit_cast(value, self.intrinsics.ptr_ty, "")
11381                );
11382                let table_set = if self
11383                    .wasm_module
11384                    .local_table_index(TableIndex::from_u32(table))
11385                    .is_some()
11386                {
11387                    self.intrinsics.table_set
11388                } else {
11389                    self.intrinsics.imported_table_set
11390                };
11391                self.build_call_with_param_attributes(
11392                    table_set,
11393                    &[
11394                        self.ctx.basic().into(),
11395                        table_index.into(),
11396                        elem.into(),
11397                        value.into(),
11398                    ],
11399                    "",
11400                )?;
11401            }
11402            Operator::TableCopy {
11403                dst_table,
11404                src_table,
11405            } => {
11406                let (dst, src, len) = self.state.pop3()?;
11407                let dst_table = self.intrinsics.i32_ty.const_int(dst_table as u64, false);
11408                let src_table = self.intrinsics.i32_ty.const_int(src_table as u64, false);
11409                self.build_call_with_param_attributes(
11410                    self.intrinsics.table_copy,
11411                    &[
11412                        self.ctx.basic().into(),
11413                        dst_table.into(),
11414                        src_table.into(),
11415                        dst.into(),
11416                        src.into(),
11417                        len.into(),
11418                    ],
11419                    "",
11420                )?;
11421            }
11422            Operator::TableInit { elem_index, table } => {
11423                let (dst, src, len) = self.state.pop3()?;
11424                let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
11425                let table = self.intrinsics.i32_ty.const_int(table as u64, false);
11426                self.build_call_with_param_attributes(
11427                    self.intrinsics.table_init,
11428                    &[
11429                        self.ctx.basic().into(),
11430                        table.into(),
11431                        segment.into(),
11432                        dst.into(),
11433                        src.into(),
11434                        len.into(),
11435                    ],
11436                    "",
11437                )?;
11438            }
11439            Operator::ElemDrop { elem_index } => {
11440                let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
11441                self.build_call_with_param_attributes(
11442                    self.intrinsics.elem_drop,
11443                    &[self.ctx.basic().into(), segment.into()],
11444                    "",
11445                )?;
11446            }
11447            Operator::TableFill { table } => {
11448                let table = self.intrinsics.i32_ty.const_int(table as u64, false);
11449                let (start, elem, len) = self.state.pop3()?;
11450                let elem = err!(
11451                    self.builder
11452                        .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
11453                );
11454                self.build_call_with_param_attributes(
11455                    self.intrinsics.table_fill,
11456                    &[
11457                        self.ctx.basic().into(),
11458                        table.into(),
11459                        start.into(),
11460                        elem.into(),
11461                        len.into(),
11462                    ],
11463                    "",
11464                )?;
11465            }
11466            Operator::TableGrow { table } => {
11467                let (elem, delta) = self.state.pop2()?;
11468                let elem = err!(
11469                    self.builder
11470                        .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
11471                );
11472                let (table_grow, table_index) = if let Some(local_table_index) = self
11473                    .wasm_module
11474                    .local_table_index(TableIndex::from_u32(table))
11475                {
11476                    (self.intrinsics.table_grow, local_table_index.as_u32())
11477                } else {
11478                    (self.intrinsics.imported_table_grow, table)
11479                };
11480                let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11481                let size = self
11482                    .build_call_with_param_attributes(
11483                        table_grow,
11484                        &[
11485                            self.ctx.basic().into(),
11486                            elem.into(),
11487                            delta.into(),
11488                            table_index.into(),
11489                        ],
11490                        "",
11491                    )?
11492                    .try_as_basic_value()
11493                    .unwrap_basic();
11494                self.state.push1(size);
11495            }
11496            Operator::TableSize { table } => {
11497                let (table_size, table_index) = if let Some(local_table_index) = self
11498                    .wasm_module
11499                    .local_table_index(TableIndex::from_u32(table))
11500                {
11501                    (self.intrinsics.table_size, local_table_index.as_u32())
11502                } else {
11503                    (self.intrinsics.imported_table_size, table)
11504                };
11505                let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11506                let size = self
11507                    .build_call_with_param_attributes(
11508                        table_size,
11509                        &[self.ctx.basic().into(), table_index.into()],
11510                        "",
11511                    )?
11512                    .try_as_basic_value()
11513                    .unwrap_basic();
11514                self.state.push1(size);
11515            }
11516            _ => unreachable!(),
11517        }
11518        Ok(())
11519    }
11520
11521    // Exception handling.
11522    // https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md
11523    fn translate_eh_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11524        match op {
11525            Operator::TryTable { try_table } => {
11526                let current_block = self
11527                    .builder
11528                    .get_insert_block()
11529                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
11530
11531                self.builder.position_at_end(current_block);
11532
11533                let end_block = self.context.append_basic_block(self.function, "try_end");
11534
11535                let end_phis = {
11536                    self.builder.position_at_end(end_block);
11537
11538                    let phis = self
11539                        .module_translation
11540                        .blocktype_params_results(&try_table.ty)?
11541                        .1
11542                        .iter()
11543                        .map(|&wp_ty| {
11544                            err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
11545                                type_to_llvm(self.intrinsics, wasm_ty)
11546                                    .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
11547                            })
11548                        })
11549                        .collect::<Result<_, _>>()?;
11550
11551                    self.builder.position_at_end(current_block);
11552                    phis
11553                };
11554
11555                // Collect unique catches. It is not a "hard" error on the wasm side,
11556                // but LLVM will definitely complain about having the same identifier
11557                // match two different branches in the switch below.
11558                let catches: Vec<_> = try_table
11559                    .catches
11560                    .into_iter()
11561                    .unique_by(|v| match v {
11562                        Catch::One { tag, .. } | Catch::OneRef { tag, .. } => *tag as i32,
11563                        Catch::All { .. } | Catch::AllRef { .. } => CATCH_ALL_TAG_VALUE,
11564                    })
11565                    .collect();
11566
11567                // Build the landing pad.
11568                let null = self.intrinsics.ptr_ty.const_zero();
11569
11570                let mut catch_tag_values = vec![];
11571                let mut lpad_clauses: Vec<BasicValueEnum<'ctx>> = catches
11572                    .iter()
11573                    .map(|catch| match catch {
11574                        Catch::All { .. } | Catch::AllRef { .. } => {
11575                            catch_tag_values.push(CATCH_ALL_TAG_VALUE as u32);
11576                            Ok(null.into())
11577                        }
11578                        Catch::One { tag, .. } | Catch::OneRef { tag, .. } => {
11579                            catch_tag_values.push(*tag);
11580                            Ok(self.get_or_insert_tag_type_info_global(*tag as i32))
11581                        }
11582                    })
11583                    .collect::<Result<Vec<BasicValueEnum<'ctx>>, CompileError>>()?;
11584
11585                // Since jumping between landingpads is not possible, we need to collect
11586                // all tags from outer try_tables as well to build a clause for *every*
11587                // possible tag that might be caught.
11588                let mut outer_catch_blocks = vec![];
11589                for outer_landingpad in self.state.landingpads.iter().rev() {
11590                    for catch_info @ TagCatchInfo { tag, .. } in &outer_landingpad.tags {
11591                        if !catch_tag_values.contains(tag) {
11592                            catch_tag_values.push(*tag);
11593                            lpad_clauses.push(if *tag as i32 == CATCH_ALL_TAG_VALUE {
11594                                null.into()
11595                            } else {
11596                                *self.tags_cache.get(&(*tag as i32)).expect(
11597                                    "If a previous try_table encountered a tag, \
11598                                    it should be in the cache",
11599                                )
11600                            });
11601                            outer_catch_blocks.push(*catch_info);
11602                        }
11603                    }
11604                }
11605
11606                // If there are no catch clauses, we have to skip everything, since
11607                // an lpad without catch clauses is invalid (and won't ever be jumped
11608                // to anyway)
11609                let mut maybe_lpad_block = None;
11610                let mut catch_blocks = vec![];
11611                if !lpad_clauses.is_empty() {
11612                    let lpad_block = self.context.append_basic_block(self.function, "catch");
11613                    let catch_all_block =
11614                        self.context.append_basic_block(self.function, "catch_all");
11615                    let catch_specific_block = self
11616                        .context
11617                        .append_basic_block(self.function, "catch_specific");
11618                    let catch_end_block =
11619                        self.context.append_basic_block(self.function, "catch_end");
11620                    let rethrow_block = self.context.append_basic_block(self.function, "rethrow");
11621
11622                    self.builder.position_at_end(lpad_block);
11623
11624                    let res = err!(self.builder.build_landing_pad(
11625                        self.intrinsics.lpad_exception_ty,
11626                        self.intrinsics.personality,
11627                        &lpad_clauses,
11628                        false,
11629                        "exc_struct",
11630                    ));
11631
11632                    let res = res.into_struct_value();
11633
11634                    let uw_exc = err!(self.builder.build_extract_value(res, 0, "exc_ptr"));
11635                    let pre_selector =
11636                        err!(self.builder.build_extract_value(res, 1, "pre_selector"));
11637
11638                    // The pre-selector can be either 0 (for catch-all) or 1 (for a
11639                    // specific, but as-yet-unknown tag).
11640                    let pre_selector_is_zero = err!(self.builder.build_int_compare(
11641                        IntPredicate::EQ,
11642                        pre_selector.into_int_value(),
11643                        self.intrinsics.i32_zero,
11644                        "pre_selector_is_zero"
11645                    ));
11646                    err!(self.builder.build_conditional_branch(
11647                        pre_selector_is_zero,
11648                        catch_all_block,
11649                        catch_specific_block
11650                    ));
11651
11652                    self.builder.position_at_end(catch_all_block);
11653                    err!(self.builder.build_unconditional_branch(catch_end_block));
11654
11655                    self.builder.position_at_end(catch_specific_block);
11656                    let selector_value = self.build_call_with_param_attributes(
11657                        self.intrinsics.personality2,
11658                        &[self.ctx.basic().into(), uw_exc.into()],
11659                        "selector",
11660                    )?;
11661                    err!(self.builder.build_unconditional_branch(catch_end_block));
11662
11663                    self.builder.position_at_end(catch_end_block);
11664                    let selector = err!(self.builder.build_phi(self.intrinsics.i32_ty, "selector"));
11665                    selector.add_incoming(&[
11666                        (
11667                            &self
11668                                .intrinsics
11669                                .i32_ty
11670                                .const_int(CATCH_ALL_TAG_VALUE as u64, false),
11671                            catch_all_block,
11672                        ),
11673                        (
11674                            &selector_value
11675                                .try_as_basic_value()
11676                                .unwrap_basic()
11677                                .into_int_value(),
11678                            catch_specific_block,
11679                        ),
11680                    ]);
11681
11682                    // Now we're done looking at the exception, it's time to deallocate and get
11683                    // the exnref out of it. When an exception is caught, "rethrowing" simply
11684                    // means starting another unwind by calling _Unwind_RaiseException with the
11685                    // same exception bits. Instead of keeping the same exception around, we
11686                    // deallocate the exception once it's caught, and if we need to rethrow, we
11687                    // just re-allocate a new exception.
11688                    //
11689                    // Note that this is different from how it's done in C++ land, where the
11690                    // exception object is kept around for rethrowing; this discrepancy exists
11691                    // because in C++, exception handling is lexical (i.e. there's an implicit
11692                    // "current exception" in catch blocks) whereas in WASM, you rethrow with
11693                    // an exnref that may very well have come from somewhere else; consider this
11694                    // (badly implemented and erroneous) pseudo-module:
11695                    //
11696                    // (module
11697                    //   (global $e (mut exnref) (ref.null exn))
11698                    //   ;; Store the given exnref, return the previous one
11699                    //   (func $delay_exnref (param exnref) (result exnref)
11700                    //     (global.get $e)
11701                    //     (local.get 0)
11702                    //     (global.set $e)
11703                    //   )
11704                    //   (func foo
11705                    //     (block $catch (result exnref)
11706                    //       (try_table (catch_all_ref $catch)
11707                    //         ...
11708                    //       )
11709                    //     )
11710                    //     (call $delay_exnref) ;; store the exnref caught above
11711                    //     throw_ref ;; throw the previous exnref
11712                    //   )
11713                    // )
11714                    //
11715                    // Here, it's impossible to reuse the same exception object since the
11716                    // exnref given to throw_ref is a different one than the one we caught
11717                    // with the try_table.
11718                    //
11719                    // Another difference is that C++ exceptions may well carry lots of data
11720                    // around; a WASM exception is just an exnref, backed by a u32, which is
11721                    // just 4 bytes, and is cheap to reallocate. C++ exceptions may also carry
11722                    // things with dtors around; another thing that doesn't exist in WASM.
11723                    //
11724                    // All of this is to say that putting exception deallocation and exnref
11725                    // retrieval in the same function has been a very deliberate choice.
11726                    let uw_exc = uw_exc.into_pointer_value();
11727                    let exnref = self.build_call_with_param_attributes(
11728                        self.intrinsics.exception_into_exnref,
11729                        &[uw_exc.into()],
11730                        "exnref",
11731                    )?;
11732
11733                    let exnref = exnref.try_as_basic_value().unwrap_basic().into_int_value();
11734                    let selector = selector.as_basic_value().into_int_value();
11735
11736                    for catch in catches.iter() {
11737                        match catch {
11738                            Catch::All { label } => {
11739                                let b = self
11740                                    .context
11741                                    .append_basic_block(self.function, "catch_all_clause");
11742                                self.builder.position_at_end(b);
11743                                let frame = self.state.frame_at_depth(*label)?;
11744
11745                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11746
11747                                self.builder.position_at_end(catch_end_block);
11748                                catch_blocks.push((b, None));
11749                            }
11750                            Catch::One { tag, label } => {
11751                                let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
11752                                let signature = &self.wasm_module.signatures[tag_idx];
11753                                let params = signature.params();
11754
11755                                let b = self.context.append_basic_block(
11756                                    self.function,
11757                                    format!("catch_one_clause_{tag}").as_str(),
11758                                );
11759                                self.builder.position_at_end(b);
11760
11761                                let exnref_phi = err!(
11762                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11763                                );
11764                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11765
11766                                // Get the payload pointer.
11767                                let exn_payload_ptr = err!(self.builder.build_direct_call(
11768                                    self.intrinsics.read_exnref,
11769                                    &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
11770                                    "exn_ptr",
11771                                ));
11772                                let exn_payload_ptr = exn_payload_ptr
11773                                    .try_as_basic_value()
11774                                    .unwrap_basic()
11775                                    .into_pointer_value();
11776
11777                                // Read each value from the data ptr.
11778                                let values = params
11779                                    .iter()
11780                                    .enumerate()
11781                                    .map(|(i, v)| {
11782                                        let name = format!("value_{i}");
11783                                        let ptr = err!(unsafe {
11784                                            self.builder.build_gep(
11785                                                self.intrinsics.i128_ty,
11786                                                exn_payload_ptr,
11787                                                &[self
11788                                                    .intrinsics
11789                                                    .i32_ty
11790                                                    .const_int(i as u64, false)],
11791                                                format!("{name}_ptr").as_str(),
11792                                            )
11793                                        });
11794                                        err_nt!(self.builder.build_load(
11795                                            type_to_llvm(self.intrinsics, *v)?,
11796                                            ptr,
11797                                            &name,
11798                                        ))
11799                                    })
11800                                    .collect::<Result<Vec<_>, CompileError>>()?;
11801
11802                                let frame = self.state.frame_at_depth(*label)?;
11803
11804                                for (phi, value) in frame.phis().iter().zip(values.iter()) {
11805                                    phi.add_incoming(&[(value, b)])
11806                                }
11807
11808                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11809
11810                                self.builder.position_at_end(catch_end_block);
11811                                catch_blocks.push((b, Some(exnref_phi)));
11812                            }
11813                            Catch::OneRef { label, tag } => {
11814                                let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
11815                                let signature = &self.wasm_module.signatures[tag_idx];
11816                                let params = signature.params();
11817
11818                                let b = self.context.append_basic_block(
11819                                    self.function,
11820                                    format!("catch_one_ref_clause_{tag}").as_str(),
11821                                );
11822                                self.builder.position_at_end(b);
11823
11824                                let exnref_phi = err!(
11825                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11826                                );
11827                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11828
11829                                // Get the payload pointer.
11830                                let exn_payload_ptr = err!(self.builder.build_direct_call(
11831                                    self.intrinsics.read_exnref,
11832                                    &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
11833                                    "exn_ptr",
11834                                ));
11835                                let exn_payload_ptr = exn_payload_ptr
11836                                    .try_as_basic_value()
11837                                    .unwrap_basic()
11838                                    .into_pointer_value();
11839
11840                                // Read each value from the data ptr.
11841                                let mut values = params
11842                                    .iter()
11843                                    .enumerate()
11844                                    .map(|(i, v)| {
11845                                        let name = format!("value_{i}");
11846                                        let ptr = err!(unsafe {
11847                                            self.builder.build_gep(
11848                                                self.intrinsics.i128_ty,
11849                                                exn_payload_ptr,
11850                                                &[self
11851                                                    .intrinsics
11852                                                    .i32_ty
11853                                                    .const_int(i as u64, false)],
11854                                                format!("{name}_ptr").as_str(),
11855                                            )
11856                                        });
11857                                        err_nt!(self.builder.build_load(
11858                                            type_to_llvm(self.intrinsics, *v)?,
11859                                            ptr,
11860                                            &name,
11861                                        ))
11862                                    })
11863                                    .collect::<Result<Vec<_>, CompileError>>()?;
11864
11865                                values.push(exnref_phi.as_basic_value());
11866
11867                                let frame = self.state.frame_at_depth(*label)?;
11868
11869                                for (phi, value) in frame.phis().iter().zip(values.iter()) {
11870                                    phi.add_incoming(&[(value, b)])
11871                                }
11872
11873                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11874
11875                                self.builder.position_at_end(catch_end_block);
11876                                catch_blocks.push((b, Some(exnref_phi)));
11877                            }
11878                            Catch::AllRef { label } => {
11879                                let b = self
11880                                    .context
11881                                    .append_basic_block(self.function, "catch_all_ref_clause");
11882                                self.builder.position_at_end(b);
11883
11884                                let exnref_phi = err!(
11885                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11886                                );
11887                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11888
11889                                let frame = self.state.frame_at_depth(*label)?;
11890
11891                                let phis = frame.phis();
11892
11893                                assert_eq!(phis.len(), 1);
11894                                phis[0].add_incoming(&[(&exnref_phi.as_basic_value(), b)]);
11895
11896                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11897
11898                                self.builder.position_at_end(catch_end_block);
11899                                catch_blocks.push((b, Some(exnref_phi)));
11900                            }
11901                        }
11902                    }
11903
11904                    for catch_info in &outer_catch_blocks {
11905                        if let Some(phi) = catch_info.exnref_phi {
11906                            phi.add_incoming(&[(&exnref, catch_end_block)]);
11907                        }
11908                    }
11909
11910                    err!(
11911                        self.builder.build_switch(
11912                            selector,
11913                            rethrow_block,
11914                            catch_blocks
11915                                .iter()
11916                                .enumerate()
11917                                .map(|(i, v)| (
11918                                    self.intrinsics
11919                                        .i32_ty
11920                                        .const_int(catch_tag_values[i] as _, false),
11921                                    v.0
11922                                ))
11923                                .chain(outer_catch_blocks.iter().map(|catch_info| (
11924                                    self.intrinsics.i32_ty.const_int(catch_info.tag as _, false),
11925                                    catch_info.catch_block
11926                                )))
11927                                .collect::<Vec<_>>()
11928                                .as_slice()
11929                        )
11930                    );
11931
11932                    // -- end
11933
11934                    // -- The rethrow block
11935                    self.builder.position_at_end(rethrow_block);
11936
11937                    self.build_call_with_param_attributes(
11938                        self.intrinsics.throw,
11939                        &[self.ctx.basic().into(), exnref.into()],
11940                        "rethrow",
11941                    )?;
11942                    // can't reach after an explicit throw!
11943                    err!(self.builder.build_unreachable());
11944
11945                    maybe_lpad_block = Some(lpad_block);
11946                }
11947
11948                // Move back to current block
11949                self.builder.position_at_end(current_block);
11950
11951                // Note: catch_tag_values also contains outer tags, but zipping with
11952                // catch_blocks will let us ignore the extra ones.
11953                let catch_tags_and_blocks = catch_tag_values
11954                    .into_iter()
11955                    .zip(catch_blocks)
11956                    .map(|(tag, (block, exnref_phi))| TagCatchInfo {
11957                        tag,
11958                        catch_block: block,
11959                        exnref_phi,
11960                    })
11961                    .collect::<Vec<_>>();
11962                self.state.push_landingpad(
11963                    maybe_lpad_block,
11964                    end_block,
11965                    end_phis,
11966                    &catch_tags_and_blocks,
11967                    self.module_translation
11968                        .blocktype_params_results(&try_table.ty)?
11969                        .0
11970                        .len(),
11971                );
11972            }
11973            Operator::Throw { tag_index } => {
11974                let current_block = self
11975                    .builder
11976                    .get_insert_block()
11977                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
11978
11979                let sig_index = self.wasm_module.tags[TagIndex::from_u32(tag_index)];
11980                let signature = &self.wasm_module.signatures[sig_index];
11981                let params = signature.params();
11982                let values = self.state.popn_save_extra(params.len())?;
11983
11984                values.iter().enumerate().try_for_each(|(i, (v, _))| {
11985                    let t = type_to_llvm(self.intrinsics, params[i])?;
11986                    if t != v.get_type() {
11987                        return Err(CompileError::Codegen(format!(
11988                            "Incompatible types: {:?} != {:?}",
11989                            t,
11990                            v.get_type()
11991                        )));
11992                    }
11993
11994                    Ok(())
11995                })?;
11996
11997                // Allocate the necessary bytes for the exception.
11998                let exnref = err!(
11999                    self.builder.build_direct_call(
12000                        self.intrinsics.alloc_exception,
12001                        &[
12002                            self.ctx.basic().into(),
12003                            self.intrinsics
12004                                .i32_ty
12005                                .const_int(tag_index as _, false)
12006                                .into()
12007                        ],
12008                        "exnref",
12009                    )
12010                );
12011                let exnref = exnref.try_as_basic_value().unwrap_basic();
12012
12013                let exn_payload_ptr = err!(self.builder.build_direct_call(
12014                    self.intrinsics.read_exnref,
12015                    &[self.ctx.basic().into(), exnref.into()],
12016                    "exn_ptr",
12017                ));
12018                let exn_payload_ptr = exn_payload_ptr
12019                    .try_as_basic_value()
12020                    .unwrap_basic()
12021                    .into_pointer_value();
12022
12023                for (i, value) in values.into_iter().enumerate() {
12024                    let ptr = err!(unsafe {
12025                        self.builder.build_gep(
12026                            self.intrinsics.i128_ty,
12027                            exn_payload_ptr,
12028                            &[self.intrinsics.i32_ty.const_int(i as u64, false)],
12029                            format!("value_{i}_ptr").as_str(),
12030                        )
12031                    });
12032                    err!(self.builder.build_store(ptr, value.0));
12033                }
12034
12035                if let Some(pad) = self.state.get_innermost_landingpad() {
12036                    let unreachable_block = self
12037                        .context
12038                        .append_basic_block(self.function, "_throw_unreachable");
12039
12040                    err!(self.builder.build_invoke(
12041                        self.intrinsics.throw,
12042                        &[self.ctx.basic(), exnref],
12043                        unreachable_block,
12044                        pad,
12045                        "throw",
12046                    ));
12047
12048                    self.builder.position_at_end(unreachable_block);
12049                    // can't reach after an explicit throw!
12050                    err!(self.builder.build_unreachable());
12051
12052                    self.builder.position_at_end(current_block);
12053                } else {
12054                    self.build_call_with_param_attributes(
12055                        self.intrinsics.throw,
12056                        &[self.ctx.basic().into(), exnref.into()],
12057                        "throw",
12058                    )?;
12059                    // can't reach after an explicit throw!
12060                    err!(self.builder.build_unreachable());
12061                }
12062
12063                self.state.reachable = false;
12064            }
12065            Operator::ThrowRef => {
12066                let current_block = self
12067                    .builder
12068                    .get_insert_block()
12069                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
12070
12071                let exnref = self.state.pop1()?;
12072
12073                if let Some(pad) = self.state.get_innermost_landingpad() {
12074                    let unreachable_block = self
12075                        .context
12076                        .append_basic_block(self.function, "_rethrow_unreachable");
12077
12078                    err!(self.builder.build_invoke(
12079                        self.intrinsics.throw,
12080                        &[self.ctx.basic(), exnref],
12081                        unreachable_block,
12082                        pad,
12083                        "throw",
12084                    ));
12085
12086                    self.builder.position_at_end(unreachable_block);
12087                    // can't reach after an explicit throw!
12088                    err!(self.builder.build_unreachable());
12089
12090                    self.builder.position_at_end(current_block);
12091                } else {
12092                    self.build_call_with_param_attributes(
12093                        self.intrinsics.throw,
12094                        &[self.ctx.basic().into(), exnref.into()],
12095                        "throw",
12096                    )?;
12097                    // can't reach after an explicit throw!
12098                    err!(self.builder.build_unreachable());
12099                }
12100
12101                self.state.reachable = false;
12102            }
12103            _ => unreachable!(),
12104        }
12105        Ok(())
12106    }
12107
12108    fn translate_operator(&mut self, op: Operator, _source_loc: u32) -> Result<(), CompileError> {
12109        //let opcode_offset: Option<usize> = None;
12110
12111        if !self.state.reachable {
12112            match op {
12113                Operator::Block { blockty: _ }
12114                | Operator::Loop { blockty: _ }
12115                | Operator::If { blockty: _ }
12116                | Operator::TryTable { .. } => {
12117                    self.unreachable_depth += 1;
12118                    return Ok(());
12119                }
12120                Operator::Else => {
12121                    if self.unreachable_depth != 0 {
12122                        return Ok(());
12123                    }
12124                }
12125                Operator::End => {
12126                    if self.unreachable_depth != 0 {
12127                        self.unreachable_depth -= 1;
12128                        return Ok(());
12129                    }
12130                }
12131                _ => {
12132                    return Ok(());
12133                }
12134            }
12135        }
12136
12137        match op {
12138            Operator::Block { .. }
12139            | Operator::Loop { .. }
12140            | Operator::Br { .. }
12141            | Operator::BrIf { .. }
12142            | Operator::BrTable { .. }
12143            | Operator::If { .. }
12144            | Operator::Else
12145            | Operator::End
12146            | Operator::Return
12147            | Operator::Unreachable => {
12148                self.translate_control_flow_operator(op)?;
12149            }
12150            Operator::Nop
12151            | Operator::Drop
12152            | Operator::I32Const { .. }
12153            | Operator::I64Const { .. }
12154            | Operator::F32Const { .. }
12155            | Operator::F64Const { .. }
12156            | Operator::V128Const { .. }
12157            | Operator::I8x16Splat
12158            | Operator::I16x8Splat
12159            | Operator::I32x4Splat
12160            | Operator::I64x2Splat
12161            | Operator::F32x4Splat
12162            | Operator::F64x2Splat
12163            | Operator::LocalGet { .. }
12164            | Operator::LocalSet { .. }
12165            | Operator::LocalTee { .. }
12166            | Operator::GlobalGet { .. }
12167            | Operator::GlobalSet { .. }
12168            | Operator::Call { .. }
12169            | Operator::ReturnCall { .. }
12170            | Operator::CallIndirect { .. }
12171            | Operator::ReturnCallIndirect { .. }
12172            | Operator::TypedSelect { .. }
12173            | Operator::Select => {
12174                self.translate_basic_operator(op)?;
12175            }
12176            Operator::I32Add
12177            | Operator::I64Add
12178            | Operator::I8x16Add
12179            | Operator::I16x8Add
12180            | Operator::I16x8ExtAddPairwiseI8x16S
12181            | Operator::I16x8ExtAddPairwiseI8x16U
12182            | Operator::I32x4Add
12183            | Operator::I32x4ExtAddPairwiseI16x8S
12184            | Operator::I32x4ExtAddPairwiseI16x8U
12185            | Operator::I64x2Add
12186            | Operator::I8x16AddSatS
12187            | Operator::I16x8AddSatS
12188            | Operator::I8x16AddSatU
12189            | Operator::I16x8AddSatU
12190            | Operator::I32Sub
12191            | Operator::I64Sub
12192            | Operator::I8x16Sub
12193            | Operator::I16x8Sub
12194            | Operator::I32x4Sub
12195            | Operator::I64x2Sub
12196            | Operator::I8x16SubSatS
12197            | Operator::I16x8SubSatS
12198            | Operator::I8x16SubSatU
12199            | Operator::I16x8SubSatU
12200            | Operator::I32Mul
12201            | Operator::I64Mul
12202            | Operator::I16x8Mul
12203            | Operator::I32x4Mul
12204            | Operator::I64x2Mul
12205            | Operator::I16x8RelaxedQ15mulrS
12206            | Operator::I16x8Q15MulrSatS
12207            | Operator::I16x8ExtMulLowI8x16S
12208            | Operator::I16x8ExtMulLowI8x16U
12209            | Operator::I16x8ExtMulHighI8x16S
12210            | Operator::I16x8ExtMulHighI8x16U
12211            | Operator::I32x4ExtMulLowI16x8S
12212            | Operator::I32x4ExtMulLowI16x8U
12213            | Operator::I32x4ExtMulHighI16x8S
12214            | Operator::I32x4ExtMulHighI16x8U
12215            | Operator::I64x2ExtMulLowI32x4S
12216            | Operator::I64x2ExtMulLowI32x4U
12217            | Operator::I64x2ExtMulHighI32x4S
12218            | Operator::I64x2ExtMulHighI32x4U
12219            | Operator::I32x4DotI16x8S
12220            | Operator::I16x8RelaxedDotI8x16I7x16S
12221            | Operator::I32x4RelaxedDotI8x16I7x16AddS
12222            | Operator::I32DivS
12223            | Operator::I64DivS
12224            | Operator::I32DivU
12225            | Operator::I64DivU
12226            | Operator::I32RemS
12227            | Operator::I64RemS
12228            | Operator::I32RemU
12229            | Operator::I64RemU
12230            | Operator::I32And
12231            | Operator::I64And
12232            | Operator::V128And
12233            | Operator::I32Or
12234            | Operator::I64Or
12235            | Operator::V128Or
12236            | Operator::I32Xor
12237            | Operator::I64Xor
12238            | Operator::V128Xor
12239            | Operator::V128AndNot
12240            | Operator::I8x16RelaxedLaneselect
12241            | Operator::I16x8RelaxedLaneselect
12242            | Operator::I32x4RelaxedLaneselect
12243            | Operator::I64x2RelaxedLaneselect
12244            | Operator::V128Bitselect
12245            | Operator::I8x16Bitmask
12246            | Operator::I16x8Bitmask
12247            | Operator::I32x4Bitmask
12248            | Operator::I64x2Bitmask
12249            | Operator::I32Shl
12250            | Operator::I64Shl
12251            | Operator::I8x16Shl
12252            | Operator::I16x8Shl
12253            | Operator::I32x4Shl
12254            | Operator::I64x2Shl
12255            | Operator::I32ShrS
12256            | Operator::I64ShrS
12257            | Operator::I8x16ShrS
12258            | Operator::I16x8ShrS
12259            | Operator::I32x4ShrS
12260            | Operator::I64x2ShrS
12261            | Operator::I32ShrU
12262            | Operator::I64ShrU
12263            | Operator::I8x16ShrU
12264            | Operator::I16x8ShrU
12265            | Operator::I32x4ShrU
12266            | Operator::I64x2ShrU
12267            | Operator::I32Rotl
12268            | Operator::I64Rotl
12269            | Operator::I32Rotr
12270            | Operator::I64Rotr
12271            | Operator::I32Clz
12272            | Operator::I64Clz
12273            | Operator::I32Ctz
12274            | Operator::I64Ctz
12275            | Operator::I8x16Popcnt
12276            | Operator::I32Popcnt
12277            | Operator::I64Popcnt
12278            | Operator::I32Eqz
12279            | Operator::I64Eqz
12280            | Operator::I8x16Abs
12281            | Operator::I16x8Abs
12282            | Operator::I32x4Abs
12283            | Operator::I64x2Abs
12284            | Operator::I8x16MinS
12285            | Operator::I8x16MinU
12286            | Operator::I8x16MaxS
12287            | Operator::I8x16MaxU
12288            | Operator::I16x8MinS
12289            | Operator::I16x8MinU
12290            | Operator::I16x8MaxS
12291            | Operator::I16x8MaxU
12292            | Operator::I32x4MinS
12293            | Operator::I32x4MinU
12294            | Operator::I32x4MaxS
12295            | Operator::I32x4MaxU
12296            | Operator::I8x16AvgrU
12297            | Operator::I16x8AvgrU
12298            | Operator::I64Add128
12299            | Operator::I64Sub128
12300            | Operator::I64MulWideS
12301            | Operator::I64MulWideU => self.translate_integer_arithmetic_operator(op)?,
12302            Operator::F32Add
12303            | Operator::F64Add
12304            | Operator::F32x4Add
12305            | Operator::F64x2Add
12306            | Operator::F32Sub
12307            | Operator::F64Sub
12308            | Operator::F32x4Sub
12309            | Operator::F64x2Sub
12310            | Operator::F32Mul
12311            | Operator::F64Mul
12312            | Operator::F32x4Mul
12313            | Operator::F32x4RelaxedMadd
12314            | Operator::F32x4RelaxedNmadd
12315            | Operator::F64x2Mul
12316            | Operator::F64x2RelaxedMadd
12317            | Operator::F64x2RelaxedNmadd
12318            | Operator::F32Div
12319            | Operator::F64Div
12320            | Operator::F32x4Div
12321            | Operator::F64x2Div
12322            | Operator::F32Sqrt
12323            | Operator::F64Sqrt
12324            | Operator::F32x4Sqrt
12325            | Operator::F64x2Sqrt
12326            | Operator::F32Min
12327            | Operator::F64Min
12328            | Operator::F32x4RelaxedMin
12329            | Operator::F32x4Min
12330            | Operator::F32x4PMin
12331            | Operator::F64x2RelaxedMin
12332            | Operator::F64x2Min
12333            | Operator::F64x2PMin
12334            | Operator::F32Max
12335            | Operator::F64Max
12336            | Operator::F32x4RelaxedMax
12337            | Operator::F32x4Max
12338            | Operator::F32x4PMax
12339            | Operator::F64x2RelaxedMax
12340            | Operator::F64x2Max
12341            | Operator::F64x2PMax
12342            | Operator::F32Ceil
12343            | Operator::F32x4Ceil
12344            | Operator::F64Ceil
12345            | Operator::F64x2Ceil
12346            | Operator::F32Floor
12347            | Operator::F32x4Floor
12348            | Operator::F64Floor
12349            | Operator::F64x2Floor
12350            | Operator::F32Trunc
12351            | Operator::F32x4Trunc
12352            | Operator::F64Trunc
12353            | Operator::F64x2Trunc
12354            | Operator::F32Nearest
12355            | Operator::F32x4Nearest
12356            | Operator::F64Nearest
12357            | Operator::F64x2Nearest
12358            | Operator::F32Abs
12359            | Operator::F64Abs
12360            | Operator::F32x4Abs
12361            | Operator::F64x2Abs
12362            | Operator::F32x4Neg
12363            | Operator::F64x2Neg
12364            | Operator::F32Neg
12365            | Operator::F64Neg
12366            | Operator::F32Copysign
12367            | Operator::F64Copysign => self.translate_floating_point_arithmetic_operator(op)?,
12368            Operator::I32Eq
12369            | Operator::I64Eq
12370            | Operator::I8x16Eq
12371            | Operator::I16x8Eq
12372            | Operator::I32x4Eq
12373            | Operator::I64x2Eq
12374            | Operator::I32Ne
12375            | Operator::I64Ne
12376            | Operator::I8x16Ne
12377            | Operator::I16x8Ne
12378            | Operator::I32x4Ne
12379            | Operator::I64x2Ne
12380            | Operator::I32LtS
12381            | Operator::I64LtS
12382            | Operator::I8x16LtS
12383            | Operator::I16x8LtS
12384            | Operator::I32x4LtS
12385            | Operator::I64x2LtS
12386            | Operator::I32LtU
12387            | Operator::I64LtU
12388            | Operator::I8x16LtU
12389            | Operator::I16x8LtU
12390            | Operator::I32x4LtU
12391            | Operator::I32LeS
12392            | Operator::I64LeS
12393            | Operator::I8x16LeS
12394            | Operator::I16x8LeS
12395            | Operator::I32x4LeS
12396            | Operator::I64x2LeS
12397            | Operator::I32LeU
12398            | Operator::I64LeU
12399            | Operator::I8x16LeU
12400            | Operator::I16x8LeU
12401            | Operator::I32x4LeU
12402            | Operator::I32GtS
12403            | Operator::I64GtS
12404            | Operator::I8x16GtS
12405            | Operator::I16x8GtS
12406            | Operator::I32x4GtS
12407            | Operator::I64x2GtS
12408            | Operator::I32GtU
12409            | Operator::I64GtU
12410            | Operator::I8x16GtU
12411            | Operator::I16x8GtU
12412            | Operator::I32x4GtU
12413            | Operator::I32GeS
12414            | Operator::I64GeS
12415            | Operator::I8x16GeS
12416            | Operator::I16x8GeS
12417            | Operator::I32x4GeS
12418            | Operator::I64x2GeS
12419            | Operator::I32GeU
12420            | Operator::I64GeU
12421            | Operator::I8x16GeU
12422            | Operator::I16x8GeU
12423            | Operator::I32x4GeU => self.translate_integer_comparison_operator(op)?,
12424            Operator::F32Eq
12425            | Operator::F64Eq
12426            | Operator::F32x4Eq
12427            | Operator::F64x2Eq
12428            | Operator::F32Ne
12429            | Operator::F64Ne
12430            | Operator::F32x4Ne
12431            | Operator::F64x2Ne
12432            | Operator::F32Lt
12433            | Operator::F64Lt
12434            | Operator::F32x4Lt
12435            | Operator::F64x2Lt
12436            | Operator::F32Le
12437            | Operator::F64Le
12438            | Operator::F32x4Le
12439            | Operator::F64x2Le
12440            | Operator::F32Gt
12441            | Operator::F64Gt
12442            | Operator::F32x4Gt
12443            | Operator::F64x2Gt
12444            | Operator::F32Ge
12445            | Operator::F64Ge
12446            | Operator::F32x4Ge
12447            | Operator::F64x2Ge => self.translate_floating_point_comparison_operator(op)?,
12448            Operator::I32WrapI64
12449            | Operator::I64ExtendI32S
12450            | Operator::I64ExtendI32U
12451            | Operator::I16x8ExtendLowI8x16S
12452            | Operator::I16x8ExtendHighI8x16S
12453            | Operator::I16x8ExtendLowI8x16U
12454            | Operator::I16x8ExtendHighI8x16U
12455            | Operator::I32x4ExtendLowI16x8S
12456            | Operator::I32x4ExtendHighI16x8S
12457            | Operator::I32x4ExtendLowI16x8U
12458            | Operator::I32x4ExtendHighI16x8U
12459            | Operator::I64x2ExtendLowI32x4U
12460            | Operator::I64x2ExtendLowI32x4S
12461            | Operator::I64x2ExtendHighI32x4U
12462            | Operator::I64x2ExtendHighI32x4S
12463            | Operator::I8x16NarrowI16x8S
12464            | Operator::I8x16NarrowI16x8U
12465            | Operator::I16x8NarrowI32x4S
12466            | Operator::I16x8NarrowI32x4U
12467            | Operator::I32x4RelaxedTruncF32x4S
12468            | Operator::I32x4TruncSatF32x4S
12469            | Operator::I32x4RelaxedTruncF32x4U
12470            | Operator::I32x4TruncSatF32x4U
12471            | Operator::I32x4RelaxedTruncF64x2SZero
12472            | Operator::I32x4RelaxedTruncF64x2UZero
12473            | Operator::I32x4TruncSatF64x2SZero
12474            | Operator::I32x4TruncSatF64x2UZero
12475            | Operator::I32TruncF32S
12476            | Operator::I32TruncF64S
12477            | Operator::I32TruncSatF32S
12478            | Operator::I32TruncSatF64S
12479            | Operator::I64TruncF32S
12480            | Operator::I64TruncF64S
12481            | Operator::I64TruncSatF32S
12482            | Operator::I64TruncSatF64S
12483            | Operator::I32TruncF32U
12484            | Operator::I32TruncF64U
12485            | Operator::I32TruncSatF32U
12486            | Operator::I32TruncSatF64U
12487            | Operator::I64TruncF32U
12488            | Operator::I64TruncF64U
12489            | Operator::I64TruncSatF32U
12490            | Operator::I64TruncSatF64U
12491            | Operator::F32DemoteF64
12492            | Operator::F64PromoteF32
12493            | Operator::F32ConvertI32S
12494            | Operator::F32ConvertI64S
12495            | Operator::F64ConvertI32S
12496            | Operator::F64ConvertI64S
12497            | Operator::F32ConvertI32U
12498            | Operator::F32ConvertI64U
12499            | Operator::F64ConvertI32U
12500            | Operator::F64ConvertI64U
12501            | Operator::F32x4ConvertI32x4S
12502            | Operator::F32x4ConvertI32x4U
12503            | Operator::F64x2ConvertLowI32x4S
12504            | Operator::F64x2ConvertLowI32x4U
12505            | Operator::F64x2PromoteLowF32x4
12506            | Operator::F32x4DemoteF64x2Zero
12507            | Operator::I32ReinterpretF32
12508            | Operator::I64ReinterpretF64
12509            | Operator::F32ReinterpretI32
12510            | Operator::F64ReinterpretI64 => self.translate_conversion_operator(op)?,
12511            Operator::I32Extend8S
12512            | Operator::I32Extend16S
12513            | Operator::I64Extend8S
12514            | Operator::I64Extend16S
12515            | Operator::I64Extend32S => self.translate_sign_extension_operator(op)?,
12516            Operator::I32Load { .. }
12517            | Operator::I64Load { .. }
12518            | Operator::F32Load { .. }
12519            | Operator::F64Load { .. }
12520            | Operator::V128Load { .. }
12521            | Operator::V128Load8Lane { .. }
12522            | Operator::V128Load16Lane { .. }
12523            | Operator::V128Load32Lane { .. }
12524            | Operator::V128Load64Lane { .. }
12525            | Operator::I32Store { .. }
12526            | Operator::I64Store { .. }
12527            | Operator::F32Store { .. }
12528            | Operator::F64Store { .. }
12529            | Operator::V128Store { .. }
12530            | Operator::V128Store8Lane { .. }
12531            | Operator::V128Store16Lane { .. }
12532            | Operator::V128Store32Lane { .. }
12533            | Operator::V128Store64Lane { .. }
12534            | Operator::I32Load8S { .. }
12535            | Operator::I32Load16S { .. }
12536            | Operator::I64Load8S { .. }
12537            | Operator::I64Load16S { .. }
12538            | Operator::I64Load32S { .. }
12539            | Operator::I32Load8U { .. }
12540            | Operator::I32Load16U { .. }
12541            | Operator::I64Load8U { .. }
12542            | Operator::I64Load16U { .. }
12543            | Operator::I64Load32U { .. }
12544            | Operator::I32Store8 { .. }
12545            | Operator::I64Store8 { .. }
12546            | Operator::I32Store16 { .. }
12547            | Operator::I64Store16 { .. }
12548            | Operator::I64Store32 { .. }
12549            | Operator::I8x16Neg
12550            | Operator::I16x8Neg
12551            | Operator::I32x4Neg
12552            | Operator::I64x2Neg
12553            | Operator::V128Not
12554            | Operator::V128AnyTrue
12555            | Operator::I8x16AllTrue
12556            | Operator::I16x8AllTrue
12557            | Operator::I32x4AllTrue
12558            | Operator::I64x2AllTrue
12559            | Operator::I8x16ExtractLaneS { .. }
12560            | Operator::I8x16ExtractLaneU { .. }
12561            | Operator::I16x8ExtractLaneS { .. }
12562            | Operator::I16x8ExtractLaneU { .. }
12563            | Operator::I32x4ExtractLane { .. }
12564            | Operator::I64x2ExtractLane { .. }
12565            | Operator::F32x4ExtractLane { .. }
12566            | Operator::F64x2ExtractLane { .. }
12567            | Operator::I8x16ReplaceLane { .. }
12568            | Operator::I16x8ReplaceLane { .. }
12569            | Operator::I32x4ReplaceLane { .. }
12570            | Operator::I64x2ReplaceLane { .. }
12571            | Operator::F32x4ReplaceLane { .. }
12572            | Operator::F64x2ReplaceLane { .. }
12573            | Operator::I8x16RelaxedSwizzle
12574            | Operator::I8x16Swizzle
12575            | Operator::I8x16Shuffle { .. }
12576            | Operator::V128Load8x8S { .. }
12577            | Operator::V128Load8x8U { .. }
12578            | Operator::V128Load16x4S { .. }
12579            | Operator::V128Load16x4U { .. }
12580            | Operator::V128Load32x2S { .. }
12581            | Operator::V128Load32x2U { .. }
12582            | Operator::V128Load32Zero { .. }
12583            | Operator::V128Load64Zero { .. }
12584            | Operator::V128Load8Splat { .. }
12585            | Operator::V128Load16Splat { .. }
12586            | Operator::V128Load32Splat { .. }
12587            | Operator::V128Load64Splat { .. }
12588            | Operator::MemoryGrow { .. }
12589            | Operator::MemorySize { .. }
12590            | Operator::MemoryInit { .. }
12591            | Operator::DataDrop { .. }
12592            | Operator::MemoryCopy { .. }
12593            | Operator::MemoryFill { .. } => self.translate_memory_operator(op)?,
12594            Operator::AtomicFence { .. }
12595            | Operator::I32AtomicLoad { .. }
12596            | Operator::I64AtomicLoad { .. }
12597            | Operator::I32AtomicLoad8U { .. }
12598            | Operator::I32AtomicLoad16U { .. }
12599            | Operator::I64AtomicLoad8U { .. }
12600            | Operator::I64AtomicLoad16U { .. }
12601            | Operator::I64AtomicLoad32U { .. }
12602            | Operator::I32AtomicStore { .. }
12603            | Operator::I64AtomicStore { .. }
12604            | Operator::I32AtomicStore8 { .. }
12605            | Operator::I64AtomicStore8 { .. }
12606            | Operator::I32AtomicStore16 { .. }
12607            | Operator::I64AtomicStore16 { .. }
12608            | Operator::I64AtomicStore32 { .. }
12609            | Operator::I32AtomicRmw8AddU { .. }
12610            | Operator::I32AtomicRmw16AddU { .. }
12611            | Operator::I32AtomicRmwAdd { .. }
12612            | Operator::I64AtomicRmw8AddU { .. }
12613            | Operator::I64AtomicRmw16AddU { .. }
12614            | Operator::I64AtomicRmw32AddU { .. }
12615            | Operator::I64AtomicRmwAdd { .. }
12616            | Operator::I32AtomicRmw8SubU { .. }
12617            | Operator::I32AtomicRmw16SubU { .. }
12618            | Operator::I32AtomicRmwSub { .. }
12619            | Operator::I64AtomicRmw8SubU { .. }
12620            | Operator::I64AtomicRmw16SubU { .. }
12621            | Operator::I64AtomicRmw32SubU { .. }
12622            | Operator::I64AtomicRmwSub { .. }
12623            | Operator::I32AtomicRmw8AndU { .. }
12624            | Operator::I32AtomicRmw16AndU { .. }
12625            | Operator::I32AtomicRmwAnd { .. }
12626            | Operator::I64AtomicRmw8AndU { .. }
12627            | Operator::I64AtomicRmw16AndU { .. }
12628            | Operator::I64AtomicRmw32AndU { .. }
12629            | Operator::I64AtomicRmwAnd { .. }
12630            | Operator::I32AtomicRmw8OrU { .. }
12631            | Operator::I32AtomicRmw16OrU { .. }
12632            | Operator::I32AtomicRmwOr { .. }
12633            | Operator::I64AtomicRmw8OrU { .. }
12634            | Operator::I64AtomicRmw16OrU { .. }
12635            | Operator::I64AtomicRmw32OrU { .. }
12636            | Operator::I64AtomicRmwOr { .. }
12637            | Operator::I32AtomicRmw8XorU { .. }
12638            | Operator::I32AtomicRmw16XorU { .. }
12639            | Operator::I32AtomicRmwXor { .. }
12640            | Operator::I64AtomicRmw8XorU { .. }
12641            | Operator::I64AtomicRmw16XorU { .. }
12642            | Operator::I64AtomicRmw32XorU { .. }
12643            | Operator::I64AtomicRmwXor { .. }
12644            | Operator::I32AtomicRmw8XchgU { .. }
12645            | Operator::I32AtomicRmw16XchgU { .. }
12646            | Operator::I32AtomicRmwXchg { .. }
12647            | Operator::I64AtomicRmw8XchgU { .. }
12648            | Operator::I64AtomicRmw16XchgU { .. }
12649            | Operator::I64AtomicRmw32XchgU { .. }
12650            | Operator::I64AtomicRmwXchg { .. }
12651            | Operator::I32AtomicRmw8CmpxchgU { .. }
12652            | Operator::I32AtomicRmw16CmpxchgU { .. }
12653            | Operator::I32AtomicRmwCmpxchg { .. }
12654            | Operator::I64AtomicRmw8CmpxchgU { .. }
12655            | Operator::I64AtomicRmw16CmpxchgU { .. }
12656            | Operator::I64AtomicRmw32CmpxchgU { .. }
12657            | Operator::I64AtomicRmwCmpxchg { .. }
12658            | Operator::MemoryAtomicWait32 { .. }
12659            | Operator::MemoryAtomicWait64 { .. }
12660            | Operator::MemoryAtomicNotify { .. } => self.translate_atomic_memory_operator(op)?,
12661            Operator::RefNull { .. } | Operator::RefIsNull | Operator::RefFunc { .. } => {
12662                self.translate_reference_operator(op)?;
12663            }
12664            Operator::TableGet { .. }
12665            | Operator::TableSet { .. }
12666            | Operator::TableCopy { .. }
12667            | Operator::TableInit { .. }
12668            | Operator::ElemDrop { .. }
12669            | Operator::TableFill { .. }
12670            | Operator::TableGrow { .. }
12671            | Operator::TableSize { .. } => self.translate_table_operator(op)?,
12672            Operator::TryTable { .. } | Operator::Throw { .. } | Operator::ThrowRef => {
12673                self.translate_eh_operator(op)?;
12674            }
12675            _ => {
12676                return Err(CompileError::Codegen(format!(
12677                    "Operator {op:?} unimplemented",
12678                )));
12679            }
12680        }
12681
12682        Ok(())
12683    }
12684
12685    fn build_call_with_param_attributes(
12686        &self,
12687        function: FunctionValue<'ctx>,
12688        args: &[BasicMetadataValueEnum<'ctx>],
12689        name: &str,
12690    ) -> Result<CallSiteValue<'ctx>, CompileError> {
12691        let call = self
12692            .builder
12693            .build_call(function, args, name)
12694            .map_err(|e| CompileError::Codegen(e.to_string()))?;
12695
12696        // https://five-embeddev.com/riscv-user-isa-manual/Priv-v1.12/rv64.html
12697        // > The compiler and calling convention maintain an invariant that all 32-bit values are held in a sign-extended format in 64-bit registers.
12698        // > Even 32-bit unsigned integers extend bit 31 into bits 63 through 32. Consequently, conversion between unsigned and signed 32-bit integers
12699        // > is a no-op, as is conversion from a signed 32-bit integer to a signed 64-bit integer.
12700        if matches!(
12701            self.target_triple.architecture,
12702            Architecture::Riscv32(..) | Architecture::Riscv64(..)
12703        ) {
12704            let param_types = function.get_type().get_param_types();
12705            for (i, ty) in param_types.into_iter().enumerate() {
12706                if ty == self.context.i32_type().into() {
12707                    call.add_attribute(
12708                        AttributeLoc::Param(i as u32),
12709                        self.context
12710                            .create_enum_attribute(Attribute::get_named_enum_kind_id("signext"), 0),
12711                    );
12712                    call.add_attribute(
12713                        AttributeLoc::Param(i as u32),
12714                        self.context
12715                            .create_enum_attribute(Attribute::get_named_enum_kind_id("noundef"), 0),
12716                    );
12717                }
12718            }
12719        }
12720
12721        Ok(call)
12722    }
12723}
12724
12725fn is_f32_arithmetic(bits: u32) -> bool {
12726    // Mask off sign bit.
12727    let bits = bits & 0x7FFF_FFFF;
12728    bits < 0x7FC0_0000
12729}
12730
12731fn is_f64_arithmetic(bits: u64) -> bool {
12732    // Mask off sign bit.
12733    let bits = bits & 0x7FFF_FFFF_FFFF_FFFF;
12734    bits < 0x7FF8_0000_0000_0000
12735}