wasmer_compiler_llvm/translator/
code.rs

1use std::collections::HashMap;
2use std::num::NonZero;
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::{compiler::ModuleBasedSymbolRegistry, config::OptimizationStyle};
12use enumset::EnumSet;
13use inkwell::{
14    AddressSpace, AtomicOrdering, AtomicRMWBinOp, DLLStorageClass, FloatPredicate, IntPredicate,
15    attributes::{Attribute, AttributeLoc},
16    builder::Builder,
17    context::Context,
18    module::{Linkage, Module},
19    passes::PassBuilderOptions,
20    targets::{FileType, TargetData, TargetMachine},
21    types::{BasicType, BasicTypeEnum, FloatMathType, IntType, PointerType, VectorType},
22    values::{
23        BasicMetadataValueEnum, BasicValue, BasicValueEnum, CallSiteValue, FloatValue,
24        FunctionValue, InstructionOpcode, InstructionValue, IntValue, LLVMTailCallKind, PhiValue,
25        PointerValue, VectorValue,
26    },
27};
28use itertools::Itertools;
29use smallvec::SmallVec;
30use target_lexicon::{Architecture, BinaryFormat, OperatingSystem, Triple};
31use wasmer_compiler::WASM_LARGE_FUNCTION_THRESHOLD;
32
33use crate::{
34    abi::{Abi, get_abi},
35    config::LLVM,
36    error::{err, err_nt},
37    object_file::{CompiledFunction, load_object_file},
38};
39use wasmer_compiler::{
40    CANONICAL_NAN_F32, CANONICAL_NAN_F64, FunctionBinaryReader, FunctionBodyData,
41    GEF32_LEQ_I32_MAX, GEF32_LEQ_I64_MAX, GEF32_LEQ_U32_MAX, GEF32_LEQ_U64_MAX, GEF64_LEQ_I32_MAX,
42    GEF64_LEQ_I64_MAX, GEF64_LEQ_U32_MAX, GEF64_LEQ_U64_MAX, LEF32_GEQ_I32_MIN, LEF32_GEQ_I64_MIN,
43    LEF32_GEQ_U32_MIN, LEF32_GEQ_U64_MIN, LEF64_GEQ_I32_MIN, LEF64_GEQ_I64_MIN, LEF64_GEQ_U32_MIN,
44    LEF64_GEQ_U64_MIN, MiddlewareBinaryReader, ModuleMiddlewareChain, ModuleTranslationState,
45    from_binaryreadererror_wasmerror,
46    misc::CompiledKind,
47    types::{
48        relocation::RelocationTarget,
49        symbols::{Symbol, SymbolRegistry},
50    },
51    wasmparser::{Catch, MemArg, Operator},
52    wpheaptype_to_type, wptype_to_type,
53};
54use wasmer_types::{
55    CompileError, FunctionIndex, FunctionType, GlobalIndex, LocalFunctionIndex, MemoryIndex,
56    ModuleInfo, SignatureHash, SignatureIndex, TableIndex, Type, target::CpuFeature,
57};
58use wasmer_types::{TagIndex, entity::PrimaryMap};
59use wasmer_vm::{MemoryStyle, TableStyle, VMOffsets};
60
61const FUNCTION_SECTION_ELF: &str = "__TEXT,wasmer_function";
62const FUNCTION_SECTION_MACHO: &str = "__TEXT";
63const FUNCTION_SEGMENT_MACHO: &str = "wasmer_function";
64
65// Since we want to use module-local tag numbers for landing pads,
66// the catch-all tag can't be zero; we instead use i32::MAX, which
67// is hopefully large enough to not conflict with any real tag.
68// If you have 2 billion tags in a single module, you deserve what you get.
69// ( Arshia: that comment above is AI-generated... AI is savage XD )
70const CATCH_ALL_TAG_VALUE: i32 = i32::MAX;
71
72pub struct FuncTranslator {
73    ctx: Context,
74    target_triple: Triple,
75    target_machines: HashMap<OptimizationStyle, TargetMachine>,
76    abi: Box<dyn Abi>,
77    binary_fmt: BinaryFormat,
78    func_section: String,
79    pointer_width: u8,
80    cpu_features: EnumSet<CpuFeature>,
81    non_volatile_memory_ops: bool,
82    wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
83}
84
85impl wasmer_compiler::FuncTranslator for FuncTranslator {}
86
87impl FuncTranslator {
88    pub fn new(
89        target_triple: Triple,
90        target_machines: HashMap<OptimizationStyle, TargetMachine>,
91        binary_fmt: BinaryFormat,
92        pointer_width: u8,
93        cpu_features: EnumSet<CpuFeature>,
94        non_volatile_memory_ops: bool,
95        wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
96    ) -> Result<Self, CompileError> {
97        let abi_source_tm = target_machines
98            .get(&OptimizationStyle::ForSpeed)
99            .expect("target_machines must contain OptimizationStyle::ForSpeed");
100        let abi = get_abi(abi_source_tm);
101        Ok(Self {
102            ctx: Context::create(),
103            target_triple,
104            target_machines,
105            abi,
106            func_section: match binary_fmt {
107                BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
108                BinaryFormat::Macho => FUNCTION_SEGMENT_MACHO.to_string(),
109                _ => {
110                    return Err(CompileError::UnsupportedTarget(format!(
111                        "Unsupported binary format: {binary_fmt:?}"
112                    )));
113                }
114            },
115            binary_fmt,
116            pointer_width,
117            cpu_features,
118            non_volatile_memory_ops,
119            wasm_apply_data_relocs_fn_index,
120        })
121    }
122
123    #[allow(clippy::too_many_arguments)]
124    pub fn translate_to_module(
125        &self,
126        wasm_module: &ModuleInfo,
127        module_translation: &ModuleTranslationState,
128        signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
129        local_func_index: &LocalFunctionIndex,
130        function_body: &FunctionBodyData,
131        config: &LLVM,
132        memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
133        _table_styles: &PrimaryMap<TableIndex, TableStyle>,
134        symbol_registry: &dyn SymbolRegistry,
135        target: &Triple,
136        opt_style: OptimizationStyle,
137    ) -> Result<Module<'_>, CompileError> {
138        // The function type, used for the callbacks.
139        let func_index = wasm_module.func_index(*local_func_index);
140        let function =
141            CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
142        let function_name =
143            symbol_registry.symbol_to_name(Symbol::LocalFunction(*local_func_index));
144
145        // We can pass and use the heap pointer (memory #0) only and only if the memory static, that means
146        // the allocated heap is never moved to a different location.
147        let m0_is_enabled = memory_styles
148            .get(MemoryIndex::from_u32(0))
149            .is_some_and(|memory| matches!(memory, MemoryStyle::Static { .. }));
150
151        let module_name = match wasm_module.name.as_ref() {
152            None => format!("<anonymous module> function {function_name}"),
153            Some(module_name) => format!("module {module_name} function {function_name}"),
154        };
155        let module = self.ctx.create_module(module_name.as_str());
156
157        let target_machine = &self.target_machines.values().next().unwrap();
158        let target_triple = target_machine.get_triple();
159        let target_data = target_machine.get_target_data();
160        module.set_triple(&target_triple);
161        module.set_data_layout(&target_data.get_data_layout());
162        let wasm_fn_type = wasm_module
163            .signatures
164            .get(wasm_module.functions[func_index])
165            .unwrap();
166
167        let offsets = VMOffsets::new(self.pointer_width, wasm_module);
168        let intrinsics = Intrinsics::declare(
169            &module,
170            &self.ctx,
171            &target_data,
172            &self.target_triple,
173            &self.binary_fmt,
174        );
175        let (func_type, func_attrs) = self.abi.func_type_to_llvm(
176            &self.ctx,
177            &intrinsics,
178            Some(&offsets),
179            wasm_fn_type,
180            m0_is_enabled,
181        )?;
182
183        let func = module.add_function(&function_name, func_type, Some(Linkage::External));
184        for (attr, attr_loc) in &func_attrs {
185            func.add_attribute(*attr_loc, *attr);
186        }
187
188        if !matches!(target.operating_system, OperatingSystem::Windows) {
189            func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe);
190        }
191
192        func.add_attribute(AttributeLoc::Function, intrinsics.uwtable);
193        func.add_attribute(AttributeLoc::Function, intrinsics.frame_pointer);
194
195        let section = match self.binary_fmt {
196            BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
197            BinaryFormat::Macho => {
198                format!("{FUNCTION_SECTION_MACHO},{FUNCTION_SEGMENT_MACHO}")
199            }
200            _ => {
201                return Err(CompileError::UnsupportedTarget(format!(
202                    "Unsupported binary format: {:?}",
203                    self.binary_fmt
204                )));
205            }
206        };
207
208        func.set_personality_function(intrinsics.personality);
209        func.as_global_value().set_section(Some(&section));
210
211        func.set_linkage(Linkage::DLLExport);
212        func.as_global_value()
213            .set_dll_storage_class(DLLStorageClass::Export);
214
215        let entry = self.ctx.append_basic_block(func, "entry");
216        let start_of_code = self.ctx.append_basic_block(func, "start_of_code");
217        let return_ = self.ctx.append_basic_block(func, "return");
218        let alloca_builder = self.ctx.create_builder();
219        let cache_builder = self.ctx.create_builder();
220        let builder = self.ctx.create_builder();
221        cache_builder.position_at_end(entry);
222        let br = err!(cache_builder.build_unconditional_branch(start_of_code));
223        alloca_builder.position_before(&br);
224        cache_builder.position_before(&br);
225        builder.position_at_end(start_of_code);
226
227        let mut state = State::new();
228        builder.position_at_end(return_);
229        let phis: SmallVec<[PhiValue; 1]> = wasm_fn_type
230            .results()
231            .iter()
232            .map(|&wasm_ty| {
233                type_to_llvm(&intrinsics, wasm_ty).map(|ty| builder.build_phi(ty, "").unwrap())
234            })
235            .collect::<Result<_, _>>()?;
236        state.push_block(return_, phis, 0);
237        builder.position_at_end(start_of_code);
238
239        let mut reader = MiddlewareBinaryReader::new_with_offset(
240            function_body.data,
241            function_body.module_offset,
242        );
243        reader.set_middleware_chain(
244            config
245                .middlewares
246                .generate_function_middleware_chain(*local_func_index),
247        );
248
249        let mut params = vec![];
250        let first_param =
251            if func_type.get_return_type().is_none() && wasm_fn_type.results().len() > 1 {
252                if m0_is_enabled { 3 } else { 2 }
253            } else if m0_is_enabled {
254                2
255            } else {
256                1
257            };
258        let mut is_first_alloca = true;
259        let mut insert_alloca = |ty, name: String| -> Result<PointerValue, CompileError> {
260            let alloca = err!(alloca_builder.build_alloca(ty, &name));
261            if is_first_alloca {
262                alloca_builder.position_at(entry, &alloca.as_instruction_value().unwrap());
263                is_first_alloca = false;
264            }
265            Ok(alloca)
266        };
267
268        // Uncomment to print, at the start of the function, the function name.
269        // (poor man's debugger!)
270        //let func_name_str =
271        //    err!(alloca_builder.build_global_string_ptr(&function_name, "function_name"));
272        //
273        //_ = alloca_builder.build_call(
274        //    intrinsics.debug_str,
275        //    &[
276        //        func_name_str.as_pointer_value().into(),
277        //        intrinsics
278        //            .i32_ty
279        //            .const_int(function_name.len() as _, false)
280        //            .into(),
281        //    ],
282        //    "",
283        //);
284
285        for idx in 0..wasm_fn_type.params().len() {
286            let ty = wasm_fn_type.params()[idx];
287            let ty = type_to_llvm(&intrinsics, ty)?;
288            let value = func
289                .get_nth_param((idx as u32).checked_add(first_param).unwrap())
290                .unwrap();
291            let alloca = insert_alloca(ty, format!("param_{idx}"))?;
292            err!(cache_builder.build_store(alloca, value));
293            params.push((ty, alloca));
294        }
295
296        let mut locals = vec![];
297        let num_locals = reader.read_local_count()?;
298        for idx in 0..num_locals {
299            let (count, ty) = reader.read_local_decl()?;
300            let ty = err!(wptype_to_type(ty));
301            let ty = type_to_llvm(&intrinsics, ty)?;
302            for _ in 0..count {
303                let alloca = insert_alloca(ty, format!("local_{idx}"))?;
304                err!(cache_builder.build_store(alloca, ty.const_zero()));
305                locals.push((ty, alloca));
306            }
307        }
308
309        let mut params_locals = params.clone();
310        params_locals.extend(locals.iter().cloned());
311
312        let mut m0_param = None;
313
314        if m0_is_enabled {
315            let m0 = self.abi.get_m0_ptr_param(&func);
316            m0.set_name("m0_base_ptr");
317            m0_param = Some(m0);
318        }
319
320        let mut fcg = LLVMFunctionCodeGenerator {
321            m0_param,
322            context: &self.ctx,
323            builder,
324            alloca_builder,
325            intrinsics: &intrinsics,
326            target_data: &target_data,
327            state,
328            function: func,
329            locals: params_locals,
330            ctx: CtxType::new(
331                wasm_module,
332                &func,
333                &cache_builder,
334                &*self.abi,
335                self.pointer_width,
336                m0_param,
337            ),
338            unreachable_depth: 0,
339            memory_styles,
340            _table_styles,
341            module: &module,
342            module_translation,
343            signature_hashes,
344            wasm_module,
345            symbol_registry,
346            abi: &*self.abi,
347            config,
348            target_triple: self.target_triple.clone(),
349            tags_cache: HashMap::new(),
350            binary_fmt: self.binary_fmt,
351            cpu_features: self.cpu_features,
352            non_volatile_memory_ops: self.non_volatile_memory_ops,
353        };
354
355        fcg.ctx.add_func(
356            func_index,
357            func.as_global_value().as_pointer_value(),
358            func_type,
359            fcg.ctx.basic(),
360            &func_attrs,
361        );
362
363        while fcg.state.has_control_frames() {
364            let pos = reader.current_position() as u32;
365            let op = reader.read_operator()?;
366            fcg.translate_operator(op, pos)?;
367        }
368
369        fcg.finalize(wasm_fn_type)?;
370
371        if let Some(ref callbacks) = config.callbacks {
372            callbacks.preopt_ir(&function, &wasm_module.hash_string(), &module);
373        }
374
375        let mut passes = vec![];
376        if config.enable_verifier {
377            passes.push("verify");
378        }
379
380        match opt_style {
381            OptimizationStyle::Disabled => {
382                passes.push("default<O0>");
383            }
384            OptimizationStyle::ForSize => {
385                // Apparently, the default<Os> could be much slower compared to -O1.
386                passes.push("default<O1>");
387            }
388            OptimizationStyle::ForSpeed => {
389                passes.push("sccp");
390                passes.push("early-cse");
391                //passes.push("deadargelim");
392                passes.push("adce");
393                passes.push("sroa");
394                passes.push("aggressive-instcombine");
395                passes.push("jump-threading");
396                //passes.push("ipsccp");
397                passes.push("simplifycfg");
398                passes.push("reassociate");
399                passes.push("loop-rotate");
400                passes.push("indvars");
401                //passes.push("lcssa");
402                //passes.push("licm");
403                //passes.push("instcombine");
404                passes.push("sccp");
405                passes.push("reassociate");
406                passes.push("simplifycfg");
407                passes.push("gvn");
408                passes.push("memcpyopt");
409                passes.push("dse");
410                passes.push("dce");
411                //passes.push("instcombine");
412                passes.push("reassociate");
413                passes.push("simplifycfg");
414                passes.push("mem2reg");
415            }
416        }
417
418        module
419            .run_passes(
420                &passes.join(","),
421                target_machine,
422                PassBuilderOptions::create(),
423            )
424            .unwrap();
425
426        if let Some(ref callbacks) = config.callbacks {
427            callbacks.postopt_ir(&function, &wasm_module.hash_string(), &module);
428        }
429
430        Ok(module)
431    }
432
433    #[allow(clippy::too_many_arguments)]
434    pub fn translate(
435        &self,
436        wasm_module: &ModuleInfo,
437        module_translation: &ModuleTranslationState,
438        signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
439        local_func_index: &LocalFunctionIndex,
440        function_body: &FunctionBodyData,
441        config: &LLVM,
442        memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
443        table_styles: &PrimaryMap<TableIndex, TableStyle>,
444        symbol_registry: &ModuleBasedSymbolRegistry,
445        target: &Triple,
446    ) -> Result<CompiledFunction, CompileError> {
447        let func_index = wasm_module.func_index(*local_func_index);
448        let opt_style = if Some(func_index) == self.wasm_apply_data_relocs_fn_index {
449            // `__wasm_apply_data_relocs` can become a very large function made up
450            // mostly of loads and stores, and even `-O1` can spend significant
451            // time optimizing it.
452            OptimizationStyle::Disabled
453        } else if function_body.data.len() as u64 > WASM_LARGE_FUNCTION_THRESHOLD {
454            OptimizationStyle::ForSize
455        } else {
456            OptimizationStyle::ForSpeed
457        };
458        let module = self.translate_to_module(
459            wasm_module,
460            module_translation,
461            signature_hashes,
462            local_func_index,
463            function_body,
464            config,
465            memory_styles,
466            table_styles,
467            symbol_registry,
468            target,
469            opt_style,
470        )?;
471        let function =
472            CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
473
474        let target_machine = self.target_machines.get(&opt_style).unwrap();
475        let memory_buffer = target_machine
476            .write_to_memory_buffer(&module, FileType::Object)
477            .unwrap();
478
479        if let Some(ref callbacks) = config.callbacks {
480            let module_hash = wasm_module.hash().map(|m| m.to_string());
481            callbacks.obj_memory_buffer(&function, &module_hash, &memory_buffer);
482            let asm_buffer = target_machine
483                .write_to_memory_buffer(&module, FileType::Assembly)
484                .unwrap();
485            callbacks.asm_memory_buffer(&function, &module_hash, &asm_buffer)
486        }
487
488        let mem_buf_slice = memory_buffer.as_slice();
489
490        load_object_file(
491            mem_buf_slice,
492            &self.func_section,
493            RelocationTarget::LocalFunc(*local_func_index),
494            |name: &str| {
495                Ok({
496                    let name = if matches!(self.binary_fmt, BinaryFormat::Macho) {
497                        name.strip_prefix("_").unwrap_or(name)
498                    } else {
499                        name
500                    }
501                    .to_string();
502                    if let Some(Symbol::LocalFunction(local_func_index)) =
503                        symbol_registry.name_to_symbol(&name)
504                    {
505                        Some(RelocationTarget::LocalFunc(local_func_index))
506                    } else {
507                        None
508                    }
509                })
510            },
511            self.binary_fmt,
512            &self.target_triple,
513        )
514    }
515}
516
517impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
518    // Create a vector where each lane contains the same value.
519    fn splat_vector(
520        &self,
521        value: BasicValueEnum<'ctx>,
522        vec_ty: VectorType<'ctx>,
523    ) -> Result<VectorValue<'ctx>, CompileError> {
524        // Use insert_element to insert the element into an undef vector, then use
525        // shuffle vector to copy that lane to all lanes.
526        err_nt!(
527            self.builder.build_shuffle_vector(
528                err!(self.builder.build_insert_element(
529                    vec_ty.get_undef(),
530                    value,
531                    self.intrinsics.i32_zero,
532                    "",
533                )),
534                vec_ty.get_undef(),
535                self.intrinsics
536                    .i32_ty
537                    .vec_type(vec_ty.get_size())
538                    .const_zero(),
539                "",
540            )
541        )
542    }
543
544    // Convert floating point vector to integer and saturate when out of range.
545    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
546    #[allow(clippy::too_many_arguments)]
547    fn trunc_sat<T: FloatMathType<'ctx>>(
548        &self,
549        fvec_ty: T,
550        ivec_ty: T::MathConvType,
551        lower_bound: u64, // Exclusive (least representable value)
552        upper_bound: u64, // Exclusive (greatest representable value)
553        int_min_value: u64,
554        int_max_value: u64,
555        value: IntValue<'ctx>,
556    ) -> Result<VectorValue<'ctx>, CompileError> {
557        // a) Compare vector with itself to identify NaN lanes.
558        // b) Compare vector with splat of inttofp(upper_bound) to identify
559        //    lanes that need to saturate to max.
560        // c) Compare vector with splat of inttofp(lower_bound) to identify
561        //    lanes that need to saturate to min.
562        // d) Use vector select (not shuffle) to pick from either the
563        //    splat vector or the input vector depending on whether the
564        //    comparison indicates that we have an unrepresentable value. Replace
565        //    unrepresentable values with zero.
566        // e) Now that the value is safe, fpto[su]i it.
567        // f) Use our previous comparison results to replace certain zeros with
568        //    int_min or int_max.
569
570        let fvec_ty = fvec_ty.as_basic_type_enum().into_vector_type();
571        let ivec_ty = ivec_ty.as_basic_type_enum().into_vector_type();
572        let fvec_element_ty = fvec_ty.get_element_type().into_float_type();
573        let ivec_element_ty = ivec_ty.get_element_type().into_int_type();
574
575        let is_signed = int_min_value != 0;
576        let int_min_value = self.splat_vector(
577            ivec_element_ty
578                .const_int(int_min_value, is_signed)
579                .as_basic_value_enum(),
580            ivec_ty,
581        )?;
582        let int_max_value = self.splat_vector(
583            ivec_element_ty
584                .const_int(int_max_value, is_signed)
585                .as_basic_value_enum(),
586            ivec_ty,
587        )?;
588        let lower_bound = if is_signed {
589            err!(self.builder.build_signed_int_to_float(
590                ivec_element_ty.const_int(lower_bound, is_signed),
591                fvec_element_ty,
592                "",
593            ))
594        } else {
595            err!(self.builder.build_unsigned_int_to_float(
596                ivec_element_ty.const_int(lower_bound, is_signed),
597                fvec_element_ty,
598                "",
599            ))
600        };
601        let upper_bound = if is_signed {
602            err!(self.builder.build_signed_int_to_float(
603                ivec_element_ty.const_int(upper_bound, is_signed),
604                fvec_element_ty,
605                "",
606            ))
607        } else {
608            err!(self.builder.build_unsigned_int_to_float(
609                ivec_element_ty.const_int(upper_bound, is_signed),
610                fvec_element_ty,
611                "",
612            ))
613        };
614
615        let value = err!(self.builder.build_bit_cast(value, fvec_ty, "")).into_vector_value();
616        let zero = fvec_ty.const_zero();
617        let lower_bound = self.splat_vector(lower_bound.as_basic_value_enum(), fvec_ty)?;
618        let upper_bound = self.splat_vector(upper_bound.as_basic_value_enum(), fvec_ty)?;
619        let nan_cmp =
620            err!(
621                self.builder
622                    .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
623            );
624        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
625            FloatPredicate::OGT,
626            value,
627            upper_bound,
628            "above_upper_bound",
629        ));
630        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
631            FloatPredicate::OLT,
632            value,
633            lower_bound,
634            "below_lower_bound",
635        ));
636        let not_representable = err!(self.builder.build_or(
637            err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
638            below_lower_bound_cmp,
639            "not_representable_as_int",
640        ));
641        let value =
642            err!(
643                self.builder
644                    .build_select(not_representable, zero, value, "safe_to_convert")
645            )
646            .into_vector_value();
647        let value = if is_signed {
648            self.builder
649                .build_float_to_signed_int(value, ivec_ty, "as_int")
650        } else {
651            self.builder
652                .build_float_to_unsigned_int(value, ivec_ty, "as_int")
653        };
654
655        let value = err!(value);
656        let value =
657            err!(
658                self.builder
659                    .build_select(above_upper_bound_cmp, int_max_value, value, "")
660            )
661            .into_vector_value();
662        err_nt!(
663            self.builder
664                .build_select(below_lower_bound_cmp, int_min_value, value, "")
665                .map(|v| v.into_vector_value())
666        )
667    }
668
669    // Convert floating point vector to integer and saturate when out of range.
670    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
671    #[allow(clippy::too_many_arguments)]
672    fn trunc_sat_into_int<T: FloatMathType<'ctx>>(
673        &self,
674        fvec_ty: T,
675        ivec_ty: T::MathConvType,
676        lower_bound: u64, // Exclusive (least representable value)
677        upper_bound: u64, // Exclusive (greatest representable value)
678        int_min_value: u64,
679        int_max_value: u64,
680        value: IntValue<'ctx>,
681    ) -> Result<IntValue<'ctx>, CompileError> {
682        let res = self.trunc_sat(
683            fvec_ty,
684            ivec_ty,
685            lower_bound,
686            upper_bound,
687            int_min_value,
688            int_max_value,
689            value,
690        )?;
691        err_nt!(
692            self.builder
693                .build_bit_cast(res, self.intrinsics.i128_ty, "")
694                .map(|v| v.into_int_value())
695        )
696    }
697
698    // Convert floating point vector to integer and saturate when out of range.
699    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
700    fn trunc_sat_scalar(
701        &self,
702        int_ty: IntType<'ctx>,
703        lower_bound: u64, // Exclusive (least representable value)
704        upper_bound: u64, // Exclusive (greatest representable value)
705        int_min_value: u64,
706        int_max_value: u64,
707        value: FloatValue<'ctx>,
708    ) -> Result<IntValue<'ctx>, CompileError> {
709        // TODO: this is a scalarized version of the process in trunc_sat. Either
710        // we should merge with trunc_sat, or we should simplify this function.
711
712        // a) Compare value with itself to identify NaN.
713        // b) Compare value inttofp(upper_bound) to identify values that need to
714        //    saturate to max.
715        // c) Compare value with inttofp(lower_bound) to identify values that need
716        //    to saturate to min.
717        // d) Use select to pick from either zero or the input vector depending on
718        //    whether the comparison indicates that we have an unrepresentable
719        //    value.
720        // e) Now that the value is safe, fpto[su]i it.
721        // f) Use our previous comparison results to replace certain zeros with
722        //    int_min or int_max.
723
724        let is_signed = int_min_value != 0;
725        let int_min_value = int_ty.const_int(int_min_value, is_signed);
726        let int_max_value = int_ty.const_int(int_max_value, is_signed);
727
728        let lower_bound = if is_signed {
729            err!(self.builder.build_signed_int_to_float(
730                int_ty.const_int(lower_bound, is_signed),
731                value.get_type(),
732                "",
733            ))
734        } else {
735            err!(self.builder.build_unsigned_int_to_float(
736                int_ty.const_int(lower_bound, is_signed),
737                value.get_type(),
738                "",
739            ))
740        };
741        let upper_bound = if is_signed {
742            err!(self.builder.build_signed_int_to_float(
743                int_ty.const_int(upper_bound, is_signed),
744                value.get_type(),
745                "",
746            ))
747        } else {
748            err!(self.builder.build_unsigned_int_to_float(
749                int_ty.const_int(upper_bound, is_signed),
750                value.get_type(),
751                "",
752            ))
753        };
754
755        let zero = value.get_type().const_zero();
756
757        let nan_cmp =
758            err!(
759                self.builder
760                    .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
761            );
762        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
763            FloatPredicate::OGT,
764            value,
765            upper_bound,
766            "above_upper_bound",
767        ));
768        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
769            FloatPredicate::OLT,
770            value,
771            lower_bound,
772            "below_lower_bound",
773        ));
774        let not_representable = err!(self.builder.build_or(
775            err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
776            below_lower_bound_cmp,
777            "not_representable_as_int",
778        ));
779        let value =
780            err!(
781                self.builder
782                    .build_select(not_representable, zero, value, "safe_to_convert")
783            )
784            .into_float_value();
785        let value = if is_signed {
786            err!(
787                self.builder
788                    .build_float_to_signed_int(value, int_ty, "as_int")
789            )
790        } else {
791            err!(
792                self.builder
793                    .build_float_to_unsigned_int(value, int_ty, "as_int")
794            )
795        };
796        let value =
797            err!(
798                self.builder
799                    .build_select(above_upper_bound_cmp, int_max_value, value, "")
800            )
801            .into_int_value();
802        let value =
803            err!(
804                self.builder
805                    .build_select(below_lower_bound_cmp, int_min_value, value, "")
806            )
807            .into_int_value();
808
809        err_nt!(
810            self.builder
811                .build_bit_cast(value, int_ty, "")
812                .map(|v| v.into_int_value())
813        )
814    }
815
816    fn trap_if_not_representable_as_int(
817        &self,
818        lower_bound: u64, // Inclusive (not a trapping value)
819        upper_bound: u64, // Inclusive (not a trapping value)
820        value: FloatValue<'ctx>,
821    ) -> Result<(), CompileError> {
822        let float_ty = value.get_type();
823        let int_ty = if float_ty == self.intrinsics.f32_ty {
824            self.intrinsics.i32_ty
825        } else {
826            self.intrinsics.i64_ty
827        };
828
829        let lower_bound = err!(self.builder.build_bit_cast(
830            int_ty.const_int(lower_bound, false),
831            float_ty,
832            ""
833        ))
834        .into_float_value();
835        let upper_bound = err!(self.builder.build_bit_cast(
836            int_ty.const_int(upper_bound, false),
837            float_ty,
838            ""
839        ))
840        .into_float_value();
841
842        // The 'U' in the float predicate is short for "unordered" which means that
843        // the comparison will compare true if either operand is a NaN. Thus, NaNs
844        // are out of bounds.
845        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
846            FloatPredicate::UGT,
847            value,
848            upper_bound,
849            "above_upper_bound",
850        ));
851        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
852            FloatPredicate::ULT,
853            value,
854            lower_bound,
855            "below_lower_bound",
856        ));
857        let out_of_bounds = err!(self.builder.build_or(
858            above_upper_bound_cmp,
859            below_lower_bound_cmp,
860            "out_of_bounds",
861        ));
862
863        let failure_block = self
864            .context
865            .append_basic_block(self.function, "conversion_failure_block");
866        let continue_block = self
867            .context
868            .append_basic_block(self.function, "conversion_success_block");
869
870        err!(
871            self.builder
872                .build_conditional_branch(out_of_bounds, failure_block, continue_block)
873        );
874        self.builder.position_at_end(failure_block);
875        let is_nan =
876            err!(
877                self.builder
878                    .build_float_compare(FloatPredicate::UNO, value, value, "is_nan")
879            );
880        let trap_code = err!(self.builder.build_select(
881            is_nan,
882            self.intrinsics.trap_bad_conversion_to_integer,
883            self.intrinsics.trap_illegal_arithmetic,
884            "",
885        ));
886        self.build_call_with_param_attributes(
887            self.intrinsics.throw_trap,
888            &[trap_code.into()],
889            "throw",
890        )?;
891        err!(self.builder.build_unreachable());
892        self.builder.position_at_end(continue_block);
893
894        Ok(())
895    }
896
897    fn trap_if_zero_or_overflow(
898        &self,
899        left: IntValue<'ctx>,
900        right: IntValue<'ctx>,
901    ) -> Result<(), CompileError> {
902        let int_type = left.get_type();
903
904        let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
905            let min_value = int_type.const_int(i32::MIN as u64, false);
906            let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
907            (min_value, neg_one_value)
908        } else if int_type == self.intrinsics.i64_ty {
909            let min_value = int_type.const_int(i64::MIN as u64, false);
910            let neg_one_value = int_type.const_int(-1i64 as u64, false);
911            (min_value, neg_one_value)
912        } else {
913            unreachable!()
914        };
915
916        let divisor_is_zero = err!(self.builder.build_int_compare(
917            IntPredicate::EQ,
918            right,
919            int_type.const_zero(),
920            "divisor_is_zero",
921        ));
922        let should_trap = err!(self.builder.build_or(
923            divisor_is_zero,
924            err!(self.builder.build_and(
925                err!(self.builder.build_int_compare(
926                    IntPredicate::EQ,
927                    left,
928                    min_value,
929                    "left_is_min"
930                )),
931                err!(self.builder.build_int_compare(
932                    IntPredicate::EQ,
933                    right,
934                    neg_one_value,
935                    "right_is_neg_one",
936                )),
937                "div_will_overflow",
938            )),
939            "div_should_trap",
940        ));
941
942        let should_trap = self
943            .build_call_with_param_attributes(
944                self.intrinsics.expect_i1,
945                &[
946                    should_trap.into(),
947                    self.intrinsics.i1_ty.const_zero().into(),
948                ],
949                "should_trap_expect",
950            )?
951            .try_as_basic_value()
952            .unwrap_basic()
953            .into_int_value();
954
955        let shouldnt_trap_block = self
956            .context
957            .append_basic_block(self.function, "shouldnt_trap_block");
958        let should_trap_block = self
959            .context
960            .append_basic_block(self.function, "should_trap_block");
961        err!(self.builder.build_conditional_branch(
962            should_trap,
963            should_trap_block,
964            shouldnt_trap_block
965        ));
966        self.builder.position_at_end(should_trap_block);
967        let trap_code = err!(self.builder.build_select(
968            divisor_is_zero,
969            self.intrinsics.trap_integer_division_by_zero,
970            self.intrinsics.trap_illegal_arithmetic,
971            "",
972        ));
973        err!(
974            self.builder
975                .build_call(self.intrinsics.throw_trap, &[trap_code.into()], "throw")
976        );
977        err!(self.builder.build_unreachable());
978        self.builder.position_at_end(shouldnt_trap_block);
979
980        Ok(())
981    }
982
983    fn trap_if_zero(&self, value: IntValue<'ctx>) -> Result<(), CompileError> {
984        let int_type = value.get_type();
985        let should_trap = err!(self.builder.build_int_compare(
986            IntPredicate::EQ,
987            value,
988            int_type.const_zero(),
989            "divisor_is_zero",
990        ));
991
992        let should_trap = self
993            .build_call_with_param_attributes(
994                self.intrinsics.expect_i1,
995                &[
996                    should_trap.into(),
997                    self.intrinsics.i1_ty.const_zero().into(),
998                ],
999                "should_trap_expect",
1000            )?
1001            .try_as_basic_value()
1002            .unwrap_basic()
1003            .into_int_value();
1004
1005        let shouldnt_trap_block = self
1006            .context
1007            .append_basic_block(self.function, "shouldnt_trap_block");
1008        let should_trap_block = self
1009            .context
1010            .append_basic_block(self.function, "should_trap_block");
1011        err!(self.builder.build_conditional_branch(
1012            should_trap,
1013            should_trap_block,
1014            shouldnt_trap_block
1015        ));
1016        self.builder.position_at_end(should_trap_block);
1017        self.build_call_with_param_attributes(
1018            self.intrinsics.throw_trap,
1019            &[self.intrinsics.trap_integer_division_by_zero.into()],
1020            "throw",
1021        )?;
1022        err!(self.builder.build_unreachable());
1023        self.builder.position_at_end(shouldnt_trap_block);
1024
1025        Ok(())
1026    }
1027
1028    fn v128_into_int_vec(
1029        &self,
1030        value: BasicValueEnum<'ctx>,
1031        info: ExtraInfo,
1032        int_vec_ty: VectorType<'ctx>,
1033    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1034        let (value, info) = if self.config.enable_nan_canonicalization {
1035            if info.has_pending_f32_nan() {
1036                let value = err!(
1037                    self.builder
1038                        .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1039                );
1040                (self.canonicalize_nans(value)?, info.strip_pending())
1041            } else if info.has_pending_f64_nan() {
1042                let value = err!(
1043                    self.builder
1044                        .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1045                );
1046                (self.canonicalize_nans(value)?, info.strip_pending())
1047            } else {
1048                (value, info)
1049            }
1050        } else {
1051            (value, info)
1052        };
1053        Ok((
1054            err!(self.builder.build_bit_cast(value, int_vec_ty, "")).into_vector_value(),
1055            info,
1056        ))
1057    }
1058
1059    fn v128_into_i8x16(
1060        &self,
1061        value: BasicValueEnum<'ctx>,
1062        info: ExtraInfo,
1063    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1064        self.v128_into_int_vec(value, info, self.intrinsics.i8x16_ty)
1065    }
1066
1067    fn v128_into_i16x8(
1068        &self,
1069        value: BasicValueEnum<'ctx>,
1070        info: ExtraInfo,
1071    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1072        self.v128_into_int_vec(value, info, self.intrinsics.i16x8_ty)
1073    }
1074
1075    fn v128_into_i32x4(
1076        &self,
1077        value: BasicValueEnum<'ctx>,
1078        info: ExtraInfo,
1079    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1080        self.v128_into_int_vec(value, info, self.intrinsics.i32x4_ty)
1081    }
1082
1083    fn v128_into_i64x2(
1084        &self,
1085        value: BasicValueEnum<'ctx>,
1086        info: ExtraInfo,
1087    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1088        self.v128_into_int_vec(value, info, self.intrinsics.i64x2_ty)
1089    }
1090
1091    // If the value is pending a 64-bit canonicalization, do it now.
1092    // Return a f32x4 vector.
1093    fn v128_into_f32x4(
1094        &self,
1095        value: BasicValueEnum<'ctx>,
1096        info: ExtraInfo,
1097    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1098        let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f64_nan()
1099        {
1100            let value = err!(
1101                self.builder
1102                    .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1103            );
1104            (self.canonicalize_nans(value)?, info.strip_pending())
1105        } else {
1106            (value, info)
1107        };
1108        Ok((
1109            err!(
1110                self.builder
1111                    .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1112            )
1113            .into_vector_value(),
1114            info,
1115        ))
1116    }
1117
1118    // If the value is pending a 32-bit canonicalization, do it now.
1119    // Return a f64x2 vector.
1120    fn v128_into_f64x2(
1121        &self,
1122        value: BasicValueEnum<'ctx>,
1123        info: ExtraInfo,
1124    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1125        let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f32_nan()
1126        {
1127            let value = err!(
1128                self.builder
1129                    .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1130            );
1131            (self.canonicalize_nans(value)?, info.strip_pending())
1132        } else {
1133            (value, info)
1134        };
1135        Ok((
1136            err!(
1137                self.builder
1138                    .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1139            )
1140            .into_vector_value(),
1141            info,
1142        ))
1143    }
1144
1145    fn apply_pending_canonicalization(
1146        &self,
1147        value: BasicValueEnum<'ctx>,
1148        info: ExtraInfo,
1149    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1150        if !self.config.enable_nan_canonicalization {
1151            return Ok(value);
1152        }
1153
1154        if info.has_pending_f32_nan() {
1155            if value.get_type().is_vector_type()
1156                || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1157            {
1158                let ty = value.get_type();
1159                let value = err!(
1160                    self.builder
1161                        .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1162                );
1163                let value = self.canonicalize_nans(value)?;
1164                err_nt!(self.builder.build_bit_cast(value, ty, ""))
1165            } else {
1166                self.canonicalize_nans(value)
1167            }
1168        } else if info.has_pending_f64_nan() {
1169            if value.get_type().is_vector_type()
1170                || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1171            {
1172                let ty = value.get_type();
1173                let value = err!(
1174                    self.builder
1175                        .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1176                );
1177                let value = self.canonicalize_nans(value)?;
1178                err_nt!(self.builder.build_bit_cast(value, ty, ""))
1179            } else {
1180                self.canonicalize_nans(value)
1181            }
1182        } else {
1183            Ok(value)
1184        }
1185    }
1186
1187    // Replaces any NaN with the canonical QNaN, otherwise leaves the value alone.
1188    fn canonicalize_nans(
1189        &self,
1190        value: BasicValueEnum<'ctx>,
1191    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1192        if !self.config.enable_nan_canonicalization {
1193            return Ok(value);
1194        }
1195
1196        let f_ty = value.get_type();
1197        if f_ty.is_vector_type() {
1198            let value = value.into_vector_value();
1199            let f_ty = f_ty.into_vector_type();
1200            let zero = f_ty.const_zero();
1201            let nan_cmp =
1202                err!(
1203                    self.builder
1204                        .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1205                );
1206            let canonical_qnan = f_ty
1207                .get_element_type()
1208                .into_float_type()
1209                .const_float(f64::NAN);
1210            let canonical_qnan = self.splat_vector(canonical_qnan.as_basic_value_enum(), f_ty)?;
1211            err_nt!(
1212                self.builder
1213                    .build_select(nan_cmp, canonical_qnan, value, "")
1214                    .map(|v| v.as_basic_value_enum())
1215            )
1216        } else {
1217            let value = value.into_float_value();
1218            let f_ty = f_ty.into_float_type();
1219            let zero = f_ty.const_zero();
1220            let nan_cmp =
1221                err!(
1222                    self.builder
1223                        .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1224                );
1225            let canonical_qnan = f_ty.const_float(f64::NAN);
1226            err_nt!(
1227                self.builder
1228                    .build_select(nan_cmp, canonical_qnan, value, "")
1229                    .map(|v| v.as_basic_value_enum())
1230            )
1231        }
1232    }
1233
1234    fn annotate_user_memaccess(
1235        &mut self,
1236        memory_index: MemoryIndex,
1237        _memarg: &MemArg,
1238        alignment: u32,
1239        memaccess: InstructionValue<'ctx>,
1240    ) -> Result<(), CompileError> {
1241        match memaccess.get_opcode() {
1242            InstructionOpcode::Load | InstructionOpcode::Store => {
1243                memaccess.set_alignment(alignment).unwrap();
1244            }
1245            _ => {}
1246        };
1247        if !self.non_volatile_memory_ops {
1248            // If this memory access must trap when out of bounds (i.e. it is a memory
1249            // access written in the user program as opposed to one used by our VM)
1250            // then mark that it can't be deleted.
1251            if let MemoryCache::Static { base_ptr: _ } = self.ctx.memory(
1252                memory_index,
1253                self.intrinsics,
1254                self.module,
1255                self.memory_styles,
1256            )? {
1257                // The best we've got is `volatile`.
1258                memaccess.set_volatile(true).map_err(|err| {
1259                    CompileError::Codegen(format!(
1260                        "could not set volatile on memory operation: {err}"
1261                    ))
1262                })?;
1263            }
1264        }
1265        tbaa_label(
1266            self.module,
1267            self.intrinsics,
1268            format!("memory {}", memory_index.as_u32()),
1269            memaccess,
1270        );
1271        Ok(())
1272    }
1273
1274    fn build_annotated_load<T: BasicType<'ctx>>(
1275        &mut self,
1276        pointee_ty: T,
1277        offset: IntValue<'ctx>,
1278        memarg: &MemArg,
1279        alignment: u32,
1280    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1281        let memory_index = MemoryIndex::from_u32(memarg.memory);
1282        let pointee_size = usize::try_from(self.target_data.get_store_size(&pointee_ty))
1283            .map_err(|_| CompileError::Codegen("pointee type size does not fit in usize".into()))?;
1284        let effective_address = self.resolve_memory_ptr(
1285            memory_index,
1286            memarg,
1287            self.intrinsics.ptr_ty,
1288            offset,
1289            pointee_size,
1290        )?;
1291        let result = err!(self.builder.build_load(pointee_ty, effective_address, ""));
1292        self.annotate_user_memaccess(
1293            MemoryIndex::from_u32(memarg.memory),
1294            memarg,
1295            alignment,
1296            result.as_instruction_value().unwrap(),
1297        )?;
1298        Ok(result)
1299    }
1300
1301    fn build_annotated_atomic_load(
1302        &mut self,
1303        outer_ty: IntType<'ctx>,
1304        inner_ty: IntType<'ctx>,
1305        offset: IntValue<'ctx>,
1306        memarg: &MemArg,
1307    ) -> Result<IntValue<'ctx>, CompileError> {
1308        let alignment = 2u32.pow(memarg.align as u32);
1309        let memory_index = MemoryIndex::from_u32(memarg.memory);
1310        let inner_size =
1311            usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1312                CompileError::Codegen("atomic inner type size does not fit in usize".into())
1313            })?;
1314        let outer_size =
1315            usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1316                CompileError::Codegen("atomic outer type size does not fit in usize".into())
1317            })?;
1318
1319        let effective_address = self.resolve_memory_ptr(
1320            memory_index,
1321            memarg,
1322            self.intrinsics.ptr_ty,
1323            offset,
1324            inner_size,
1325        )?;
1326        self.trap_if_misaligned(
1327            memarg,
1328            effective_address,
1329            u8::try_from(inner_size).map_err(|_| {
1330                CompileError::Codegen("atomic inner type size does not fit in u8".into())
1331            })?,
1332        )?;
1333
1334        let result = err!(
1335            self.builder
1336                .build_load(inner_ty, effective_address, "atomic_load")
1337        );
1338        let load = result.into_int_value();
1339        let load_inst = load.as_instruction_value().unwrap();
1340        self.annotate_user_memaccess(memory_index, memarg, alignment, load_inst)?;
1341        load_inst
1342            .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
1343            .unwrap();
1344
1345        if inner_size < outer_size {
1346            Ok(err_nt!(
1347                self.builder.build_int_z_extend(load, outer_ty, "")
1348            )?)
1349        } else {
1350            Ok(load)
1351        }
1352    }
1353
1354    fn build_annotated_store<T: BasicType<'ctx>>(
1355        &mut self,
1356        pointee_ty: T,
1357        offset: IntValue<'ctx>,
1358        value: BasicValueEnum<'ctx>,
1359        memarg: &MemArg,
1360        alignment: u32,
1361    ) -> Result<(), CompileError> {
1362        let memory_index = MemoryIndex::from_u32(memarg.memory);
1363        let pointee_size = usize::try_from(self.target_data.get_store_size(&pointee_ty))
1364            .map_err(|_| CompileError::Codegen("pointee type size does not fit in usize".into()))?;
1365        let effective_address = self.resolve_memory_ptr(
1366            memory_index,
1367            memarg,
1368            self.intrinsics.ptr_ty,
1369            offset,
1370            pointee_size,
1371        )?;
1372
1373        // Build a dead load (if non-volatile memory operations are disabled) to preserve
1374        // artifacts from partial store operations.
1375        if !self.non_volatile_memory_ops {
1376            self.build_annotated_load(pointee_ty, offset, memarg, alignment)?;
1377        }
1378
1379        let store = err!(self.builder.build_store(effective_address, value));
1380        self.annotate_user_memaccess(memory_index, memarg, alignment, store)
1381    }
1382
1383    fn build_annotated_atomic_store(
1384        &mut self,
1385        outer_ty: IntType<'ctx>,
1386        inner_ty: IntType<'ctx>,
1387        offset: IntValue<'ctx>,
1388        value: IntValue<'ctx>,
1389        memarg: &MemArg,
1390    ) -> Result<(), CompileError> {
1391        let alignment = 2u32.pow(memarg.align as u32);
1392        let memory_index = MemoryIndex::from_u32(memarg.memory);
1393        let inner_size =
1394            usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1395                CompileError::Codegen("atomic inner type size does not fit in usize".into())
1396            })?;
1397        let outer_size =
1398            usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1399                CompileError::Codegen("atomic outer type size does not fit in usize".into())
1400            })?;
1401
1402        let effective_address = self.resolve_memory_ptr(
1403            memory_index,
1404            memarg,
1405            self.intrinsics.ptr_ty,
1406            offset,
1407            inner_size,
1408        )?;
1409        self.trap_if_misaligned(
1410            memarg,
1411            effective_address,
1412            u8::try_from(inner_size).map_err(|_| {
1413                CompileError::Codegen("atomic inner type size does not fit in u8".into())
1414            })?,
1415        )?;
1416
1417        let value = if inner_size < outer_size {
1418            err!(self.builder.build_int_truncate(value, inner_ty, ""))
1419        } else {
1420            value
1421        };
1422        let store = err!(self.builder.build_store(effective_address, value));
1423        self.annotate_user_memaccess(memory_index, memarg, alignment, store)?;
1424        store
1425            .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
1426            .unwrap();
1427        Ok(())
1428    }
1429
1430    fn build_annotated_atomic_rmw(
1431        &mut self,
1432        outer_ty: IntType<'ctx>,
1433        inner_ty: IntType<'ctx>,
1434        offset: IntValue<'ctx>,
1435        value: IntValue<'ctx>,
1436        memarg: &MemArg,
1437        op: AtomicRMWBinOp,
1438    ) -> Result<IntValue<'ctx>, CompileError> {
1439        let alignment = 2u32.pow(memarg.align as u32);
1440        let memory_index = MemoryIndex::from_u32(memarg.memory);
1441        let inner_size =
1442            usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1443                CompileError::Codegen("atomic inner type size does not fit in usize".into())
1444            })?;
1445        let outer_size =
1446            usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1447                CompileError::Codegen("atomic outer type size does not fit in usize".into())
1448            })?;
1449
1450        let effective_address = self.resolve_memory_ptr(
1451            memory_index,
1452            memarg,
1453            self.intrinsics.ptr_ty,
1454            offset,
1455            inner_size,
1456        )?;
1457        self.trap_if_misaligned(
1458            memarg,
1459            effective_address,
1460            u8::try_from(inner_size).map_err(|_| {
1461                CompileError::Codegen("atomic inner type size does not fit in u8".into())
1462            })?,
1463        )?;
1464        let value = if inner_size < outer_size {
1465            err!(self.builder.build_int_truncate(value, inner_ty, ""))
1466        } else {
1467            value
1468        };
1469        let old = self
1470            .builder
1471            .build_atomicrmw(
1472                op,
1473                effective_address,
1474                value,
1475                AtomicOrdering::SequentiallyConsistent,
1476            )
1477            .unwrap();
1478        self.annotate_user_memaccess(
1479            memory_index,
1480            memarg,
1481            alignment,
1482            old.as_instruction_value().unwrap(),
1483        )?;
1484
1485        let value = if inner_size < outer_size {
1486            err!(self.builder.build_int_z_extend(old, outer_ty, ""))
1487        } else {
1488            old
1489        };
1490        Ok(value)
1491    }
1492
1493    fn build_annotated_atomic_rmw_cmpxchg(
1494        &mut self,
1495        outer_ty: IntType<'ctx>,
1496        inner_ty: IntType<'ctx>,
1497        offset: IntValue<'ctx>,
1498        cmp: IntValue<'ctx>,
1499        new: IntValue<'ctx>,
1500        memarg: &MemArg,
1501    ) -> Result<IntValue<'ctx>, CompileError> {
1502        let alignment = 2u32.pow(memarg.align as u32);
1503        let memory_index = MemoryIndex::from_u32(memarg.memory);
1504        let inner_size =
1505            usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1506                CompileError::Codegen("atomic inner type size does not fit in usize".into())
1507            })?;
1508        let outer_size =
1509            usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1510                CompileError::Codegen("atomic outer type size does not fit in usize".into())
1511            })?;
1512
1513        let effective_address = self.resolve_memory_ptr(
1514            memory_index,
1515            memarg,
1516            self.intrinsics.ptr_ty,
1517            offset,
1518            inner_size,
1519        )?;
1520        self.trap_if_misaligned(
1521            memarg,
1522            effective_address,
1523            u8::try_from(inner_size).map_err(|_| {
1524                CompileError::Codegen("atomic inner type size does not fit in u8".into())
1525            })?,
1526        )?;
1527        let (cmp, new) = if inner_size < outer_size {
1528            (
1529                err!(self.builder.build_int_truncate(cmp, inner_ty, "")),
1530                err!(self.builder.build_int_truncate(new, inner_ty, "")),
1531            )
1532        } else {
1533            (cmp, new)
1534        };
1535        let old = self
1536            .builder
1537            .build_cmpxchg(
1538                effective_address,
1539                cmp,
1540                new,
1541                AtomicOrdering::SequentiallyConsistent,
1542                AtomicOrdering::SequentiallyConsistent,
1543            )
1544            .unwrap();
1545        self.annotate_user_memaccess(
1546            memory_index,
1547            memarg,
1548            alignment,
1549            old.as_instruction_value().unwrap(),
1550        )?;
1551        let old = self
1552            .builder
1553            .build_extract_value(old, 0, "")
1554            .unwrap()
1555            .into_int_value();
1556
1557        let value = if inner_size < outer_size {
1558            err!(self.builder.build_int_z_extend(old, outer_ty, ""))
1559        } else {
1560            old
1561        };
1562        Ok(value)
1563    }
1564
1565    fn translate_atomic_rmw(
1566        &mut self,
1567        outer_ty: IntType<'ctx>,
1568        inner_ty: IntType<'ctx>,
1569        memarg: &MemArg,
1570        op: AtomicRMWBinOp,
1571        extra_info: Option<ExtraInfo>,
1572    ) -> Result<(), CompileError> {
1573        let value = self.state.pop1()?.into_int_value();
1574        let offset = self.state.pop1()?.into_int_value();
1575        let old = self.build_annotated_atomic_rmw(outer_ty, inner_ty, offset, value, memarg, op)?;
1576        if let Some(extra_info) = extra_info {
1577            self.state.push1_extra(old, extra_info);
1578        } else {
1579            self.state.push1(old);
1580        }
1581        Ok(())
1582    }
1583
1584    fn translate_atomic_rmw_cmpxchg(
1585        &mut self,
1586        outer_ty: IntType<'ctx>,
1587        inner_ty: IntType<'ctx>,
1588        memarg: &MemArg,
1589        extra_info: Option<ExtraInfo>,
1590    ) -> Result<(), CompileError> {
1591        let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
1592        let cmp = self
1593            .apply_pending_canonicalization(cmp, cmp_info)?
1594            .into_int_value();
1595        let new = self
1596            .apply_pending_canonicalization(new, new_info)?
1597            .into_int_value();
1598        let offset = self.state.pop1()?.into_int_value();
1599        let old =
1600            self.build_annotated_atomic_rmw_cmpxchg(outer_ty, inner_ty, offset, cmp, new, memarg)?;
1601        if let Some(extra_info) = extra_info {
1602            self.state.push1_extra(old, extra_info);
1603        } else {
1604            self.state.push1(old);
1605        }
1606        Ok(())
1607    }
1608
1609    fn resolve_memory_ptr(
1610        &mut self,
1611        memory_index: MemoryIndex,
1612        memarg: &MemArg,
1613        ptr_ty: PointerType<'ctx>,
1614        var_offset: IntValue<'ctx>,
1615        value_size: usize,
1616    ) -> Result<PointerValue<'ctx>, CompileError> {
1617        let builder = &self.builder;
1618        let intrinsics = &self.intrinsics;
1619        let context = &self.context;
1620        let function = &self.function;
1621
1622        // Compute the offset into the storage.
1623        let imm_offset = intrinsics.i64_ty.const_int(memarg.offset, false);
1624        let var_offset = err!(builder.build_int_z_extend(var_offset, intrinsics.i64_ty, ""));
1625        let offset = err!(builder.build_int_add(var_offset, imm_offset, ""));
1626
1627        // Look up the memory base (as pointer) and bounds (as unsigned integer).
1628        let base_ptr = if let Some(m0) = self.m0_param {
1629            m0
1630        } else {
1631            match self
1632                .ctx
1633                .memory(memory_index, intrinsics, self.module, self.memory_styles)?
1634            {
1635                MemoryCache::Dynamic {
1636                    ptr_to_base_ptr,
1637                    ptr_to_current_length,
1638                } => {
1639                    // Bounds check it.
1640                    let minimum = self.wasm_module.memories[memory_index].minimum;
1641                    let value_size_v = intrinsics.i64_ty.const_int(value_size as u64, false);
1642                    let ptr_in_bounds = if offset.is_const() {
1643                        // When the offset is constant, if it's below the minimum
1644                        // memory size, we've statically shown that it's safe.
1645                        let load_offset_end =
1646                            offset.const_add(value_size_v).get_zero_extended_constant();
1647                        if load_offset_end.is_some_and(|load_offset_end| {
1648                            load_offset_end <= minimum.bytes().0 as u64
1649                        }) {
1650                            Some(intrinsics.i64_ty.const_int(1, false))
1651                        } else {
1652                            None
1653                        }
1654                    } else {
1655                        None
1656                    };
1657
1658                    let ptr_in_bounds = match ptr_in_bounds {
1659                        Some(ptr) => ptr,
1660                        None => {
1661                            let load_offset_end = err!(builder.build_int_add(
1662                                offset,
1663                                value_size_v,
1664                                "load_offset_end"
1665                            ));
1666
1667                            let current_length = err!(builder.build_load(
1668                                self.intrinsics.i32_ty,
1669                                ptr_to_current_length,
1670                                "current_length"
1671                            ))
1672                            .into_int_value();
1673                            tbaa_label(
1674                                self.module,
1675                                self.intrinsics,
1676                                format!("memory {} length", memory_index.as_u32()),
1677                                current_length.as_instruction_value().unwrap(),
1678                            );
1679                            let current_length = err!(builder.build_int_z_extend(
1680                                current_length,
1681                                intrinsics.i64_ty,
1682                                "current_length_zextd"
1683                            ));
1684
1685                            err!(builder.build_int_compare(
1686                                IntPredicate::ULE,
1687                                load_offset_end,
1688                                current_length,
1689                                "ptr_in_bounds",
1690                            ))
1691                        }
1692                    };
1693
1694                    if !ptr_in_bounds.is_constant_int()
1695                        || ptr_in_bounds.get_zero_extended_constant().unwrap() != 1
1696                    {
1697                        // LLVM may have folded this into 'i1 true' in which case we know
1698                        // the pointer is in bounds. LLVM may also have folded it into a
1699                        // constant expression, not known to be either true or false yet.
1700                        // If it's false, unknown-but-constant, or not-a-constant, emit a
1701                        // runtime bounds check. LLVM may yet succeed at optimizing it away.
1702                        let ptr_in_bounds = err!(self.build_call_with_param_attributes(
1703                            intrinsics.expect_i1,
1704                            &[
1705                                ptr_in_bounds.into(),
1706                                intrinsics.i1_ty.const_int(1, true).into(),
1707                            ],
1708                            "ptr_in_bounds_expect",
1709                        ))
1710                        .try_as_basic_value()
1711                        .unwrap_basic()
1712                        .into_int_value();
1713
1714                        let in_bounds_continue_block =
1715                            context.append_basic_block(*function, "in_bounds_continue_block");
1716                        let not_in_bounds_block =
1717                            context.append_basic_block(*function, "not_in_bounds_block");
1718                        err!(builder.build_conditional_branch(
1719                            ptr_in_bounds,
1720                            in_bounds_continue_block,
1721                            not_in_bounds_block,
1722                        ));
1723                        builder.position_at_end(not_in_bounds_block);
1724                        err!(self.build_call_with_param_attributes(
1725                            intrinsics.throw_trap,
1726                            &[intrinsics.trap_memory_oob.into()],
1727                            "throw",
1728                        ));
1729                        err!(builder.build_unreachable());
1730                        builder.position_at_end(in_bounds_continue_block);
1731                    }
1732                    let ptr_to_base =
1733                        err!(builder.build_load(intrinsics.ptr_ty, ptr_to_base_ptr, "ptr_to_base"))
1734                            .into_pointer_value();
1735                    tbaa_label(
1736                        self.module,
1737                        self.intrinsics,
1738                        format!("memory base_ptr {}", memory_index.as_u32()),
1739                        ptr_to_base.as_instruction_value().unwrap(),
1740                    );
1741                    ptr_to_base
1742                }
1743                MemoryCache::Static { base_ptr } => base_ptr,
1744            }
1745        };
1746        let value_ptr = unsafe {
1747            err!(builder.build_gep(self.intrinsics.i8_ty, base_ptr, &[offset], "mem_value_ptr"))
1748        };
1749        err_nt!(
1750            builder
1751                .build_bit_cast(value_ptr, ptr_ty, "mem_value")
1752                .map(|v| v.into_pointer_value())
1753        )
1754    }
1755
1756    fn trap_if_misaligned(
1757        &self,
1758        _memarg: &MemArg,
1759        ptr: PointerValue<'ctx>,
1760        align: u8,
1761    ) -> Result<(), CompileError> {
1762        if align <= 1 {
1763            return Ok(());
1764        }
1765        let value = err!(self.builder.build_ptr_to_int(
1766            ptr,
1767            self.intrinsics.i64_ty,
1768            "mischeck_value"
1769        ));
1770        let and = err!(self.builder.build_and(
1771            value,
1772            self.intrinsics.i64_ty.const_int((align - 1).into(), false),
1773            "misaligncheck",
1774        ));
1775        let aligned = err!(self.builder.build_int_compare(
1776            IntPredicate::EQ,
1777            and,
1778            self.intrinsics.i64_zero,
1779            "is_aligned"
1780        ));
1781        let aligned = self
1782            .build_call_with_param_attributes(
1783                self.intrinsics.expect_i1,
1784                &[
1785                    aligned.into(),
1786                    self.intrinsics.i1_ty.const_int(1, false).into(),
1787                ],
1788                "is_aligned_expect",
1789            )?
1790            .try_as_basic_value()
1791            .unwrap_basic()
1792            .into_int_value();
1793
1794        let continue_block = self
1795            .context
1796            .append_basic_block(self.function, "aligned_access_continue_block");
1797        let not_aligned_block = self
1798            .context
1799            .append_basic_block(self.function, "misaligned_trap_block");
1800        err!(
1801            self.builder
1802                .build_conditional_branch(aligned, continue_block, not_aligned_block)
1803        );
1804
1805        self.builder.position_at_end(not_aligned_block);
1806        self.build_call_with_param_attributes(
1807            self.intrinsics.throw_trap,
1808            &[self.intrinsics.trap_unaligned_atomic.into()],
1809            "throw",
1810        )?;
1811        err!(self.builder.build_unreachable());
1812
1813        self.builder.position_at_end(continue_block);
1814        Ok(())
1815    }
1816
1817    fn finalize(&mut self, wasm_fn_type: &FunctionType) -> Result<(), CompileError> {
1818        let func_type = self.function.get_type();
1819
1820        let results = self.state.popn_save_extra(wasm_fn_type.results().len())?;
1821        let results = err!(
1822            results
1823                .into_iter()
1824                .map(|(v, i)| self.apply_pending_canonicalization(v, i))
1825                .collect::<Result<Vec<_>, _>>()
1826        );
1827
1828        if wasm_fn_type.results().is_empty() {
1829            err!(self.builder.build_return(None));
1830        } else if self.abi.is_sret(wasm_fn_type)? {
1831            let sret = self
1832                .function
1833                .get_first_param()
1834                .unwrap()
1835                .into_pointer_value();
1836            let llvm_params: Vec<_> = wasm_fn_type
1837                .results()
1838                .iter()
1839                .map(|x| type_to_llvm(self.intrinsics, *x).unwrap())
1840                .collect();
1841            let mut struct_value = self
1842                .context
1843                .struct_type(llvm_params.as_slice(), false)
1844                .get_undef();
1845            for (idx, value) in results.into_iter().enumerate() {
1846                let value = err!(self.builder.build_bit_cast(
1847                    value,
1848                    type_to_llvm(self.intrinsics, wasm_fn_type.results()[idx])?,
1849                    "",
1850                ));
1851                struct_value =
1852                    err!(
1853                        self.builder
1854                            .build_insert_value(struct_value, value, idx as u32, "")
1855                    )
1856                    .into_struct_value();
1857            }
1858            err!(self.builder.build_store(sret, struct_value));
1859            err!(self.builder.build_return(None));
1860        } else {
1861            err!(
1862                self.builder
1863                    .build_return(Some(&self.abi.pack_values_for_register_return(
1864                        self.intrinsics,
1865                        &self.builder,
1866                        &results,
1867                        &func_type,
1868                    )?))
1869            );
1870        }
1871        Ok(())
1872    }
1873
1874    // Generates a global constant with the tag's module-local index, which can be used
1875    // as the "type info" of a catch clause.
1876    fn get_or_insert_tag_type_info_global(&mut self, tag: i32) -> BasicValueEnum<'ctx> {
1877        if let Some(tag) = self.tags_cache.get(&tag) {
1878            return *tag;
1879        }
1880
1881        let tag_ty = self
1882            .context
1883            .struct_type(&[self.intrinsics.i32_ty.into()], false);
1884        let tag_glbl = self.module.add_global(
1885            tag_ty,
1886            Some(AddressSpace::default()),
1887            &format!("__wasmer_eh_type_info_{tag}"),
1888        );
1889        tag_glbl.set_initializer(
1890            &tag_ty
1891                .const_named_struct(&[self.intrinsics.i32_ty.const_int(tag as _, false).into()])
1892                .as_basic_value_enum(),
1893        );
1894
1895        tag_glbl.set_linkage(Linkage::External);
1896        tag_glbl.set_constant(true);
1897        // Why set this to a specific section? On macOS it would land on a specific read only data
1898        // section. GOT-based relocations will probably be generated with a non-zero addend, making
1899        // some EH-related intricacies not working.
1900        //
1901        // The general idea is that each tag has its own section, so the GOT-based relocation can
1902        // have a zero addend, i.e. the data of the tag is the first (and only) value in a specific
1903        // section we can target in relocations.
1904        if matches!(self.binary_fmt, target_lexicon::BinaryFormat::Macho) {
1905            tag_glbl.set_section(Some(&format!("{FUNCTION_SECTION_MACHO},_eh_ti_{tag}")));
1906        }
1907
1908        let tag_glbl = tag_glbl.as_basic_value_enum();
1909
1910        self.tags_cache.insert(tag, tag_glbl);
1911        tag_glbl
1912    }
1913
1914    fn emit_return_call(
1915        &mut self,
1916        call_site: CallSiteValue<'ctx>,
1917        callee_llvm_func_type: inkwell::types::FunctionType<'ctx>,
1918    ) -> Result<(), CompileError> {
1919        // This is an unintuitive spec corner case: a tail call must bypass all enclosing
1920        // try_table blocks in the function. See https://github.com/WebAssembly/exception-handling/issues/249.
1921        //
1922        // The LLVM MustTail is more restrictive than the one defined in the WebAssembly spec.
1923        // WebAssembly types alone are not enough here: the lowered ABI can add hidden arguments
1924        // like `m0` and `sret`, so we must compare the actual LLVM function types instead.
1925        let tail_call_kind = if self.function.get_type() == callee_llvm_func_type {
1926            LLVMTailCallKind::LLVMTailCallKindMustTail
1927        } else {
1928            LLVMTailCallKind::LLVMTailCallKindTail
1929        };
1930        call_site.set_tail_call_kind(tail_call_kind);
1931
1932        if self.function.get_type().get_return_type().is_none() {
1933            err!(self.builder.build_return(None));
1934        } else {
1935            let ret = call_site.try_as_basic_value();
1936            if ret.is_instruction() {
1937                return Err(CompileError::Codegen(
1938                    "return_call expected a non-void call result".to_string(),
1939                ));
1940            }
1941            err!(self.builder.build_return(Some(&ret.unwrap_basic())));
1942        }
1943        Ok(())
1944    }
1945
1946    // Return sret pointer if the functions needs the hidden argument for multiple return values.
1947    fn current_sret_ptr(&self, func_type: &FunctionType) -> Option<PointerValue<'ctx>> {
1948        self.abi.is_sret(func_type).ok().map(|_| {
1949            self.function
1950                .get_first_param()
1951                .unwrap()
1952                .into_pointer_value()
1953        })
1954    }
1955
1956    fn build_m0_indirect_call(
1957        &mut self,
1958        table_index: u32,
1959        ctx_ptr: PointerValue<'ctx>,
1960        func_type: &FunctionType,
1961        func_ptr: PointerValue<'ctx>,
1962        func_index: IntValue<'ctx>,
1963        is_return_call: bool,
1964    ) -> Result<(), CompileError> {
1965        let Some(m0) = self.m0_param else {
1966            return Err(CompileError::Codegen(
1967                "Call to build_m0_indirect_call without m0 parameter!".to_string(),
1968            ));
1969        };
1970
1971        let params = self.state.popn_save_extra(func_type.params().len())?;
1972
1973        let mut local_func_indices = vec![];
1974        let mut foreign_func_indices = vec![];
1975
1976        for t in &self.wasm_module.table_initializers {
1977            if t.table_index.as_u32() == table_index {
1978                for (func_in_table_idx, func_idx) in t.elements.iter().enumerate() {
1979                    if self.wasm_module.local_func_index(*func_idx).is_some() {
1980                        local_func_indices.push(func_in_table_idx)
1981                    } else {
1982                        foreign_func_indices.push(func_in_table_idx)
1983                    }
1984                }
1985                break;
1986            }
1987        }
1988
1989        let needs_switch = self.m0_param.is_some()
1990            && !local_func_indices.is_empty()
1991            && !foreign_func_indices.is_empty();
1992
1993        if needs_switch {
1994            let foreign_idx_block = self
1995                .context
1996                .append_basic_block(self.function, "foreign_call_block");
1997            let local_idx_block = self
1998                .context
1999                .append_basic_block(self.function, "local_call_block");
2000            let unreachable_indirect_call_branch_block = self
2001                .context
2002                .append_basic_block(self.function, "unreachable_indirect_call_branch");
2003
2004            let cont =
2005                (!is_return_call).then(|| self.context.append_basic_block(self.function, "cont"));
2006
2007            err!(
2008                self.builder.build_switch(
2009                    func_index,
2010                    unreachable_indirect_call_branch_block,
2011                    &local_func_indices
2012                        .into_iter()
2013                        .map(|v| (
2014                            self.intrinsics.i32_ty.const_int(v as _, false),
2015                            local_idx_block
2016                        ))
2017                        .chain(foreign_func_indices.into_iter().map(|v| (
2018                            self.intrinsics.i32_ty.const_int(v as _, false),
2019                            foreign_idx_block
2020                        )))
2021                        .collect::<Vec<_>>()
2022                )
2023            );
2024
2025            self.builder
2026                .position_at_end(unreachable_indirect_call_branch_block);
2027            err!(self.builder.build_unreachable());
2028
2029            //let current_block = self.builder.get_insert_block().unwrap();
2030            self.builder.position_at_end(local_idx_block);
2031            let (local_call_site, local_llvm_func_type) = self.build_indirect_call_with_params(
2032                ctx_ptr,
2033                func_type,
2034                func_ptr,
2035                Some(m0),
2036                is_return_call,
2037                &params,
2038            )?;
2039
2040            let local_rets = if is_return_call {
2041                self.emit_return_call(local_call_site, local_llvm_func_type)?;
2042                Vec::new()
2043            } else {
2044                let rets = self.abi.rets_from_call(
2045                    &self.builder,
2046                    self.intrinsics,
2047                    local_call_site,
2048                    func_type,
2049                )?;
2050                err!(
2051                    self.builder
2052                        .build_unconditional_branch(cont.expect("non-return call requires cont"))
2053                );
2054                rets
2055            };
2056
2057            self.builder.position_at_end(foreign_idx_block);
2058            let (foreign_call_site, foreign_llvm_func_type) = self
2059                .build_indirect_call_with_params(
2060                    ctx_ptr,
2061                    func_type,
2062                    func_ptr,
2063                    None,
2064                    is_return_call,
2065                    &params,
2066                )?;
2067
2068            let foreign_rets = if is_return_call {
2069                self.emit_return_call(foreign_call_site, foreign_llvm_func_type)?;
2070                Vec::new()
2071            } else {
2072                let rets = self.abi.rets_from_call(
2073                    &self.builder,
2074                    self.intrinsics,
2075                    foreign_call_site,
2076                    func_type,
2077                )?;
2078                err!(
2079                    self.builder
2080                        .build_unconditional_branch(cont.expect("non-return call requires cont"))
2081                );
2082                rets
2083            };
2084
2085            if is_return_call {
2086                return Ok(());
2087            }
2088
2089            self.builder
2090                .position_at_end(cont.expect("non-return call requires cont"));
2091
2092            for i in 0..foreign_rets.len() {
2093                let f_i = foreign_rets[i];
2094                let l_i = local_rets[i];
2095                let ty = f_i.get_type();
2096                let v = err!(self.builder.build_phi(ty, ""));
2097                v.add_incoming(&[(&f_i, foreign_idx_block), (&l_i, local_idx_block)]);
2098                self.state.push1(v.as_basic_value());
2099            }
2100        } else if foreign_func_indices.is_empty() {
2101            let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
2102                ctx_ptr,
2103                func_type,
2104                func_ptr,
2105                Some(m0),
2106                is_return_call,
2107                &params,
2108            )?;
2109
2110            if is_return_call {
2111                self.emit_return_call(call_site, llvm_func_type)?;
2112            } else {
2113                self.abi
2114                    .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2115                    .iter()
2116                    .for_each(|ret| self.state.push1(*ret));
2117            }
2118        } else {
2119            let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
2120                ctx_ptr,
2121                func_type,
2122                func_ptr,
2123                None,
2124                is_return_call,
2125                &params,
2126            )?;
2127            if is_return_call {
2128                self.emit_return_call(call_site, llvm_func_type)?;
2129            } else {
2130                self.abi
2131                    .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2132                    .iter()
2133                    .for_each(|ret| self.state.push1(*ret));
2134            }
2135        }
2136
2137        Ok(())
2138    }
2139
2140    fn build_indirect_call(
2141        &mut self,
2142        ctx_ptr: PointerValue<'ctx>,
2143        func_type: &FunctionType,
2144        func_ptr: PointerValue<'ctx>,
2145        m0_param: Option<PointerValue<'ctx>>,
2146        is_return_call: bool,
2147    ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
2148        let params = self.state.popn_save_extra(func_type.params().len())?;
2149        self.build_indirect_call_with_params(
2150            ctx_ptr,
2151            func_type,
2152            func_ptr,
2153            m0_param,
2154            is_return_call,
2155            &params,
2156        )
2157    }
2158
2159    fn build_indirect_call_with_params(
2160        &mut self,
2161        ctx_ptr: PointerValue<'ctx>,
2162        func_type: &FunctionType,
2163        func_ptr: PointerValue<'ctx>,
2164        m0_param: Option<PointerValue<'ctx>>,
2165        is_return_call: bool,
2166        params: &[(BasicValueEnum<'ctx>, ExtraInfo)],
2167    ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
2168        let (llvm_func_type, llvm_func_attrs) = self.abi.func_type_to_llvm(
2169            self.context,
2170            self.intrinsics,
2171            Some(self.ctx.get_offsets()),
2172            func_type,
2173            m0_param.is_some(),
2174        )?;
2175
2176        // Apply pending canonicalization.
2177        let params = params
2178            .iter()
2179            .zip(func_type.params().iter())
2180            .map(|((v, info), wasm_ty)| match wasm_ty {
2181                Type::F32 => err_nt!(self.builder.build_bit_cast(
2182                    self.apply_pending_canonicalization(*v, *info)?,
2183                    self.intrinsics.f32_ty,
2184                    "",
2185                )),
2186                Type::F64 => err_nt!(self.builder.build_bit_cast(
2187                    self.apply_pending_canonicalization(*v, *info)?,
2188                    self.intrinsics.f64_ty,
2189                    "",
2190                )),
2191                Type::V128 => self.apply_pending_canonicalization(*v, *info),
2192                _ => Ok(*v),
2193            })
2194            .collect::<Result<Vec<_>, _>>()?;
2195
2196        let params = self.abi.args_to_call(
2197            &self.alloca_builder,
2198            func_type,
2199            &llvm_func_type,
2200            ctx_ptr,
2201            params.as_slice(),
2202            self.intrinsics,
2203            m0_param,
2204            is_return_call
2205                .then(|| self.current_sret_ptr(func_type))
2206                .flatten(),
2207        )?;
2208
2209        let typed_func_ptr = err!(self.builder.build_pointer_cast(
2210            func_ptr,
2211            self.context.ptr_type(AddressSpace::default()),
2212            "typed_func_ptr",
2213        ));
2214
2215        let call_site_local = self.build_indirect_call_or_invoke(
2216            llvm_func_type,
2217            typed_func_ptr,
2218            params.as_slice(),
2219            "then_block",
2220            is_return_call,
2221        )?;
2222        for (attr, attr_loc) in llvm_func_attrs {
2223            call_site_local.add_attribute(attr_loc, attr);
2224        }
2225
2226        Ok((call_site_local, llvm_func_type))
2227    }
2228
2229    fn build_indirect_call_or_invoke(
2230        &mut self,
2231        llvm_func_type: inkwell::types::FunctionType<'ctx>,
2232        func_ptr: PointerValue<'ctx>,
2233        params: &[BasicValueEnum<'ctx>],
2234        then_block_name: &str,
2235        is_return_call: bool,
2236    ) -> Result<CallSiteValue<'ctx>, CompileError> {
2237        // This is an unintuitive spec corner case: a tail call must bypass all enclosing
2238        // try_table blocks in the function. See https://github.com/WebAssembly/exception-handling/issues/249.
2239        if let Some(lpad) = self.state.get_innermost_landingpad()
2240            && !is_return_call
2241        {
2242            let then_block = self
2243                .context
2244                .append_basic_block(self.function, then_block_name);
2245
2246            let ret = err!(self.builder.build_indirect_invoke(
2247                llvm_func_type,
2248                func_ptr,
2249                params,
2250                then_block,
2251                lpad,
2252                "",
2253            ));
2254
2255            self.builder.position_at_end(then_block);
2256            Ok(ret)
2257        } else {
2258            let call_params = params
2259                .iter()
2260                .copied()
2261                .map(Into::into)
2262                .collect::<Vec<BasicMetadataValueEnum>>();
2263            Ok(err!(self.builder.build_indirect_call(
2264                llvm_func_type,
2265                func_ptr,
2266                call_params.as_slice(),
2267                ""
2268            )))
2269        }
2270    }
2271}
2272
2273pub struct LLVMFunctionCodeGenerator<'ctx, 'a> {
2274    m0_param: Option<PointerValue<'ctx>>,
2275    context: &'ctx Context,
2276    builder: Builder<'ctx>,
2277    alloca_builder: Builder<'ctx>,
2278    intrinsics: &'a Intrinsics<'ctx>,
2279    target_data: &'a TargetData,
2280    state: State<'ctx>,
2281    function: FunctionValue<'ctx>,
2282    locals: Vec<(BasicTypeEnum<'ctx>, PointerValue<'ctx>)>, // Contains params and locals
2283    ctx: CtxType<'ctx, 'a>,
2284    unreachable_depth: usize,
2285    memory_styles: &'a PrimaryMap<MemoryIndex, MemoryStyle>,
2286    _table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
2287    module: &'a Module<'ctx>,
2288    module_translation: &'a ModuleTranslationState,
2289    signature_hashes: &'a PrimaryMap<SignatureIndex, SignatureHash>,
2290    wasm_module: &'a ModuleInfo,
2291    symbol_registry: &'a dyn SymbolRegistry,
2292    abi: &'a dyn Abi,
2293    config: &'a LLVM,
2294    target_triple: Triple,
2295    tags_cache: HashMap<i32, BasicValueEnum<'ctx>>,
2296    binary_fmt: target_lexicon::BinaryFormat,
2297    cpu_features: EnumSet<CpuFeature>,
2298    non_volatile_memory_ops: bool,
2299}
2300
2301impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
2302    fn quiet_nan(&self, value: BasicValueEnum<'ctx>) -> Result<BasicValueEnum<'ctx>, CompileError> {
2303        let intrinsic = if value
2304            .get_type()
2305            .eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2306        {
2307            Some(self.intrinsics.add_f32)
2308        } else if value
2309            .get_type()
2310            .eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2311        {
2312            Some(self.intrinsics.add_f64)
2313        } else if value
2314            .get_type()
2315            .eq(&self.intrinsics.f32x4_ty.as_basic_type_enum())
2316        {
2317            Some(self.intrinsics.add_f32x4)
2318        } else if value
2319            .get_type()
2320            .eq(&self.intrinsics.f64x2_ty.as_basic_type_enum())
2321        {
2322            Some(self.intrinsics.add_f64x2)
2323        } else {
2324            None
2325        };
2326
2327        match intrinsic {
2328            Some(intrinsic) => err_nt!(
2329                self.builder
2330                    .build_call(
2331                        intrinsic,
2332                        &[
2333                            value.into(),
2334                            value.get_type().const_zero().into(),
2335                            self.intrinsics.fp_rounding_md,
2336                            self.intrinsics.fp_exception_md,
2337                        ],
2338                        "",
2339                    )
2340                    .map(|v| v.try_as_basic_value().unwrap_basic())
2341            ),
2342            None => Ok(value),
2343        }
2344    }
2345
2346    fn finalize_minmax_result(
2347        &self,
2348        value: BasicValueEnum<'ctx>,
2349    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
2350        let ty = value.get_type();
2351        if ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2352            || ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2353        {
2354            let value = value.into_float_value();
2355            let is_nan = err!(self.builder.build_float_compare(
2356                FloatPredicate::UNO,
2357                value,
2358                value,
2359                "res_is_nan"
2360            ));
2361            let quiet = self.quiet_nan(value.as_basic_value_enum())?;
2362            let result =
2363                err!(
2364                    self.builder
2365                        .build_select(is_nan, quiet, value.as_basic_value_enum(), "")
2366                );
2367            Ok(result.as_basic_value_enum())
2368        } else if ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum()) {
2369            let value = value.into_vector_value();
2370            let is_nan = self
2371                .build_call_with_param_attributes(
2372                    self.intrinsics.cmp_f32x4,
2373                    &[
2374                        value.into(),
2375                        value.into(),
2376                        self.intrinsics.fp_uno_md,
2377                        self.intrinsics.fp_exception_md,
2378                    ],
2379                    "",
2380                )?
2381                .try_as_basic_value()
2382                .unwrap_basic()
2383                .into_vector_value();
2384            let quiet = self
2385                .quiet_nan(value.as_basic_value_enum())?
2386                .into_vector_value();
2387            let result = err!(self.builder.build_select(
2388                is_nan,
2389                quiet.as_basic_value_enum(),
2390                value.as_basic_value_enum(),
2391                "",
2392            ));
2393            Ok(result.as_basic_value_enum())
2394        } else if ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum()) {
2395            let value = value.into_vector_value();
2396            let is_nan = self
2397                .build_call_with_param_attributes(
2398                    self.intrinsics.cmp_f64x2,
2399                    &[
2400                        value.into(),
2401                        value.into(),
2402                        self.intrinsics.fp_uno_md,
2403                        self.intrinsics.fp_exception_md,
2404                    ],
2405                    "",
2406                )?
2407                .try_as_basic_value()
2408                .unwrap_basic()
2409                .into_vector_value();
2410            let quiet = self
2411                .quiet_nan(value.as_basic_value_enum())?
2412                .into_vector_value();
2413            let result = err!(self.builder.build_select(
2414                is_nan,
2415                quiet.as_basic_value_enum(),
2416                value.as_basic_value_enum(),
2417                "",
2418            ));
2419            Ok(result.as_basic_value_enum())
2420        } else {
2421            Ok(value)
2422        }
2423    }
2424
2425    fn finalize_rounding_result(
2426        &self,
2427        value: BasicValueEnum<'ctx>,
2428        info: ExtraInfo,
2429    ) -> Result<(BasicValueEnum<'ctx>, ExtraInfo), CompileError> {
2430        let ty = value.get_type();
2431        let is_f32 = ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum());
2432        let is_f64 = ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum());
2433        let is_f32x4 = ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum());
2434        let is_f64x2 = ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum());
2435        debug_assert!(is_f32 || is_f64 || is_f32x4 || is_f64x2);
2436
2437        if matches!(
2438            self.target_triple.architecture,
2439            Architecture::Riscv32(..) | Architecture::Riscv64(..)
2440        ) {
2441            if is_f32 || is_f64 {
2442                let input = value.into_float_value();
2443                let is_nan = err!(self.builder.build_float_compare(
2444                    FloatPredicate::UNO,
2445                    input,
2446                    input,
2447                    "res_is_nan",
2448                ));
2449                let canonical_nan_bits = if is_f32 {
2450                    self.intrinsics
2451                        .i32_ty
2452                        .const_int(CANONICAL_NAN_F32 as _, false)
2453                } else {
2454                    self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false)
2455                };
2456                let canonical_nan = err!(self.builder.build_bit_cast(
2457                    canonical_nan_bits,
2458                    ty,
2459                    "canonical_nan",
2460                ));
2461                let res =
2462                    err!(
2463                        self.builder
2464                            .build_select(is_nan, canonical_nan, value, "canonical_nan",)
2465                    );
2466                Ok((res, info))
2467            } else if is_f32x4 {
2468                let value = value.into_vector_value();
2469                let is_nan = err!(self.builder.build_call(
2470                    self.intrinsics.cmp_f32x4,
2471                    &[
2472                        value.into(),
2473                        value.into(),
2474                        self.intrinsics.fp_uno_md,
2475                        self.intrinsics.fp_exception_md,
2476                    ],
2477                    "",
2478                ))
2479                .try_as_basic_value()
2480                .unwrap_basic()
2481                .into_vector_value();
2482                let canonical_nan_bits = self
2483                    .intrinsics
2484                    .i32_ty
2485                    .const_int(CANONICAL_NAN_F32 as _, false);
2486                let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 4]);
2487                let canonical_nan = err!(self.builder.build_bit_cast(
2488                    canonical_nan_bits,
2489                    self.intrinsics.f32x4_ty,
2490                    "canonical_nan",
2491                ));
2492                let res = err!(self.builder.build_select(
2493                    is_nan,
2494                    canonical_nan.as_basic_value_enum(),
2495                    value.as_basic_value_enum(),
2496                    "canonical_nan",
2497                ));
2498                Ok((res, info))
2499            } else {
2500                let value = value.into_vector_value();
2501                let is_nan = err!(self.builder.build_call(
2502                    self.intrinsics.cmp_f64x2,
2503                    &[
2504                        value.into(),
2505                        value.into(),
2506                        self.intrinsics.fp_uno_md,
2507                        self.intrinsics.fp_exception_md,
2508                    ],
2509                    "",
2510                ))
2511                .try_as_basic_value()
2512                .unwrap_basic()
2513                .into_vector_value();
2514                let canonical_nan_bits = self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false);
2515                let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 2]);
2516                let canonical_nan = err!(self.builder.build_bit_cast(
2517                    canonical_nan_bits,
2518                    self.intrinsics.f64x2_ty,
2519                    "canonical_nan",
2520                ));
2521                let res = err!(self.builder.build_select(
2522                    is_nan,
2523                    canonical_nan.as_basic_value_enum(),
2524                    value.as_basic_value_enum(),
2525                    "canonical_nan",
2526                ));
2527                Ok((res, info))
2528            }
2529        } else {
2530            Ok((
2531                value,
2532                (info
2533                    | if is_f32 || is_f32x4 {
2534                        ExtraInfo::pending_f32_nan()
2535                    } else {
2536                        ExtraInfo::pending_f64_nan()
2537                    })?,
2538            ))
2539        }
2540    }
2541
2542    // Control Flow instructions.
2543    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#control-flow-instructions
2544    fn translate_control_flow_operator(&mut self, op: Operator) -> Result<(), CompileError> {
2545        match op {
2546            Operator::Block { blockty } => {
2547                let current_block = self
2548                    .builder
2549                    .get_insert_block()
2550                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2551
2552                let end_block = self.context.append_basic_block(self.function, "end");
2553                self.builder.position_at_end(end_block);
2554
2555                let phis: SmallVec<[PhiValue<'ctx>; 1]> = self
2556                    .module_translation
2557                    .blocktype_params_results(&blockty)?
2558                    .1
2559                    .iter()
2560                    .map(|&wp_ty| {
2561                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2562                            type_to_llvm(self.intrinsics, wasm_ty)
2563                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2564                        })
2565                    })
2566                    .collect::<Result<_, _>>()?;
2567
2568                self.state.push_block(
2569                    end_block,
2570                    phis,
2571                    self.module_translation
2572                        .blocktype_params_results(&blockty)?
2573                        .0
2574                        .len(),
2575                );
2576                self.builder.position_at_end(current_block);
2577            }
2578            Operator::Loop { blockty } => {
2579                let loop_body = self.context.append_basic_block(self.function, "loop_body");
2580                let loop_next = self.context.append_basic_block(self.function, "loop_outer");
2581                let pre_loop_block = self.builder.get_insert_block().unwrap();
2582
2583                let blocktypes = self.module_translation.blocktype_params_results(&blockty)?;
2584
2585                self.builder.position_at_end(loop_next);
2586                let phis = blocktypes
2587                    .1
2588                    .iter()
2589                    .map(|&wp_ty| {
2590                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2591                            type_to_llvm(self.intrinsics, wasm_ty)
2592                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2593                        })
2594                    })
2595                    .collect::<Result<_, _>>()?;
2596                self.builder.position_at_end(loop_body);
2597                let loop_phis: SmallVec<[PhiValue<'ctx>; 1]> = blocktypes
2598                    .0
2599                    .iter()
2600                    .map(|&wp_ty| {
2601                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2602                            type_to_llvm(self.intrinsics, wasm_ty)
2603                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2604                        })
2605                    })
2606                    .collect::<Result<_, _>>()?;
2607
2608                // Pop the loop parameters and canonicalize them in
2609                // pre_loop_block (before the terminator is emitted) so that the
2610                // select instruction dominates the phi uses.
2611                self.builder.position_at_end(pre_loop_block);
2612                for phi in loop_phis.iter().rev() {
2613                    let (value, info) = self.state.pop1_extra()?;
2614                    let value = self.apply_pending_canonicalization(value, info)?;
2615                    phi.add_incoming(&[(&value, pre_loop_block)]);
2616                }
2617
2618                err!(self.builder.build_unconditional_branch(loop_body));
2619
2620                self.builder.position_at_end(loop_body);
2621                for phi in &loop_phis {
2622                    self.state.push1(phi.as_basic_value());
2623                }
2624
2625                let num_inputs = loop_phis.len();
2626                self.state
2627                    .push_loop(loop_body, loop_next, loop_phis, phis, num_inputs);
2628            }
2629            Operator::Br { relative_depth } => {
2630                let frame = self.state.frame_at_depth(relative_depth)?;
2631
2632                let current_block = self
2633                    .builder
2634                    .get_insert_block()
2635                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2636
2637                let phis = if frame.is_loop() {
2638                    frame.loop_body_phis()
2639                } else {
2640                    frame.phis()
2641                };
2642
2643                let len = phis.len();
2644                let values = self.state.peekn_extra(len)?;
2645                let values = values
2646                    .iter()
2647                    .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2648                    .collect::<Result<Vec<_>, _>>()?;
2649
2650                // For each result of the block we're branching to,
2651                // pop a value off the value stack and load it into
2652                // the corresponding phi.
2653                for (phi, value) in phis.iter().zip(values) {
2654                    phi.add_incoming(&[(&value, current_block)]);
2655                }
2656
2657                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2658
2659                self.state.popn(len)?;
2660                self.state.reachable = false;
2661            }
2662            Operator::BrIf { relative_depth } => {
2663                let cond = self.state.pop1()?;
2664                let frame = self.state.frame_at_depth(relative_depth)?;
2665
2666                let current_block = self
2667                    .builder
2668                    .get_insert_block()
2669                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2670
2671                let phis = if frame.is_loop() {
2672                    frame.loop_body_phis()
2673                } else {
2674                    frame.phis()
2675                };
2676
2677                let param_stack = self.state.peekn_extra(phis.len())?;
2678                let param_stack = param_stack
2679                    .iter()
2680                    .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2681                    .collect::<Result<Vec<_>, _>>()?;
2682
2683                for (phi, value) in phis.iter().zip(param_stack) {
2684                    phi.add_incoming(&[(&value, current_block)]);
2685                }
2686
2687                let else_block = self.context.append_basic_block(self.function, "else");
2688
2689                let cond_value = err!(self.builder.build_int_compare(
2690                    IntPredicate::NE,
2691                    cond.into_int_value(),
2692                    self.intrinsics.i32_zero,
2693                    "",
2694                ));
2695                err!(self.builder.build_conditional_branch(
2696                    cond_value,
2697                    *frame.br_dest(),
2698                    else_block
2699                ));
2700                self.builder.position_at_end(else_block);
2701            }
2702            Operator::BrTable { ref targets } => {
2703                let current_block = self
2704                    .builder
2705                    .get_insert_block()
2706                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2707
2708                let index = self.state.pop1()?;
2709
2710                let default_frame = self.state.frame_at_depth(targets.default())?;
2711
2712                let phis = if default_frame.is_loop() {
2713                    default_frame.loop_body_phis()
2714                } else {
2715                    default_frame.phis()
2716                };
2717                let args = self.state.peekn(phis.len())?;
2718
2719                for (phi, value) in phis.iter().zip(args.iter()) {
2720                    phi.add_incoming(&[(value, current_block)]);
2721                }
2722
2723                let cases: Vec<_> = targets
2724                    .targets()
2725                    .enumerate()
2726                    .map(|(case_index, depth)| {
2727                        let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
2728                        let frame_result: Result<&ControlFrame, CompileError> =
2729                            self.state.frame_at_depth(depth);
2730                        let frame = match frame_result {
2731                            Ok(v) => v,
2732                            Err(e) => return Err(e),
2733                        };
2734                        let case_index_literal =
2735                            self.context.i32_type().const_int(case_index as u64, false);
2736                        let phis = if frame.is_loop() {
2737                            frame.loop_body_phis()
2738                        } else {
2739                            frame.phis()
2740                        };
2741                        for (phi, value) in phis.iter().zip(args.iter()) {
2742                            phi.add_incoming(&[(value, current_block)]);
2743                        }
2744
2745                        Ok((case_index_literal, *frame.br_dest()))
2746                    })
2747                    .collect::<Result<_, _>>()?;
2748
2749                err!(self.builder.build_switch(
2750                    index.into_int_value(),
2751                    *default_frame.br_dest(),
2752                    &cases[..],
2753                ));
2754
2755                let args_len = args.len();
2756                self.state.popn(args_len)?;
2757                self.state.reachable = false;
2758            }
2759            Operator::If { blockty } => {
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                let if_then_block = self.context.append_basic_block(self.function, "if_then");
2765                let if_else_block = self.context.append_basic_block(self.function, "if_else");
2766                let end_block = self.context.append_basic_block(self.function, "if_end");
2767
2768                let end_phis = {
2769                    self.builder.position_at_end(end_block);
2770
2771                    let phis = self
2772                        .module_translation
2773                        .blocktype_params_results(&blockty)?
2774                        .1
2775                        .iter()
2776                        .map(|&wp_ty| {
2777                            err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2778                                type_to_llvm(self.intrinsics, wasm_ty)
2779                                    .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2780                            })
2781                        })
2782                        .collect::<Result<_, _>>()?;
2783
2784                    self.builder.position_at_end(current_block);
2785                    phis
2786                };
2787
2788                let block_param_types = self
2789                    .module_translation
2790                    .blocktype_params_results(&blockty)?
2791                    .0
2792                    .iter()
2793                    .map(|&wp_ty| {
2794                        err_nt!(wptype_to_type(wp_ty))
2795                            .and_then(|wasm_ty| type_to_llvm(self.intrinsics, wasm_ty))
2796                    })
2797                    .collect::<Result<Vec<_>, _>>()?;
2798
2799                // Build else_phis in if_else_block and then_phis in if_then_block.
2800                self.builder.position_at_end(if_else_block);
2801                let else_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2802                    .iter()
2803                    .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2804                    .collect::<Result<SmallVec<_>, _>>()?;
2805                self.builder.position_at_end(if_then_block);
2806                let then_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2807                    .iter()
2808                    .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2809                    .collect::<Result<SmallVec<_>, _>>()?;
2810
2811                // Pop the condition.
2812                let cond = self.state.pop1()?;
2813
2814                // Pop the block parameters and canonicalize them in current_block
2815                // (before the terminator is emitted) so that the select instruction
2816                // dominates the phi uses.
2817                self.builder.position_at_end(current_block);
2818                for (else_phi, then_phi) in else_phis.iter().rev().zip(then_phis.iter().rev()) {
2819                    let (value, info) = self.state.pop1_extra()?;
2820                    let value = self.apply_pending_canonicalization(value, info)?;
2821                    else_phi.add_incoming(&[(&value, current_block)]);
2822                    then_phi.add_incoming(&[(&value, current_block)]);
2823                }
2824
2825                let cond_value = err!(self.builder.build_int_compare(
2826                    IntPredicate::NE,
2827                    cond.into_int_value(),
2828                    self.intrinsics.i32_zero,
2829                    "",
2830                ));
2831
2832                err!(self.builder.build_conditional_branch(
2833                    cond_value,
2834                    if_then_block,
2835                    if_else_block
2836                ));
2837
2838                self.builder.position_at_end(if_then_block);
2839                for phi in then_phis.iter() {
2840                    self.state.push1(phi.as_basic_value());
2841                }
2842
2843                self.state.push_if(
2844                    if_then_block,
2845                    if_else_block,
2846                    end_block,
2847                    then_phis,
2848                    else_phis,
2849                    end_phis,
2850                    block_param_types.len(),
2851                );
2852            }
2853            Operator::Else => {
2854                if self.state.reachable {
2855                    let frame = self.state.frame_at_depth(0)?;
2856                    let current_block = self.builder.get_insert_block().ok_or_else(|| {
2857                        CompileError::Codegen("not currently in a block".to_string())
2858                    })?;
2859
2860                    for phi in frame.phis().to_vec().iter().rev() {
2861                        let (value, info) = self.state.pop1_extra()?;
2862                        let value = self.apply_pending_canonicalization(value, info)?;
2863                        phi.add_incoming(&[(&value, current_block)])
2864                    }
2865
2866                    let frame = self.state.frame_at_depth(0)?;
2867                    err!(self.builder.build_unconditional_branch(*frame.code_after()));
2868                }
2869
2870                let (if_else_block, if_else_state) = if let ControlFrame::IfElse {
2871                    if_else,
2872                    if_else_state,
2873                    ..
2874                } = self.state.frame_at_depth_mut(0)?
2875                {
2876                    (if_else, if_else_state)
2877                } else {
2878                    unreachable!()
2879                };
2880
2881                *if_else_state = IfElseState::Else;
2882
2883                self.builder.position_at_end(*if_else_block);
2884                self.state.reachable = true;
2885
2886                if let ControlFrame::IfElse { else_phis, .. } = self.state.frame_at_depth(0)? {
2887                    // Push our own 'else' phi nodes to the stack.
2888                    for phi in else_phis.clone().iter() {
2889                        self.state.push1(phi.as_basic_value());
2890                    }
2891                };
2892            }
2893
2894            Operator::End => {
2895                let frame = self.state.pop_frame()?;
2896                let current_block = self
2897                    .builder
2898                    .get_insert_block()
2899                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2900
2901                if self.state.reachable {
2902                    for phi in frame.phis().iter().rev() {
2903                        let (value, info) = self.state.pop1_extra()?;
2904                        let value = self.apply_pending_canonicalization(value, info)?;
2905                        phi.add_incoming(&[(&value, current_block)]);
2906                    }
2907
2908                    err!(self.builder.build_unconditional_branch(*frame.code_after()));
2909                }
2910
2911                if let ControlFrame::IfElse {
2912                    if_else,
2913                    next,
2914                    if_else_state: IfElseState::If,
2915                    else_phis,
2916                    ..
2917                } = &frame
2918                {
2919                    for (phi, else_phi) in frame.phis().iter().zip(else_phis.iter()) {
2920                        phi.add_incoming(&[(&else_phi.as_basic_value(), *if_else)]);
2921                    }
2922                    self.builder.position_at_end(*if_else);
2923                    err!(self.builder.build_unconditional_branch(*next));
2924                } else if let ControlFrame::Landingpad { .. } = &frame {
2925                    self.state.pop_landingpad();
2926                };
2927
2928                self.builder.position_at_end(*frame.code_after());
2929                self.state.reset_stack(&frame);
2930
2931                self.state.reachable = true;
2932
2933                // Push each phi value to the value stack.
2934                for phi in frame.phis() {
2935                    if phi.count_incoming() != 0 {
2936                        self.state.push1(phi.as_basic_value());
2937                    } else {
2938                        // TODO if there are no incoming phi values, it means
2939                        // this block has no predecessors, and we can skip it
2940                        // altogether. However, fixing this is non-trivial as
2941                        // some places in the code rely on code getting generated
2942                        // for unreachable end blocks. For now, we let LLVM remove
2943                        // the block during dead code elimination instead.
2944                        let basic_ty = phi.as_basic_value().get_type();
2945                        let placeholder_value = basic_ty.const_zero();
2946                        self.state.push1(placeholder_value);
2947                        phi.as_instruction().erase_from_basic_block();
2948                    }
2949                }
2950            }
2951            Operator::Return => {
2952                let current_block = self
2953                    .builder
2954                    .get_insert_block()
2955                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2956
2957                let frame = self.state.outermost_frame()?;
2958                for phi in frame.phis().to_vec().iter().rev() {
2959                    let (arg, info) = self.state.pop1_extra()?;
2960                    let arg = self.apply_pending_canonicalization(arg, info)?;
2961                    phi.add_incoming(&[(&arg, current_block)]);
2962                }
2963                let frame = self.state.outermost_frame()?;
2964                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2965
2966                self.state.reachable = false;
2967            }
2968
2969            Operator::Unreachable => {
2970                self.build_call_with_param_attributes(
2971                    self.intrinsics.throw_trap,
2972                    &[self.intrinsics.trap_unreachable.into()],
2973                    "throw",
2974                )?;
2975                err!(self.builder.build_unreachable());
2976
2977                self.state.reachable = false;
2978            }
2979            _ => unreachable!(),
2980        }
2981
2982        Ok(())
2983    }
2984
2985    // Basic instructions.
2986    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#basic-instructions
2987    fn translate_basic_operator(&mut self, op: Operator) -> Result<(), CompileError> {
2988        let vmctx = &self.ctx.basic().into_pointer_value();
2989
2990        match op {
2991            Operator::Nop => {
2992                // Do nothing.
2993            }
2994            Operator::Drop => {
2995                self.state.pop1()?;
2996            }
2997
2998            // Generate const values.
2999            Operator::I32Const { value } => {
3000                let i = self.intrinsics.i32_ty.const_int(value as u64, false);
3001                let info = if is_f32_arithmetic(value as u32) {
3002                    ExtraInfo::arithmetic_f32()
3003                } else {
3004                    Default::default()
3005                };
3006                self.state.push1_extra(i, info);
3007            }
3008            Operator::I64Const { value } => {
3009                let i = self.intrinsics.i64_ty.const_int(value as u64, false);
3010                let info = if is_f64_arithmetic(value as u64) {
3011                    ExtraInfo::arithmetic_f64()
3012                } else {
3013                    Default::default()
3014                };
3015                self.state.push1_extra(i, info);
3016            }
3017            Operator::F32Const { value } => {
3018                let bits = self.intrinsics.i32_ty.const_int(value.bits() as u64, false);
3019                let info = if is_f32_arithmetic(value.bits()) {
3020                    ExtraInfo::arithmetic_f32()
3021                } else {
3022                    Default::default()
3023                };
3024                let f = err!(
3025                    self.builder
3026                        .build_bit_cast(bits, self.intrinsics.f32_ty, "f")
3027                );
3028                self.state.push1_extra(f, info);
3029            }
3030            Operator::F64Const { value } => {
3031                let bits = self.intrinsics.i64_ty.const_int(value.bits(), false);
3032                let info = if is_f64_arithmetic(value.bits()) {
3033                    ExtraInfo::arithmetic_f64()
3034                } else {
3035                    Default::default()
3036                };
3037                let f = err!(
3038                    self.builder
3039                        .build_bit_cast(bits, self.intrinsics.f64_ty, "f")
3040                );
3041                self.state.push1_extra(f, info);
3042            }
3043            Operator::V128Const { value } => {
3044                let mut hi: [u8; 8] = Default::default();
3045                let mut lo: [u8; 8] = Default::default();
3046                hi.copy_from_slice(&value.bytes()[0..8]);
3047                lo.copy_from_slice(&value.bytes()[8..16]);
3048                let packed = [u64::from_le_bytes(hi), u64::from_le_bytes(lo)];
3049                let i = self
3050                    .intrinsics
3051                    .i128_ty
3052                    .const_int_arbitrary_precision(&packed);
3053                let mut quad1: [u8; 4] = Default::default();
3054                let mut quad2: [u8; 4] = Default::default();
3055                let mut quad3: [u8; 4] = Default::default();
3056                let mut quad4: [u8; 4] = Default::default();
3057                quad1.copy_from_slice(&value.bytes()[0..4]);
3058                quad2.copy_from_slice(&value.bytes()[4..8]);
3059                quad3.copy_from_slice(&value.bytes()[8..12]);
3060                quad4.copy_from_slice(&value.bytes()[12..16]);
3061                let mut info: ExtraInfo = Default::default();
3062                if is_f32_arithmetic(u32::from_le_bytes(quad1))
3063                    && is_f32_arithmetic(u32::from_le_bytes(quad2))
3064                    && is_f32_arithmetic(u32::from_le_bytes(quad3))
3065                    && is_f32_arithmetic(u32::from_le_bytes(quad4))
3066                {
3067                    info |= ExtraInfo::arithmetic_f32();
3068                }
3069                if is_f64_arithmetic(packed[0]) && is_f64_arithmetic(packed[1]) {
3070                    info |= ExtraInfo::arithmetic_f64();
3071                }
3072                self.state.push1_extra(i, info);
3073            }
3074
3075            Operator::I8x16Splat => {
3076                let (v, i) = self.state.pop1_extra()?;
3077                let v = v.into_int_value();
3078                let v = err!(
3079                    self.builder
3080                        .build_int_truncate(v, self.intrinsics.i8_ty, "")
3081                );
3082                let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
3083                let res = err!(
3084                    self.builder
3085                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3086                );
3087                self.state.push1_extra(res, i);
3088            }
3089            Operator::I16x8Splat => {
3090                let (v, i) = self.state.pop1_extra()?;
3091                let v = v.into_int_value();
3092                let v = err!(
3093                    self.builder
3094                        .build_int_truncate(v, self.intrinsics.i16_ty, "")
3095                );
3096                let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
3097                let res = err!(
3098                    self.builder
3099                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3100                );
3101                self.state.push1_extra(res, i);
3102            }
3103            Operator::I32x4Splat => {
3104                let (v, i) = self.state.pop1_extra()?;
3105                let res = self.splat_vector(v, self.intrinsics.i32x4_ty)?;
3106                let res = err!(
3107                    self.builder
3108                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3109                );
3110                self.state.push1_extra(res, i);
3111            }
3112            Operator::I64x2Splat => {
3113                let (v, i) = self.state.pop1_extra()?;
3114                let res = self.splat_vector(v, self.intrinsics.i64x2_ty)?;
3115                let res = err!(
3116                    self.builder
3117                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3118                );
3119                self.state.push1_extra(res, i);
3120            }
3121            Operator::F32x4Splat => {
3122                let (v, i) = self.state.pop1_extra()?;
3123                let res = self.splat_vector(v, self.intrinsics.f32x4_ty)?;
3124                let res = err!(
3125                    self.builder
3126                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3127                );
3128                // The spec is unclear, we interpret splat as preserving NaN
3129                // payload bits.
3130                self.state.push1_extra(res, i);
3131            }
3132            Operator::F64x2Splat => {
3133                let (v, i) = self.state.pop1_extra()?;
3134                let res = self.splat_vector(v, self.intrinsics.f64x2_ty)?;
3135                let res = err!(
3136                    self.builder
3137                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3138                );
3139                // The spec is unclear, we interpret splat as preserving NaN
3140                // payload bits.
3141                self.state.push1_extra(res, i);
3142            }
3143
3144            // Operate on self.locals.
3145            Operator::LocalGet { local_index } => {
3146                let (type_value, pointer_value) = self.locals[local_index as usize];
3147                let v = err!(self.builder.build_load(
3148                    type_value,
3149                    pointer_value,
3150                    &format!("local_{local_index}_get")
3151                ));
3152                tbaa_label(
3153                    self.module,
3154                    self.intrinsics,
3155                    format!("local {local_index}"),
3156                    v.as_instruction_value().unwrap(),
3157                );
3158                self.state.push1(v);
3159            }
3160            Operator::LocalSet { local_index } => {
3161                let pointer_value = self.locals[local_index as usize].1;
3162                let (v, i) = self.state.pop1_extra()?;
3163                let v = self.apply_pending_canonicalization(v, i)?;
3164                let store = err!(self.builder.build_store(pointer_value, v));
3165                tbaa_label(
3166                    self.module,
3167                    self.intrinsics,
3168                    format!("local {local_index}"),
3169                    store,
3170                );
3171            }
3172            Operator::LocalTee { local_index } => {
3173                let pointer_value = self.locals[local_index as usize].1;
3174                let (v, i) = self.state.peek1_extra()?;
3175                let v = self.apply_pending_canonicalization(v, i)?;
3176                let store = err!(self.builder.build_store(pointer_value, v));
3177                tbaa_label(
3178                    self.module,
3179                    self.intrinsics,
3180                    format!("local {local_index}"),
3181                    store,
3182                );
3183            }
3184
3185            Operator::GlobalGet { global_index } => {
3186                let global_index = GlobalIndex::from_u32(global_index);
3187                match self
3188                    .ctx
3189                    .global(global_index, self.intrinsics, self.module)?
3190                {
3191                    GlobalCache::Const { value } => {
3192                        self.state.push1(*value);
3193                    }
3194                    GlobalCache::Mut {
3195                        ptr_to_value,
3196                        value_type,
3197                    } => {
3198                        let value = err!(self.builder.build_load(*value_type, *ptr_to_value, ""));
3199                        tbaa_label(
3200                            self.module,
3201                            self.intrinsics,
3202                            format!("global {}", global_index.as_u32()),
3203                            value.as_instruction_value().unwrap(),
3204                        );
3205                        self.state.push1(value);
3206                    }
3207                }
3208            }
3209            Operator::GlobalSet { global_index } => {
3210                let global_index = GlobalIndex::from_u32(global_index);
3211                match self
3212                    .ctx
3213                    .global(global_index, self.intrinsics, self.module)?
3214                {
3215                    GlobalCache::Const { value: _ } => {
3216                        return Err(CompileError::Codegen(format!(
3217                            "global.set on immutable global index {}",
3218                            global_index.as_u32()
3219                        )));
3220                    }
3221                    GlobalCache::Mut { ptr_to_value, .. } => {
3222                        let ptr_to_value = *ptr_to_value;
3223                        let (value, info) = self.state.pop1_extra()?;
3224                        let value = self.apply_pending_canonicalization(value, info)?;
3225                        let store = err!(self.builder.build_store(ptr_to_value, value));
3226                        tbaa_label(
3227                            self.module,
3228                            self.intrinsics,
3229                            format!("global {}", global_index.as_u32()),
3230                            store,
3231                        );
3232                    }
3233                }
3234            }
3235
3236            // `TypedSelect` must be used for extern refs so ref counting should
3237            // be done with TypedSelect. But otherwise they're the same.
3238            Operator::TypedSelect { .. } | Operator::Select => {
3239                let ((v1, i1), (v2, i2), (cond, _)) = self.state.pop3_extra()?;
3240                // We don't bother canonicalizing 'cond' here because we only
3241                // compare it to zero, and that's invariant under
3242                // canonicalization.
3243
3244                // If the pending bits of v1 and v2 are the same, we can pass
3245                // them along to the result. Otherwise, apply pending
3246                // canonicalization now.
3247                let (v1, i1, v2, i2) = if i1.has_pending_f32_nan() != i2.has_pending_f32_nan()
3248                    || i1.has_pending_f64_nan() != i2.has_pending_f64_nan()
3249                {
3250                    (
3251                        self.apply_pending_canonicalization(v1, i1)?,
3252                        i1.strip_pending(),
3253                        self.apply_pending_canonicalization(v2, i2)?,
3254                        i2.strip_pending(),
3255                    )
3256                } else {
3257                    (v1, i1, v2, i2)
3258                };
3259                let cond_value = err!(self.builder.build_int_compare(
3260                    IntPredicate::NE,
3261                    cond.into_int_value(),
3262                    self.intrinsics.i32_zero,
3263                    "",
3264                ));
3265                let res = err!(self.builder.build_select(cond_value, v1, v2, ""));
3266                let info = {
3267                    let mut info = (i1.strip_pending() & i2.strip_pending())?;
3268                    if i1.has_pending_f32_nan() {
3269                        debug_assert!(i2.has_pending_f32_nan());
3270                        info = (info | ExtraInfo::pending_f32_nan())?;
3271                    }
3272                    if i1.has_pending_f64_nan() {
3273                        debug_assert!(i2.has_pending_f64_nan());
3274                        info = (info | ExtraInfo::pending_f64_nan())?;
3275                    }
3276                    info
3277                };
3278                self.state.push1_extra(res, info);
3279            }
3280            Operator::Call { function_index } | Operator::ReturnCall { function_index } => {
3281                let is_return_call = matches!(op, Operator::ReturnCall { .. });
3282                let func_index = FunctionIndex::from_u32(function_index);
3283                let sigindex = &self.wasm_module.functions[func_index];
3284                let func_type = &self.wasm_module.signatures[*sigindex];
3285
3286                let FunctionCache {
3287                    func,
3288                    llvm_func_type,
3289                    vmctx: callee_vmctx,
3290                    imported_include_m0_param,
3291                    attrs,
3292                } = if let Some(local_func_index) = self.wasm_module.local_func_index(func_index) {
3293                    let function_name = self
3294                        .symbol_registry
3295                        .symbol_to_name(Symbol::LocalFunction(local_func_index));
3296
3297                    self.ctx.local_func(
3298                        local_func_index,
3299                        func_index,
3300                        self.intrinsics,
3301                        self.module,
3302                        self.context,
3303                        func_type,
3304                        &function_name,
3305                    )?
3306                } else {
3307                    self.ctx
3308                        .imported_func(func_index, self.intrinsics, self.context, func_type)?
3309                };
3310                let llvm_func_type = *llvm_func_type;
3311                let func = *func;
3312                let callee_vmctx = *callee_vmctx;
3313                let imported_include_m0_param = *imported_include_m0_param;
3314                let attrs = attrs.clone();
3315
3316                /*
3317                let func_ptr = self.llvm.functions.borrow_mut()[&func_index];
3318
3319                (params, func_ptr.as_global_value().as_pointer_value())
3320                */
3321                let params = self.state.popn_save_extra(func_type.params().len())?;
3322
3323                // Apply pending canonicalization.
3324                let params = params
3325                    .iter()
3326                    .zip(func_type.params().iter())
3327                    .map(|((v, info), wasm_ty)| match wasm_ty {
3328                        Type::F32 => err_nt!(self.builder.build_bit_cast(
3329                            self.apply_pending_canonicalization(*v, *info)?,
3330                            self.intrinsics.f32_ty,
3331                            "",
3332                        )),
3333                        Type::F64 => err_nt!(self.builder.build_bit_cast(
3334                            self.apply_pending_canonicalization(*v, *info)?,
3335                            self.intrinsics.f64_ty,
3336                            "",
3337                        )),
3338                        Type::V128 => self.apply_pending_canonicalization(*v, *info),
3339                        _ => Ok(*v),
3340                    })
3341                    .collect::<Result<Vec<_>, _>>()?;
3342
3343                if let (Some(m0_param), Some(include_m0_param)) =
3344                    (self.m0_param, imported_include_m0_param)
3345                {
3346                    /* For imported functions, we must be careful about when to include `g0_param`:
3347                    imports from another Wasm module expect it, while host-function imports do not.
3348                    We intentionally not leverage tail-calls for such function calls. */
3349                    let (llvm_func_type_no_m0, llvm_func_attrs_no_m0) =
3350                        self.abi.func_type_to_llvm(
3351                            self.context,
3352                            self.intrinsics,
3353                            Some(self.ctx.get_offsets()),
3354                            func_type,
3355                            false,
3356                        )?;
3357                    let params_with_m0 = self.abi.args_to_call(
3358                        &self.alloca_builder,
3359                        func_type,
3360                        &llvm_func_type,
3361                        callee_vmctx.into_pointer_value(),
3362                        params.as_slice(),
3363                        self.intrinsics,
3364                        Some(m0_param),
3365                        is_return_call
3366                            .then(|| self.current_sret_ptr(func_type))
3367                            .flatten(),
3368                    )?;
3369                    let params_no_m0 = self.abi.args_to_call(
3370                        &self.alloca_builder,
3371                        func_type,
3372                        &llvm_func_type_no_m0,
3373                        callee_vmctx.into_pointer_value(),
3374                        params.as_slice(),
3375                        self.intrinsics,
3376                        None,
3377                        is_return_call
3378                            .then(|| self.current_sret_ptr(func_type))
3379                            .flatten(),
3380                    )?;
3381
3382                    let include_m0_call_block = self
3383                        .context
3384                        .append_basic_block(self.function, "call_block_with_m0");
3385                    let skip_m0_call_block =
3386                        self.context.append_basic_block(self.function, "call_block");
3387                    let call_cont = self.context.append_basic_block(self.function, "call_cont");
3388                    err!(self.builder.build_conditional_branch(
3389                        include_m0_param,
3390                        include_m0_call_block,
3391                        skip_m0_call_block,
3392                    ));
3393
3394                    self.builder.position_at_end(include_m0_call_block);
3395                    let call_site_with_m0 = self.build_indirect_call_or_invoke(
3396                        llvm_func_type,
3397                        func,
3398                        params_with_m0.as_slice(),
3399                        "then_block_with_m0",
3400                        is_return_call,
3401                    )?;
3402                    for (attr, attr_loc) in &attrs {
3403                        call_site_with_m0.add_attribute(*attr_loc, *attr);
3404                    }
3405                    let rets_with_m0 = self.abi.rets_from_call(
3406                        &self.builder,
3407                        self.intrinsics,
3408                        call_site_with_m0,
3409                        func_type,
3410                    )?;
3411                    let with_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3412                        CompileError::Codegen(
3413                            "missing insertion block after call with m0".to_string(),
3414                        )
3415                    })?;
3416                    err!(self.builder.build_unconditional_branch(call_cont));
3417
3418                    self.builder.position_at_end(skip_m0_call_block);
3419                    let call_site_no_m0 = self.build_indirect_call_or_invoke(
3420                        llvm_func_type_no_m0,
3421                        func,
3422                        params_no_m0.as_slice(),
3423                        "then_block",
3424                        is_return_call,
3425                    )?;
3426                    for (attr, attr_loc) in &llvm_func_attrs_no_m0 {
3427                        call_site_no_m0.add_attribute(*attr_loc, *attr);
3428                    }
3429                    let rets_no_m0 = self.abi.rets_from_call(
3430                        &self.builder,
3431                        self.intrinsics,
3432                        call_site_no_m0,
3433                        func_type,
3434                    )?;
3435                    let no_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3436                        CompileError::Codegen(
3437                            "missing insertion block after call without m0".to_string(),
3438                        )
3439                    })?;
3440                    err!(self.builder.build_unconditional_branch(call_cont));
3441
3442                    self.builder.position_at_end(call_cont);
3443                    for i in 0..rets_with_m0.len() {
3444                        let with_m0 = rets_with_m0[i];
3445                        let no_m0 = rets_no_m0[i];
3446                        let phi = err!(self.builder.build_phi(with_m0.get_type(), ""));
3447                        phi.add_incoming(&[(&with_m0, with_m0_pred), (&no_m0, no_m0_pred)]);
3448                        self.state.push1(phi.as_basic_value());
3449                    }
3450                } else {
3451                    let params = self.abi.args_to_call(
3452                        &self.alloca_builder,
3453                        func_type,
3454                        &llvm_func_type,
3455                        callee_vmctx.into_pointer_value(),
3456                        params.as_slice(),
3457                        self.intrinsics,
3458                        self.m0_param,
3459                        if is_return_call {
3460                            self.current_sret_ptr(func_type)
3461                        } else {
3462                            None
3463                        },
3464                    )?;
3465
3466                    let call_site = self.build_indirect_call_or_invoke(
3467                        llvm_func_type,
3468                        func,
3469                        params.as_slice(),
3470                        "then_block",
3471                        is_return_call,
3472                    )?;
3473                    for (attr, attr_loc) in attrs {
3474                        call_site.add_attribute(attr_loc, attr);
3475                    }
3476
3477                    if is_return_call {
3478                        self.emit_return_call(call_site, llvm_func_type)?;
3479                        self.state.reachable = false;
3480                    } else {
3481                        self.abi
3482                            .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3483                            .iter()
3484                            .for_each(|ret| self.state.push1(*ret));
3485                    }
3486                }
3487            }
3488            Operator::CallIndirect {
3489                type_index,
3490                table_index,
3491            }
3492            | Operator::ReturnCallIndirect {
3493                type_index,
3494                table_index,
3495            } => {
3496                let is_return_call = matches!(op, Operator::ReturnCallIndirect { .. });
3497                let sigindex = SignatureIndex::from_u32(type_index);
3498                let table_index = TableIndex::from_u32(table_index);
3499                let func_type = &self.wasm_module.signatures[sigindex];
3500                let table = self.wasm_module.tables.get(table_index).unwrap();
3501                let local_fixed_funcref_table = self
3502                    .wasm_module
3503                    .local_table_index(table_index)
3504                    .filter(|_| table.is_fixed_funcref_table());
3505                let expected_signature_hash = self
3506                    .intrinsics
3507                    .i32_ty
3508                    .const_int(u64::from(self.signature_hashes[sigindex].as_u32()), false);
3509
3510                let func_index = self.state.pop1()?.into_int_value();
3511                let generic_table = if local_fixed_funcref_table.is_none() {
3512                    Some(self.ctx.table(
3513                        table_index,
3514                        self.intrinsics,
3515                        self.module,
3516                        &self.builder,
3517                    )?)
3518                } else {
3519                    None
3520                };
3521
3522                let table_bound = if local_fixed_funcref_table.is_some() {
3523                    self.intrinsics
3524                        .i32_ty
3525                        .const_int(table.minimum.into(), false)
3526                } else {
3527                    let (_, table_bound) = *generic_table.as_ref().unwrap();
3528                    err!(self.builder.build_int_truncate(
3529                        table_bound,
3530                        self.intrinsics.i32_ty,
3531                        "truncated_table_bounds",
3532                    ))
3533                };
3534
3535                // First, check if the index is outside of the table bounds.
3536                let index_in_bounds = err!(self.builder.build_int_compare(
3537                    IntPredicate::ULT,
3538                    func_index,
3539                    table_bound,
3540                    "index_in_bounds",
3541                ));
3542
3543                let index_in_bounds = self
3544                    .build_call_with_param_attributes(
3545                        self.intrinsics.expect_i1,
3546                        &[
3547                            index_in_bounds.into(),
3548                            self.intrinsics.i1_ty.const_int(1, false).into(),
3549                        ],
3550                        "index_in_bounds_expect",
3551                    )?
3552                    .try_as_basic_value()
3553                    .unwrap_basic()
3554                    .into_int_value();
3555
3556                let in_bounds_continue_block = self
3557                    .context
3558                    .append_basic_block(self.function, "in_bounds_continue_block");
3559                let not_in_bounds_block = self
3560                    .context
3561                    .append_basic_block(self.function, "not_in_bounds_block");
3562                err!(self.builder.build_conditional_branch(
3563                    index_in_bounds,
3564                    in_bounds_continue_block,
3565                    not_in_bounds_block,
3566                ));
3567                self.builder.position_at_end(not_in_bounds_block);
3568                self.build_call_with_param_attributes(
3569                    self.intrinsics.throw_trap,
3570                    &[self.intrinsics.trap_table_access_oob.into()],
3571                    "throw",
3572                )?;
3573                err!(self.builder.build_unreachable());
3574                self.builder.position_at_end(in_bounds_continue_block);
3575
3576                let anyfunc_struct_ptr = if let Some(local_table_index) = local_fixed_funcref_table
3577                {
3578                    let anyfuncs = self.ctx.fixed_funcref_table_anyfuncs(
3579                        local_table_index,
3580                        self.intrinsics,
3581                        &self.builder,
3582                    )?;
3583                    unsafe {
3584                        err!(self.builder.build_in_bounds_gep(
3585                            self.intrinsics.anyfunc_ty,
3586                            anyfuncs,
3587                            &[func_index],
3588                            "anyfunc_struct_ptr",
3589                        ))
3590                    }
3591                } else {
3592                    let (table_base, _) = *generic_table.as_ref().unwrap();
3593
3594                    // We assume the table has the `funcref` (pointer to `anyfunc`)
3595                    // element type.
3596                    let casted_table_base = err!(self.builder.build_pointer_cast(
3597                        table_base,
3598                        self.context.ptr_type(AddressSpace::default()),
3599                        "casted_table_base",
3600                    ));
3601
3602                    let funcref_ptr = unsafe {
3603                        err!(self.builder.build_in_bounds_gep(
3604                            self.intrinsics.ptr_ty,
3605                            casted_table_base,
3606                            &[func_index],
3607                            "funcref_ptr",
3608                        ))
3609                    };
3610
3611                    // a funcref (pointer to `anyfunc`)
3612                    let anyfunc_struct_ptr = err!(self.builder.build_load(
3613                        self.intrinsics.ptr_ty,
3614                        funcref_ptr,
3615                        "anyfunc_struct_ptr",
3616                    ))
3617                    .into_pointer_value();
3618
3619                    if !table.readonly {
3620                        // trap if we're trying to call a null funcref
3621                        let funcref_not_null = err!(
3622                            self.builder
3623                                .build_is_not_null(anyfunc_struct_ptr, "null_funcref_check")
3624                        );
3625
3626                        let funcref_continue_deref_block = self
3627                            .context
3628                            .append_basic_block(self.function, "funcref_continue_deref_block");
3629
3630                        let funcref_is_null_block = self
3631                            .context
3632                            .append_basic_block(self.function, "funcref_is_null_block");
3633                        err!(self.builder.build_conditional_branch(
3634                            funcref_not_null,
3635                            funcref_continue_deref_block,
3636                            funcref_is_null_block,
3637                        ));
3638                        self.builder.position_at_end(funcref_is_null_block);
3639                        self.build_call_with_param_attributes(
3640                            self.intrinsics.throw_trap,
3641                            &[self.intrinsics.trap_call_indirect_null.into()],
3642                            "throw",
3643                        )?;
3644                        err!(self.builder.build_unreachable());
3645                        self.builder.position_at_end(funcref_continue_deref_block);
3646                    }
3647
3648                    anyfunc_struct_ptr
3649                };
3650
3651                // Load things from the anyfunc data structure.
3652                let sig_hash_ptr = self
3653                    .builder
3654                    .build_struct_gep(
3655                        self.intrinsics.anyfunc_ty,
3656                        anyfunc_struct_ptr,
3657                        1,
3658                        "sig_hash_ptr",
3659                    )
3660                    .unwrap();
3661                let func_ptr_ptr = self
3662                    .builder
3663                    .build_struct_gep(
3664                        self.intrinsics.anyfunc_ty,
3665                        anyfunc_struct_ptr,
3666                        0,
3667                        "func_ptr_ptr",
3668                    )
3669                    .unwrap();
3670                let (func_ptr, found_signature_hash) = (
3671                    err!(
3672                        self.builder
3673                            .build_load(self.intrinsics.ptr_ty, func_ptr_ptr, "func_ptr")
3674                    )
3675                    .into_pointer_value(),
3676                    err!(
3677                        self.builder
3678                            .build_load(self.intrinsics.i32_ty, sig_hash_ptr, "sig_hash")
3679                    )
3680                    .into_int_value(),
3681                );
3682
3683                // Next, check if the table element is initialized.
3684
3685                // TODO: we may not need this check anymore
3686                let elem_initialized = err!(self.builder.build_is_not_null(func_ptr, ""));
3687
3688                // Next, check if the signature id is correct.
3689
3690                let sig_hashes_equal = err!(self.builder.build_int_compare(
3691                    IntPredicate::EQ,
3692                    expected_signature_hash,
3693                    found_signature_hash,
3694                    "sig_hashes_equal",
3695                ));
3696
3697                let initialized_and_sig_hashes_match = err!(self.builder.build_and(
3698                    elem_initialized,
3699                    sig_hashes_equal,
3700                    ""
3701                ));
3702
3703                // Tell llvm that the expected and found signature hashes should match.
3704                let initialized_and_sig_hashes_match = self
3705                    .build_call_with_param_attributes(
3706                        self.intrinsics.expect_i1,
3707                        &[
3708                            initialized_and_sig_hashes_match.into(),
3709                            self.intrinsics.i1_ty.const_int(1, false).into(),
3710                        ],
3711                        "initialized_and_sig_hashes_match_expect",
3712                    )?
3713                    .try_as_basic_value()
3714                    .unwrap_basic()
3715                    .into_int_value();
3716
3717                let continue_block = self
3718                    .context
3719                    .append_basic_block(self.function, "continue_block");
3720                let sighashes_notequal_block = self
3721                    .context
3722                    .append_basic_block(self.function, "sighashes_notequal_block");
3723                err!(self.builder.build_conditional_branch(
3724                    initialized_and_sig_hashes_match,
3725                    continue_block,
3726                    sighashes_notequal_block,
3727                ));
3728
3729                self.builder.position_at_end(sighashes_notequal_block);
3730                let trap_code = err!(self.builder.build_select(
3731                    elem_initialized,
3732                    self.intrinsics.trap_call_indirect_sig,
3733                    self.intrinsics.trap_call_indirect_null,
3734                    "",
3735                ));
3736                self.build_call_with_param_attributes(
3737                    self.intrinsics.throw_trap,
3738                    &[trap_code.into()],
3739                    "throw",
3740                )?;
3741                err!(self.builder.build_unreachable());
3742                self.builder.position_at_end(continue_block);
3743
3744                let callee_vmctx = if table.readonly {
3745                    *vmctx
3746                } else {
3747                    let ctx_ptr_ptr = self
3748                        .builder
3749                        .build_struct_gep(
3750                            self.intrinsics.anyfunc_ty,
3751                            anyfunc_struct_ptr,
3752                            2,
3753                            "ctx_ptr_ptr",
3754                        )
3755                        .unwrap();
3756                    err!(
3757                        self.builder
3758                            .build_load(self.intrinsics.ptr_ty, ctx_ptr_ptr, "ctx_ptr")
3759                    )
3760                    .into_pointer_value()
3761                };
3762
3763                if self.m0_param.is_some() {
3764                    self.build_m0_indirect_call(
3765                        table_index.as_u32(),
3766                        callee_vmctx,
3767                        func_type,
3768                        func_ptr,
3769                        func_index,
3770                        is_return_call,
3771                    )?;
3772                } else {
3773                    let (call_site, llvm_func_type) = self.build_indirect_call(
3774                        callee_vmctx,
3775                        func_type,
3776                        func_ptr,
3777                        None,
3778                        is_return_call,
3779                    )?;
3780
3781                    if is_return_call {
3782                        self.emit_return_call(call_site, llvm_func_type)?;
3783                    } else {
3784                        self.abi
3785                            .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3786                            .iter()
3787                            .for_each(|ret| self.state.push1(*ret));
3788                    }
3789                }
3790
3791                if is_return_call {
3792                    self.state.reachable = false;
3793                }
3794            }
3795            _ => unreachable!(),
3796        }
3797        Ok(())
3798    }
3799
3800    // Integer Arithmetic instructions.
3801    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-arithmetic-instructions
3802    fn translate_integer_arithmetic_operator(&mut self, op: Operator) -> Result<(), CompileError> {
3803        match op {
3804            Operator::I32Add | Operator::I64Add => {
3805                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3806                let v1 = self.apply_pending_canonicalization(v1, i1)?;
3807                let v2 = self.apply_pending_canonicalization(v2, i2)?;
3808                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3809                let res = err!(self.builder.build_int_add(v1, v2, ""));
3810                self.state.push1(res);
3811            }
3812            Operator::I8x16Add => {
3813                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3814                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3815                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3816                let res = err!(self.builder.build_int_add(v1, v2, ""));
3817                let res = err!(
3818                    self.builder
3819                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3820                );
3821                self.state.push1(res);
3822            }
3823            Operator::I16x8Add => {
3824                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3825                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3826                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3827                let res = err!(self.builder.build_int_add(v1, v2, ""));
3828                let res = err!(
3829                    self.builder
3830                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3831                );
3832                self.state.push1(res);
3833            }
3834            Operator::I16x8ExtAddPairwiseI8x16S | Operator::I16x8ExtAddPairwiseI8x16U => {
3835                let extend_op = match op {
3836                    Operator::I16x8ExtAddPairwiseI8x16S => {
3837                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, "")
3838                    }
3839                    Operator::I16x8ExtAddPairwiseI8x16U => {
3840                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, "")
3841                    }
3842                    _ => unreachable!("Unhandled internal variant"),
3843                };
3844                let (v, i) = self.state.pop1_extra()?;
3845                let (v, _) = self.v128_into_i8x16(v, i)?;
3846
3847                let left = err!(self.builder.build_shuffle_vector(
3848                    v,
3849                    v.get_type().get_undef(),
3850                    VectorType::const_vector(&[
3851                        self.intrinsics.i32_consts[0],
3852                        self.intrinsics.i32_consts[2],
3853                        self.intrinsics.i32_consts[4],
3854                        self.intrinsics.i32_consts[6],
3855                        self.intrinsics.i32_consts[8],
3856                        self.intrinsics.i32_consts[10],
3857                        self.intrinsics.i32_consts[12],
3858                        self.intrinsics.i32_consts[14],
3859                    ]),
3860                    "",
3861                ));
3862                let left = err!(extend_op(self, left));
3863                let right = err!(self.builder.build_shuffle_vector(
3864                    v,
3865                    v.get_type().get_undef(),
3866                    VectorType::const_vector(&[
3867                        self.intrinsics.i32_consts[1],
3868                        self.intrinsics.i32_consts[3],
3869                        self.intrinsics.i32_consts[5],
3870                        self.intrinsics.i32_consts[7],
3871                        self.intrinsics.i32_consts[9],
3872                        self.intrinsics.i32_consts[11],
3873                        self.intrinsics.i32_consts[13],
3874                        self.intrinsics.i32_consts[15],
3875                    ]),
3876                    "",
3877                ));
3878                let right = err!(extend_op(self, right));
3879
3880                let res = err!(self.builder.build_int_add(left, right, ""));
3881                let res = err!(
3882                    self.builder
3883                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3884                );
3885                self.state.push1(res);
3886            }
3887            Operator::I32x4Add => {
3888                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3889                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3890                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3891                let res = err!(self.builder.build_int_add(v1, v2, ""));
3892                let res = err!(
3893                    self.builder
3894                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3895                );
3896                self.state.push1(res);
3897            }
3898            Operator::I32x4ExtAddPairwiseI16x8S | Operator::I32x4ExtAddPairwiseI16x8U => {
3899                let extend_op = match op {
3900                    Operator::I32x4ExtAddPairwiseI16x8S => {
3901                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
3902                    }
3903                    Operator::I32x4ExtAddPairwiseI16x8U => {
3904                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
3905                    }
3906                    _ => unreachable!("Unhandled internal variant"),
3907                };
3908                let (v, i) = self.state.pop1_extra()?;
3909                let (v, _) = self.v128_into_i16x8(v, i)?;
3910
3911                let left = err!(self.builder.build_shuffle_vector(
3912                    v,
3913                    v.get_type().get_undef(),
3914                    VectorType::const_vector(&[
3915                        self.intrinsics.i32_consts[0],
3916                        self.intrinsics.i32_consts[2],
3917                        self.intrinsics.i32_consts[4],
3918                        self.intrinsics.i32_consts[6],
3919                    ]),
3920                    "",
3921                ));
3922                let left = err!(extend_op(self, left));
3923                let right = err!(self.builder.build_shuffle_vector(
3924                    v,
3925                    v.get_type().get_undef(),
3926                    VectorType::const_vector(&[
3927                        self.intrinsics.i32_consts[1],
3928                        self.intrinsics.i32_consts[3],
3929                        self.intrinsics.i32_consts[5],
3930                        self.intrinsics.i32_consts[7],
3931                    ]),
3932                    "",
3933                ));
3934                let right = err!(extend_op(self, right));
3935
3936                let res = err!(self.builder.build_int_add(left, right, ""));
3937                let res = err!(
3938                    self.builder
3939                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3940                );
3941                self.state.push1(res);
3942            }
3943            Operator::I64x2Add => {
3944                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3945                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3946                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3947                let res = err!(self.builder.build_int_add(v1, v2, ""));
3948                let res = err!(
3949                    self.builder
3950                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3951                );
3952                self.state.push1(res);
3953            }
3954            Operator::I8x16AddSatS => {
3955                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3956                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3957                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3958                let res = self
3959                    .build_call_with_param_attributes(
3960                        self.intrinsics.sadd_sat_i8x16,
3961                        &[v1.into(), v2.into()],
3962                        "",
3963                    )?
3964                    .try_as_basic_value()
3965                    .unwrap_basic();
3966                let res = err!(
3967                    self.builder
3968                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3969                );
3970                self.state.push1(res);
3971            }
3972            Operator::I16x8AddSatS => {
3973                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3974                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3975                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3976                let res = self
3977                    .build_call_with_param_attributes(
3978                        self.intrinsics.sadd_sat_i16x8,
3979                        &[v1.into(), v2.into()],
3980                        "",
3981                    )?
3982                    .try_as_basic_value()
3983                    .unwrap_basic();
3984                let res = err!(
3985                    self.builder
3986                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3987                );
3988                self.state.push1(res);
3989            }
3990            Operator::I8x16AddSatU => {
3991                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3992                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3993                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3994                let res = self
3995                    .build_call_with_param_attributes(
3996                        self.intrinsics.uadd_sat_i8x16,
3997                        &[v1.into(), v2.into()],
3998                        "",
3999                    )?
4000                    .try_as_basic_value()
4001                    .unwrap_basic();
4002                let res = err!(
4003                    self.builder
4004                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4005                );
4006                self.state.push1(res);
4007            }
4008            Operator::I16x8AddSatU => {
4009                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4010                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4011                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4012                let res = self
4013                    .build_call_with_param_attributes(
4014                        self.intrinsics.uadd_sat_i16x8,
4015                        &[v1.into(), v2.into()],
4016                        "",
4017                    )?
4018                    .try_as_basic_value()
4019                    .unwrap_basic();
4020                let res = err!(
4021                    self.builder
4022                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4023                );
4024                self.state.push1(res);
4025            }
4026            Operator::I32Sub | Operator::I64Sub => {
4027                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4028                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4029                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4030                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4031                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4032                self.state.push1(res);
4033            }
4034            Operator::I8x16Sub => {
4035                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4036                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4037                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4038                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4039                let res = err!(
4040                    self.builder
4041                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4042                );
4043                self.state.push1(res);
4044            }
4045            Operator::I16x8Sub => {
4046                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4047                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4048                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4049                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4050                let res = err!(
4051                    self.builder
4052                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4053                );
4054                self.state.push1(res);
4055            }
4056            Operator::I32x4Sub => {
4057                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4058                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4059                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4060                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4061                let res = err!(
4062                    self.builder
4063                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4064                );
4065                self.state.push1(res);
4066            }
4067            Operator::I64x2Sub => {
4068                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4069                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4070                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4071                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4072                let res = err!(
4073                    self.builder
4074                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4075                );
4076                self.state.push1(res);
4077            }
4078            Operator::I8x16SubSatS => {
4079                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4080                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4081                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4082                let res = self
4083                    .build_call_with_param_attributes(
4084                        self.intrinsics.ssub_sat_i8x16,
4085                        &[v1.into(), v2.into()],
4086                        "",
4087                    )?
4088                    .try_as_basic_value()
4089                    .unwrap_basic();
4090                let res = err!(
4091                    self.builder
4092                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4093                );
4094                self.state.push1(res);
4095            }
4096            Operator::I16x8SubSatS => {
4097                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4098                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4099                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4100                let res = self
4101                    .build_call_with_param_attributes(
4102                        self.intrinsics.ssub_sat_i16x8,
4103                        &[v1.into(), v2.into()],
4104                        "",
4105                    )?
4106                    .try_as_basic_value()
4107                    .unwrap_basic();
4108                let res = err!(
4109                    self.builder
4110                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4111                );
4112                self.state.push1(res);
4113            }
4114            Operator::I8x16SubSatU => {
4115                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4116                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4117                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4118                let res = self
4119                    .build_call_with_param_attributes(
4120                        self.intrinsics.usub_sat_i8x16,
4121                        &[v1.into(), v2.into()],
4122                        "",
4123                    )?
4124                    .try_as_basic_value()
4125                    .unwrap_basic();
4126                let res = err!(
4127                    self.builder
4128                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4129                );
4130                self.state.push1(res);
4131            }
4132            Operator::I16x8SubSatU => {
4133                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4134                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4135                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4136                let res = self
4137                    .build_call_with_param_attributes(
4138                        self.intrinsics.usub_sat_i16x8,
4139                        &[v1.into(), v2.into()],
4140                        "",
4141                    )?
4142                    .try_as_basic_value()
4143                    .unwrap_basic();
4144                let res = err!(
4145                    self.builder
4146                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4147                );
4148                self.state.push1(res);
4149            }
4150            Operator::I32Mul | Operator::I64Mul => {
4151                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4152                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4153                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4154                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4155                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4156                self.state.push1(res);
4157            }
4158            Operator::I16x8Mul => {
4159                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4160                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4161                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4162                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4163                let res = err!(
4164                    self.builder
4165                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4166                );
4167                self.state.push1(res);
4168            }
4169            Operator::I32x4Mul => {
4170                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4171                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4172                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4173                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4174                let res = err!(
4175                    self.builder
4176                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4177                );
4178                self.state.push1(res);
4179            }
4180            Operator::I64x2Mul => {
4181                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4182                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4183                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4184                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4185                let res = err!(
4186                    self.builder
4187                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4188                );
4189                self.state.push1(res);
4190            }
4191            Operator::I16x8RelaxedQ15mulrS if self.cpu_features.contains(CpuFeature::SSSE3) => {
4192                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4193                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4194                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4195                let res = self
4196                    .build_call_with_param_attributes(
4197                        self.intrinsics.x86_64.pmulhrsw128,
4198                        &[v1.into(), v2.into()],
4199                        "",
4200                    )?
4201                    .try_as_basic_value()
4202                    .unwrap_basic();
4203                let res = err!(
4204                    self.builder
4205                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4206                );
4207                self.state.push1(res);
4208            }
4209            Operator::I16x8Q15MulrSatS | Operator::I16x8RelaxedQ15mulrS => {
4210                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4211                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4212                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4213
4214                let max_value = self.intrinsics.i16_ty.const_int(i16::MAX as u64, false);
4215                let max_values = VectorType::const_vector(&[max_value; 8]);
4216
4217                let v1 = err!(
4218                    self.builder
4219                        .build_int_s_extend(v1, self.intrinsics.i32x8_ty, "")
4220                );
4221                let v2 = err!(
4222                    self.builder
4223                        .build_int_s_extend(v2, self.intrinsics.i32x8_ty, "")
4224                );
4225                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4226
4227                // magic number specified by the spec
4228                let bit = self.intrinsics.i32_ty.const_int(0x4000, false);
4229                let bits = VectorType::const_vector(&[bit; 8]);
4230
4231                let res = err!(self.builder.build_int_add(res, bits, ""));
4232
4233                let fifteen = self.intrinsics.i32_consts[15];
4234                let fifteens = VectorType::const_vector(&[fifteen; 8]);
4235
4236                let res = err!(self.builder.build_right_shift(res, fifteens, true, ""));
4237                let saturate_up = {
4238                    let max_values = err!(self.builder.build_int_s_extend(
4239                        max_values,
4240                        self.intrinsics.i32x8_ty,
4241                        ""
4242                    ));
4243                    err!(
4244                        self.builder
4245                            .build_int_compare(IntPredicate::SGT, res, max_values, "")
4246                    )
4247                };
4248
4249                let res = err!(
4250                    self.builder
4251                        .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
4252                );
4253
4254                let res = err!(self.builder.build_select(saturate_up, max_values, res, ""))
4255                    .into_vector_value();
4256                let res = err!(
4257                    self.builder
4258                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4259                );
4260                self.state.push1(res);
4261            }
4262            Operator::I16x8ExtMulLowI8x16S
4263            | Operator::I16x8ExtMulLowI8x16U
4264            | Operator::I16x8ExtMulHighI8x16S
4265            | Operator::I16x8ExtMulHighI8x16U => {
4266                let extend_op = match op {
4267                    Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulHighI8x16S => {
4268                        |s: &Self, v| -> Result<VectorValue, CompileError> {
4269                            err_nt!(s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, ""))
4270                        }
4271                    }
4272                    Operator::I16x8ExtMulLowI8x16U | Operator::I16x8ExtMulHighI8x16U => {
4273                        |s: &Self, v| -> Result<VectorValue, CompileError> {
4274                            err_nt!(s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, ""))
4275                        }
4276                    }
4277                    _ => unreachable!("Unhandled internal variant"),
4278                };
4279                let shuffle_array = match op {
4280                    Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulLowI8x16U => [
4281                        self.intrinsics.i32_consts[0],
4282                        self.intrinsics.i32_consts[1],
4283                        self.intrinsics.i32_consts[2],
4284                        self.intrinsics.i32_consts[3],
4285                        self.intrinsics.i32_consts[4],
4286                        self.intrinsics.i32_consts[5],
4287                        self.intrinsics.i32_consts[6],
4288                        self.intrinsics.i32_consts[7],
4289                    ],
4290                    Operator::I16x8ExtMulHighI8x16S | Operator::I16x8ExtMulHighI8x16U => [
4291                        self.intrinsics.i32_consts[8],
4292                        self.intrinsics.i32_consts[9],
4293                        self.intrinsics.i32_consts[10],
4294                        self.intrinsics.i32_consts[11],
4295                        self.intrinsics.i32_consts[12],
4296                        self.intrinsics.i32_consts[13],
4297                        self.intrinsics.i32_consts[14],
4298                        self.intrinsics.i32_consts[15],
4299                    ],
4300                    _ => unreachable!("Unhandled internal variant"),
4301                };
4302                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4303                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4304                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4305                let val1 = err!(self.builder.build_shuffle_vector(
4306                    v1,
4307                    v1.get_type().get_undef(),
4308                    VectorType::const_vector(&shuffle_array),
4309                    "",
4310                ));
4311                let val1 = err!(extend_op(self, val1));
4312                let val2 = err!(self.builder.build_shuffle_vector(
4313                    v2,
4314                    v2.get_type().get_undef(),
4315                    VectorType::const_vector(&shuffle_array),
4316                    "",
4317                ));
4318                let val2 = err!(extend_op(self, val2));
4319                let res = err!(self.builder.build_int_mul(val1, val2, ""));
4320                let res = err!(
4321                    self.builder
4322                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4323                );
4324                self.state.push1(res);
4325            }
4326            Operator::I32x4ExtMulLowI16x8S
4327            | Operator::I32x4ExtMulLowI16x8U
4328            | Operator::I32x4ExtMulHighI16x8S
4329            | Operator::I32x4ExtMulHighI16x8U => {
4330                let extend_op = match op {
4331                    Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulHighI16x8S => {
4332                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
4333                    }
4334                    Operator::I32x4ExtMulLowI16x8U | Operator::I32x4ExtMulHighI16x8U => {
4335                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
4336                    }
4337                    _ => unreachable!("Unhandled internal variant"),
4338                };
4339                let shuffle_array = match op {
4340                    Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulLowI16x8U => [
4341                        self.intrinsics.i32_consts[0],
4342                        self.intrinsics.i32_consts[1],
4343                        self.intrinsics.i32_consts[2],
4344                        self.intrinsics.i32_consts[3],
4345                    ],
4346                    Operator::I32x4ExtMulHighI16x8S | Operator::I32x4ExtMulHighI16x8U => [
4347                        self.intrinsics.i32_consts[4],
4348                        self.intrinsics.i32_consts[5],
4349                        self.intrinsics.i32_consts[6],
4350                        self.intrinsics.i32_consts[7],
4351                    ],
4352                    _ => unreachable!("Unhandled internal variant"),
4353                };
4354                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4355                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4356                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4357                let val1 = err!(self.builder.build_shuffle_vector(
4358                    v1,
4359                    v1.get_type().get_undef(),
4360                    VectorType::const_vector(&shuffle_array),
4361                    "",
4362                ));
4363                let val1 = err!(extend_op(self, val1));
4364                let val2 = err!(self.builder.build_shuffle_vector(
4365                    v2,
4366                    v2.get_type().get_undef(),
4367                    VectorType::const_vector(&shuffle_array),
4368                    "",
4369                ));
4370                let val2 = err!(extend_op(self, val2));
4371                let res = err!(self.builder.build_int_mul(val1, val2, ""));
4372                let res = err!(
4373                    self.builder
4374                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4375                );
4376                self.state.push1(res);
4377            }
4378            Operator::I64x2ExtMulLowI32x4S
4379            | Operator::I64x2ExtMulLowI32x4U
4380            | Operator::I64x2ExtMulHighI32x4S
4381            | Operator::I64x2ExtMulHighI32x4U => {
4382                let extend_op = match op {
4383                    Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulHighI32x4S => {
4384                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
4385                    }
4386                    Operator::I64x2ExtMulLowI32x4U | Operator::I64x2ExtMulHighI32x4U => {
4387                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
4388                    }
4389                    _ => unreachable!("Unhandled internal variant"),
4390                };
4391                let shuffle_array = match op {
4392                    Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulLowI32x4U => {
4393                        [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
4394                    }
4395                    Operator::I64x2ExtMulHighI32x4S | Operator::I64x2ExtMulHighI32x4U => {
4396                        [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
4397                    }
4398                    _ => unreachable!("Unhandled internal variant"),
4399                };
4400                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4401                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4402                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4403                let val1 = err!(self.builder.build_shuffle_vector(
4404                    v1,
4405                    v1.get_type().get_undef(),
4406                    VectorType::const_vector(&shuffle_array),
4407                    "",
4408                ));
4409                let val1 = err!(extend_op(self, val1));
4410                let val2 = err!(self.builder.build_shuffle_vector(
4411                    v2,
4412                    v2.get_type().get_undef(),
4413                    VectorType::const_vector(&shuffle_array),
4414                    "",
4415                ));
4416                let val2 = err!(extend_op(self, val2));
4417                let res = err!(self.builder.build_int_mul(val1, val2, ""));
4418                let res = err!(
4419                    self.builder
4420                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4421                );
4422                self.state.push1(res);
4423            }
4424            Operator::I32x4DotI16x8S => {
4425                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4426                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4427                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4428                let low_i16 = [
4429                    self.intrinsics.i32_consts[0],
4430                    self.intrinsics.i32_consts[2],
4431                    self.intrinsics.i32_consts[4],
4432                    self.intrinsics.i32_consts[6],
4433                ];
4434                let high_i16 = [
4435                    self.intrinsics.i32_consts[1],
4436                    self.intrinsics.i32_consts[3],
4437                    self.intrinsics.i32_consts[5],
4438                    self.intrinsics.i32_consts[7],
4439                ];
4440                let v1_low = err!(self.builder.build_shuffle_vector(
4441                    v1,
4442                    v1.get_type().get_undef(),
4443                    VectorType::const_vector(&low_i16),
4444                    "",
4445                ));
4446                let v1_low = err!(self.builder.build_int_s_extend(
4447                    v1_low,
4448                    self.intrinsics.i32x4_ty,
4449                    ""
4450                ));
4451                let v1_high = err!(self.builder.build_shuffle_vector(
4452                    v1,
4453                    v1.get_type().get_undef(),
4454                    VectorType::const_vector(&high_i16),
4455                    "",
4456                ));
4457                let v1_high = err!(self.builder.build_int_s_extend(
4458                    v1_high,
4459                    self.intrinsics.i32x4_ty,
4460                    ""
4461                ));
4462                let v2_low = err!(self.builder.build_shuffle_vector(
4463                    v2,
4464                    v2.get_type().get_undef(),
4465                    VectorType::const_vector(&low_i16),
4466                    "",
4467                ));
4468                let v2_low = err!(self.builder.build_int_s_extend(
4469                    v2_low,
4470                    self.intrinsics.i32x4_ty,
4471                    ""
4472                ));
4473                let v2_high = err!(self.builder.build_shuffle_vector(
4474                    v2,
4475                    v2.get_type().get_undef(),
4476                    VectorType::const_vector(&high_i16),
4477                    "",
4478                ));
4479                let v2_high = err!(self.builder.build_int_s_extend(
4480                    v2_high,
4481                    self.intrinsics.i32x4_ty,
4482                    ""
4483                ));
4484                let low_product = err!(self.builder.build_int_mul(v1_low, v2_low, ""));
4485                let high_product = err!(self.builder.build_int_mul(v1_high, v2_high, ""));
4486
4487                let res = err!(self.builder.build_int_add(low_product, high_product, ""));
4488                let res = err!(
4489                    self.builder
4490                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4491                );
4492                self.state.push1(res);
4493            }
4494            Operator::I16x8RelaxedDotI8x16I7x16S
4495                if self.cpu_features.contains(CpuFeature::SSSE3) =>
4496            {
4497                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4498                let (a, _) = self.v128_into_i8x16(v1, i1)?;
4499                let (b, _) = self.v128_into_i8x16(v2, i2)?;
4500
4501                let res = self
4502                    .build_call_with_param_attributes(
4503                        self.intrinsics.x86_64.pmaddubsw128,
4504                        &[b.into(), a.into()],
4505                        "",
4506                    )?
4507                    .try_as_basic_value()
4508                    .unwrap_basic()
4509                    .into_vector_value();
4510                let res = err!(
4511                    self.builder
4512                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4513                );
4514                self.state.push1(res);
4515            }
4516            Operator::I16x8RelaxedDotI8x16I7x16S => {
4517                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4518                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4519                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4520
4521                let left_indices = [
4522                    self.intrinsics.i32_consts[0],
4523                    self.intrinsics.i32_consts[2],
4524                    self.intrinsics.i32_consts[4],
4525                    self.intrinsics.i32_consts[6],
4526                    self.intrinsics.i32_consts[8],
4527                    self.intrinsics.i32_consts[10],
4528                    self.intrinsics.i32_consts[12],
4529                    self.intrinsics.i32_consts[14],
4530                ];
4531                let right_indices = [
4532                    self.intrinsics.i32_consts[1],
4533                    self.intrinsics.i32_consts[3],
4534                    self.intrinsics.i32_consts[5],
4535                    self.intrinsics.i32_consts[7],
4536                    self.intrinsics.i32_consts[9],
4537                    self.intrinsics.i32_consts[11],
4538                    self.intrinsics.i32_consts[13],
4539                    self.intrinsics.i32_consts[15],
4540                ];
4541
4542                let v1_left = err!(self.builder.build_shuffle_vector(
4543                    v1,
4544                    v1.get_type().get_undef(),
4545                    VectorType::const_vector(&left_indices),
4546                    "",
4547                ));
4548                let v1_left = err!(self.builder.build_int_s_extend(
4549                    v1_left,
4550                    self.intrinsics.i16x8_ty,
4551                    ""
4552                ));
4553                let v1_right = err!(self.builder.build_shuffle_vector(
4554                    v1,
4555                    v1.get_type().get_undef(),
4556                    VectorType::const_vector(&right_indices),
4557                    "",
4558                ));
4559                let v1_right = err!(self.builder.build_int_s_extend(
4560                    v1_right,
4561                    self.intrinsics.i16x8_ty,
4562                    ""
4563                ));
4564
4565                let v2_left = err!(self.builder.build_shuffle_vector(
4566                    v2,
4567                    v2.get_type().get_undef(),
4568                    VectorType::const_vector(&left_indices),
4569                    "",
4570                ));
4571                let v2_left = err!(self.builder.build_int_s_extend(
4572                    v2_left,
4573                    self.intrinsics.i16x8_ty,
4574                    ""
4575                ));
4576                let v2_right = err!(self.builder.build_shuffle_vector(
4577                    v2,
4578                    v2.get_type().get_undef(),
4579                    VectorType::const_vector(&right_indices),
4580                    "",
4581                ));
4582                let v2_right = err!(self.builder.build_int_s_extend(
4583                    v2_right,
4584                    self.intrinsics.i16x8_ty,
4585                    ""
4586                ));
4587
4588                let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4589                let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4590                let res = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4591                let res = err!(
4592                    self.builder
4593                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4594                );
4595                self.state.push1(res);
4596            }
4597            Operator::I32x4RelaxedDotI8x16I7x16AddS
4598                if self.cpu_features.contains(CpuFeature::SSSE3) =>
4599            {
4600                let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4601                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4602                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4603                let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4604
4605                // PMADDUBSW computes pairwise u8*i8 with i16 saturation, which
4606                // is one of the valid relaxed dot-product behaviors.
4607                let dot16 = self
4608                    .build_call_with_param_attributes(
4609                        self.intrinsics.x86_64.pmaddubsw128,
4610                        &[v2.into(), v1.into()],
4611                        "",
4612                    )?
4613                    .try_as_basic_value()
4614                    .unwrap_basic()
4615                    .into_vector_value();
4616                let ones =
4617                    VectorType::const_vector(&[self.intrinsics.i16_ty.const_int(1, false); 8]);
4618                let dot32 = self
4619                    .build_call_with_param_attributes(
4620                        self.intrinsics.x86_64.pmaddwd128,
4621                        &[dot16.into(), ones.into()],
4622                        "",
4623                    )?
4624                    .try_as_basic_value()
4625                    .unwrap_basic()
4626                    .into_vector_value();
4627                let res = err!(self.builder.build_int_add(dot32, acc, ""));
4628                let res = err!(
4629                    self.builder
4630                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4631                );
4632                self.state.push1(res);
4633            }
4634            Operator::I32x4RelaxedDotI8x16I7x16AddS => {
4635                let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4636                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4637                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4638                let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4639
4640                let left_indices = [
4641                    self.intrinsics.i32_consts[0],
4642                    self.intrinsics.i32_consts[2],
4643                    self.intrinsics.i32_consts[4],
4644                    self.intrinsics.i32_consts[6],
4645                    self.intrinsics.i32_consts[8],
4646                    self.intrinsics.i32_consts[10],
4647                    self.intrinsics.i32_consts[12],
4648                    self.intrinsics.i32_consts[14],
4649                ];
4650                let right_indices = [
4651                    self.intrinsics.i32_consts[1],
4652                    self.intrinsics.i32_consts[3],
4653                    self.intrinsics.i32_consts[5],
4654                    self.intrinsics.i32_consts[7],
4655                    self.intrinsics.i32_consts[9],
4656                    self.intrinsics.i32_consts[11],
4657                    self.intrinsics.i32_consts[13],
4658                    self.intrinsics.i32_consts[15],
4659                ];
4660
4661                let v1_left = err!(self.builder.build_shuffle_vector(
4662                    v1,
4663                    v1.get_type().get_undef(),
4664                    VectorType::const_vector(&left_indices),
4665                    "",
4666                ));
4667                let v1_left = err!(self.builder.build_int_s_extend(
4668                    v1_left,
4669                    self.intrinsics.i16x8_ty,
4670                    ""
4671                ));
4672                let v1_right = err!(self.builder.build_shuffle_vector(
4673                    v1,
4674                    v1.get_type().get_undef(),
4675                    VectorType::const_vector(&right_indices),
4676                    "",
4677                ));
4678                let v1_right = err!(self.builder.build_int_s_extend(
4679                    v1_right,
4680                    self.intrinsics.i16x8_ty,
4681                    ""
4682                ));
4683
4684                let v2_left = err!(self.builder.build_shuffle_vector(
4685                    v2,
4686                    v2.get_type().get_undef(),
4687                    VectorType::const_vector(&left_indices),
4688                    "",
4689                ));
4690                let v2_left = err!(self.builder.build_int_s_extend(
4691                    v2_left,
4692                    self.intrinsics.i16x8_ty,
4693                    ""
4694                ));
4695                let v2_right = err!(self.builder.build_shuffle_vector(
4696                    v2,
4697                    v2.get_type().get_undef(),
4698                    VectorType::const_vector(&right_indices),
4699                    "",
4700                ));
4701                let v2_right = err!(self.builder.build_int_s_extend(
4702                    v2_right,
4703                    self.intrinsics.i16x8_ty,
4704                    ""
4705                ));
4706
4707                let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4708                let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4709                let dot16 = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4710
4711                let pair_left = err!(self.builder.build_shuffle_vector(
4712                    dot16,
4713                    dot16.get_type().get_undef(),
4714                    VectorType::const_vector(&[
4715                        self.intrinsics.i32_consts[0],
4716                        self.intrinsics.i32_consts[2],
4717                        self.intrinsics.i32_consts[4],
4718                        self.intrinsics.i32_consts[6],
4719                    ]),
4720                    "",
4721                ));
4722                let pair_left = err!(self.builder.build_int_s_extend(
4723                    pair_left,
4724                    self.intrinsics.i32x4_ty,
4725                    ""
4726                ));
4727                let pair_right = err!(self.builder.build_shuffle_vector(
4728                    dot16,
4729                    dot16.get_type().get_undef(),
4730                    VectorType::const_vector(&[
4731                        self.intrinsics.i32_consts[1],
4732                        self.intrinsics.i32_consts[3],
4733                        self.intrinsics.i32_consts[5],
4734                        self.intrinsics.i32_consts[7],
4735                    ]),
4736                    "",
4737                ));
4738                let pair_right = err!(self.builder.build_int_s_extend(
4739                    pair_right,
4740                    self.intrinsics.i32x4_ty,
4741                    ""
4742                ));
4743                let dot32 = err!(self.builder.build_int_add(pair_left, pair_right, ""));
4744                let res = err!(self.builder.build_int_add(dot32, acc, ""));
4745                let res = err!(
4746                    self.builder
4747                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4748                );
4749                self.state.push1(res);
4750            }
4751            Operator::I32DivS | Operator::I64DivS => {
4752                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4753                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4754                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4755                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4756
4757                self.trap_if_zero_or_overflow(v1, v2)?;
4758
4759                let res = err!(self.builder.build_int_signed_div(v1, v2, ""));
4760                self.state.push1(res);
4761            }
4762            Operator::I32DivU | Operator::I64DivU => {
4763                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4764                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4765                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4766                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4767
4768                self.trap_if_zero(v2)?;
4769
4770                let res = err!(self.builder.build_int_unsigned_div(v1, v2, ""));
4771                self.state.push1(res);
4772            }
4773            Operator::I32RemS | Operator::I64RemS => {
4774                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4775                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4776                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4777                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4778                let int_type = v1.get_type();
4779                let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
4780                    let min_value = int_type.const_int(i32::MIN as u64, false);
4781                    let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
4782                    (min_value, neg_one_value)
4783                } else if int_type == self.intrinsics.i64_ty {
4784                    let min_value = int_type.const_int(i64::MIN as u64, false);
4785                    let neg_one_value = int_type.const_int(-1i64 as u64, false);
4786                    (min_value, neg_one_value)
4787                } else {
4788                    unreachable!()
4789                };
4790
4791                self.trap_if_zero(v2)?;
4792
4793                // "Overflow also leads to undefined behavior; this is a rare
4794                // case, but can occur, for example, by taking the remainder of
4795                // a 32-bit division of -2147483648 by -1. (The remainder
4796                // doesn’t actually overflow, but this rule lets srem be
4797                // implemented using instructions that return both the result
4798                // of the division and the remainder.)"
4799                //   -- https://llvm.org/docs/LangRef.html#srem-instruction
4800                //
4801                // In Wasm, the i32.rem_s i32.const -2147483648 i32.const -1 is
4802                // i32.const 0. We implement this by swapping out the left value
4803                // for 0 in this case.
4804                let will_overflow = err!(self.builder.build_and(
4805                    err!(self.builder.build_int_compare(
4806                        IntPredicate::EQ,
4807                        v1,
4808                        min_value,
4809                        "left_is_min"
4810                    )),
4811                    err!(self.builder.build_int_compare(
4812                        IntPredicate::EQ,
4813                        v2,
4814                        neg_one_value,
4815                        "right_is_neg_one",
4816                    )),
4817                    "srem_will_overflow",
4818                ));
4819                let v1 =
4820                    err!(
4821                        self.builder
4822                            .build_select(will_overflow, int_type.const_zero(), v1, "")
4823                    )
4824                    .into_int_value();
4825                let res = err!(self.builder.build_int_signed_rem(v1, v2, ""));
4826                self.state.push1(res);
4827            }
4828            Operator::I32RemU | Operator::I64RemU => {
4829                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4830                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4831                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4832                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4833
4834                self.trap_if_zero(v2)?;
4835
4836                let res = err!(self.builder.build_int_unsigned_rem(v1, v2, ""));
4837                self.state.push1(res);
4838            }
4839            Operator::I32And | Operator::I64And | Operator::V128And => {
4840                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4841                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4842                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4843                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4844                let res = err!(self.builder.build_and(v1, v2, ""));
4845                self.state.push1(res);
4846            }
4847            Operator::I32Or | Operator::I64Or | Operator::V128Or => {
4848                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4849                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4850                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4851                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4852                let res = err!(self.builder.build_or(v1, v2, ""));
4853                self.state.push1(res);
4854            }
4855            Operator::I32Xor | Operator::I64Xor | Operator::V128Xor => {
4856                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4857                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4858                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4859                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4860                let res = err!(self.builder.build_xor(v1, v2, ""));
4861                self.state.push1(res);
4862            }
4863            Operator::V128AndNot => {
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 v2 = err!(self.builder.build_not(v2, ""));
4869                let res = err!(self.builder.build_and(v1, v2, ""));
4870                self.state.push1(res);
4871            }
4872            Operator::I8x16RelaxedLaneselect
4873            | Operator::I16x8RelaxedLaneselect
4874            | Operator::I32x4RelaxedLaneselect
4875            | Operator::I64x2RelaxedLaneselect
4876                if self.cpu_features.contains(CpuFeature::SSE41) =>
4877            {
4878                let ((v1, i1), (v2, i2), (mask, mask_info)) = self.state.pop3_extra()?;
4879                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4880                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4881                let mask = self.apply_pending_canonicalization(mask, mask_info)?;
4882
4883                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4884                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4885                let (mask, _) = self.v128_into_i8x16(mask, mask_info)?;
4886                let res = self
4887                    .build_call_with_param_attributes(
4888                        self.intrinsics.x86_64.pblendvb,
4889                        &[v2.into(), v1.into(), mask.into()],
4890                        "",
4891                    )?
4892                    .try_as_basic_value()
4893                    .unwrap_basic();
4894                let res = err!(
4895                    self.builder
4896                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4897                );
4898                self.state.push1(res);
4899            }
4900            Operator::I8x16RelaxedLaneselect
4901            | Operator::I16x8RelaxedLaneselect
4902            | Operator::I32x4RelaxedLaneselect
4903            | Operator::I64x2RelaxedLaneselect
4904            | Operator::V128Bitselect => {
4905                let ((v1, i1), (v2, i2), (cond, cond_info)) = self.state.pop3_extra()?;
4906                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4907                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4908                let cond = self.apply_pending_canonicalization(cond, cond_info)?;
4909                let v1 = err!(
4910                    self.builder
4911                        .build_bit_cast(v1, self.intrinsics.i1x128_ty, "")
4912                )
4913                .into_vector_value();
4914                let v2 = err!(
4915                    self.builder
4916                        .build_bit_cast(v2, self.intrinsics.i1x128_ty, "")
4917                )
4918                .into_vector_value();
4919                let cond = err!(
4920                    self.builder
4921                        .build_bit_cast(cond, self.intrinsics.i1x128_ty, "")
4922                )
4923                .into_vector_value();
4924                let res = err!(self.builder.build_select(cond, v1, v2, ""));
4925                let res = err!(
4926                    self.builder
4927                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4928                );
4929                self.state.push1(res);
4930            }
4931            Operator::I8x16Bitmask => {
4932                let (v, i) = self.state.pop1_extra()?;
4933                let (v, _) = self.v128_into_i8x16(v, i)?;
4934
4935                let zeros = self.intrinsics.i8x16_ty.const_zero();
4936                let res = err!(
4937                    self.builder
4938                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
4939                );
4940                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i16_ty, ""))
4941                    .into_int_value();
4942                let res = err!(
4943                    self.builder
4944                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4945                );
4946                self.state.push1(res);
4947            }
4948            Operator::I16x8Bitmask => {
4949                let (v, i) = self.state.pop1_extra()?;
4950                let (v, _) = self.v128_into_i16x8(v, i)?;
4951
4952                let zeros = self.intrinsics.i16x8_ty.const_zero();
4953                let res = err!(
4954                    self.builder
4955                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
4956                );
4957                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i8_ty, ""))
4958                    .into_int_value();
4959                let res = err!(
4960                    self.builder
4961                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4962                );
4963                self.state.push1(res);
4964            }
4965            Operator::I32x4Bitmask => {
4966                let (v, i) = self.state.pop1_extra()?;
4967                let (v, _) = self.v128_into_i32x4(v, i)?;
4968
4969                let zeros = self.intrinsics.i32x4_ty.const_zero();
4970                let res = err!(
4971                    self.builder
4972                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
4973                );
4974                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i4_ty, ""))
4975                    .into_int_value();
4976                let res = err!(
4977                    self.builder
4978                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4979                );
4980                self.state.push1(res);
4981            }
4982            Operator::I64x2Bitmask => {
4983                let (v, i) = self.state.pop1_extra()?;
4984                let (v, _) = self.v128_into_i64x2(v, i)?;
4985
4986                let zeros = self.intrinsics.i64x2_ty.const_zero();
4987                let res = err!(
4988                    self.builder
4989                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
4990                );
4991                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i2_ty, ""))
4992                    .into_int_value();
4993                let res = err!(
4994                    self.builder
4995                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4996                );
4997                self.state.push1(res);
4998            }
4999            Operator::I32Shl => {
5000                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5001                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5002                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5003                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5004                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5005                let v2 = err!(self.builder.build_and(v2, mask, ""));
5006                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5007                self.state.push1(res);
5008            }
5009            Operator::I64Shl => {
5010                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5011                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5012                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5013                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5014                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5015                let v2 = err!(self.builder.build_and(v2, mask, ""));
5016                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5017                self.state.push1(res);
5018            }
5019            Operator::I8x16Shl => {
5020                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5021                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5022                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5023                let v2 = v2.into_int_value();
5024                let v2 = err!(
5025                    self.builder
5026                        .build_and(v2, self.intrinsics.i32_consts[7], "")
5027                );
5028                let v2 = err!(
5029                    self.builder
5030                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5031                );
5032                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5033                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5034                let res = err!(
5035                    self.builder
5036                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5037                );
5038                self.state.push1(res);
5039            }
5040            Operator::I16x8Shl => {
5041                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5042                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5043                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5044                let v2 = v2.into_int_value();
5045                let v2 = err!(
5046                    self.builder
5047                        .build_and(v2, self.intrinsics.i32_consts[15], "")
5048                );
5049                let v2 = err!(
5050                    self.builder
5051                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5052                );
5053                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5054                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5055                let res = err!(
5056                    self.builder
5057                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5058                );
5059                self.state.push1(res);
5060            }
5061            Operator::I32x4Shl => {
5062                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5063                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5064                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5065                let v2 = v2.into_int_value();
5066                let v2 = err!(self.builder.build_and(
5067                    v2,
5068                    self.intrinsics.i32_ty.const_int(31, false),
5069                    ""
5070                ));
5071                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5072                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5073                let res = err!(
5074                    self.builder
5075                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5076                );
5077                self.state.push1(res);
5078            }
5079            Operator::I64x2Shl => {
5080                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5081                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5082                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5083                let v2 = v2.into_int_value();
5084                let v2 = err!(self.builder.build_and(
5085                    v2,
5086                    self.intrinsics.i32_ty.const_int(63, false),
5087                    ""
5088                ));
5089                let v2 = err!(
5090                    self.builder
5091                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5092                );
5093                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5094                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5095                let res = err!(
5096                    self.builder
5097                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5098                );
5099                self.state.push1(res);
5100            }
5101            Operator::I32ShrS => {
5102                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5103                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5104                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5105                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5106                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5107                let v2 = err!(self.builder.build_and(v2, mask, ""));
5108                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5109                self.state.push1(res);
5110            }
5111            Operator::I64ShrS => {
5112                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5113                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5114                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5115                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5116                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5117                let v2 = err!(self.builder.build_and(v2, mask, ""));
5118                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5119                self.state.push1(res);
5120            }
5121            Operator::I8x16ShrS => {
5122                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5123                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5124                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5125                let v2 = v2.into_int_value();
5126                let v2 = err!(
5127                    self.builder
5128                        .build_and(v2, self.intrinsics.i32_consts[7], "")
5129                );
5130                let v2 = err!(
5131                    self.builder
5132                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5133                );
5134                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5135                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5136                let res = err!(
5137                    self.builder
5138                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5139                );
5140                self.state.push1(res);
5141            }
5142            Operator::I16x8ShrS => {
5143                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5144                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5145                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5146                let v2 = v2.into_int_value();
5147                let v2 = err!(
5148                    self.builder
5149                        .build_and(v2, self.intrinsics.i32_consts[15], "")
5150                );
5151                let v2 = err!(
5152                    self.builder
5153                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5154                );
5155                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5156                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5157                let res = err!(
5158                    self.builder
5159                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5160                );
5161                self.state.push1(res);
5162            }
5163            Operator::I32x4ShrS => {
5164                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5165                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5166                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5167                let v2 = v2.into_int_value();
5168                let v2 = err!(self.builder.build_and(
5169                    v2,
5170                    self.intrinsics.i32_ty.const_int(31, false),
5171                    ""
5172                ));
5173                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5174                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5175                let res = err!(
5176                    self.builder
5177                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5178                );
5179                self.state.push1(res);
5180            }
5181            Operator::I64x2ShrS => {
5182                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5183                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5184                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5185                let v2 = v2.into_int_value();
5186                let v2 = err!(self.builder.build_and(
5187                    v2,
5188                    self.intrinsics.i32_ty.const_int(63, false),
5189                    ""
5190                ));
5191                let v2 = err!(
5192                    self.builder
5193                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5194                );
5195                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5196                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5197                let res = err!(
5198                    self.builder
5199                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5200                );
5201                self.state.push1(res);
5202            }
5203            Operator::I32ShrU => {
5204                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5205                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5206                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5207                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5208                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5209                let v2 = err!(self.builder.build_and(v2, mask, ""));
5210                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5211                self.state.push1(res);
5212            }
5213            Operator::I64ShrU => {
5214                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5215                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5216                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5217                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5218                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5219                let v2 = err!(self.builder.build_and(v2, mask, ""));
5220                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5221                self.state.push1(res);
5222            }
5223            Operator::I8x16ShrU => {
5224                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5225                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5226                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5227                let v2 = v2.into_int_value();
5228                let v2 = err!(
5229                    self.builder
5230                        .build_and(v2, self.intrinsics.i32_consts[7], "")
5231                );
5232                let v2 = err!(
5233                    self.builder
5234                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5235                );
5236                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5237                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5238                let res = err!(
5239                    self.builder
5240                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5241                );
5242                self.state.push1(res);
5243            }
5244            Operator::I16x8ShrU => {
5245                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5246                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5247                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5248                let v2 = v2.into_int_value();
5249                let v2 = err!(
5250                    self.builder
5251                        .build_and(v2, self.intrinsics.i32_consts[15], "")
5252                );
5253                let v2 = err!(
5254                    self.builder
5255                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5256                );
5257                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5258                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5259                let res = err!(
5260                    self.builder
5261                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5262                );
5263                self.state.push1(res);
5264            }
5265            Operator::I32x4ShrU => {
5266                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5267                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5268                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5269                let v2 = v2.into_int_value();
5270                let v2 = err!(self.builder.build_and(
5271                    v2,
5272                    self.intrinsics.i32_ty.const_int(31, false),
5273                    ""
5274                ));
5275                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5276                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5277                let res = err!(
5278                    self.builder
5279                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5280                );
5281                self.state.push1(res);
5282            }
5283            Operator::I64x2ShrU => {
5284                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5285                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5286                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5287                let v2 = v2.into_int_value();
5288                let v2 = err!(self.builder.build_and(
5289                    v2,
5290                    self.intrinsics.i32_ty.const_int(63, false),
5291                    ""
5292                ));
5293                let v2 = err!(
5294                    self.builder
5295                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5296                );
5297                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5298                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5299                let res = err!(
5300                    self.builder
5301                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5302                );
5303                self.state.push1(res);
5304            }
5305            Operator::I32Rotl => {
5306                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5307                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5308                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5309                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5310                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5311                let v2 = err!(self.builder.build_and(v2, mask, ""));
5312                let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5313                let rhs = {
5314                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5315                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5316                    err!(self.builder.build_right_shift(v1, rhs, false, ""))
5317                };
5318                let res = err!(self.builder.build_or(lhs, rhs, ""));
5319                self.state.push1(res);
5320            }
5321            Operator::I64Rotl => {
5322                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5323                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5324                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5325                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5326                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5327                let v2 = err!(self.builder.build_and(v2, mask, ""));
5328                let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5329                let rhs = {
5330                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5331                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5332                    err!(self.builder.build_right_shift(v1, rhs, false, ""))
5333                };
5334                let res = err!(self.builder.build_or(lhs, rhs, ""));
5335                self.state.push1(res);
5336            }
5337            Operator::I32Rotr => {
5338                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5339                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5340                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5341                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5342                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5343                let v2 = err!(self.builder.build_and(v2, mask, ""));
5344                let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5345                let rhs = {
5346                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5347                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5348                    err!(self.builder.build_left_shift(v1, rhs, ""))
5349                };
5350                let res = err!(self.builder.build_or(lhs, rhs, ""));
5351                self.state.push1(res);
5352            }
5353            Operator::I64Rotr => {
5354                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5355                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5356                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5357                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5358                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5359                let v2 = err!(self.builder.build_and(v2, mask, ""));
5360                let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5361                let rhs = {
5362                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5363                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5364                    err!(self.builder.build_left_shift(v1, rhs, ""))
5365                };
5366                let res = err!(self.builder.build_or(lhs, rhs, ""));
5367                self.state.push1(res);
5368            }
5369            Operator::I32Clz => {
5370                let (input, info) = self.state.pop1_extra()?;
5371                let input = self.apply_pending_canonicalization(input, info)?;
5372                let is_zero_undef = self.intrinsics.i1_zero;
5373                let res = self
5374                    .build_call_with_param_attributes(
5375                        self.intrinsics.ctlz_i32,
5376                        &[input.into(), is_zero_undef.into()],
5377                        "",
5378                    )?
5379                    .try_as_basic_value()
5380                    .unwrap_basic();
5381                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5382            }
5383            Operator::I64Clz => {
5384                let (input, info) = self.state.pop1_extra()?;
5385                let input = self.apply_pending_canonicalization(input, info)?;
5386                let is_zero_undef = self.intrinsics.i1_zero;
5387                let res = self
5388                    .build_call_with_param_attributes(
5389                        self.intrinsics.ctlz_i64,
5390                        &[input.into(), is_zero_undef.into()],
5391                        "",
5392                    )?
5393                    .try_as_basic_value()
5394                    .unwrap_basic();
5395                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5396            }
5397            Operator::I32Ctz => {
5398                let (input, info) = self.state.pop1_extra()?;
5399                let input = self.apply_pending_canonicalization(input, info)?;
5400                let is_zero_undef = self.intrinsics.i1_zero;
5401                let res = self
5402                    .build_call_with_param_attributes(
5403                        self.intrinsics.cttz_i32,
5404                        &[input.into(), is_zero_undef.into()],
5405                        "",
5406                    )?
5407                    .try_as_basic_value()
5408                    .unwrap_basic();
5409                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5410            }
5411            Operator::I64Ctz => {
5412                let (input, info) = self.state.pop1_extra()?;
5413                let input = self.apply_pending_canonicalization(input, info)?;
5414                let is_zero_undef = self.intrinsics.i1_zero;
5415                let res = self
5416                    .build_call_with_param_attributes(
5417                        self.intrinsics.cttz_i64,
5418                        &[input.into(), is_zero_undef.into()],
5419                        "",
5420                    )?
5421                    .try_as_basic_value()
5422                    .unwrap_basic();
5423                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5424            }
5425            Operator::I8x16Popcnt => {
5426                let (v, i) = self.state.pop1_extra()?;
5427                let (v, _) = self.v128_into_i8x16(v, i)?;
5428                let res = self
5429                    .build_call_with_param_attributes(self.intrinsics.ctpop_i8x16, &[v.into()], "")?
5430                    .try_as_basic_value()
5431                    .unwrap_basic();
5432                let res = err!(
5433                    self.builder
5434                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5435                );
5436                self.state.push1(res);
5437            }
5438            Operator::I32Popcnt => {
5439                let (input, info) = self.state.pop1_extra()?;
5440                let input = self.apply_pending_canonicalization(input, info)?;
5441                let res = self
5442                    .build_call_with_param_attributes(
5443                        self.intrinsics.ctpop_i32,
5444                        &[input.into()],
5445                        "",
5446                    )?
5447                    .try_as_basic_value()
5448                    .unwrap_basic();
5449                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5450            }
5451            Operator::I64Popcnt => {
5452                let (input, info) = self.state.pop1_extra()?;
5453                let input = self.apply_pending_canonicalization(input, info)?;
5454                let res = self
5455                    .build_call_with_param_attributes(
5456                        self.intrinsics.ctpop_i64,
5457                        &[input.into()],
5458                        "",
5459                    )?
5460                    .try_as_basic_value()
5461                    .unwrap_basic();
5462                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5463            }
5464            Operator::I32Eqz => {
5465                let input = self.state.pop1()?.into_int_value();
5466                let cond = err!(self.builder.build_int_compare(
5467                    IntPredicate::EQ,
5468                    input,
5469                    self.intrinsics.i32_zero,
5470                    "",
5471                ));
5472                let res = err!(
5473                    self.builder
5474                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5475                );
5476                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5477            }
5478            Operator::I64Eqz => {
5479                let input = self.state.pop1()?.into_int_value();
5480                let cond = err!(self.builder.build_int_compare(
5481                    IntPredicate::EQ,
5482                    input,
5483                    self.intrinsics.i64_zero,
5484                    "",
5485                ));
5486                let res = err!(
5487                    self.builder
5488                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5489                );
5490                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5491            }
5492            Operator::I8x16Abs => {
5493                let (v, i) = self.state.pop1_extra()?;
5494                let (v, _) = self.v128_into_i8x16(v, i)?;
5495
5496                let seven = self.intrinsics.i8_ty.const_int(7, false);
5497                let seven = VectorType::const_vector(&[seven; 16]);
5498                let all_sign_bits = err!(self.builder.build_right_shift(v, seven, true, ""));
5499                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5500                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5501                let res = err!(
5502                    self.builder
5503                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5504                );
5505                self.state.push1(res);
5506            }
5507            Operator::I16x8Abs => {
5508                let (v, i) = self.state.pop1_extra()?;
5509                let (v, _) = self.v128_into_i16x8(v, i)?;
5510
5511                let fifteen = self.intrinsics.i16_ty.const_int(15, false);
5512                let fifteen = VectorType::const_vector(&[fifteen; 8]);
5513                let all_sign_bits = err!(self.builder.build_right_shift(v, fifteen, true, ""));
5514                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5515                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5516                let res = err!(
5517                    self.builder
5518                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5519                );
5520                self.state.push1(res);
5521            }
5522            Operator::I32x4Abs => {
5523                let (v, i) = self.state.pop1_extra()?;
5524                let (v, _) = self.v128_into_i32x4(v, i)?;
5525
5526                let thirtyone = self.intrinsics.i32_ty.const_int(31, false);
5527                let thirtyone = VectorType::const_vector(&[thirtyone; 4]);
5528                let all_sign_bits = err!(self.builder.build_right_shift(v, thirtyone, true, ""));
5529                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5530                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5531                let res = err!(
5532                    self.builder
5533                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5534                );
5535                self.state.push1(res);
5536            }
5537            Operator::I64x2Abs => {
5538                let (v, i) = self.state.pop1_extra()?;
5539                let (v, _) = self.v128_into_i64x2(v, i)?;
5540
5541                let sixtythree = self.intrinsics.i64_ty.const_int(63, false);
5542                let sixtythree = VectorType::const_vector(&[sixtythree; 2]);
5543                let all_sign_bits = err!(self.builder.build_right_shift(v, sixtythree, true, ""));
5544                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5545                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5546                let res = err!(
5547                    self.builder
5548                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5549                );
5550                self.state.push1(res);
5551            }
5552            Operator::I8x16MinS => {
5553                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5554                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5555                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5556                let cmp = err!(
5557                    self.builder
5558                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5559                );
5560                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5561                let res = err!(
5562                    self.builder
5563                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5564                );
5565                self.state.push1(res);
5566            }
5567            Operator::I8x16MinU => {
5568                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5569                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5570                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5571                let cmp = err!(
5572                    self.builder
5573                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5574                );
5575                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5576                let res = err!(
5577                    self.builder
5578                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5579                );
5580                self.state.push1(res);
5581            }
5582            Operator::I8x16MaxS => {
5583                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5584                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5585                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5586                let cmp = err!(
5587                    self.builder
5588                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5589                );
5590                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
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::I8x16MaxU => {
5598                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5599                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5600                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5601                let cmp = err!(
5602                    self.builder
5603                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5604                );
5605                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
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::I16x8MinS => {
5613                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5614                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5615                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5616                let cmp = err!(
5617                    self.builder
5618                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5619                );
5620                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
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::I16x8MinU => {
5628                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5629                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5630                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5631                let cmp = err!(
5632                    self.builder
5633                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5634                );
5635                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
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::I16x8MaxS => {
5643                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5644                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5645                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5646                let cmp = err!(
5647                    self.builder
5648                        .build_int_compare(IntPredicate::SGT, 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::I16x8MaxU => {
5658                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5659                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5660                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5661                let cmp = err!(
5662                    self.builder
5663                        .build_int_compare(IntPredicate::UGT, 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::I32x4MinS => {
5673                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5674                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5675                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5676                let cmp = err!(
5677                    self.builder
5678                        .build_int_compare(IntPredicate::SLT, 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::I32x4MinU => {
5688                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5689                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5690                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5691                let cmp = err!(
5692                    self.builder
5693                        .build_int_compare(IntPredicate::ULT, 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::I32x4MaxS => {
5703                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5704                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5705                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5706                let cmp = err!(
5707                    self.builder
5708                        .build_int_compare(IntPredicate::SGT, 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::I32x4MaxU => {
5718                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5719                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5720                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5721                let cmp = err!(
5722                    self.builder
5723                        .build_int_compare(IntPredicate::UGT, 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::I8x16AvgrU => {
5733                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5734                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5735                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5736
5737                // This approach is faster on x86-64 when the PAVG[BW]
5738                // instructions are available. On other platforms, an alternative
5739                // implementation appears likely to outperform, described here:
5740                //   %a = or %v1, %v2
5741                //   %b = and %a, 1
5742                //   %v1 = lshr %v1, 1
5743                //   %v2 = lshr %v2, 1
5744                //   %sum = add %v1, %v2
5745                //   %res = add %sum, %b
5746
5747                let ext_ty = self.intrinsics.i16_ty.vec_type(16);
5748                let one = self.intrinsics.i16_ty.const_int(1, false);
5749                let one = VectorType::const_vector(&[one; 16]);
5750
5751                let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5752                let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5753                let res = err!(self.builder.build_int_add(
5754                    err!(self.builder.build_int_add(one, v1, "")),
5755                    v2,
5756                    ""
5757                ));
5758                let res = err!(self.builder.build_right_shift(res, one, false, ""));
5759                let res = err!(
5760                    self.builder
5761                        .build_int_truncate(res, self.intrinsics.i8x16_ty, "")
5762                );
5763                let res = err!(
5764                    self.builder
5765                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5766                );
5767                self.state.push1(res);
5768            }
5769            Operator::I16x8AvgrU => {
5770                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5771                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5772                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5773
5774                // This approach is faster on x86-64 when the PAVG[BW]
5775                // instructions are available. On other platforms, an alternative
5776                // implementation appears likely to outperform, described here:
5777                //   %a = or %v1, %v2
5778                //   %b = and %a, 1
5779                //   %v1 = lshr %v1, 1
5780                //   %v2 = lshr %v2, 1
5781                //   %sum = add %v1, %v2
5782                //   %res = add %sum, %b
5783
5784                let ext_ty = self.intrinsics.i32_ty.vec_type(8);
5785                let one = self.intrinsics.i32_consts[1];
5786                let one = VectorType::const_vector(&[one; 8]);
5787
5788                let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5789                let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5790                let res = err!(self.builder.build_int_add(
5791                    err!(self.builder.build_int_add(one, v1, "")),
5792                    v2,
5793                    ""
5794                ));
5795                let res = err!(self.builder.build_right_shift(res, one, false, ""));
5796                let res = err!(
5797                    self.builder
5798                        .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
5799                );
5800                let res = err!(
5801                    self.builder
5802                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5803                );
5804                self.state.push1(res);
5805            }
5806            Operator::I64Add128 | Operator::I64Sub128 => {
5807                let (rhs_hi, rhs_hi_info) = self.state.pop1_extra()?;
5808                let (rhs_lo, rhs_lo_info) = self.state.pop1_extra()?;
5809                let (lhs_hi, lhs_hi_info) = self.state.pop1_extra()?;
5810                let (lhs_lo, lhs_lo_info) = self.state.pop1_extra()?;
5811
5812                let lhs_lo = self
5813                    .apply_pending_canonicalization(lhs_lo, lhs_lo_info)?
5814                    .into_int_value();
5815                let lhs_hi = self
5816                    .apply_pending_canonicalization(lhs_hi, lhs_hi_info)?
5817                    .into_int_value();
5818                let rhs_lo = self
5819                    .apply_pending_canonicalization(rhs_lo, rhs_lo_info)?
5820                    .into_int_value();
5821                let rhs_hi = self
5822                    .apply_pending_canonicalization(rhs_hi, rhs_hi_info)?
5823                    .into_int_value();
5824
5825                let idx0 = self.intrinsics.i32_ty.const_zero();
5826                let idx1 = self.intrinsics.i32_ty.const_int(1, false);
5827
5828                let lhs = self.intrinsics.i64x2_ty.get_undef();
5829                let lhs = err!(self.builder.build_insert_element(lhs, lhs_lo, idx0, ""));
5830                let lhs = err!(self.builder.build_insert_element(lhs, lhs_hi, idx1, ""));
5831                let lhs = err!(
5832                    self.builder
5833                        .build_bit_cast(lhs, self.intrinsics.i128_ty, "a")
5834                )
5835                .into_int_value();
5836
5837                let rhs = self.intrinsics.i64x2_ty.get_undef();
5838                let rhs = err!(self.builder.build_insert_element(rhs, rhs_lo, idx0, ""));
5839                let rhs = err!(self.builder.build_insert_element(rhs, rhs_hi, idx1, ""));
5840                let rhs = err!(
5841                    self.builder
5842                        .build_bit_cast(rhs, self.intrinsics.i128_ty, "b")
5843                )
5844                .into_int_value();
5845
5846                let result = err!(match op {
5847                    Operator::I64Add128 => self.builder.build_int_add(lhs, rhs, ""),
5848                    Operator::I64Sub128 => self.builder.build_int_sub(lhs, rhs, ""),
5849                    _ => unreachable!(),
5850                });
5851                let result = err!(self.builder.build_bit_cast(
5852                    result,
5853                    self.intrinsics.i64x2_ty,
5854                    ""
5855                ))
5856                .into_vector_value();
5857                let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
5858                let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
5859
5860                self.state.push1(result_lo);
5861                self.state.push1(result_hi);
5862            }
5863            Operator::I64MulWideS | Operator::I64MulWideU => {
5864                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
5865                let lhs = self
5866                    .apply_pending_canonicalization(lhs, lhs_info)?
5867                    .into_int_value();
5868                let rhs = self
5869                    .apply_pending_canonicalization(rhs, rhs_info)?
5870                    .into_int_value();
5871
5872                let lhs = err!(match op {
5873                    Operator::I64MulWideS => {
5874                        self.builder
5875                            .build_int_s_extend(lhs, self.intrinsics.i128_ty, "a")
5876                    }
5877                    Operator::I64MulWideU => {
5878                        self.builder
5879                            .build_int_z_extend(lhs, self.intrinsics.i128_ty, "a")
5880                    }
5881                    _ => unreachable!(),
5882                });
5883                let rhs = err!(match op {
5884                    Operator::I64MulWideS => {
5885                        self.builder
5886                            .build_int_s_extend(rhs, self.intrinsics.i128_ty, "b")
5887                    }
5888                    Operator::I64MulWideU => {
5889                        self.builder
5890                            .build_int_z_extend(rhs, self.intrinsics.i128_ty, "b")
5891                    }
5892                    _ => unreachable!(),
5893                });
5894
5895                let result = err!(self.builder.build_int_mul(lhs, rhs, ""));
5896                let result = err!(self.builder.build_bit_cast(
5897                    result,
5898                    self.intrinsics.i64x2_ty,
5899                    ""
5900                ))
5901                .into_vector_value();
5902                let idx0 = self.intrinsics.i32_ty.const_zero();
5903                let idx1 = self.intrinsics.i32_ty.const_int(1, false);
5904                let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
5905                let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
5906
5907                self.state.push1(result_lo);
5908                self.state.push1(result_hi);
5909            }
5910            _ => unreachable!(),
5911        }
5912        Ok(())
5913    }
5914
5915    // Floating-Point Arithmetic instructions.
5916    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-arithmetic-instructions
5917    fn translate_floating_point_arithmetic_operator(
5918        &mut self,
5919        op: Operator,
5920    ) -> Result<(), CompileError> {
5921        match op {
5922            Operator::F32Add => {
5923                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5924                let res = self
5925                    .build_call_with_param_attributes(
5926                        self.intrinsics.add_f32,
5927                        &[
5928                            v1.into(),
5929                            v2.into(),
5930                            self.intrinsics.fp_rounding_md,
5931                            self.intrinsics.fp_exception_md,
5932                        ],
5933                        "",
5934                    )?
5935                    .try_as_basic_value()
5936                    .unwrap_basic();
5937                self.state.push1_extra(
5938                    res,
5939                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5940                );
5941            }
5942            Operator::F64Add => {
5943                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5944                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5945                let res = self
5946                    .build_call_with_param_attributes(
5947                        self.intrinsics.add_f64,
5948                        &[
5949                            v1.into(),
5950                            v2.into(),
5951                            self.intrinsics.fp_rounding_md,
5952                            self.intrinsics.fp_exception_md,
5953                        ],
5954                        "",
5955                    )?
5956                    .try_as_basic_value()
5957                    .unwrap_basic();
5958                self.state.push1_extra(
5959                    res,
5960                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5961                );
5962            }
5963            Operator::F32x4Add => {
5964                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5965                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5966                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5967                let res = self
5968                    .build_call_with_param_attributes(
5969                        self.intrinsics.add_f32x4,
5970                        &[
5971                            v1.into(),
5972                            v2.into(),
5973                            self.intrinsics.fp_rounding_md,
5974                            self.intrinsics.fp_exception_md,
5975                        ],
5976                        "",
5977                    )?
5978                    .try_as_basic_value()
5979                    .unwrap_basic();
5980                let res = err!(
5981                    self.builder
5982                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5983                );
5984                self.state.push1_extra(
5985                    res,
5986                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5987                );
5988            }
5989            Operator::F64x2Add => {
5990                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5991                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5992                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5993                let res = self
5994                    .build_call_with_param_attributes(
5995                        self.intrinsics.add_f64x2,
5996                        &[
5997                            v1.into(),
5998                            v2.into(),
5999                            self.intrinsics.fp_rounding_md,
6000                            self.intrinsics.fp_exception_md,
6001                        ],
6002                        "",
6003                    )?
6004                    .try_as_basic_value()
6005                    .unwrap_basic();
6006                let res = err!(
6007                    self.builder
6008                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6009                );
6010                self.state.push1_extra(
6011                    res,
6012                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6013                );
6014            }
6015            Operator::F32Sub => {
6016                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6017                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6018                let res = self
6019                    .build_call_with_param_attributes(
6020                        self.intrinsics.sub_f32,
6021                        &[
6022                            v1.into(),
6023                            v2.into(),
6024                            self.intrinsics.fp_rounding_md,
6025                            self.intrinsics.fp_exception_md,
6026                        ],
6027                        "",
6028                    )?
6029                    .try_as_basic_value()
6030                    .unwrap_basic();
6031                self.state.push1_extra(
6032                    res,
6033                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6034                );
6035            }
6036            Operator::F64Sub => {
6037                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6038                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6039                let res = self
6040                    .build_call_with_param_attributes(
6041                        self.intrinsics.sub_f64,
6042                        &[
6043                            v1.into(),
6044                            v2.into(),
6045                            self.intrinsics.fp_rounding_md,
6046                            self.intrinsics.fp_exception_md,
6047                        ],
6048                        "",
6049                    )?
6050                    .try_as_basic_value()
6051                    .unwrap_basic();
6052                self.state.push1_extra(
6053                    res,
6054                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6055                );
6056            }
6057            Operator::F32x4Sub => {
6058                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6059                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6060                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6061                let res = self
6062                    .build_call_with_param_attributes(
6063                        self.intrinsics.sub_f32x4,
6064                        &[
6065                            v1.into(),
6066                            v2.into(),
6067                            self.intrinsics.fp_rounding_md,
6068                            self.intrinsics.fp_exception_md,
6069                        ],
6070                        "",
6071                    )?
6072                    .try_as_basic_value()
6073                    .unwrap_basic();
6074                let res = err!(
6075                    self.builder
6076                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6077                );
6078                self.state.push1_extra(
6079                    res,
6080                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6081                );
6082            }
6083            Operator::F64x2Sub => {
6084                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6085                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6086                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6087                let res = self
6088                    .build_call_with_param_attributes(
6089                        self.intrinsics.sub_f64x2,
6090                        &[
6091                            v1.into(),
6092                            v2.into(),
6093                            self.intrinsics.fp_rounding_md,
6094                            self.intrinsics.fp_exception_md,
6095                        ],
6096                        "",
6097                    )?
6098                    .try_as_basic_value()
6099                    .unwrap_basic();
6100                let res = err!(
6101                    self.builder
6102                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6103                );
6104                self.state.push1_extra(
6105                    res,
6106                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6107                );
6108            }
6109            Operator::F32Mul => {
6110                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6111                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6112                let res = self
6113                    .build_call_with_param_attributes(
6114                        self.intrinsics.mul_f32,
6115                        &[
6116                            v1.into(),
6117                            v2.into(),
6118                            self.intrinsics.fp_rounding_md,
6119                            self.intrinsics.fp_exception_md,
6120                        ],
6121                        "",
6122                    )?
6123                    .try_as_basic_value()
6124                    .unwrap_basic();
6125                self.state.push1_extra(
6126                    res,
6127                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6128                );
6129            }
6130            Operator::F64Mul => {
6131                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6132                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6133                let res = self
6134                    .build_call_with_param_attributes(
6135                        self.intrinsics.mul_f64,
6136                        &[
6137                            v1.into(),
6138                            v2.into(),
6139                            self.intrinsics.fp_rounding_md,
6140                            self.intrinsics.fp_exception_md,
6141                        ],
6142                        "",
6143                    )?
6144                    .try_as_basic_value()
6145                    .unwrap_basic();
6146                self.state.push1_extra(
6147                    res,
6148                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6149                );
6150            }
6151            Operator::F32x4Mul => {
6152                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6153                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6154                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6155                let res = self
6156                    .build_call_with_param_attributes(
6157                        self.intrinsics.mul_f32x4,
6158                        &[
6159                            v1.into(),
6160                            v2.into(),
6161                            self.intrinsics.fp_rounding_md,
6162                            self.intrinsics.fp_exception_md,
6163                        ],
6164                        "",
6165                    )?
6166                    .try_as_basic_value()
6167                    .unwrap_basic();
6168                let res = err!(
6169                    self.builder
6170                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6171                );
6172                self.state.push1_extra(
6173                    res,
6174                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6175                );
6176            }
6177            Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd
6178                if self.cpu_features.contains(CpuFeature::FMA) =>
6179            {
6180                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6181                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6182                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6183                let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
6184
6185                let v1 = match op {
6186                    Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6187                    _ => v1,
6188                };
6189                let res = self
6190                    .build_call_with_param_attributes(
6191                        self.intrinsics.muladd_f32x4,
6192                        &[
6193                            v1.into(),
6194                            v2.into(),
6195                            v3.into(),
6196                            self.intrinsics.fp_rounding_md,
6197                            self.intrinsics.fp_exception_md,
6198                        ],
6199                        "",
6200                    )?
6201                    .try_as_basic_value()
6202                    .unwrap_basic();
6203                let res = err!(
6204                    self.builder
6205                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6206                );
6207                let info = (i1.strip_pending() & i2.strip_pending())?;
6208                let info = (info & i3.strip_pending())?;
6209                let info = (info | ExtraInfo::pending_f32_nan())?;
6210                self.state.push1_extra(res, info);
6211            }
6212            Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd => {
6213                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6214                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6215                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6216                let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
6217
6218                let v1 = match op {
6219                    Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6220                    _ => v1,
6221                };
6222                let mul = self
6223                    .build_call_with_param_attributes(
6224                        self.intrinsics.mul_f32x4,
6225                        &[
6226                            v1.into(),
6227                            v2.into(),
6228                            self.intrinsics.fp_rounding_md,
6229                            self.intrinsics.fp_exception_md,
6230                        ],
6231                        "",
6232                    )?
6233                    .try_as_basic_value()
6234                    .unwrap_basic();
6235                let mul = mul.into_vector_value();
6236                let res = self
6237                    .build_call_with_param_attributes(
6238                        self.intrinsics.add_f32x4,
6239                        &[
6240                            mul.into(),
6241                            v3.into(),
6242                            self.intrinsics.fp_rounding_md,
6243                            self.intrinsics.fp_exception_md,
6244                        ],
6245                        "",
6246                    )?
6247                    .try_as_basic_value()
6248                    .unwrap_basic();
6249                let res = err!(
6250                    self.builder
6251                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6252                );
6253                let info = (i1.strip_pending() & i2.strip_pending())?;
6254                let info = (info & i3.strip_pending())?;
6255                let info = (info | ExtraInfo::pending_f32_nan())?;
6256                self.state.push1_extra(res, info);
6257            }
6258            Operator::F64x2Mul => {
6259                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6260                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6261                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6262                let res = self
6263                    .build_call_with_param_attributes(
6264                        self.intrinsics.mul_f64x2,
6265                        &[
6266                            v1.into(),
6267                            v2.into(),
6268                            self.intrinsics.fp_rounding_md,
6269                            self.intrinsics.fp_exception_md,
6270                        ],
6271                        "",
6272                    )?
6273                    .try_as_basic_value()
6274                    .unwrap_basic();
6275                let res = err!(
6276                    self.builder
6277                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6278                );
6279                self.state.push1_extra(
6280                    res,
6281                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6282                );
6283            }
6284            Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd
6285                if self.cpu_features.contains(CpuFeature::FMA) =>
6286            {
6287                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6288                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6289                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6290                let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
6291
6292                let v1 = match op {
6293                    Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6294                    _ => v1,
6295                };
6296                let res = self
6297                    .build_call_with_param_attributes(
6298                        self.intrinsics.muladd_f64x2,
6299                        &[
6300                            v1.into(),
6301                            v2.into(),
6302                            v3.into(),
6303                            self.intrinsics.fp_rounding_md,
6304                            self.intrinsics.fp_exception_md,
6305                        ],
6306                        "",
6307                    )?
6308                    .try_as_basic_value()
6309                    .unwrap_basic();
6310                let res = err!(
6311                    self.builder
6312                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6313                );
6314                let info = (i1.strip_pending() & i2.strip_pending())?;
6315                let info = (info & i3.strip_pending())?;
6316                let info = (info | ExtraInfo::pending_f64_nan())?;
6317                self.state.push1_extra(res, info);
6318            }
6319            Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd => {
6320                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6321                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6322                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6323                let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
6324
6325                let v1 = match op {
6326                    Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6327                    _ => v1,
6328                };
6329                let mul = self
6330                    .build_call_with_param_attributes(
6331                        self.intrinsics.mul_f64x2,
6332                        &[
6333                            v1.into(),
6334                            v2.into(),
6335                            self.intrinsics.fp_rounding_md,
6336                            self.intrinsics.fp_exception_md,
6337                        ],
6338                        "",
6339                    )?
6340                    .try_as_basic_value()
6341                    .unwrap_basic();
6342                let mul = mul.into_vector_value();
6343                let res = self
6344                    .build_call_with_param_attributes(
6345                        self.intrinsics.add_f64x2,
6346                        &[
6347                            mul.into(),
6348                            v3.into(),
6349                            self.intrinsics.fp_rounding_md,
6350                            self.intrinsics.fp_exception_md,
6351                        ],
6352                        "",
6353                    )?
6354                    .try_as_basic_value()
6355                    .unwrap_basic();
6356                let res = err!(
6357                    self.builder
6358                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6359                );
6360                let info = (i1.strip_pending() & i2.strip_pending())?;
6361                let info = (info & i3.strip_pending())?;
6362                let info = (info | ExtraInfo::pending_f64_nan())?;
6363                self.state.push1_extra(res, info);
6364            }
6365            Operator::F32Div => {
6366                let (v1, v2) = self.state.pop2()?;
6367                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6368                let res = self
6369                    .build_call_with_param_attributes(
6370                        self.intrinsics.div_f32,
6371                        &[
6372                            v1.into(),
6373                            v2.into(),
6374                            self.intrinsics.fp_rounding_md,
6375                            self.intrinsics.fp_exception_md,
6376                        ],
6377                        "",
6378                    )?
6379                    .try_as_basic_value()
6380                    .unwrap_basic();
6381                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6382            }
6383            Operator::F64Div => {
6384                let (v1, v2) = self.state.pop2()?;
6385                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6386                let res = self
6387                    .build_call_with_param_attributes(
6388                        self.intrinsics.div_f64,
6389                        &[
6390                            v1.into(),
6391                            v2.into(),
6392                            self.intrinsics.fp_rounding_md,
6393                            self.intrinsics.fp_exception_md,
6394                        ],
6395                        "",
6396                    )?
6397                    .try_as_basic_value()
6398                    .unwrap_basic();
6399                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6400            }
6401            Operator::F32x4Div => {
6402                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6403                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
6404                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
6405                let res = self
6406                    .build_call_with_param_attributes(
6407                        self.intrinsics.div_f32x4,
6408                        &[
6409                            v1.into(),
6410                            v2.into(),
6411                            self.intrinsics.fp_rounding_md,
6412                            self.intrinsics.fp_exception_md,
6413                        ],
6414                        "",
6415                    )?
6416                    .try_as_basic_value()
6417                    .unwrap_basic();
6418                let res = err!(
6419                    self.builder
6420                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6421                );
6422                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6423            }
6424            Operator::F64x2Div => {
6425                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6426                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
6427                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
6428                let res = self
6429                    .build_call_with_param_attributes(
6430                        self.intrinsics.div_f64x2,
6431                        &[
6432                            v1.into(),
6433                            v2.into(),
6434                            self.intrinsics.fp_rounding_md,
6435                            self.intrinsics.fp_exception_md,
6436                        ],
6437                        "",
6438                    )?
6439                    .try_as_basic_value()
6440                    .unwrap_basic();
6441                let res = err!(
6442                    self.builder
6443                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6444                );
6445                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6446            }
6447            Operator::F32Sqrt => {
6448                let input = self.state.pop1()?;
6449                let res = self
6450                    .build_call_with_param_attributes(
6451                        self.intrinsics.sqrt_f32,
6452                        &[input.into()],
6453                        "",
6454                    )?
6455                    .try_as_basic_value()
6456                    .unwrap_basic();
6457                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6458            }
6459            Operator::F64Sqrt => {
6460                let input = self.state.pop1()?;
6461                let res = self
6462                    .build_call_with_param_attributes(
6463                        self.intrinsics.sqrt_f64,
6464                        &[input.into()],
6465                        "",
6466                    )?
6467                    .try_as_basic_value()
6468                    .unwrap_basic();
6469                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6470            }
6471            Operator::F32x4Sqrt => {
6472                let (v, i) = self.state.pop1_extra()?;
6473                let (v, _) = self.v128_into_f32x4(v, i)?;
6474                let res = self
6475                    .build_call_with_param_attributes(self.intrinsics.sqrt_f32x4, &[v.into()], "")?
6476                    .try_as_basic_value()
6477                    .unwrap_basic();
6478                let bits = err!(
6479                    self.builder
6480                        .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6481                );
6482                self.state.push1_extra(bits, ExtraInfo::pending_f32_nan());
6483            }
6484            Operator::F64x2Sqrt => {
6485                let (v, i) = self.state.pop1_extra()?;
6486                let (v, _) = self.v128_into_f64x2(v, i)?;
6487                let res = self
6488                    .build_call_with_param_attributes(self.intrinsics.sqrt_f64x2, &[v.into()], "")?
6489                    .try_as_basic_value()
6490                    .unwrap_basic();
6491                let bits = err!(
6492                    self.builder
6493                        .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6494                );
6495                self.state.push1(bits);
6496            }
6497            Operator::F32Min => {
6498                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6499                let lhs = self
6500                    .apply_pending_canonicalization(lhs, lhs_info)?
6501                    .into_float_value();
6502                let rhs = self
6503                    .apply_pending_canonicalization(rhs, rhs_info)?
6504                    .into_float_value();
6505
6506                let res = self
6507                    .build_call_with_param_attributes(
6508                        self.intrinsics.minimum_f32,
6509                        &[lhs.into(), rhs.into()],
6510                        "",
6511                    )?
6512                    .try_as_basic_value()
6513                    .unwrap_basic();
6514
6515                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6516                let res = res.into_float_value();
6517
6518                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6519            }
6520            Operator::F64Min => {
6521                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6522                let lhs = self
6523                    .apply_pending_canonicalization(lhs, lhs_info)?
6524                    .into_float_value();
6525                let rhs = self
6526                    .apply_pending_canonicalization(rhs, rhs_info)?
6527                    .into_float_value();
6528
6529                let res = self
6530                    .build_call_with_param_attributes(
6531                        self.intrinsics.minimum_f64,
6532                        &[lhs.into(), rhs.into()],
6533                        "",
6534                    )?
6535                    .try_as_basic_value()
6536                    .unwrap_basic();
6537
6538                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6539                let res = res.into_float_value();
6540
6541                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6542            }
6543            Operator::F32x4RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6544                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6545                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6546                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6547                let res = self
6548                    .build_call_with_param_attributes(
6549                        self.intrinsics.x86_64.min_ps,
6550                        &[v1.into(), v2.into()],
6551                        "",
6552                    )?
6553                    .try_as_basic_value()
6554                    .unwrap_basic();
6555                let res = err!(
6556                    self.builder
6557                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6558                );
6559                self.state.push1_extra(
6560                    res,
6561                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6562                );
6563            }
6564            Operator::F32x4Min | Operator::F32x4RelaxedMin => {
6565                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6566                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6567                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6568                let res = self
6569                    .build_call_with_param_attributes(
6570                        self.intrinsics.minimum_f32x4,
6571                        &[v1.into(), v2.into()],
6572                        "",
6573                    )?
6574                    .try_as_basic_value()
6575                    .unwrap_basic();
6576
6577                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6578                let res = res.into_vector_value();
6579
6580                let res = err!(
6581                    self.builder
6582                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6583                );
6584                self.state.push1_extra(
6585                    res,
6586                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6587                );
6588            }
6589            Operator::F32x4PMin => {
6590                // Pseudo-min: b < a ? b : a
6591                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6592                let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6593                let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6594                let cmp = err!(
6595                    self.builder
6596                        .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6597                );
6598                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6599                let res = err!(
6600                    self.builder
6601                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6602                );
6603                self.state.push1(res);
6604            }
6605            Operator::F64x2RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6606                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6607                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6608                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6609                let res = self
6610                    .build_call_with_param_attributes(
6611                        self.intrinsics.x86_64.min_pd,
6612                        &[v1.into(), v2.into()],
6613                        "",
6614                    )?
6615                    .try_as_basic_value()
6616                    .unwrap_basic();
6617                let res = err!(
6618                    self.builder
6619                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6620                );
6621                self.state.push1_extra(
6622                    res,
6623                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6624                );
6625            }
6626            Operator::F64x2Min | Operator::F64x2RelaxedMin => {
6627                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6628                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6629                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6630                let res = self
6631                    .build_call_with_param_attributes(
6632                        self.intrinsics.minimum_f64x2,
6633                        &[v1.into(), v2.into()],
6634                        "",
6635                    )?
6636                    .try_as_basic_value()
6637                    .unwrap_basic();
6638
6639                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6640                let res = res.into_vector_value();
6641
6642                let res = err!(
6643                    self.builder
6644                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6645                );
6646                self.state.push1_extra(
6647                    res,
6648                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6649                );
6650            }
6651            Operator::F64x2PMin => {
6652                // Pseudo-min: b < a ? b : a
6653                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6654                let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6655                let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6656                let cmp = err!(
6657                    self.builder
6658                        .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6659                );
6660                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6661                let res = err!(
6662                    self.builder
6663                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6664                );
6665                self.state.push1(res);
6666            }
6667            Operator::F32Max => {
6668                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6669                let lhs = self
6670                    .apply_pending_canonicalization(lhs, lhs_info)?
6671                    .into_float_value();
6672                let rhs = self
6673                    .apply_pending_canonicalization(rhs, rhs_info)?
6674                    .into_float_value();
6675
6676                let res = self
6677                    .build_call_with_param_attributes(
6678                        self.intrinsics.maximum_f32,
6679                        &[lhs.into(), rhs.into()],
6680                        "",
6681                    )?
6682                    .try_as_basic_value()
6683                    .unwrap_basic();
6684
6685                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6686                let res = res.into_float_value();
6687
6688                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6689            }
6690            Operator::F64Max => {
6691                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6692                let lhs = self
6693                    .apply_pending_canonicalization(lhs, lhs_info)?
6694                    .into_float_value();
6695                let rhs = self
6696                    .apply_pending_canonicalization(rhs, rhs_info)?
6697                    .into_float_value();
6698
6699                let res = self
6700                    .build_call_with_param_attributes(
6701                        self.intrinsics.maximum_f64,
6702                        &[lhs.into(), rhs.into()],
6703                        "",
6704                    )?
6705                    .try_as_basic_value()
6706                    .unwrap_basic();
6707
6708                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6709                let res = res.into_float_value();
6710
6711                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6712            }
6713            Operator::F32x4RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6714                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6715                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6716                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6717                let res = self
6718                    .build_call_with_param_attributes(
6719                        self.intrinsics.x86_64.max_ps,
6720                        &[v1.into(), v2.into()],
6721                        "",
6722                    )?
6723                    .try_as_basic_value()
6724                    .unwrap_basic();
6725                let res = err!(
6726                    self.builder
6727                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6728                );
6729                self.state.push1_extra(
6730                    res,
6731                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6732                );
6733            }
6734            Operator::F32x4Max | Operator::F32x4RelaxedMax => {
6735                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6736                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6737                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6738                let res = self
6739                    .build_call_with_param_attributes(
6740                        self.intrinsics.maximum_f32x4,
6741                        &[v1.into(), v2.into()],
6742                        "",
6743                    )?
6744                    .try_as_basic_value()
6745                    .unwrap_basic();
6746
6747                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6748                let res = res.into_vector_value();
6749
6750                let res = err!(
6751                    self.builder
6752                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6753                );
6754                self.state.push1_extra(
6755                    res,
6756                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6757                );
6758            }
6759            Operator::F32x4PMax => {
6760                // Pseudo-max: a < b ? b : a
6761                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6762                let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6763                let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6764                let cmp = err!(
6765                    self.builder
6766                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6767                );
6768                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6769
6770                let res = err!(
6771                    self.builder
6772                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6773                );
6774                self.state.push1(res);
6775            }
6776            Operator::F64x2RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6777                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6778                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6779                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6780                let res = self
6781                    .build_call_with_param_attributes(
6782                        self.intrinsics.x86_64.max_pd,
6783                        &[v1.into(), v2.into()],
6784                        "",
6785                    )?
6786                    .try_as_basic_value()
6787                    .unwrap_basic();
6788                let res = err!(
6789                    self.builder
6790                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6791                );
6792                self.state.push1_extra(
6793                    res,
6794                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6795                );
6796            }
6797            Operator::F64x2Max | Operator::F64x2RelaxedMax => {
6798                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6799                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6800                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6801                let res = self
6802                    .build_call_with_param_attributes(
6803                        self.intrinsics.maximum_f64x2,
6804                        &[v1.into(), v2.into()],
6805                        "",
6806                    )?
6807                    .try_as_basic_value()
6808                    .unwrap_basic();
6809
6810                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6811                let res = res.into_vector_value();
6812
6813                let res = err!(
6814                    self.builder
6815                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6816                );
6817                self.state.push1_extra(
6818                    res,
6819                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6820                );
6821            }
6822            Operator::F64x2PMax => {
6823                // Pseudo-max: a < b ? b : a
6824                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6825                let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6826                let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6827                let cmp = err!(
6828                    self.builder
6829                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6830                );
6831                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6832                let res = err!(
6833                    self.builder
6834                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6835                );
6836                self.state.push1(res);
6837            }
6838            Operator::F32Ceil => {
6839                let (input, info) = self.state.pop1_extra()?;
6840                let res = err!(self.build_call_with_param_attributes(
6841                    self.intrinsics.ceil_f32,
6842                    &[input.into()],
6843                    ""
6844                ))
6845                .try_as_basic_value()
6846                .unwrap_basic();
6847                let (res, info) = self.finalize_rounding_result(res, info)?;
6848                self.state.push1_extra(res, info);
6849            }
6850            Operator::F32x4Ceil => {
6851                let (v, i) = self.state.pop1_extra()?;
6852                let (v, _) = self.v128_into_f32x4(v, i)?;
6853                let res = err!(self.build_call_with_param_attributes(
6854                    self.intrinsics.ceil_f32x4,
6855                    &[v.into()],
6856                    ""
6857                ))
6858                .try_as_basic_value()
6859                .unwrap_basic();
6860                let (res, info) = self.finalize_rounding_result(res, i)?;
6861                let res = err!(
6862                    self.builder
6863                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6864                );
6865                self.state.push1_extra(res, info);
6866            }
6867            Operator::F64Ceil => {
6868                let (input, info) = self.state.pop1_extra()?;
6869                let res = err!(self.build_call_with_param_attributes(
6870                    self.intrinsics.ceil_f64,
6871                    &[input.into()],
6872                    ""
6873                ))
6874                .try_as_basic_value()
6875                .unwrap_basic();
6876                let (res, info) = self.finalize_rounding_result(res, info)?;
6877                self.state.push1_extra(res, info);
6878            }
6879            Operator::F64x2Ceil => {
6880                let (v, i) = self.state.pop1_extra()?;
6881                let (v, _) = self.v128_into_f64x2(v, i)?;
6882                let res = err!(self.build_call_with_param_attributes(
6883                    self.intrinsics.ceil_f64x2,
6884                    &[v.into()],
6885                    ""
6886                ))
6887                .try_as_basic_value()
6888                .unwrap_basic();
6889                let (res, info) = self.finalize_rounding_result(res, i)?;
6890                let res = err!(
6891                    self.builder
6892                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6893                );
6894                self.state.push1_extra(res, info);
6895            }
6896            Operator::F32Floor => {
6897                let (input, info) = self.state.pop1_extra()?;
6898                let res = err!(self.build_call_with_param_attributes(
6899                    self.intrinsics.floor_f32,
6900                    &[input.into()],
6901                    ""
6902                ))
6903                .try_as_basic_value()
6904                .unwrap_basic();
6905                let (res, info) = self.finalize_rounding_result(res, info)?;
6906                self.state.push1_extra(res, info);
6907            }
6908            Operator::F32x4Floor => {
6909                let (v, i) = self.state.pop1_extra()?;
6910                let (v, _) = self.v128_into_f32x4(v, i)?;
6911                let res = err!(self.build_call_with_param_attributes(
6912                    self.intrinsics.floor_f32x4,
6913                    &[v.into()],
6914                    ""
6915                ))
6916                .try_as_basic_value()
6917                .unwrap_basic();
6918                let (res, info) = self.finalize_rounding_result(res, i)?;
6919                let res = err!(
6920                    self.builder
6921                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6922                );
6923                self.state.push1_extra(res, info);
6924            }
6925            Operator::F64Floor => {
6926                let (input, info) = self.state.pop1_extra()?;
6927                let res = err!(self.build_call_with_param_attributes(
6928                    self.intrinsics.floor_f64,
6929                    &[input.into()],
6930                    ""
6931                ))
6932                .try_as_basic_value()
6933                .unwrap_basic();
6934                let (res, info) = self.finalize_rounding_result(res, info)?;
6935                self.state.push1_extra(res, info);
6936            }
6937            Operator::F64x2Floor => {
6938                let (v, i) = self.state.pop1_extra()?;
6939                let (v, _) = self.v128_into_f64x2(v, i)?;
6940                let res = err!(self.build_call_with_param_attributes(
6941                    self.intrinsics.floor_f64x2,
6942                    &[v.into()],
6943                    ""
6944                ))
6945                .try_as_basic_value()
6946                .unwrap_basic();
6947                let (res, info) = self.finalize_rounding_result(res, i)?;
6948                let res = err!(
6949                    self.builder
6950                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6951                );
6952                self.state.push1_extra(res, info);
6953            }
6954            Operator::F32Trunc => {
6955                let (v, info) = self.state.pop1_extra()?;
6956                let res = err!(
6957                    self.builder
6958                        .build_call(self.intrinsics.trunc_f32, &[v.into()], "")
6959                )
6960                .try_as_basic_value()
6961                .unwrap_basic();
6962                let (res, info) = self.finalize_rounding_result(res, info)?;
6963                self.state.push1_extra(res, info);
6964            }
6965            Operator::F32x4Trunc => {
6966                let (v, i) = self.state.pop1_extra()?;
6967                let (v, _) = self.v128_into_f32x4(v, i)?;
6968                let res = err!(self.build_call_with_param_attributes(
6969                    self.intrinsics.trunc_f32x4,
6970                    &[v.into()],
6971                    ""
6972                ))
6973                .try_as_basic_value()
6974                .unwrap_basic();
6975                let (res, info) = self.finalize_rounding_result(res, i)?;
6976                let res = err!(
6977                    self.builder
6978                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6979                );
6980                self.state.push1_extra(res, info);
6981            }
6982            Operator::F64Trunc => {
6983                let (v, info) = self.state.pop1_extra()?;
6984                let res = err!(
6985                    self.builder
6986                        .build_call(self.intrinsics.trunc_f64, &[v.into()], "")
6987                )
6988                .try_as_basic_value()
6989                .unwrap_basic();
6990                let (res, info) = self.finalize_rounding_result(res, info)?;
6991                self.state.push1_extra(res, info);
6992            }
6993            Operator::F64x2Trunc => {
6994                let (v, i) = self.state.pop1_extra()?;
6995                let (v, _) = self.v128_into_f64x2(v, i)?;
6996                let res = err!(self.build_call_with_param_attributes(
6997                    self.intrinsics.trunc_f64x2,
6998                    &[v.into()],
6999                    ""
7000                ))
7001                .try_as_basic_value()
7002                .unwrap_basic();
7003                let (res, info) = self.finalize_rounding_result(res, i)?;
7004                let res = err!(
7005                    self.builder
7006                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7007                );
7008                self.state.push1_extra(res, info);
7009            }
7010            Operator::F32Nearest => {
7011                let (v, info) = self.state.pop1_extra()?;
7012                let res = err!(self.build_call_with_param_attributes(
7013                    self.intrinsics.nearbyint_f32,
7014                    &[v.into()],
7015                    ""
7016                ))
7017                .try_as_basic_value()
7018                .unwrap_basic();
7019                let (res, info) = self.finalize_rounding_result(res, info)?;
7020                self.state.push1_extra(res, info);
7021            }
7022            Operator::F32x4Nearest => {
7023                let (v, i) = self.state.pop1_extra()?;
7024                let (v, _) = self.v128_into_f32x4(v, i)?;
7025                let res = err!(self.build_call_with_param_attributes(
7026                    self.intrinsics.nearbyint_f32x4,
7027                    &[v.into()],
7028                    ""
7029                ))
7030                .try_as_basic_value()
7031                .unwrap_basic();
7032                let (res, info) = self.finalize_rounding_result(res, i)?;
7033                let res = err!(
7034                    self.builder
7035                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7036                );
7037                self.state.push1_extra(res, info);
7038            }
7039            Operator::F64Nearest => {
7040                let (v, info) = self.state.pop1_extra()?;
7041                let res = err!(self.build_call_with_param_attributes(
7042                    self.intrinsics.nearbyint_f64,
7043                    &[v.into()],
7044                    ""
7045                ))
7046                .try_as_basic_value()
7047                .unwrap_basic();
7048                let (res, info) = self.finalize_rounding_result(res, info)?;
7049                self.state.push1_extra(res, info);
7050            }
7051            Operator::F64x2Nearest => {
7052                let (v, i) = self.state.pop1_extra()?;
7053                let (v, _) = self.v128_into_f64x2(v, i)?;
7054                let res = err!(self.build_call_with_param_attributes(
7055                    self.intrinsics.nearbyint_f64x2,
7056                    &[v.into()],
7057                    ""
7058                ))
7059                .try_as_basic_value()
7060                .unwrap_basic();
7061                let (res, info) = self.finalize_rounding_result(res, i)?;
7062                let res = err!(
7063                    self.builder
7064                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7065                );
7066                self.state.push1_extra(res, info);
7067            }
7068            Operator::F32Abs => {
7069                let (v, i) = self.state.pop1_extra()?;
7070                let v = self.apply_pending_canonicalization(v, i)?;
7071                let res = err!(
7072                    self.builder
7073                        .build_call(self.intrinsics.fabs_f32, &[v.into()], "")
7074                )
7075                .try_as_basic_value()
7076                .unwrap_basic();
7077                // The exact NaN returned by F32Abs is fully defined. Do not
7078                // adjust.
7079                self.state.push1_extra(res, i.strip_pending());
7080            }
7081            Operator::F64Abs => {
7082                let (v, i) = self.state.pop1_extra()?;
7083                let v = self.apply_pending_canonicalization(v, i)?;
7084                let res = err!(
7085                    self.builder
7086                        .build_call(self.intrinsics.fabs_f64, &[v.into()], "")
7087                )
7088                .try_as_basic_value()
7089                .unwrap_basic();
7090                // The exact NaN returned by F64Abs is fully defined. Do not
7091                // adjust.
7092                self.state.push1_extra(res, i.strip_pending());
7093            }
7094            Operator::F32x4Abs => {
7095                let (v, i) = self.state.pop1_extra()?;
7096                let v = err!(self.builder.build_bit_cast(
7097                    v.into_int_value(),
7098                    self.intrinsics.f32x4_ty,
7099                    ""
7100                ));
7101                let v = self.apply_pending_canonicalization(v, i)?;
7102                let res = self
7103                    .build_call_with_param_attributes(self.intrinsics.fabs_f32x4, &[v.into()], "")?
7104                    .try_as_basic_value()
7105                    .unwrap_basic();
7106                let res = err!(
7107                    self.builder
7108                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7109                );
7110                // The exact NaN returned by F32x4Abs is fully defined. Do not
7111                // adjust.
7112                self.state.push1_extra(res, i.strip_pending());
7113            }
7114            Operator::F64x2Abs => {
7115                let (v, i) = self.state.pop1_extra()?;
7116                let v = err!(self.builder.build_bit_cast(
7117                    v.into_int_value(),
7118                    self.intrinsics.f64x2_ty,
7119                    ""
7120                ));
7121                let v = self.apply_pending_canonicalization(v, i)?;
7122                let res = self
7123                    .build_call_with_param_attributes(self.intrinsics.fabs_f64x2, &[v.into()], "")?
7124                    .try_as_basic_value()
7125                    .unwrap_basic();
7126                let res = err!(
7127                    self.builder
7128                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7129                );
7130                // The exact NaN returned by F32x4Abs is fully defined. Do not
7131                // adjust.
7132                self.state.push1_extra(res, i.strip_pending());
7133            }
7134            Operator::F32x4Neg => {
7135                let (v, i) = self.state.pop1_extra()?;
7136                let v = err!(self.builder.build_bit_cast(
7137                    v.into_int_value(),
7138                    self.intrinsics.f32x4_ty,
7139                    ""
7140                ));
7141                let v = self
7142                    .apply_pending_canonicalization(v, i)?
7143                    .into_vector_value();
7144                let res = err!(self.builder.build_float_neg(v, ""));
7145                let res = err!(
7146                    self.builder
7147                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7148                );
7149                // The exact NaN returned by F32x4Neg is fully defined. Do not
7150                // adjust.
7151                self.state.push1_extra(res, i.strip_pending());
7152            }
7153            Operator::F64x2Neg => {
7154                let (v, i) = self.state.pop1_extra()?;
7155                let v = err!(self.builder.build_bit_cast(
7156                    v.into_int_value(),
7157                    self.intrinsics.f64x2_ty,
7158                    ""
7159                ));
7160                let v = self
7161                    .apply_pending_canonicalization(v, i)?
7162                    .into_vector_value();
7163                let res = err!(self.builder.build_float_neg(v, ""));
7164                let res = err!(
7165                    self.builder
7166                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7167                );
7168                // The exact NaN returned by F64x2Neg is fully defined. Do not
7169                // adjust.
7170                self.state.push1_extra(res, i.strip_pending());
7171            }
7172            Operator::F32Neg | Operator::F64Neg => {
7173                let (v, i) = self.state.pop1_extra()?;
7174                let v = self
7175                    .apply_pending_canonicalization(v, i)?
7176                    .into_float_value();
7177                let res = err!(self.builder.build_float_neg(v, ""));
7178                // The exact NaN returned by F32Neg and F64Neg are fully defined.
7179                // Do not adjust.
7180                self.state.push1_extra(res, i.strip_pending());
7181            }
7182            Operator::F32Copysign => {
7183                let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
7184                let mag = self.apply_pending_canonicalization(mag, mag_info)?;
7185                let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
7186                let res = self
7187                    .build_call_with_param_attributes(
7188                        self.intrinsics.copysign_f32,
7189                        &[mag.into(), sgn.into()],
7190                        "",
7191                    )?
7192                    .try_as_basic_value()
7193                    .unwrap_basic();
7194                // The exact NaN returned by F32Copysign is fully defined.
7195                // Do not adjust.
7196                self.state.push1_extra(res, mag_info.strip_pending());
7197            }
7198            Operator::F64Copysign => {
7199                let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
7200                let mag = self.apply_pending_canonicalization(mag, mag_info)?;
7201                let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
7202                let res = self
7203                    .build_call_with_param_attributes(
7204                        self.intrinsics.copysign_f64,
7205                        &[mag.into(), sgn.into()],
7206                        "",
7207                    )?
7208                    .try_as_basic_value()
7209                    .unwrap_basic();
7210                // The exact NaN returned by F32Copysign is fully defined.
7211                // Do not adjust.
7212                self.state.push1_extra(res, mag_info.strip_pending());
7213            }
7214            _ => unreachable!(),
7215        }
7216        Ok(())
7217    }
7218
7219    // Integer Comparison instructions.
7220    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-comparison-instructions
7221    fn translate_integer_comparison_operator(&mut self, op: Operator) -> Result<(), CompileError> {
7222        match op {
7223            Operator::I32Eq | Operator::I64Eq => {
7224                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7225                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7226                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7227                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7228                let cond = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7229                let res = err!(
7230                    self.builder
7231                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7232                );
7233                self.state.push1_extra(
7234                    res,
7235                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7236                );
7237            }
7238            Operator::I8x16Eq => {
7239                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7240                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7241                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7242                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7243                let res = err!(
7244                    self.builder
7245                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7246                );
7247                let res = err!(
7248                    self.builder
7249                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7250                );
7251                self.state.push1(res);
7252            }
7253            Operator::I16x8Eq => {
7254                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7255                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7256                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7257                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7258                let res = err!(
7259                    self.builder
7260                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7261                );
7262                let res = err!(
7263                    self.builder
7264                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7265                );
7266                self.state.push1(res);
7267            }
7268            Operator::I32x4Eq => {
7269                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7270                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7271                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7272                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7273                let res = err!(
7274                    self.builder
7275                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7276                );
7277                let res = err!(
7278                    self.builder
7279                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7280                );
7281                self.state.push1(res);
7282            }
7283            Operator::I64x2Eq => {
7284                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7285                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7286                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7287                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7288                let res = err!(
7289                    self.builder
7290                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7291                );
7292                let res = err!(
7293                    self.builder
7294                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7295                );
7296                self.state.push1(res);
7297            }
7298            Operator::I32Ne | Operator::I64Ne => {
7299                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7300                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7301                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7302                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7303                let cond = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7304                let res = err!(
7305                    self.builder
7306                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7307                );
7308                self.state.push1_extra(
7309                    res,
7310                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7311                );
7312            }
7313            Operator::I8x16Ne => {
7314                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7315                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7316                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7317                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7318                let res = err!(
7319                    self.builder
7320                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7321                );
7322                let res = err!(
7323                    self.builder
7324                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7325                );
7326                self.state.push1(res);
7327            }
7328            Operator::I16x8Ne => {
7329                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7330                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7331                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7332                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7333                let res = err!(
7334                    self.builder
7335                        .build_int_s_extend(res, self.intrinsics.i16x8_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::I32x4Ne => {
7344                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7345                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7346                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7347                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7348                let res = err!(
7349                    self.builder
7350                        .build_int_s_extend(res, self.intrinsics.i32x4_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::I64x2Ne => {
7359                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7360                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7361                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7362                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7363                let res = err!(
7364                    self.builder
7365                        .build_int_s_extend(res, self.intrinsics.i64x2_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::I32LtS | Operator::I64LtS => {
7374                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7375                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7376                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7377                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7378                let cond = err!(
7379                    self.builder
7380                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7381                );
7382                let res = err!(
7383                    self.builder
7384                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7385                );
7386                self.state.push1_extra(
7387                    res,
7388                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7389                );
7390            }
7391            Operator::I8x16LtS => {
7392                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7393                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7394                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7395                let res = err!(
7396                    self.builder
7397                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7398                );
7399                let res = err!(
7400                    self.builder
7401                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7402                );
7403                let res = err!(
7404                    self.builder
7405                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7406                );
7407                self.state.push1(res);
7408            }
7409            Operator::I16x8LtS => {
7410                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7411                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7412                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7413                let res = err!(
7414                    self.builder
7415                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7416                );
7417                let res = err!(
7418                    self.builder
7419                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7420                );
7421                let res = err!(
7422                    self.builder
7423                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7424                );
7425                self.state.push1(res);
7426            }
7427            Operator::I32x4LtS => {
7428                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7429                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7430                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7431                let res = err!(
7432                    self.builder
7433                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7434                );
7435                let res = err!(
7436                    self.builder
7437                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7438                );
7439                let res = err!(
7440                    self.builder
7441                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7442                );
7443                self.state.push1(res);
7444            }
7445            Operator::I64x2LtS => {
7446                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7447                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7448                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7449                let res = err!(
7450                    self.builder
7451                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7452                );
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::I32LtU | Operator::I64LtU => {
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::ULT, 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(res);
7477            }
7478            Operator::I8x16LtU => {
7479                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7480                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7481                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7482                let res = err!(
7483                    self.builder
7484                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7485                );
7486                let res = err!(
7487                    self.builder
7488                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7489                );
7490                let res = err!(
7491                    self.builder
7492                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7493                );
7494                self.state.push1(res);
7495            }
7496            Operator::I16x8LtU => {
7497                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7498                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7499                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7500                let res = err!(
7501                    self.builder
7502                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7503                );
7504                let res = err!(
7505                    self.builder
7506                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7507                );
7508                let res = err!(
7509                    self.builder
7510                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7511                );
7512                self.state.push1(res);
7513            }
7514            Operator::I32x4LtU => {
7515                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7516                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7517                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7518                let res = err!(
7519                    self.builder
7520                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7521                );
7522                let res = err!(
7523                    self.builder
7524                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7525                );
7526                let res = err!(
7527                    self.builder
7528                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7529                );
7530                self.state.push1(res);
7531            }
7532            Operator::I32LeS | Operator::I64LeS => {
7533                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7534                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7535                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7536                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7537                let cond = err!(
7538                    self.builder
7539                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7540                );
7541                let res = err!(
7542                    self.builder
7543                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7544                );
7545                self.state.push1_extra(
7546                    res,
7547                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7548                );
7549            }
7550            Operator::I8x16LeS => {
7551                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7552                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7553                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7554                let res = err!(
7555                    self.builder
7556                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7557                );
7558                let res = err!(
7559                    self.builder
7560                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7561                );
7562                let res = err!(
7563                    self.builder
7564                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7565                );
7566                self.state.push1(res);
7567            }
7568            Operator::I16x8LeS => {
7569                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7570                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7571                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7572                let res = err!(
7573                    self.builder
7574                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7575                );
7576                let res = err!(
7577                    self.builder
7578                        .build_int_s_extend(res, self.intrinsics.i16x8_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::I32x4LeS => {
7587                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7588                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7589                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7590                let res = err!(
7591                    self.builder
7592                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7593                );
7594                let res = err!(
7595                    self.builder
7596                        .build_int_s_extend(res, self.intrinsics.i32x4_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::I64x2LeS => {
7605                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7606                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7607                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7608                let res = err!(
7609                    self.builder
7610                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7611                );
7612                let res = err!(
7613                    self.builder
7614                        .build_int_s_extend(res, self.intrinsics.i64x2_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::I32LeU | Operator::I64LeU => {
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::ULE, 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::I8x16LeU => {
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::ULE, 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::I16x8LeU => {
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::ULE, 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::I32x4LeU => {
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::ULE, 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::I32GtS | Operator::I64GtS => {
7695                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7696                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7697                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7698                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7699                let cond = err!(
7700                    self.builder
7701                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7702                );
7703                let res = err!(
7704                    self.builder
7705                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7706                );
7707                self.state.push1_extra(
7708                    res,
7709                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7710                );
7711            }
7712            Operator::I8x16GtS => {
7713                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7714                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7715                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7716                let res = err!(
7717                    self.builder
7718                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7719                );
7720                let res = err!(
7721                    self.builder
7722                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7723                );
7724                let res = err!(
7725                    self.builder
7726                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7727                );
7728                self.state.push1(res);
7729            }
7730            Operator::I16x8GtS => {
7731                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7732                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7733                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7734                let res = err!(
7735                    self.builder
7736                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7737                );
7738                let res = err!(
7739                    self.builder
7740                        .build_int_s_extend(res, self.intrinsics.i16x8_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::I32x4GtS => {
7749                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7750                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7751                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7752                let res = err!(
7753                    self.builder
7754                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7755                );
7756                let res = err!(
7757                    self.builder
7758                        .build_int_s_extend(res, self.intrinsics.i32x4_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::I64x2GtS => {
7767                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7768                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7769                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7770                let res = err!(
7771                    self.builder
7772                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7773                );
7774                let res = err!(
7775                    self.builder
7776                        .build_int_s_extend(res, self.intrinsics.i64x2_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::I32GtU | Operator::I64GtU => {
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::UGT, 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::I8x16GtU => {
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::UGT, 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::I16x8GtU => {
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::UGT, 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::I32x4GtU => {
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::UGT, 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::I32GeS | Operator::I64GeS => {
7857                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7858                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7859                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7860                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7861                let cond = err!(
7862                    self.builder
7863                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7864                );
7865                let res = err!(
7866                    self.builder
7867                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7868                );
7869                self.state.push1(res);
7870            }
7871            Operator::I8x16GeS => {
7872                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7873                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7874                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7875                let res = err!(
7876                    self.builder
7877                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7878                );
7879                let res = err!(
7880                    self.builder
7881                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7882                );
7883                let res = err!(
7884                    self.builder
7885                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7886                );
7887                self.state.push1(res);
7888            }
7889            Operator::I16x8GeS => {
7890                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7891                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7892                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7893                let res = err!(
7894                    self.builder
7895                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7896                );
7897                let res = err!(
7898                    self.builder
7899                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7900                );
7901                let res = err!(
7902                    self.builder
7903                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7904                );
7905                self.state.push1(res);
7906            }
7907            Operator::I32x4GeS => {
7908                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7909                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7910                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7911                let res = err!(
7912                    self.builder
7913                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7914                );
7915                let res = err!(
7916                    self.builder
7917                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7918                );
7919                let res = err!(
7920                    self.builder
7921                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7922                );
7923                self.state.push1(res);
7924            }
7925            Operator::I64x2GeS => {
7926                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7927                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7928                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7929                let res = err!(
7930                    self.builder
7931                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7932                );
7933                let res = err!(
7934                    self.builder
7935                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7936                );
7937                let res = err!(
7938                    self.builder
7939                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7940                );
7941                self.state.push1(res);
7942            }
7943            Operator::I32GeU | Operator::I64GeU => {
7944                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7945                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7946                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7947                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7948                let cond = err!(
7949                    self.builder
7950                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
7951                );
7952                let res = err!(
7953                    self.builder
7954                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7955                );
7956                self.state.push1_extra(
7957                    res,
7958                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7959                );
7960            }
7961            Operator::I8x16GeU => {
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::UGE, 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::I16x8GeU => {
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::UGE, 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::I32x4GeU => {
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::UGE, 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            _ => unreachable!(),
8016        }
8017        Ok(())
8018    }
8019
8020    // Floating-Point Comparison instructions.
8021    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-comparison-instructions
8022    fn translate_floating_point_comparison_operator(
8023        &mut self,
8024        op: Operator,
8025    ) -> Result<(), CompileError> {
8026        match op {
8027            Operator::F32Eq | Operator::F64Eq => {
8028                let (v1, v2) = self.state.pop2()?;
8029                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8030                let cond = err!(
8031                    self.builder
8032                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8033                );
8034                let res = err!(
8035                    self.builder
8036                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8037                );
8038                self.state.push1_extra(
8039                    res,
8040                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8041                );
8042            }
8043            Operator::F32x4Eq => {
8044                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8045                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8046                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8047                let res = err!(
8048                    self.builder
8049                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8050                );
8051                let res = err!(
8052                    self.builder
8053                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8054                );
8055                let res = err!(
8056                    self.builder
8057                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8058                );
8059                self.state.push1(res);
8060            }
8061            Operator::F64x2Eq => {
8062                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8063                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8064                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8065                let res = err!(
8066                    self.builder
8067                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8068                );
8069                let res = err!(
8070                    self.builder
8071                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8072                );
8073                let res = err!(
8074                    self.builder
8075                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8076                );
8077                self.state.push1(res);
8078            }
8079            Operator::F32Ne | Operator::F64Ne => {
8080                let (v1, v2) = self.state.pop2()?;
8081                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8082                let cond = err!(
8083                    self.builder
8084                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8085                );
8086                let res = err!(
8087                    self.builder
8088                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8089                );
8090                self.state.push1_extra(
8091                    res,
8092                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8093                );
8094            }
8095            Operator::F32x4Ne => {
8096                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8097                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8098                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8099                let res = err!(
8100                    self.builder
8101                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8102                );
8103                let res = err!(
8104                    self.builder
8105                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8106                );
8107                let res = err!(
8108                    self.builder
8109                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8110                );
8111                self.state.push1(res);
8112            }
8113            Operator::F64x2Ne => {
8114                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8115                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8116                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8117                let res = err!(
8118                    self.builder
8119                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8120                );
8121                let res = err!(
8122                    self.builder
8123                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8124                );
8125                let res = err!(
8126                    self.builder
8127                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8128                );
8129                self.state.push1(res);
8130            }
8131            Operator::F32Lt | Operator::F64Lt => {
8132                let (v1, v2) = self.state.pop2()?;
8133                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8134                let cond = err!(
8135                    self.builder
8136                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8137                );
8138                let res = err!(
8139                    self.builder
8140                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8141                );
8142                self.state.push1_extra(
8143                    res,
8144                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8145                );
8146            }
8147            Operator::F32x4Lt => {
8148                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8149                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8150                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8151                let res = err!(
8152                    self.builder
8153                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8154                );
8155                let res = err!(
8156                    self.builder
8157                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8158                );
8159                let res = err!(
8160                    self.builder
8161                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8162                );
8163                self.state.push1(res);
8164            }
8165            Operator::F64x2Lt => {
8166                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8167                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8168                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8169                let res = err!(
8170                    self.builder
8171                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8172                );
8173                let res = err!(
8174                    self.builder
8175                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8176                );
8177                let res = err!(
8178                    self.builder
8179                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8180                );
8181                self.state.push1(res);
8182            }
8183            Operator::F32Le | Operator::F64Le => {
8184                let (v1, v2) = self.state.pop2()?;
8185                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8186                let cond = err!(
8187                    self.builder
8188                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8189                );
8190                let res = err!(
8191                    self.builder
8192                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8193                );
8194                self.state.push1_extra(
8195                    res,
8196                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8197                );
8198            }
8199            Operator::F32x4Le => {
8200                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8201                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8202                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8203                let res = err!(
8204                    self.builder
8205                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8206                );
8207                let res = err!(
8208                    self.builder
8209                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8210                );
8211                let res = err!(
8212                    self.builder
8213                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8214                );
8215                self.state.push1(res);
8216            }
8217            Operator::F64x2Le => {
8218                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8219                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8220                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8221                let res = err!(
8222                    self.builder
8223                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8224                );
8225                let res = err!(
8226                    self.builder
8227                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8228                );
8229                let res = err!(
8230                    self.builder
8231                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8232                );
8233                self.state.push1(res);
8234            }
8235            Operator::F32Gt | Operator::F64Gt => {
8236                let (v1, v2) = self.state.pop2()?;
8237                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8238                let cond = err!(
8239                    self.builder
8240                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8241                );
8242                let res = err!(
8243                    self.builder
8244                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8245                );
8246                self.state.push1_extra(
8247                    res,
8248                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8249                );
8250            }
8251            Operator::F32x4Gt => {
8252                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8253                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8254                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8255                let res = err!(
8256                    self.builder
8257                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8258                );
8259                let res = err!(
8260                    self.builder
8261                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8262                );
8263                let res = err!(
8264                    self.builder
8265                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8266                );
8267                self.state.push1(res);
8268            }
8269            Operator::F64x2Gt => {
8270                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8271                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8272                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8273                let res = err!(
8274                    self.builder
8275                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8276                );
8277                let res = err!(
8278                    self.builder
8279                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8280                );
8281                let res = err!(
8282                    self.builder
8283                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8284                );
8285                self.state.push1(res);
8286            }
8287            Operator::F32Ge | Operator::F64Ge => {
8288                let (v1, v2) = self.state.pop2()?;
8289                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8290                let cond = err!(
8291                    self.builder
8292                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8293                );
8294                let res = err!(
8295                    self.builder
8296                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8297                );
8298                self.state.push1_extra(
8299                    res,
8300                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8301                );
8302            }
8303            Operator::F32x4Ge => {
8304                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8305                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8306                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8307                let res = err!(
8308                    self.builder
8309                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8310                );
8311                let res = err!(
8312                    self.builder
8313                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8314                );
8315                let res = err!(
8316                    self.builder
8317                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8318                );
8319                self.state.push1(res);
8320            }
8321            Operator::F64x2Ge => {
8322                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8323                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8324                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8325                let res = err!(
8326                    self.builder
8327                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8328                );
8329                let res = err!(
8330                    self.builder
8331                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8332                );
8333                let res = err!(
8334                    self.builder
8335                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8336                );
8337                self.state.push1(res);
8338            }
8339            _ => unreachable!(),
8340        }
8341        Ok(())
8342    }
8343
8344    // Conversion instructions.
8345    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#conversion-instructions
8346    fn translate_conversion_operator(&mut self, op: Operator) -> Result<(), CompileError> {
8347        match op {
8348            Operator::I32WrapI64 => {
8349                let (v, i) = self.state.pop1_extra()?;
8350                let v = self.apply_pending_canonicalization(v, i)?;
8351                let v = v.into_int_value();
8352                let res = err!(
8353                    self.builder
8354                        .build_int_truncate(v, self.intrinsics.i32_ty, "")
8355                );
8356                self.state.push1(res);
8357            }
8358            Operator::I64ExtendI32S => {
8359                let (v, i) = self.state.pop1_extra()?;
8360                let v = self.apply_pending_canonicalization(v, i)?;
8361                let v = v.into_int_value();
8362                let res = err!(
8363                    self.builder
8364                        .build_int_s_extend(v, self.intrinsics.i64_ty, "")
8365                );
8366                self.state.push1(res);
8367            }
8368            Operator::I64ExtendI32U => {
8369                let (v, i) = self.state.pop1_extra()?;
8370                let v = self.apply_pending_canonicalization(v, i)?;
8371                let v = v.into_int_value();
8372                let res = err!(
8373                    self.builder
8374                        .build_int_z_extend(v, self.intrinsics.i64_ty, "")
8375                );
8376                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
8377            }
8378            Operator::I16x8ExtendLowI8x16S => {
8379                let (v, i) = self.state.pop1_extra()?;
8380                let (v, _) = self.v128_into_i8x16(v, i)?;
8381                let low = err!(self.builder.build_shuffle_vector(
8382                    v,
8383                    v.get_type().get_undef(),
8384                    VectorType::const_vector(&[
8385                        self.intrinsics.i32_consts[0],
8386                        self.intrinsics.i32_consts[1],
8387                        self.intrinsics.i32_consts[2],
8388                        self.intrinsics.i32_consts[3],
8389                        self.intrinsics.i32_consts[4],
8390                        self.intrinsics.i32_consts[5],
8391                        self.intrinsics.i32_consts[6],
8392                        self.intrinsics.i32_consts[7],
8393                    ]),
8394                    "",
8395                ));
8396                let res = err!(
8397                    self.builder
8398                        .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
8399                );
8400                let res = err!(
8401                    self.builder
8402                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8403                );
8404                self.state.push1(res);
8405            }
8406            Operator::I16x8ExtendHighI8x16S => {
8407                let (v, i) = self.state.pop1_extra()?;
8408                let (v, _) = self.v128_into_i8x16(v, i)?;
8409                let low = err!(self.builder.build_shuffle_vector(
8410                    v,
8411                    v.get_type().get_undef(),
8412                    VectorType::const_vector(&[
8413                        self.intrinsics.i32_consts[8],
8414                        self.intrinsics.i32_consts[9],
8415                        self.intrinsics.i32_consts[10],
8416                        self.intrinsics.i32_consts[11],
8417                        self.intrinsics.i32_consts[12],
8418                        self.intrinsics.i32_consts[13],
8419                        self.intrinsics.i32_consts[14],
8420                        self.intrinsics.i32_consts[15],
8421                    ]),
8422                    "",
8423                ));
8424                let res = err!(
8425                    self.builder
8426                        .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
8427                );
8428                let res = err!(
8429                    self.builder
8430                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8431                );
8432                self.state.push1(res);
8433            }
8434            Operator::I16x8ExtendLowI8x16U => {
8435                let (v, i) = self.state.pop1_extra()?;
8436                let (v, _) = self.v128_into_i8x16(v, i)?;
8437                let low = err!(self.builder.build_shuffle_vector(
8438                    v,
8439                    v.get_type().get_undef(),
8440                    VectorType::const_vector(&[
8441                        self.intrinsics.i32_consts[0],
8442                        self.intrinsics.i32_consts[1],
8443                        self.intrinsics.i32_consts[2],
8444                        self.intrinsics.i32_consts[3],
8445                        self.intrinsics.i32_consts[4],
8446                        self.intrinsics.i32_consts[5],
8447                        self.intrinsics.i32_consts[6],
8448                        self.intrinsics.i32_consts[7],
8449                    ]),
8450                    "",
8451                ));
8452                let res = err!(
8453                    self.builder
8454                        .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8455                );
8456                let res = err!(
8457                    self.builder
8458                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8459                );
8460                self.state.push1(res);
8461            }
8462            Operator::I16x8ExtendHighI8x16U => {
8463                let (v, i) = self.state.pop1_extra()?;
8464                let (v, _) = self.v128_into_i8x16(v, i)?;
8465                let low = err!(self.builder.build_shuffle_vector(
8466                    v,
8467                    v.get_type().get_undef(),
8468                    VectorType::const_vector(&[
8469                        self.intrinsics.i32_consts[8],
8470                        self.intrinsics.i32_consts[9],
8471                        self.intrinsics.i32_consts[10],
8472                        self.intrinsics.i32_consts[11],
8473                        self.intrinsics.i32_consts[12],
8474                        self.intrinsics.i32_consts[13],
8475                        self.intrinsics.i32_consts[14],
8476                        self.intrinsics.i32_consts[15],
8477                    ]),
8478                    "",
8479                ));
8480                let res = err!(
8481                    self.builder
8482                        .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8483                );
8484                let res = err!(
8485                    self.builder
8486                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8487                );
8488                self.state.push1(res);
8489            }
8490            Operator::I32x4ExtendLowI16x8S => {
8491                let (v, i) = self.state.pop1_extra()?;
8492                let (v, _) = self.v128_into_i16x8(v, i)?;
8493                let low = err!(self.builder.build_shuffle_vector(
8494                    v,
8495                    v.get_type().get_undef(),
8496                    VectorType::const_vector(&[
8497                        self.intrinsics.i32_consts[0],
8498                        self.intrinsics.i32_consts[1],
8499                        self.intrinsics.i32_consts[2],
8500                        self.intrinsics.i32_consts[3],
8501                    ]),
8502                    "",
8503                ));
8504                let res = err!(
8505                    self.builder
8506                        .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8507                );
8508                let res = err!(
8509                    self.builder
8510                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8511                );
8512                self.state.push1(res);
8513            }
8514            Operator::I32x4ExtendHighI16x8S => {
8515                let (v, i) = self.state.pop1_extra()?;
8516                let (v, _) = self.v128_into_i16x8(v, i)?;
8517                let low = err!(self.builder.build_shuffle_vector(
8518                    v,
8519                    v.get_type().get_undef(),
8520                    VectorType::const_vector(&[
8521                        self.intrinsics.i32_consts[4],
8522                        self.intrinsics.i32_consts[5],
8523                        self.intrinsics.i32_consts[6],
8524                        self.intrinsics.i32_consts[7],
8525                    ]),
8526                    "",
8527                ));
8528                let res = err!(
8529                    self.builder
8530                        .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8531                );
8532                let res = err!(
8533                    self.builder
8534                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8535                );
8536                self.state.push1(res);
8537            }
8538            Operator::I32x4ExtendLowI16x8U => {
8539                let (v, i) = self.state.pop1_extra()?;
8540                let (v, _) = self.v128_into_i16x8(v, i)?;
8541                let low = err!(self.builder.build_shuffle_vector(
8542                    v,
8543                    v.get_type().get_undef(),
8544                    VectorType::const_vector(&[
8545                        self.intrinsics.i32_consts[0],
8546                        self.intrinsics.i32_consts[1],
8547                        self.intrinsics.i32_consts[2],
8548                        self.intrinsics.i32_consts[3],
8549                    ]),
8550                    "",
8551                ));
8552                let res = err!(
8553                    self.builder
8554                        .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8555                );
8556                let res = err!(
8557                    self.builder
8558                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8559                );
8560                self.state.push1(res);
8561            }
8562            Operator::I32x4ExtendHighI16x8U => {
8563                let (v, i) = self.state.pop1_extra()?;
8564                let (v, _) = self.v128_into_i16x8(v, i)?;
8565                let low = err!(self.builder.build_shuffle_vector(
8566                    v,
8567                    v.get_type().get_undef(),
8568                    VectorType::const_vector(&[
8569                        self.intrinsics.i32_consts[4],
8570                        self.intrinsics.i32_consts[5],
8571                        self.intrinsics.i32_consts[6],
8572                        self.intrinsics.i32_consts[7],
8573                    ]),
8574                    "",
8575                ));
8576                let res = err!(
8577                    self.builder
8578                        .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8579                );
8580                let res = err!(
8581                    self.builder
8582                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8583                );
8584                self.state.push1(res);
8585            }
8586            Operator::I64x2ExtendLowI32x4U
8587            | Operator::I64x2ExtendLowI32x4S
8588            | Operator::I64x2ExtendHighI32x4U
8589            | Operator::I64x2ExtendHighI32x4S => {
8590                let extend = match op {
8591                    Operator::I64x2ExtendLowI32x4U | Operator::I64x2ExtendHighI32x4U => {
8592                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
8593                    }
8594                    Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendHighI32x4S => {
8595                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
8596                    }
8597                    _ => unreachable!("Unhandled inner case"),
8598                };
8599                let indices = match op {
8600                    Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendLowI32x4U => {
8601                        [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
8602                    }
8603                    Operator::I64x2ExtendHighI32x4S | Operator::I64x2ExtendHighI32x4U => {
8604                        [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
8605                    }
8606                    _ => unreachable!("Unhandled inner case"),
8607                };
8608                let (v, i) = self.state.pop1_extra()?;
8609                let (v, _) = self.v128_into_i32x4(v, i)?;
8610                let low = err!(self.builder.build_shuffle_vector(
8611                    v,
8612                    v.get_type().get_undef(),
8613                    VectorType::const_vector(&indices),
8614                    "",
8615                ));
8616                let res = err!(extend(self, low));
8617                let res = err!(
8618                    self.builder
8619                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8620                );
8621                self.state.push1(res);
8622            }
8623            Operator::I8x16NarrowI16x8S => {
8624                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8625                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8626                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8627                let min = self.intrinsics.i16_ty.const_int(0xff80, false);
8628                let max = self.intrinsics.i16_ty.const_int(0x007f, false);
8629                let min = VectorType::const_vector(&[min; 8]);
8630                let max = VectorType::const_vector(&[max; 8]);
8631                let apply_min_clamp_v1 =
8632                    err!(
8633                        self.builder
8634                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8635                    );
8636                let apply_max_clamp_v1 =
8637                    err!(
8638                        self.builder
8639                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8640                    );
8641                let apply_min_clamp_v2 =
8642                    err!(
8643                        self.builder
8644                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8645                    );
8646                let apply_max_clamp_v2 =
8647                    err!(
8648                        self.builder
8649                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8650                    );
8651                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8652                    .into_vector_value();
8653                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8654                    .into_vector_value();
8655                let v1 = err!(self.builder.build_int_truncate(
8656                    v1,
8657                    self.intrinsics.i8_ty.vec_type(8),
8658                    ""
8659                ));
8660                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8661                    .into_vector_value();
8662                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8663                    .into_vector_value();
8664                let v2 = err!(self.builder.build_int_truncate(
8665                    v2,
8666                    self.intrinsics.i8_ty.vec_type(8),
8667                    ""
8668                ));
8669                let res = err!(self.builder.build_shuffle_vector(
8670                    v1,
8671                    v2,
8672                    VectorType::const_vector(&[
8673                        self.intrinsics.i32_consts[0],
8674                        self.intrinsics.i32_consts[1],
8675                        self.intrinsics.i32_consts[2],
8676                        self.intrinsics.i32_consts[3],
8677                        self.intrinsics.i32_consts[4],
8678                        self.intrinsics.i32_consts[5],
8679                        self.intrinsics.i32_consts[6],
8680                        self.intrinsics.i32_consts[7],
8681                        self.intrinsics.i32_consts[8],
8682                        self.intrinsics.i32_consts[9],
8683                        self.intrinsics.i32_consts[10],
8684                        self.intrinsics.i32_consts[11],
8685                        self.intrinsics.i32_consts[12],
8686                        self.intrinsics.i32_consts[13],
8687                        self.intrinsics.i32_consts[14],
8688                        self.intrinsics.i32_consts[15],
8689                    ]),
8690                    "",
8691                ));
8692                let res = err!(
8693                    self.builder
8694                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8695                );
8696                self.state.push1(res);
8697            }
8698            Operator::I8x16NarrowI16x8U => {
8699                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8700                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8701                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8702                let min = self.intrinsics.i16x8_ty.const_zero();
8703                let max = self.intrinsics.i16_ty.const_int(0x00ff, false);
8704                let max = VectorType::const_vector(&[max; 8]);
8705                let apply_min_clamp_v1 =
8706                    err!(
8707                        self.builder
8708                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8709                    );
8710                let apply_max_clamp_v1 =
8711                    err!(
8712                        self.builder
8713                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8714                    );
8715                let apply_min_clamp_v2 =
8716                    err!(
8717                        self.builder
8718                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8719                    );
8720                let apply_max_clamp_v2 =
8721                    err!(
8722                        self.builder
8723                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8724                    );
8725                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8726                    .into_vector_value();
8727                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8728                    .into_vector_value();
8729                let v1 = err!(self.builder.build_int_truncate(
8730                    v1,
8731                    self.intrinsics.i8_ty.vec_type(8),
8732                    ""
8733                ));
8734                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8735                    .into_vector_value();
8736                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8737                    .into_vector_value();
8738                let v2 = err!(self.builder.build_int_truncate(
8739                    v2,
8740                    self.intrinsics.i8_ty.vec_type(8),
8741                    ""
8742                ));
8743                let res = err!(self.builder.build_shuffle_vector(
8744                    v1,
8745                    v2,
8746                    VectorType::const_vector(&[
8747                        self.intrinsics.i32_consts[0],
8748                        self.intrinsics.i32_consts[1],
8749                        self.intrinsics.i32_consts[2],
8750                        self.intrinsics.i32_consts[3],
8751                        self.intrinsics.i32_consts[4],
8752                        self.intrinsics.i32_consts[5],
8753                        self.intrinsics.i32_consts[6],
8754                        self.intrinsics.i32_consts[7],
8755                        self.intrinsics.i32_consts[8],
8756                        self.intrinsics.i32_consts[9],
8757                        self.intrinsics.i32_consts[10],
8758                        self.intrinsics.i32_consts[11],
8759                        self.intrinsics.i32_consts[12],
8760                        self.intrinsics.i32_consts[13],
8761                        self.intrinsics.i32_consts[14],
8762                        self.intrinsics.i32_consts[15],
8763                    ]),
8764                    "",
8765                ));
8766                let res = err!(
8767                    self.builder
8768                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8769                );
8770                self.state.push1(res);
8771            }
8772            Operator::I16x8NarrowI32x4S => {
8773                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8774                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8775                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8776                let min = self.intrinsics.i32_ty.const_int(0xffff8000, false);
8777                let max = self.intrinsics.i32_ty.const_int(0x00007fff, false);
8778                let min = VectorType::const_vector(&[min; 4]);
8779                let max = VectorType::const_vector(&[max; 4]);
8780                let apply_min_clamp_v1 =
8781                    err!(
8782                        self.builder
8783                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8784                    );
8785                let apply_max_clamp_v1 =
8786                    err!(
8787                        self.builder
8788                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8789                    );
8790                let apply_min_clamp_v2 =
8791                    err!(
8792                        self.builder
8793                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8794                    );
8795                let apply_max_clamp_v2 =
8796                    err!(
8797                        self.builder
8798                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8799                    );
8800                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8801                    .into_vector_value();
8802                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8803                    .into_vector_value();
8804                let v1 = err!(self.builder.build_int_truncate(
8805                    v1,
8806                    self.intrinsics.i16_ty.vec_type(4),
8807                    ""
8808                ));
8809                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8810                    .into_vector_value();
8811                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8812                    .into_vector_value();
8813                let v2 = err!(self.builder.build_int_truncate(
8814                    v2,
8815                    self.intrinsics.i16_ty.vec_type(4),
8816                    ""
8817                ));
8818                let res = err!(self.builder.build_shuffle_vector(
8819                    v1,
8820                    v2,
8821                    VectorType::const_vector(&[
8822                        self.intrinsics.i32_consts[0],
8823                        self.intrinsics.i32_consts[1],
8824                        self.intrinsics.i32_consts[2],
8825                        self.intrinsics.i32_consts[3],
8826                        self.intrinsics.i32_consts[4],
8827                        self.intrinsics.i32_consts[5],
8828                        self.intrinsics.i32_consts[6],
8829                        self.intrinsics.i32_consts[7],
8830                    ]),
8831                    "",
8832                ));
8833                let res = err!(
8834                    self.builder
8835                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8836                );
8837                self.state.push1(res);
8838            }
8839            Operator::I16x8NarrowI32x4U => {
8840                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8841                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8842                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8843                let min = self.intrinsics.i32x4_ty.const_zero();
8844                let max = self.intrinsics.i32_ty.const_int(0xffff, false);
8845                let max = VectorType::const_vector(&[max; 4]);
8846                let apply_min_clamp_v1 =
8847                    err!(
8848                        self.builder
8849                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8850                    );
8851                let apply_max_clamp_v1 =
8852                    err!(
8853                        self.builder
8854                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8855                    );
8856                let apply_min_clamp_v2 =
8857                    err!(
8858                        self.builder
8859                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8860                    );
8861                let apply_max_clamp_v2 =
8862                    err!(
8863                        self.builder
8864                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8865                    );
8866                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8867                    .into_vector_value();
8868                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8869                    .into_vector_value();
8870                let v1 = err!(self.builder.build_int_truncate(
8871                    v1,
8872                    self.intrinsics.i16_ty.vec_type(4),
8873                    ""
8874                ));
8875                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8876                    .into_vector_value();
8877                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8878                    .into_vector_value();
8879                let v2 = err!(self.builder.build_int_truncate(
8880                    v2,
8881                    self.intrinsics.i16_ty.vec_type(4),
8882                    ""
8883                ));
8884                let res = err!(self.builder.build_shuffle_vector(
8885                    v1,
8886                    v2,
8887                    VectorType::const_vector(&[
8888                        self.intrinsics.i32_consts[0],
8889                        self.intrinsics.i32_consts[1],
8890                        self.intrinsics.i32_consts[2],
8891                        self.intrinsics.i32_consts[3],
8892                        self.intrinsics.i32_consts[4],
8893                        self.intrinsics.i32_consts[5],
8894                        self.intrinsics.i32_consts[6],
8895                        self.intrinsics.i32_consts[7],
8896                    ]),
8897                    "",
8898                ));
8899                let res = err!(
8900                    self.builder
8901                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8902                );
8903                self.state.push1(res);
8904            }
8905            Operator::I32x4RelaxedTruncF32x4S if self.cpu_features.contains(CpuFeature::SSE2) => {
8906                let (v, i) = self.state.pop1_extra()?;
8907                let (v, _) = self.v128_into_f32x4(v, i)?;
8908                let res = self
8909                    .build_call_with_param_attributes(
8910                        self.intrinsics.x86_64.cvttps2dq,
8911                        &[v.into()],
8912                        "",
8913                    )?
8914                    .try_as_basic_value()
8915                    .unwrap_basic();
8916                let res = err!(
8917                    self.builder
8918                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8919                );
8920                self.state.push1(res);
8921            }
8922            Operator::I32x4TruncSatF32x4S | Operator::I32x4RelaxedTruncF32x4S => {
8923                let (v, i) = self.state.pop1_extra()?;
8924                let v = self.apply_pending_canonicalization(v, i)?;
8925                let v = v.into_int_value();
8926                let res = self.trunc_sat_into_int(
8927                    self.intrinsics.f32x4_ty,
8928                    self.intrinsics.i32x4_ty,
8929                    LEF32_GEQ_I32_MIN,
8930                    GEF32_LEQ_I32_MAX,
8931                    i32::MIN as u64,
8932                    i32::MAX as u64,
8933                    v,
8934                )?;
8935                self.state.push1(res);
8936            }
8937            Operator::I32x4RelaxedTruncF32x4U
8938                if self.cpu_features.contains(CpuFeature::AVX512F)
8939                    && self.cpu_features.contains(CpuFeature::AVX512VL) =>
8940            {
8941                let (v, i) = self.state.pop1_extra()?;
8942                let (v, _) = self.v128_into_f32x4(v, i)?;
8943                let res = self
8944                    .build_call_with_param_attributes(
8945                        self.intrinsics.x86_64.cvtps2udq128,
8946                        &[
8947                            v.into(),
8948                            self.intrinsics.i32x4_ty.const_zero().into(),
8949                            self.intrinsics.i8_ty.const_int(0xff, false).into(),
8950                        ],
8951                        "",
8952                    )?
8953                    .try_as_basic_value()
8954                    .unwrap_basic();
8955                let res = err!(
8956                    self.builder
8957                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8958                );
8959                self.state.push1(res);
8960            }
8961            Operator::I32x4TruncSatF32x4U | Operator::I32x4RelaxedTruncF32x4U => {
8962                let (v, i) = self.state.pop1_extra()?;
8963                let v = self.apply_pending_canonicalization(v, i)?;
8964                let v = v.into_int_value();
8965                let res = self.trunc_sat_into_int(
8966                    self.intrinsics.f32x4_ty,
8967                    self.intrinsics.i32x4_ty,
8968                    LEF32_GEQ_U32_MIN,
8969                    GEF32_LEQ_U32_MAX,
8970                    u32::MIN as u64,
8971                    u32::MAX as u64,
8972                    v,
8973                )?;
8974                self.state.push1(res);
8975            }
8976            Operator::I32x4RelaxedTruncF64x2SZero
8977                if self.cpu_features.contains(CpuFeature::SSE2) =>
8978            {
8979                let (v, i) = self.state.pop1_extra()?;
8980                let (v, _) = self.v128_into_f64x2(v, i)?;
8981                let res = self
8982                    .build_call_with_param_attributes(
8983                        self.intrinsics.x86_64.cvtpd2dq,
8984                        &[v.into()],
8985                        "",
8986                    )?
8987                    .try_as_basic_value()
8988                    .unwrap_basic();
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::I32x4RelaxedTruncF64x2UZero
8996                if self.cpu_features.contains(CpuFeature::AVX512F)
8997                    && self.cpu_features.contains(CpuFeature::AVX512VL) =>
8998            {
8999                let (v, i) = self.state.pop1_extra()?;
9000                let (v, _) = self.v128_into_f64x2(v, i)?;
9001                let res = self
9002                    .build_call_with_param_attributes(
9003                        self.intrinsics.x86_64.cvtpd2udq128,
9004                        &[
9005                            v.into(),
9006                            self.intrinsics.i32x4_ty.const_zero().into(),
9007                            self.intrinsics.i8_ty.const_int(0xff, false).into(),
9008                        ],
9009                        "",
9010                    )?
9011                    .try_as_basic_value()
9012                    .unwrap_basic();
9013                let res = err!(
9014                    self.builder
9015                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9016                );
9017                self.state.push1(res);
9018            }
9019            Operator::I32x4TruncSatF64x2SZero
9020            | Operator::I32x4TruncSatF64x2UZero
9021            | Operator::I32x4RelaxedTruncF64x2SZero
9022            | Operator::I32x4RelaxedTruncF64x2UZero => {
9023                let ((min, max), (cmp_min, cmp_max)) = match op {
9024                    Operator::I32x4TruncSatF64x2SZero => (
9025                        (i32::MIN as u64, i32::MAX as u64),
9026                        (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
9027                    ),
9028                    Operator::I32x4TruncSatF64x2UZero => (
9029                        (u32::MIN as u64, u32::MAX as u64),
9030                        (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
9031                    ),
9032                    Operator::I32x4RelaxedTruncF64x2SZero => (
9033                        (i32::MIN as u64, i32::MAX as u64),
9034                        (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
9035                    ),
9036                    Operator::I32x4RelaxedTruncF64x2UZero => (
9037                        (u32::MIN as u64, u32::MAX as u64),
9038                        (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
9039                    ),
9040                    _ => unreachable!("Unhandled internal variant"),
9041                };
9042                let (v, i) = self.state.pop1_extra()?;
9043                let v = self.apply_pending_canonicalization(v, i)?;
9044                let v = v.into_int_value();
9045                let res = self.trunc_sat(
9046                    self.intrinsics.f64x2_ty,
9047                    self.intrinsics.i32_ty.vec_type(2),
9048                    cmp_min,
9049                    cmp_max,
9050                    min,
9051                    max,
9052                    v,
9053                )?;
9054
9055                let zero = self.intrinsics.i32_consts[0];
9056                let zeros = VectorType::const_vector(&[zero; 2]);
9057                let res = err!(self.builder.build_shuffle_vector(
9058                    res,
9059                    zeros,
9060                    VectorType::const_vector(&[
9061                        self.intrinsics.i32_consts[0],
9062                        self.intrinsics.i32_consts[1],
9063                        self.intrinsics.i32_consts[2],
9064                        self.intrinsics.i32_consts[3],
9065                    ]),
9066                    "",
9067                ));
9068                let res = err!(
9069                    self.builder
9070                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9071                );
9072                self.state.push1(res);
9073            }
9074            // Operator::I64x2TruncSatF64x2S => {
9075            //     let (v, i) = self.state.pop1_extra()?;
9076            //     let v = self.apply_pending_canonicalization(v, i)?;
9077            //     let v = v.into_int_value();
9078            //     let res = self.trunc_sat_into_int(
9079            //         self.intrinsics.f64x2_ty,
9080            //         self.intrinsics.i64x2_ty,
9081            //         i64::MIN as u64,
9082            //         i64::MAX as u64,
9083            //         i64::MIN as u64,
9084            //         i64::MAX as u64,
9085            //         v,
9086            //     )?;
9087            //     self.state.push1(res);
9088            // }
9089            // Operator::I64x2TruncSatF64x2U => {
9090            //     let (v, i) = self.state.pop1_extra()?;
9091            //     let v = self.apply_pending_canonicalization(v, i)?;
9092            //     let v = v.into_int_value();
9093            //     let res = self.trunc_sat_into_int(
9094            //         self.intrinsics.f64x2_ty,
9095            //         self.intrinsics.i64x2_ty,
9096            //         u64::MIN,
9097            //         u64::MAX,
9098            //         u64::MIN,
9099            //         u64::MAX,
9100            //         v,
9101            //     )?;
9102            //     self.state.push1(res);
9103            // }
9104            Operator::I32TruncF32S => {
9105                let v1 = self.state.pop1()?.into_float_value();
9106                self.trap_if_not_representable_as_int(
9107                    0xcf000000, // -2147483600.0
9108                    0x4effffff, // 2147483500.0
9109                    v1,
9110                )?;
9111                let res = err!(self.builder.build_float_to_signed_int(
9112                    v1,
9113                    self.intrinsics.i32_ty,
9114                    ""
9115                ));
9116                self.state.push1(res);
9117            }
9118            Operator::I32TruncF64S => {
9119                let v1 = self.state.pop1()?.into_float_value();
9120                self.trap_if_not_representable_as_int(
9121                    0xc1e00000001fffff, // -2147483648.9999995
9122                    0x41dfffffffffffff, // 2147483647.9999998
9123                    v1,
9124                )?;
9125                let res = err!(self.builder.build_float_to_signed_int(
9126                    v1,
9127                    self.intrinsics.i32_ty,
9128                    ""
9129                ));
9130                self.state.push1(res);
9131            }
9132            Operator::I32TruncSatF32S => {
9133                let (v, i) = self.state.pop1_extra()?;
9134                let v = self.apply_pending_canonicalization(v, i)?;
9135                let v = v.into_float_value();
9136                let res = self.trunc_sat_scalar(
9137                    self.intrinsics.i32_ty,
9138                    LEF32_GEQ_I32_MIN,
9139                    GEF32_LEQ_I32_MAX,
9140                    i32::MIN as u32 as u64,
9141                    i32::MAX as u32 as u64,
9142                    v,
9143                )?;
9144                self.state.push1(res);
9145            }
9146            Operator::I32TruncSatF64S => {
9147                let (v, i) = self.state.pop1_extra()?;
9148                let v = self.apply_pending_canonicalization(v, i)?;
9149                let v = v.into_float_value();
9150                let res = self.trunc_sat_scalar(
9151                    self.intrinsics.i32_ty,
9152                    LEF64_GEQ_I32_MIN,
9153                    GEF64_LEQ_I32_MAX,
9154                    i32::MIN as u64,
9155                    i32::MAX as u64,
9156                    v,
9157                )?;
9158                self.state.push1(res);
9159            }
9160            Operator::I64TruncF32S => {
9161                let v1 = self.state.pop1()?.into_float_value();
9162                self.trap_if_not_representable_as_int(
9163                    0xdf000000, // -9223372000000000000.0
9164                    0x5effffff, // 9223371500000000000.0
9165                    v1,
9166                )?;
9167                let res = err!(self.builder.build_float_to_signed_int(
9168                    v1,
9169                    self.intrinsics.i64_ty,
9170                    ""
9171                ));
9172                self.state.push1(res);
9173            }
9174            Operator::I64TruncF64S => {
9175                let v1 = self.state.pop1()?.into_float_value();
9176                self.trap_if_not_representable_as_int(
9177                    0xc3e0000000000000, // -9223372036854776000.0
9178                    0x43dfffffffffffff, // 9223372036854775000.0
9179                    v1,
9180                )?;
9181                let res = err!(self.builder.build_float_to_signed_int(
9182                    v1,
9183                    self.intrinsics.i64_ty,
9184                    ""
9185                ));
9186                self.state.push1(res);
9187            }
9188            Operator::I64TruncSatF32S => {
9189                let (v, i) = self.state.pop1_extra()?;
9190                let v = self.apply_pending_canonicalization(v, i)?;
9191                let v = v.into_float_value();
9192                let res = self.trunc_sat_scalar(
9193                    self.intrinsics.i64_ty,
9194                    LEF32_GEQ_I64_MIN,
9195                    GEF32_LEQ_I64_MAX,
9196                    i64::MIN as u64,
9197                    i64::MAX as u64,
9198                    v,
9199                )?;
9200                self.state.push1(res);
9201            }
9202            Operator::I64TruncSatF64S => {
9203                let (v, i) = self.state.pop1_extra()?;
9204                let v = self.apply_pending_canonicalization(v, i)?;
9205                let v = v.into_float_value();
9206                let res = self.trunc_sat_scalar(
9207                    self.intrinsics.i64_ty,
9208                    LEF64_GEQ_I64_MIN,
9209                    GEF64_LEQ_I64_MAX,
9210                    i64::MIN as u64,
9211                    i64::MAX as u64,
9212                    v,
9213                )?;
9214                self.state.push1(res);
9215            }
9216            Operator::I32TruncF32U => {
9217                let v1 = self.state.pop1()?.into_float_value();
9218                self.trap_if_not_representable_as_int(
9219                    0xbf7fffff, // -0.99999994
9220                    0x4f7fffff, // 4294967000.0
9221                    v1,
9222                )?;
9223                let res = err!(self.builder.build_float_to_unsigned_int(
9224                    v1,
9225                    self.intrinsics.i32_ty,
9226                    ""
9227                ));
9228                self.state.push1(res);
9229            }
9230            Operator::I32TruncF64U => {
9231                let v1 = self.state.pop1()?.into_float_value();
9232                self.trap_if_not_representable_as_int(
9233                    0xbfefffffffffffff, // -0.9999999999999999
9234                    0x41efffffffffffff, // 4294967295.9999995
9235                    v1,
9236                )?;
9237                let res = err!(self.builder.build_float_to_unsigned_int(
9238                    v1,
9239                    self.intrinsics.i32_ty,
9240                    ""
9241                ));
9242                self.state.push1(res);
9243            }
9244            Operator::I32TruncSatF32U => {
9245                let (v, i) = self.state.pop1_extra()?;
9246                let v = self.apply_pending_canonicalization(v, i)?;
9247                let v = v.into_float_value();
9248                let res = self.trunc_sat_scalar(
9249                    self.intrinsics.i32_ty,
9250                    LEF32_GEQ_U32_MIN,
9251                    GEF32_LEQ_U32_MAX,
9252                    u32::MIN as u64,
9253                    u32::MAX as u64,
9254                    v,
9255                )?;
9256                self.state.push1(res);
9257            }
9258            Operator::I32TruncSatF64U => {
9259                let (v, i) = self.state.pop1_extra()?;
9260                let v = self.apply_pending_canonicalization(v, i)?;
9261                let v = v.into_float_value();
9262                let res = self.trunc_sat_scalar(
9263                    self.intrinsics.i32_ty,
9264                    LEF64_GEQ_U32_MIN,
9265                    GEF64_LEQ_U32_MAX,
9266                    u32::MIN as u64,
9267                    u32::MAX as u64,
9268                    v,
9269                )?;
9270                self.state.push1(res);
9271            }
9272            Operator::I64TruncF32U => {
9273                let v1 = self.state.pop1()?.into_float_value();
9274                self.trap_if_not_representable_as_int(
9275                    0xbf7fffff, // -0.99999994
9276                    0x5f7fffff, // 18446743000000000000.0
9277                    v1,
9278                )?;
9279                let res = err!(self.builder.build_float_to_unsigned_int(
9280                    v1,
9281                    self.intrinsics.i64_ty,
9282                    ""
9283                ));
9284                self.state.push1(res);
9285            }
9286            Operator::I64TruncF64U => {
9287                let v1 = self.state.pop1()?.into_float_value();
9288                self.trap_if_not_representable_as_int(
9289                    0xbfefffffffffffff, // -0.9999999999999999
9290                    0x43efffffffffffff, // 18446744073709550000.0
9291                    v1,
9292                )?;
9293                let res = err!(self.builder.build_float_to_unsigned_int(
9294                    v1,
9295                    self.intrinsics.i64_ty,
9296                    ""
9297                ));
9298                self.state.push1(res);
9299            }
9300            Operator::I64TruncSatF32U => {
9301                let (v, i) = self.state.pop1_extra()?;
9302                let v = self.apply_pending_canonicalization(v, i)?;
9303                let v = v.into_float_value();
9304                let res = self.trunc_sat_scalar(
9305                    self.intrinsics.i64_ty,
9306                    LEF32_GEQ_U64_MIN,
9307                    GEF32_LEQ_U64_MAX,
9308                    u64::MIN,
9309                    u64::MAX,
9310                    v,
9311                )?;
9312                self.state.push1(res);
9313            }
9314            Operator::I64TruncSatF64U => {
9315                let (v, i) = self.state.pop1_extra()?;
9316                let v = self.apply_pending_canonicalization(v, i)?;
9317                let v = v.into_float_value();
9318                let res = self.trunc_sat_scalar(
9319                    self.intrinsics.i64_ty,
9320                    LEF64_GEQ_U64_MIN,
9321                    GEF64_LEQ_U64_MAX,
9322                    u64::MIN,
9323                    u64::MAX,
9324                    v,
9325                )?;
9326                self.state.push1(res);
9327            }
9328            Operator::F32DemoteF64 => {
9329                let v = self.state.pop1()?;
9330                let v = v.into_float_value();
9331                let res = self
9332                    .build_call_with_param_attributes(
9333                        self.intrinsics.fptrunc_f64,
9334                        &[
9335                            v.into(),
9336                            self.intrinsics.fp_rounding_md,
9337                            self.intrinsics.fp_exception_md,
9338                        ],
9339                        "",
9340                    )?
9341                    .try_as_basic_value()
9342                    .unwrap_basic();
9343                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9344            }
9345            Operator::F64PromoteF32 => {
9346                let v = self.state.pop1()?;
9347                let v = v.into_float_value();
9348                let res = self
9349                    .build_call_with_param_attributes(
9350                        self.intrinsics.fpext_f32,
9351                        &[v.into(), self.intrinsics.fp_exception_md],
9352                        "",
9353                    )?
9354                    .try_as_basic_value()
9355                    .unwrap_basic();
9356                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9357            }
9358            Operator::F32ConvertI32S | Operator::F32ConvertI64S => {
9359                let (v, i) = self.state.pop1_extra()?;
9360                let v = self.apply_pending_canonicalization(v, i)?;
9361                let v = v.into_int_value();
9362                let res = err!(self.builder.build_signed_int_to_float(
9363                    v,
9364                    self.intrinsics.f32_ty,
9365                    ""
9366                ));
9367                self.state.push1(res);
9368            }
9369            Operator::F64ConvertI32S | Operator::F64ConvertI64S => {
9370                let (v, i) = self.state.pop1_extra()?;
9371                let v = self.apply_pending_canonicalization(v, i)?;
9372                let v = v.into_int_value();
9373                let res = err!(self.builder.build_signed_int_to_float(
9374                    v,
9375                    self.intrinsics.f64_ty,
9376                    ""
9377                ));
9378                self.state.push1(res);
9379            }
9380            Operator::F32ConvertI32U | Operator::F32ConvertI64U => {
9381                let (v, i) = self.state.pop1_extra()?;
9382                let v = self.apply_pending_canonicalization(v, i)?;
9383                let v = v.into_int_value();
9384                let res = err!(self.builder.build_unsigned_int_to_float(
9385                    v,
9386                    self.intrinsics.f32_ty,
9387                    ""
9388                ));
9389                self.state.push1(res);
9390            }
9391            Operator::F64ConvertI32U | Operator::F64ConvertI64U => {
9392                let (v, i) = self.state.pop1_extra()?;
9393                let v = self.apply_pending_canonicalization(v, i)?;
9394                let v = v.into_int_value();
9395                let res = err!(self.builder.build_unsigned_int_to_float(
9396                    v,
9397                    self.intrinsics.f64_ty,
9398                    ""
9399                ));
9400                self.state.push1(res);
9401            }
9402            Operator::F32x4ConvertI32x4S => {
9403                let v = self.state.pop1()?;
9404                let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
9405                    .into_vector_value();
9406                let res = err!(self.builder.build_signed_int_to_float(
9407                    v,
9408                    self.intrinsics.f32x4_ty,
9409                    ""
9410                ));
9411                let res = err!(
9412                    self.builder
9413                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9414                );
9415                self.state.push1(res);
9416            }
9417            Operator::F32x4ConvertI32x4U => {
9418                let v = self.state.pop1()?;
9419                let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
9420                    .into_vector_value();
9421                let res = err!(self.builder.build_unsigned_int_to_float(
9422                    v,
9423                    self.intrinsics.f32x4_ty,
9424                    ""
9425                ));
9426                let res = err!(
9427                    self.builder
9428                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9429                );
9430                self.state.push1(res);
9431            }
9432            Operator::F64x2ConvertLowI32x4S | Operator::F64x2ConvertLowI32x4U => {
9433                let extend = match op {
9434                    Operator::F64x2ConvertLowI32x4U => {
9435                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
9436                    }
9437                    Operator::F64x2ConvertLowI32x4S => {
9438                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
9439                    }
9440                    _ => unreachable!("Unhandled inner case"),
9441                };
9442                let (v, i) = self.state.pop1_extra()?;
9443                let (v, _) = self.v128_into_i32x4(v, i)?;
9444                let low = err!(self.builder.build_shuffle_vector(
9445                    v,
9446                    v.get_type().get_undef(),
9447                    VectorType::const_vector(&[
9448                        self.intrinsics.i32_consts[0],
9449                        self.intrinsics.i32_consts[1],
9450                    ]),
9451                    "",
9452                ));
9453                let res = err!(extend(self, low));
9454                let res = err!(self.builder.build_signed_int_to_float(
9455                    res,
9456                    self.intrinsics.f64x2_ty,
9457                    ""
9458                ));
9459                let res = err!(
9460                    self.builder
9461                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9462                );
9463                self.state.push1(res);
9464            }
9465            Operator::F64x2PromoteLowF32x4 => {
9466                let (v, i) = self.state.pop1_extra()?;
9467                let (v, _) = self.v128_into_f32x4(v, i)?;
9468                let low = err!(self.builder.build_shuffle_vector(
9469                    v,
9470                    v.get_type().get_undef(),
9471                    VectorType::const_vector(&[
9472                        self.intrinsics.i32_consts[0],
9473                        self.intrinsics.i32_consts[1],
9474                    ]),
9475                    "",
9476                ));
9477                let res = err!(
9478                    self.builder
9479                        .build_float_ext(low, self.intrinsics.f64x2_ty, "")
9480                );
9481                let res = err!(
9482                    self.builder
9483                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9484                );
9485                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9486            }
9487            Operator::F32x4DemoteF64x2Zero => {
9488                let (v, i) = self.state.pop1_extra()?;
9489                let (v, _) = self.v128_into_f64x2(v, i)?;
9490                let f32x2_ty = self.intrinsics.f32_ty.vec_type(2);
9491                let res = err!(self.builder.build_float_trunc(v, f32x2_ty, ""));
9492                let zeros = f32x2_ty.const_zero();
9493                let res = err!(self.builder.build_shuffle_vector(
9494                    res,
9495                    zeros,
9496                    VectorType::const_vector(&[
9497                        self.intrinsics.i32_consts[0],
9498                        self.intrinsics.i32_consts[1],
9499                        self.intrinsics.i32_consts[2],
9500                        self.intrinsics.i32_consts[3],
9501                    ]),
9502                    "",
9503                ));
9504                let res = err!(
9505                    self.builder
9506                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9507                );
9508                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9509            }
9510            // Operator::F64x2ConvertI64x2S => {
9511            //     let v = self.state.pop1()?;
9512            //     let v = self
9513            //         .builder
9514            //         .build_bit_cast(v, self.intrinsics.i64x2_ty, "")
9515            //         .into_vector_value();
9516            //     let res = self
9517            //         .builder
9518            //         .build_signed_int_to_float(v, self.intrinsics.f64x2_ty, "");
9519            //     let res = check_err!(self.builder.build_bit_cast(res, self.intrinsics.i128_ty, ""));
9520            //     self.state.push1(res);
9521            // }
9522            // Operator::F64x2ConvertI64x2U => {
9523            //     let v = self.state.pop1()?;
9524            //     let v = self
9525            //         .builder
9526            //         .build_bit_cast(v, self.intrinsics.i64x2_ty, "")
9527            //         .into_vector_value();
9528            //     let res = self
9529            //         .builder
9530            //         .build_unsigned_int_to_float(v, self.intrinsics.f64x2_ty, "");
9531            //     let res = check_err!(self.builder.build_bit_cast(res, self.intrinsics.i128_ty, ""));
9532            //     self.state.push1(res);
9533            // }
9534            Operator::I32ReinterpretF32 => {
9535                let (v, i) = self.state.pop1_extra()?;
9536                let v = self.apply_pending_canonicalization(v, i)?;
9537                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i32_ty, ""));
9538                self.state.push1_extra(ret, ExtraInfo::arithmetic_f32());
9539            }
9540            Operator::I64ReinterpretF64 => {
9541                let (v, i) = self.state.pop1_extra()?;
9542                let v = self.apply_pending_canonicalization(v, i)?;
9543                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i64_ty, ""));
9544                self.state.push1_extra(ret, ExtraInfo::arithmetic_f64());
9545            }
9546            Operator::F32ReinterpretI32 => {
9547                let (v, i) = self.state.pop1_extra()?;
9548                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f32_ty, ""));
9549                self.state.push1_extra(ret, i);
9550            }
9551            Operator::F64ReinterpretI64 => {
9552                let (v, i) = self.state.pop1_extra()?;
9553                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f64_ty, ""));
9554                self.state.push1_extra(ret, i);
9555            }
9556            _ => unreachable!(),
9557        }
9558        Ok(())
9559    }
9560
9561    // Sign-extension operators.
9562    // https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md
9563    fn translate_sign_extension_operator(&mut self, op: Operator) -> Result<(), CompileError> {
9564        match op {
9565            Operator::I32Extend8S => {
9566                let value = self.state.pop1()?.into_int_value();
9567                let narrow_value = err!(self.builder.build_int_truncate(
9568                    value,
9569                    self.intrinsics.i8_ty,
9570                    ""
9571                ));
9572                let extended_value = err!(self.builder.build_int_s_extend(
9573                    narrow_value,
9574                    self.intrinsics.i32_ty,
9575                    ""
9576                ));
9577                self.state.push1(extended_value);
9578            }
9579            Operator::I32Extend16S => {
9580                let value = self.state.pop1()?.into_int_value();
9581                let narrow_value = err!(self.builder.build_int_truncate(
9582                    value,
9583                    self.intrinsics.i16_ty,
9584                    ""
9585                ));
9586                let extended_value = err!(self.builder.build_int_s_extend(
9587                    narrow_value,
9588                    self.intrinsics.i32_ty,
9589                    ""
9590                ));
9591                self.state.push1(extended_value);
9592            }
9593            Operator::I64Extend8S => {
9594                let value = self.state.pop1()?.into_int_value();
9595                let narrow_value = err!(self.builder.build_int_truncate(
9596                    value,
9597                    self.intrinsics.i8_ty,
9598                    ""
9599                ));
9600                let extended_value = err!(self.builder.build_int_s_extend(
9601                    narrow_value,
9602                    self.intrinsics.i64_ty,
9603                    ""
9604                ));
9605                self.state.push1(extended_value);
9606            }
9607            Operator::I64Extend16S => {
9608                let value = self.state.pop1()?.into_int_value();
9609                let narrow_value = err!(self.builder.build_int_truncate(
9610                    value,
9611                    self.intrinsics.i16_ty,
9612                    ""
9613                ));
9614                let extended_value = err!(self.builder.build_int_s_extend(
9615                    narrow_value,
9616                    self.intrinsics.i64_ty,
9617                    ""
9618                ));
9619                self.state.push1(extended_value);
9620            }
9621            Operator::I64Extend32S => {
9622                let value = self.state.pop1()?.into_int_value();
9623                let narrow_value = err!(self.builder.build_int_truncate(
9624                    value,
9625                    self.intrinsics.i32_ty,
9626                    ""
9627                ));
9628                let extended_value = err!(self.builder.build_int_s_extend(
9629                    narrow_value,
9630                    self.intrinsics.i64_ty,
9631                    ""
9632                ));
9633                self.state.push1(extended_value);
9634            }
9635            _ => unreachable!(),
9636        }
9637        Ok(())
9638    }
9639
9640    // Load and Store instructions.
9641    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#load-and-store-instructions
9642    fn translate_memory_operator(&mut self, op: Operator) -> Result<(), CompileError> {
9643        let vmctx = &self.ctx.basic().into_pointer_value();
9644
9645        match op {
9646            Operator::I32Load { ref memarg } => {
9647                let offset = self.state.pop1()?.into_int_value();
9648                let result =
9649                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9650                self.state.push1(result);
9651            }
9652            Operator::I64Load { ref memarg } => {
9653                let offset = self.state.pop1()?.into_int_value();
9654                let result =
9655                    self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
9656                self.state.push1(result);
9657            }
9658            Operator::F32Load { ref memarg } => {
9659                let offset = self.state.pop1()?.into_int_value();
9660                let result =
9661                    self.build_annotated_load(self.intrinsics.f32_ty, offset, memarg, 1)?;
9662                self.state.push1(result);
9663            }
9664            Operator::F64Load { ref memarg } => {
9665                let offset = self.state.pop1()?.into_int_value();
9666                let result =
9667                    self.build_annotated_load(self.intrinsics.f64_ty, offset, memarg, 1)?;
9668                self.state.push1(result);
9669            }
9670            Operator::V128Load { ref memarg } => {
9671                let offset = self.state.pop1()?.into_int_value();
9672                let result =
9673                    self.build_annotated_load(self.intrinsics.i128_ty, offset, memarg, 1)?;
9674                self.state.push1(result);
9675            }
9676            Operator::V128Load8Lane { ref memarg, lane } => {
9677                let (v, i) = self.state.pop1_extra()?;
9678                let (v, _i) = self.v128_into_i8x16(v, i)?;
9679                let offset = self.state.pop1()?.into_int_value();
9680                let element =
9681                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9682                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9683                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9684                let res = err!(
9685                    self.builder
9686                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9687                );
9688                self.state.push1(res);
9689            }
9690            Operator::V128Load16Lane { ref memarg, lane } => {
9691                let (v, i) = self.state.pop1_extra()?;
9692                let (v, i) = self.v128_into_i16x8(v, i)?;
9693                let offset = self.state.pop1()?.into_int_value();
9694                let element =
9695                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9696                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9697                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9698                let res = err!(
9699                    self.builder
9700                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9701                );
9702                self.state.push1_extra(res, i);
9703            }
9704            Operator::V128Load32Lane { ref memarg, lane } => {
9705                let (v, i) = self.state.pop1_extra()?;
9706                let (v, i) = self.v128_into_i32x4(v, i)?;
9707                let offset = self.state.pop1()?.into_int_value();
9708                let element =
9709                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9710                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9711                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9712                let res = err!(
9713                    self.builder
9714                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9715                );
9716                self.state.push1_extra(res, i);
9717            }
9718            Operator::V128Load64Lane { ref memarg, lane } => {
9719                let (v, i) = self.state.pop1_extra()?;
9720                let (v, i) = self.v128_into_i64x2(v, i)?;
9721                let offset = self.state.pop1()?.into_int_value();
9722                let element =
9723                    self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
9724                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9725                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9726                let res = err!(
9727                    self.builder
9728                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9729                );
9730                self.state.push1_extra(res, i);
9731            }
9732
9733            Operator::I32Store { ref memarg } => {
9734                let value = self.state.pop1()?;
9735                let offset = self.state.pop1()?.into_int_value();
9736                self.build_annotated_store(self.intrinsics.i32_ty, offset, value, memarg, 1)?;
9737            }
9738            Operator::I64Store { ref memarg } => {
9739                let value = self.state.pop1()?;
9740                let offset = self.state.pop1()?.into_int_value();
9741                self.build_annotated_store(self.intrinsics.i64_ty, offset, value, memarg, 1)?;
9742            }
9743            Operator::F32Store { ref memarg } => {
9744                let (v, i) = self.state.pop1_extra()?;
9745                let v = self.apply_pending_canonicalization(v, i)?;
9746                let offset = self.state.pop1()?.into_int_value();
9747                self.build_annotated_store(self.intrinsics.f32_ty, offset, v, memarg, 1)?;
9748            }
9749            Operator::F64Store { ref memarg } => {
9750                let (v, i) = self.state.pop1_extra()?;
9751                let v = self.apply_pending_canonicalization(v, i)?;
9752                let offset = self.state.pop1()?.into_int_value();
9753                self.build_annotated_store(self.intrinsics.f64_ty, offset, v, memarg, 1)?;
9754            }
9755            Operator::V128Store { ref memarg } => {
9756                let (v, i) = self.state.pop1_extra()?;
9757                let v = self.apply_pending_canonicalization(v, i)?;
9758                let offset = self.state.pop1()?.into_int_value();
9759                self.build_annotated_store(self.intrinsics.i128_ty, offset, v, memarg, 1)?;
9760            }
9761            Operator::V128Store8Lane { ref memarg, lane } => {
9762                let (v, i) = self.state.pop1_extra()?;
9763                let (v, _i) = self.v128_into_i8x16(v, i)?;
9764                let offset = self.state.pop1()?.into_int_value();
9765                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9766                let val = err!(self.builder.build_extract_element(v, idx, ""));
9767                self.build_annotated_store(self.intrinsics.i8_ty, offset, val, memarg, 1)?;
9768            }
9769            Operator::V128Store16Lane { ref memarg, lane } => {
9770                let (v, i) = self.state.pop1_extra()?;
9771                let (v, _i) = self.v128_into_i16x8(v, i)?;
9772                let offset = self.state.pop1()?.into_int_value();
9773                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9774                let val = err!(self.builder.build_extract_element(v, idx, ""));
9775                self.build_annotated_store(self.intrinsics.i16_ty, offset, val, memarg, 1)?;
9776            }
9777            Operator::V128Store32Lane { ref memarg, lane } => {
9778                let (v, i) = self.state.pop1_extra()?;
9779                let (v, _i) = self.v128_into_i32x4(v, i)?;
9780                let offset = self.state.pop1()?.into_int_value();
9781                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9782                let val = err!(self.builder.build_extract_element(v, idx, ""));
9783                self.build_annotated_store(self.intrinsics.i32_ty, offset, val, memarg, 1)?;
9784            }
9785            Operator::V128Store64Lane { ref memarg, lane } => {
9786                let (v, i) = self.state.pop1_extra()?;
9787                let (v, _i) = self.v128_into_i64x2(v, i)?;
9788                let offset = self.state.pop1()?.into_int_value();
9789                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9790                let val = err!(self.builder.build_extract_element(v, idx, ""));
9791                self.build_annotated_store(self.intrinsics.i64_ty, offset, val, memarg, 1)?;
9792            }
9793            Operator::I32Load8S { ref memarg } => {
9794                let offset = self.state.pop1()?.into_int_value();
9795                let narrow_result =
9796                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9797                let result = err!(self.builder.build_int_s_extend(
9798                    narrow_result.into_int_value(),
9799                    self.intrinsics.i32_ty,
9800                    "",
9801                ));
9802                self.state.push1(result);
9803            }
9804            Operator::I32Load16S { ref memarg } => {
9805                let offset = self.state.pop1()?.into_int_value();
9806                let narrow_result =
9807                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9808                let result = err!(self.builder.build_int_s_extend(
9809                    narrow_result.into_int_value(),
9810                    self.intrinsics.i32_ty,
9811                    "",
9812                ));
9813                self.state.push1(result);
9814            }
9815            Operator::I64Load8S { ref memarg } => {
9816                let offset = self.state.pop1()?.into_int_value();
9817                let narrow_result =
9818                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9819                let result = err!(self.builder.build_int_s_extend(
9820                    narrow_result.into_int_value(),
9821                    self.intrinsics.i64_ty,
9822                    ""
9823                ));
9824                self.state.push1(result);
9825            }
9826            Operator::I64Load16S { ref memarg } => {
9827                let offset = self.state.pop1()?.into_int_value();
9828                let narrow_result =
9829                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9830                let result = err!(self.builder.build_int_s_extend(
9831                    narrow_result.into_int_value(),
9832                    self.intrinsics.i64_ty,
9833                    ""
9834                ));
9835                self.state.push1(result);
9836            }
9837            Operator::I64Load32S { ref memarg } => {
9838                let offset = self.state.pop1()?.into_int_value();
9839                let narrow_result =
9840                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9841                let result = err!(self.builder.build_int_s_extend(
9842                    narrow_result.into_int_value(),
9843                    self.intrinsics.i64_ty,
9844                    "",
9845                ));
9846                self.state.push1(result);
9847            }
9848
9849            Operator::I32Load8U { ref memarg } => {
9850                let offset = self.state.pop1()?.into_int_value();
9851                let narrow_result =
9852                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9853                let result = err!(self.builder.build_int_z_extend(
9854                    narrow_result.into_int_value(),
9855                    self.intrinsics.i32_ty,
9856                    "",
9857                ));
9858                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9859            }
9860            Operator::I32Load16U { ref memarg } => {
9861                let offset = self.state.pop1()?.into_int_value();
9862                let narrow_result =
9863                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9864                let result = err!(self.builder.build_int_z_extend(
9865                    narrow_result.into_int_value(),
9866                    self.intrinsics.i32_ty,
9867                    "",
9868                ));
9869                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9870            }
9871            Operator::I64Load8U { ref memarg } => {
9872                let offset = self.state.pop1()?.into_int_value();
9873                let narrow_result =
9874                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9875                let result = err!(self.builder.build_int_z_extend(
9876                    narrow_result.into_int_value(),
9877                    self.intrinsics.i64_ty,
9878                    "",
9879                ));
9880                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9881            }
9882            Operator::I64Load16U { ref memarg } => {
9883                let offset = self.state.pop1()?.into_int_value();
9884                let narrow_result =
9885                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9886                let result = err!(self.builder.build_int_z_extend(
9887                    narrow_result.into_int_value(),
9888                    self.intrinsics.i64_ty,
9889                    "",
9890                ));
9891                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9892            }
9893            Operator::I64Load32U { ref memarg } => {
9894                let offset = self.state.pop1()?.into_int_value();
9895                let narrow_result =
9896                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9897                let result = err!(self.builder.build_int_z_extend(
9898                    narrow_result.into_int_value(),
9899                    self.intrinsics.i64_ty,
9900                    "",
9901                ));
9902                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9903            }
9904
9905            Operator::I32Store8 { ref memarg } | Operator::I64Store8 { ref memarg } => {
9906                let value = self.state.pop1()?.into_int_value();
9907                let offset = self.state.pop1()?.into_int_value();
9908                let narrow_value = err!(self.builder.build_int_truncate(
9909                    value,
9910                    self.intrinsics.i8_ty,
9911                    ""
9912                ));
9913                self.build_annotated_store(
9914                    self.intrinsics.i8_ty,
9915                    offset,
9916                    narrow_value.into(),
9917                    memarg,
9918                    1,
9919                )?;
9920            }
9921            Operator::I32Store16 { ref memarg } | Operator::I64Store16 { ref memarg } => {
9922                let value = self.state.pop1()?.into_int_value();
9923                let offset = self.state.pop1()?.into_int_value();
9924                let narrow_value = err!(self.builder.build_int_truncate(
9925                    value,
9926                    self.intrinsics.i16_ty,
9927                    ""
9928                ));
9929                self.build_annotated_store(
9930                    self.intrinsics.i16_ty,
9931                    offset,
9932                    narrow_value.into(),
9933                    memarg,
9934                    1,
9935                )?;
9936            }
9937            Operator::I64Store32 { ref memarg } => {
9938                let value = self.state.pop1()?.into_int_value();
9939                let offset = self.state.pop1()?.into_int_value();
9940                let narrow_value = err!(self.builder.build_int_truncate(
9941                    value,
9942                    self.intrinsics.i32_ty,
9943                    ""
9944                ));
9945                self.build_annotated_store(
9946                    self.intrinsics.i32_ty,
9947                    offset,
9948                    narrow_value.into(),
9949                    memarg,
9950                    1,
9951                )?;
9952            }
9953            Operator::I8x16Neg => {
9954                let (v, i) = self.state.pop1_extra()?;
9955                let (v, _) = self.v128_into_i8x16(v, i)?;
9956                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9957                let res = err!(
9958                    self.builder
9959                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9960                );
9961                self.state.push1(res);
9962            }
9963            Operator::I16x8Neg => {
9964                let (v, i) = self.state.pop1_extra()?;
9965                let (v, _) = self.v128_into_i16x8(v, i)?;
9966                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9967                let res = err!(
9968                    self.builder
9969                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9970                );
9971                self.state.push1(res);
9972            }
9973            Operator::I32x4Neg => {
9974                let (v, i) = self.state.pop1_extra()?;
9975                let (v, _) = self.v128_into_i32x4(v, i)?;
9976                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9977                let res = err!(
9978                    self.builder
9979                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9980                );
9981                self.state.push1(res);
9982            }
9983            Operator::I64x2Neg => {
9984                let (v, i) = self.state.pop1_extra()?;
9985                let (v, _) = self.v128_into_i64x2(v, i)?;
9986                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9987                let res = err!(
9988                    self.builder
9989                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9990                );
9991                self.state.push1(res);
9992            }
9993            Operator::V128Not => {
9994                let (v, i) = self.state.pop1_extra()?;
9995                let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
9996                let res = err!(self.builder.build_not(v, ""));
9997                self.state.push1(res);
9998            }
9999            Operator::V128AnyTrue => {
10000                // | Operator::I64x2AnyTrue
10001                // Skip canonicalization, it never changes non-zero values to zero or vice versa.
10002                let v = self.state.pop1()?.into_int_value();
10003                let res = err!(self.builder.build_int_compare(
10004                    IntPredicate::NE,
10005                    v,
10006                    v.get_type().const_zero(),
10007                    "",
10008                ));
10009                let res = err!(
10010                    self.builder
10011                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10012                );
10013                self.state.push1_extra(
10014                    res,
10015                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10016                );
10017            }
10018            Operator::I8x16AllTrue
10019            | Operator::I16x8AllTrue
10020            | Operator::I32x4AllTrue
10021            | Operator::I64x2AllTrue => {
10022                let vec_ty = match op {
10023                    Operator::I8x16AllTrue => self.intrinsics.i8x16_ty,
10024                    Operator::I16x8AllTrue => self.intrinsics.i16x8_ty,
10025                    Operator::I32x4AllTrue => self.intrinsics.i32x4_ty,
10026                    Operator::I64x2AllTrue => self.intrinsics.i64x2_ty,
10027                    _ => unreachable!(),
10028                };
10029                let (v, i) = self.state.pop1_extra()?;
10030                let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10031                let lane_int_ty = self
10032                    .context
10033                    .custom_width_int_type(NonZero::new(vec_ty.get_size()).unwrap())
10034                    .unwrap();
10035                let vec = err!(self.builder.build_bit_cast(v, vec_ty, "vec")).into_vector_value();
10036                let mask = err!(self.builder.build_int_compare(
10037                    IntPredicate::NE,
10038                    vec,
10039                    vec_ty.const_zero(),
10040                    "mask",
10041                ));
10042                let cmask =
10043                    err!(self.builder.build_bit_cast(mask, lane_int_ty, "cmask")).into_int_value();
10044                let res = err!(self.builder.build_int_compare(
10045                    IntPredicate::EQ,
10046                    cmask,
10047                    lane_int_ty.const_int(u64::MAX, true),
10048                    "",
10049                ));
10050                let res = err!(
10051                    self.builder
10052                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10053                );
10054                self.state.push1_extra(
10055                    res,
10056                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10057                );
10058            }
10059            Operator::I8x16ExtractLaneS { lane } => {
10060                let (v, i) = self.state.pop1_extra()?;
10061                let (v, _) = self.v128_into_i8x16(v, i)?;
10062                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10063                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10064                let res = err!(
10065                    self.builder
10066                        .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10067                );
10068                self.state.push1(res);
10069            }
10070            Operator::I8x16ExtractLaneU { lane } => {
10071                let (v, i) = self.state.pop1_extra()?;
10072                let (v, _) = self.v128_into_i8x16(v, i)?;
10073                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10074                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10075                let res = err!(
10076                    self.builder
10077                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10078                );
10079                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10080            }
10081            Operator::I16x8ExtractLaneS { lane } => {
10082                let (v, i) = self.state.pop1_extra()?;
10083                let (v, _) = self.v128_into_i16x8(v, i)?;
10084                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10085                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10086                let res = err!(
10087                    self.builder
10088                        .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10089                );
10090                self.state.push1(res);
10091            }
10092            Operator::I16x8ExtractLaneU { lane } => {
10093                let (v, i) = self.state.pop1_extra()?;
10094                let (v, _) = self.v128_into_i16x8(v, i)?;
10095                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10096                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10097                let res = err!(
10098                    self.builder
10099                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10100                );
10101                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10102            }
10103            Operator::I32x4ExtractLane { lane } => {
10104                let (v, i) = self.state.pop1_extra()?;
10105                let (v, i) = self.v128_into_i32x4(v, i)?;
10106                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10107                let res = err!(self.builder.build_extract_element(v, idx, ""));
10108                self.state.push1_extra(res, i);
10109            }
10110            Operator::I64x2ExtractLane { lane } => {
10111                let (v, i) = self.state.pop1_extra()?;
10112                let (v, i) = self.v128_into_i64x2(v, i)?;
10113                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10114                let res = err!(self.builder.build_extract_element(v, idx, ""));
10115                self.state.push1_extra(res, i);
10116            }
10117            Operator::F32x4ExtractLane { lane } => {
10118                let (v, i) = self.state.pop1_extra()?;
10119                let (v, i) = self.v128_into_f32x4(v, i)?;
10120                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10121                let res = err!(self.builder.build_extract_element(v, idx, ""));
10122                self.state.push1_extra(res, i);
10123            }
10124            Operator::F64x2ExtractLane { lane } => {
10125                let (v, i) = self.state.pop1_extra()?;
10126                let (v, i) = self.v128_into_f64x2(v, i)?;
10127                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10128                let res = err!(self.builder.build_extract_element(v, idx, ""));
10129                self.state.push1_extra(res, i);
10130            }
10131            Operator::I8x16ReplaceLane { lane } => {
10132                let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10133                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10134                let v2 = v2.into_int_value();
10135                let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i8_ty, ""));
10136                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10137                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10138                let res = err!(
10139                    self.builder
10140                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10141                );
10142                self.state.push1(res);
10143            }
10144            Operator::I16x8ReplaceLane { lane } => {
10145                let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10146                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
10147                let v2 = v2.into_int_value();
10148                let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i16_ty, ""));
10149                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10150                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10151                let res = err!(
10152                    self.builder
10153                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10154                );
10155                self.state.push1(res);
10156            }
10157            Operator::I32x4ReplaceLane { lane } => {
10158                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10159                let (v1, i1) = self.v128_into_i32x4(v1, i1)?;
10160                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10161                let v2 = v2.into_int_value();
10162                let i2 = i2.strip_pending();
10163                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10164                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10165                let res = err!(
10166                    self.builder
10167                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10168                );
10169                self.state
10170                    .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f32())?);
10171            }
10172            Operator::I64x2ReplaceLane { lane } => {
10173                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10174                let (v1, i1) = self.v128_into_i64x2(v1, i1)?;
10175                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10176                let v2 = v2.into_int_value();
10177                let i2 = i2.strip_pending();
10178                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10179                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10180                let res = err!(
10181                    self.builder
10182                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10183                );
10184                self.state
10185                    .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f64())?);
10186            }
10187            Operator::F32x4ReplaceLane { lane } => {
10188                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10189                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
10190                let push_pending_f32_nan_to_result =
10191                    i1.has_pending_f32_nan() && i2.has_pending_f32_nan();
10192                let (v1, v2) = if !push_pending_f32_nan_to_result {
10193                    (
10194                        self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10195                            .into_vector_value(),
10196                        self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10197                            .into_float_value(),
10198                    )
10199                } else {
10200                    (v1, v2.into_float_value())
10201                };
10202                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10203                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10204                let res = err!(
10205                    self.builder
10206                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10207                );
10208                let info = if push_pending_f32_nan_to_result {
10209                    ExtraInfo::pending_f32_nan()
10210                } else {
10211                    (i1.strip_pending() & i2.strip_pending())?
10212                };
10213                self.state.push1_extra(res, info);
10214            }
10215            Operator::F64x2ReplaceLane { lane } => {
10216                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10217                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
10218                let push_pending_f64_nan_to_result =
10219                    i1.has_pending_f64_nan() && i2.has_pending_f64_nan();
10220                let (v1, v2) = if !push_pending_f64_nan_to_result {
10221                    (
10222                        self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10223                            .into_vector_value(),
10224                        self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10225                            .into_float_value(),
10226                    )
10227                } else {
10228                    (v1, v2.into_float_value())
10229                };
10230                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10231                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10232                let res = err!(
10233                    self.builder
10234                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10235                );
10236                let info = if push_pending_f64_nan_to_result {
10237                    ExtraInfo::pending_f64_nan()
10238                } else {
10239                    (i1.strip_pending() & i2.strip_pending())?
10240                };
10241                self.state.push1_extra(res, info);
10242            }
10243            Operator::I8x16RelaxedSwizzle if self.cpu_features.contains(CpuFeature::SSSE3) => {
10244                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10245                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10246                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10247
10248                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10249                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
10250                let res = self
10251                    .build_call_with_param_attributes(
10252                        self.intrinsics.x86_64.pshufb128,
10253                        &[v1.into(), v2.into()],
10254                        "",
10255                    )?
10256                    .try_as_basic_value()
10257                    .unwrap_basic();
10258                let res = err!(
10259                    self.builder
10260                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10261                );
10262                self.state.push1(res);
10263            }
10264            Operator::I8x16Swizzle | Operator::I8x16RelaxedSwizzle => {
10265                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10266                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10267                let v1 = err!(
10268                    self.builder
10269                        .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10270                )
10271                .into_vector_value();
10272                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10273                let v2 = err!(
10274                    self.builder
10275                        .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10276                )
10277                .into_vector_value();
10278                let lanes = self.intrinsics.i8_ty.const_int(16, false);
10279                let lanes =
10280                    self.splat_vector(lanes.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
10281                let mut res = self.intrinsics.i8x16_ty.get_undef();
10282                let idx_out_of_range = err!(self.builder.build_int_compare(
10283                    IntPredicate::UGE,
10284                    v2,
10285                    lanes,
10286                    "idx_out_of_range",
10287                ));
10288                let idx_clamped = err!(self.builder.build_select(
10289                    idx_out_of_range,
10290                    self.intrinsics.i8x16_ty.const_zero(),
10291                    v2,
10292                    "idx_clamped",
10293                ))
10294                .into_vector_value();
10295                for i in 0..16 {
10296                    let idx = err!(self.builder.build_extract_element(
10297                        idx_clamped,
10298                        self.intrinsics.i32_ty.const_int(i, false),
10299                        "idx",
10300                    ))
10301                    .into_int_value();
10302                    let replace_with_zero = err!(self.builder.build_extract_element(
10303                        idx_out_of_range,
10304                        self.intrinsics.i32_ty.const_int(i, false),
10305                        "replace_with_zero",
10306                    ))
10307                    .into_int_value();
10308                    let elem =
10309                        err!(self.builder.build_extract_element(v1, idx, "elem")).into_int_value();
10310                    let elem_or_zero = err!(self.builder.build_select(
10311                        replace_with_zero,
10312                        self.intrinsics.i8_zero,
10313                        elem,
10314                        "elem_or_zero",
10315                    ));
10316                    res = err!(self.builder.build_insert_element(
10317                        res,
10318                        elem_or_zero,
10319                        self.intrinsics.i32_ty.const_int(i, false),
10320                        "",
10321                    ));
10322                }
10323                let res = err!(
10324                    self.builder
10325                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10326                );
10327                self.state.push1(res);
10328            }
10329            Operator::I8x16Shuffle { lanes } => {
10330                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10331                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10332                let v1 = err!(
10333                    self.builder
10334                        .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10335                )
10336                .into_vector_value();
10337                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10338                let v2 = err!(
10339                    self.builder
10340                        .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10341                )
10342                .into_vector_value();
10343                let mask = VectorType::const_vector(
10344                    lanes
10345                        .iter()
10346                        .map(|l| self.intrinsics.i32_ty.const_int((*l).into(), false))
10347                        .collect::<Vec<IntValue>>()
10348                        .as_slice(),
10349                );
10350                let res = err!(self.builder.build_shuffle_vector(v1, v2, mask, ""));
10351                let res = err!(
10352                    self.builder
10353                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10354                );
10355                self.state.push1(res);
10356            }
10357            Operator::V128Load8x8S { ref memarg } => {
10358                let offset = self.state.pop1()?.into_int_value();
10359                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10360                let v = err!(
10361                    self.builder
10362                        .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10363                )
10364                .into_vector_value();
10365                let res = err!(
10366                    self.builder
10367                        .build_int_s_extend(v, self.intrinsics.i16x8_ty, "")
10368                );
10369                let res = err!(
10370                    self.builder
10371                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10372                );
10373                self.state.push1(res);
10374            }
10375            Operator::V128Load8x8U { ref memarg } => {
10376                let offset = self.state.pop1()?.into_int_value();
10377                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10378                let v = err!(
10379                    self.builder
10380                        .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10381                )
10382                .into_vector_value();
10383                let res = err!(
10384                    self.builder
10385                        .build_int_z_extend(v, self.intrinsics.i16x8_ty, "")
10386                );
10387                let res = err!(
10388                    self.builder
10389                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10390                );
10391                self.state.push1(res);
10392            }
10393            Operator::V128Load16x4S { ref memarg } => {
10394                let offset = self.state.pop1()?.into_int_value();
10395                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10396                let v = err!(self.builder.build_bit_cast(
10397                    v,
10398                    self.intrinsics.i16_ty.vec_type(4),
10399                    ""
10400                ))
10401                .into_vector_value();
10402                let res = err!(
10403                    self.builder
10404                        .build_int_s_extend(v, self.intrinsics.i32x4_ty, "")
10405                );
10406                let res = err!(
10407                    self.builder
10408                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10409                );
10410                self.state.push1(res);
10411            }
10412            Operator::V128Load16x4U { ref memarg } => {
10413                let offset = self.state.pop1()?.into_int_value();
10414                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10415                let v = err!(self.builder.build_bit_cast(
10416                    v,
10417                    self.intrinsics.i16_ty.vec_type(4),
10418                    ""
10419                ))
10420                .into_vector_value();
10421                let res = err!(
10422                    self.builder
10423                        .build_int_z_extend(v, self.intrinsics.i32x4_ty, "")
10424                );
10425                let res = err!(
10426                    self.builder
10427                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10428                );
10429                self.state.push1(res);
10430            }
10431            Operator::V128Load32x2S { ref memarg } => {
10432                let offset = self.state.pop1()?.into_int_value();
10433                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10434                let v = err!(self.builder.build_bit_cast(
10435                    v,
10436                    self.intrinsics.i32_ty.vec_type(2),
10437                    ""
10438                ))
10439                .into_vector_value();
10440                let res = err!(
10441                    self.builder
10442                        .build_int_s_extend(v, self.intrinsics.i64x2_ty, "")
10443                );
10444                let res = err!(
10445                    self.builder
10446                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10447                );
10448                self.state.push1(res);
10449            }
10450            Operator::V128Load32x2U { ref memarg } => {
10451                let offset = self.state.pop1()?.into_int_value();
10452                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10453                let v = err!(self.builder.build_bit_cast(
10454                    v,
10455                    self.intrinsics.i32_ty.vec_type(2),
10456                    ""
10457                ))
10458                .into_vector_value();
10459                let res = err!(
10460                    self.builder
10461                        .build_int_z_extend(v, self.intrinsics.i64x2_ty, "")
10462                );
10463                let res = err!(
10464                    self.builder
10465                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10466                );
10467                self.state.push1(res);
10468            }
10469            Operator::V128Load32Zero { ref memarg } => {
10470                let offset = self.state.pop1()?.into_int_value();
10471                let element =
10472                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10473                let res = err!(self.builder.build_int_z_extend(
10474                    element.into_int_value(),
10475                    self.intrinsics.i128_ty,
10476                    "",
10477                ));
10478                self.state.push1(res);
10479            }
10480            Operator::V128Load64Zero { ref memarg } => {
10481                let offset = self.state.pop1()?.into_int_value();
10482                let element =
10483                    self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10484                let res = err!(self.builder.build_int_z_extend(
10485                    element.into_int_value(),
10486                    self.intrinsics.i128_ty,
10487                    "",
10488                ));
10489                self.state.push1(res);
10490            }
10491            Operator::V128Load8Splat { ref memarg } => {
10492                let offset = self.state.pop1()?.into_int_value();
10493                let element =
10494                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
10495                let res = self.splat_vector(element, self.intrinsics.i8x16_ty)?;
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::V128Load16Splat { ref memarg } => {
10503                let offset = self.state.pop1()?.into_int_value();
10504                let element =
10505                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10506                let res = self.splat_vector(element, self.intrinsics.i16x8_ty)?;
10507                let res = err!(
10508                    self.builder
10509                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10510                );
10511                self.state.push1(res);
10512            }
10513            Operator::V128Load32Splat { ref memarg } => {
10514                let offset = self.state.pop1()?.into_int_value();
10515                let element =
10516                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10517                let res = self.splat_vector(element, self.intrinsics.i32x4_ty)?;
10518                let res = err!(
10519                    self.builder
10520                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10521                );
10522                self.state.push1(res);
10523            }
10524            Operator::V128Load64Splat { ref memarg } => {
10525                let offset = self.state.pop1()?.into_int_value();
10526                let element =
10527                    self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10528                let res = self.splat_vector(element, self.intrinsics.i64x2_ty)?;
10529                let res = err!(
10530                    self.builder
10531                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10532                );
10533                self.state.push1(res);
10534            }
10535
10536            Operator::MemoryGrow { mem } => {
10537                let memory_index = MemoryIndex::from_u32(mem);
10538                let delta = self.state.pop1()?;
10539                let grow_fn_ptr = self.ctx.memory_grow(memory_index, self.intrinsics)?;
10540                let grow = err!(self.builder.build_indirect_call(
10541                    self.intrinsics.memory_grow_ty,
10542                    grow_fn_ptr,
10543                    &[
10544                        vmctx.as_basic_value_enum().into(),
10545                        delta.into(),
10546                        self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
10547                    ],
10548                    "",
10549                ));
10550                self.state.push1(grow.try_as_basic_value().unwrap_basic());
10551            }
10552            Operator::MemorySize { mem } => {
10553                let memory_index = MemoryIndex::from_u32(mem);
10554                let size_fn_ptr = self.ctx.memory_size(memory_index, self.intrinsics)?;
10555                let size = err!(self.builder.build_indirect_call(
10556                    self.intrinsics.memory_size_ty,
10557                    size_fn_ptr,
10558                    &[
10559                        vmctx.as_basic_value_enum().into(),
10560                        self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
10561                    ],
10562                    "",
10563                ));
10564                //size.add_attribute(AttributeLoc::Function, self.intrinsics.readonly);
10565                self.state.push1(size.try_as_basic_value().unwrap_basic());
10566            }
10567            Operator::MemoryInit { data_index, mem } => {
10568                let (dest, src, len) = self.state.pop3()?;
10569                let mem = self.intrinsics.i32_ty.const_int(mem.into(), false);
10570                let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
10571                self.build_call_with_param_attributes(
10572                    self.intrinsics.memory_init,
10573                    &[
10574                        vmctx.as_basic_value_enum().into(),
10575                        mem.into(),
10576                        segment.into(),
10577                        dest.into(),
10578                        src.into(),
10579                        len.into(),
10580                    ],
10581                    "",
10582                )?;
10583            }
10584            Operator::DataDrop { data_index } => {
10585                let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
10586                self.build_call_with_param_attributes(
10587                    self.intrinsics.data_drop,
10588                    &[vmctx.as_basic_value_enum().into(), segment.into()],
10589                    "",
10590                )?;
10591            }
10592            Operator::MemoryCopy { dst_mem, src_mem } => {
10593                // ignored until we support multiple memories
10594                let _dst = dst_mem;
10595                let (memory_copy, src) = if let Some(local_memory_index) = self
10596                    .wasm_module
10597                    .local_memory_index(MemoryIndex::from_u32(src_mem))
10598                {
10599                    (self.intrinsics.memory_copy, local_memory_index.as_u32())
10600                } else {
10601                    (self.intrinsics.imported_memory_copy, src_mem)
10602                };
10603
10604                let (dest_pos, src_pos, len) = self.state.pop3()?;
10605                let src_index = self.intrinsics.i32_ty.const_int(src.into(), false);
10606                self.build_call_with_param_attributes(
10607                    memory_copy,
10608                    &[
10609                        vmctx.as_basic_value_enum().into(),
10610                        src_index.into(),
10611                        dest_pos.into(),
10612                        src_pos.into(),
10613                        len.into(),
10614                    ],
10615                    "",
10616                )?;
10617            }
10618            Operator::MemoryFill { mem } => {
10619                let (memory_fill, mem) = if let Some(local_memory_index) = self
10620                    .wasm_module
10621                    .local_memory_index(MemoryIndex::from_u32(mem))
10622                {
10623                    (self.intrinsics.memory_fill, local_memory_index.as_u32())
10624                } else {
10625                    (self.intrinsics.imported_memory_fill, mem)
10626                };
10627
10628                let (dst, val, len) = self.state.pop3()?;
10629                let mem_index = self.intrinsics.i32_ty.const_int(mem.into(), false);
10630                self.build_call_with_param_attributes(
10631                    memory_fill,
10632                    &[
10633                        vmctx.as_basic_value_enum().into(),
10634                        mem_index.into(),
10635                        dst.into(),
10636                        val.into(),
10637                        len.into(),
10638                    ],
10639                    "",
10640                )?;
10641            }
10642            _ => unreachable!(),
10643        }
10644        Ok(())
10645    }
10646
10647    // Atomic memory operations.
10648    fn translate_atomic_memory_operator(&mut self, op: Operator) -> Result<(), CompileError> {
10649        let vmctx = &self.ctx.basic().into_pointer_value();
10650
10651        match op {
10652            Operator::AtomicFence => {
10653                // Fence is a nop.
10654                //
10655                // Fence was added to preserve information about fences from
10656                // source languages. If in the future Wasm extends the memory
10657                // model, and if we hadn't recorded what fences used to be there,
10658                // it would lead to data races that weren't present in the
10659                // original source language.
10660            }
10661            Operator::I32AtomicLoad { ref memarg } => {
10662                let offset = self.state.pop1()?.into_int_value();
10663                let result = self.build_annotated_atomic_load(
10664                    self.intrinsics.i32_ty,
10665                    self.intrinsics.i32_ty,
10666                    offset,
10667                    memarg,
10668                )?;
10669                self.state.push1(result);
10670            }
10671            Operator::I64AtomicLoad { ref memarg } => {
10672                let offset = self.state.pop1()?.into_int_value();
10673                let result = self.build_annotated_atomic_load(
10674                    self.intrinsics.i64_ty,
10675                    self.intrinsics.i64_ty,
10676                    offset,
10677                    memarg,
10678                )?;
10679                self.state.push1(result);
10680            }
10681            Operator::I32AtomicLoad8U { ref memarg } => {
10682                let offset = self.state.pop1()?.into_int_value();
10683                let result = self.build_annotated_atomic_load(
10684                    self.intrinsics.i32_ty,
10685                    self.intrinsics.i8_ty,
10686                    offset,
10687                    memarg,
10688                )?;
10689                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10690            }
10691            Operator::I32AtomicLoad16U { ref memarg } => {
10692                let offset = self.state.pop1()?.into_int_value();
10693                let result = self.build_annotated_atomic_load(
10694                    self.intrinsics.i32_ty,
10695                    self.intrinsics.i16_ty,
10696                    offset,
10697                    memarg,
10698                )?;
10699                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10700            }
10701            Operator::I64AtomicLoad8U { ref memarg } => {
10702                let offset = self.state.pop1()?.into_int_value();
10703                let result = self.build_annotated_atomic_load(
10704                    self.intrinsics.i64_ty,
10705                    self.intrinsics.i8_ty,
10706                    offset,
10707                    memarg,
10708                )?;
10709                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10710            }
10711            Operator::I64AtomicLoad16U { ref memarg } => {
10712                let offset = self.state.pop1()?.into_int_value();
10713                let result = self.build_annotated_atomic_load(
10714                    self.intrinsics.i64_ty,
10715                    self.intrinsics.i16_ty,
10716                    offset,
10717                    memarg,
10718                )?;
10719                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10720            }
10721            Operator::I64AtomicLoad32U { ref memarg } => {
10722                let offset = self.state.pop1()?.into_int_value();
10723                let result = self.build_annotated_atomic_load(
10724                    self.intrinsics.i64_ty,
10725                    self.intrinsics.i32_ty,
10726                    offset,
10727                    memarg,
10728                )?;
10729                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10730            }
10731            Operator::I32AtomicStore { ref memarg } => {
10732                let value = self.state.pop1()?.into_int_value();
10733                let offset = self.state.pop1()?.into_int_value();
10734                self.build_annotated_atomic_store(
10735                    self.intrinsics.i32_ty,
10736                    self.intrinsics.i32_ty,
10737                    offset,
10738                    value,
10739                    memarg,
10740                )?;
10741            }
10742            Operator::I64AtomicStore { ref memarg } => {
10743                let value = self.state.pop1()?.into_int_value();
10744                let offset = self.state.pop1()?.into_int_value();
10745                self.build_annotated_atomic_store(
10746                    self.intrinsics.i64_ty,
10747                    self.intrinsics.i64_ty,
10748                    offset,
10749                    value,
10750                    memarg,
10751                )?;
10752            }
10753            Operator::I32AtomicStore8 { ref memarg } | Operator::I64AtomicStore8 { ref memarg } => {
10754                let value = self.state.pop1()?.into_int_value();
10755                let offset = self.state.pop1()?.into_int_value();
10756                self.build_annotated_atomic_store(
10757                    value.get_type(),
10758                    self.intrinsics.i8_ty,
10759                    offset,
10760                    value,
10761                    memarg,
10762                )?;
10763            }
10764            Operator::I32AtomicStore16 { ref memarg }
10765            | Operator::I64AtomicStore16 { ref memarg } => {
10766                let value = self.state.pop1()?.into_int_value();
10767                let offset = self.state.pop1()?.into_int_value();
10768                self.build_annotated_atomic_store(
10769                    value.get_type(),
10770                    self.intrinsics.i16_ty,
10771                    offset,
10772                    value,
10773                    memarg,
10774                )?;
10775            }
10776            Operator::I64AtomicStore32 { ref memarg } => {
10777                let value = self.state.pop1()?.into_int_value();
10778                let offset = self.state.pop1()?.into_int_value();
10779                self.build_annotated_atomic_store(
10780                    self.intrinsics.i64_ty,
10781                    self.intrinsics.i32_ty,
10782                    offset,
10783                    value,
10784                    memarg,
10785                )?;
10786            }
10787            Operator::I32AtomicRmw8AddU { ref memarg } => self.translate_atomic_rmw(
10788                self.intrinsics.i32_ty,
10789                self.intrinsics.i8_ty,
10790                memarg,
10791                AtomicRMWBinOp::Add,
10792                Some(ExtraInfo::arithmetic_f32()),
10793            )?,
10794            Operator::I32AtomicRmw16AddU { ref memarg } => self.translate_atomic_rmw(
10795                self.intrinsics.i32_ty,
10796                self.intrinsics.i16_ty,
10797                memarg,
10798                AtomicRMWBinOp::Add,
10799                Some(ExtraInfo::arithmetic_f32()),
10800            )?,
10801            Operator::I32AtomicRmwAdd { ref memarg } => self.translate_atomic_rmw(
10802                self.intrinsics.i32_ty,
10803                self.intrinsics.i32_ty,
10804                memarg,
10805                AtomicRMWBinOp::Add,
10806                None,
10807            )?,
10808            Operator::I64AtomicRmw8AddU { ref memarg } => self.translate_atomic_rmw(
10809                self.intrinsics.i64_ty,
10810                self.intrinsics.i8_ty,
10811                memarg,
10812                AtomicRMWBinOp::Add,
10813                Some(ExtraInfo::arithmetic_f64()),
10814            )?,
10815            Operator::I64AtomicRmw16AddU { ref memarg } => self.translate_atomic_rmw(
10816                self.intrinsics.i64_ty,
10817                self.intrinsics.i16_ty,
10818                memarg,
10819                AtomicRMWBinOp::Add,
10820                Some(ExtraInfo::arithmetic_f64()),
10821            )?,
10822            Operator::I64AtomicRmw32AddU { ref memarg } => self.translate_atomic_rmw(
10823                self.intrinsics.i64_ty,
10824                self.intrinsics.i32_ty,
10825                memarg,
10826                AtomicRMWBinOp::Add,
10827                Some(ExtraInfo::arithmetic_f64()),
10828            )?,
10829            Operator::I64AtomicRmwAdd { ref memarg } => self.translate_atomic_rmw(
10830                self.intrinsics.i64_ty,
10831                self.intrinsics.i64_ty,
10832                memarg,
10833                AtomicRMWBinOp::Add,
10834                None,
10835            )?,
10836            Operator::I32AtomicRmw8SubU { ref memarg } => self.translate_atomic_rmw(
10837                self.intrinsics.i32_ty,
10838                self.intrinsics.i8_ty,
10839                memarg,
10840                AtomicRMWBinOp::Sub,
10841                Some(ExtraInfo::arithmetic_f32()),
10842            )?,
10843            Operator::I32AtomicRmw16SubU { ref memarg } => self.translate_atomic_rmw(
10844                self.intrinsics.i32_ty,
10845                self.intrinsics.i16_ty,
10846                memarg,
10847                AtomicRMWBinOp::Sub,
10848                Some(ExtraInfo::arithmetic_f32()),
10849            )?,
10850            Operator::I32AtomicRmwSub { ref memarg } => self.translate_atomic_rmw(
10851                self.intrinsics.i32_ty,
10852                self.intrinsics.i32_ty,
10853                memarg,
10854                AtomicRMWBinOp::Sub,
10855                None,
10856            )?,
10857            Operator::I64AtomicRmw8SubU { ref memarg } => self.translate_atomic_rmw(
10858                self.intrinsics.i64_ty,
10859                self.intrinsics.i8_ty,
10860                memarg,
10861                AtomicRMWBinOp::Sub,
10862                Some(ExtraInfo::arithmetic_f32()),
10863            )?,
10864            Operator::I64AtomicRmw16SubU { ref memarg } => self.translate_atomic_rmw(
10865                self.intrinsics.i64_ty,
10866                self.intrinsics.i16_ty,
10867                memarg,
10868                AtomicRMWBinOp::Sub,
10869                Some(ExtraInfo::arithmetic_f64()),
10870            )?,
10871            Operator::I64AtomicRmw32SubU { ref memarg } => self.translate_atomic_rmw(
10872                self.intrinsics.i64_ty,
10873                self.intrinsics.i32_ty,
10874                memarg,
10875                AtomicRMWBinOp::Sub,
10876                Some(ExtraInfo::arithmetic_f64()),
10877            )?,
10878            Operator::I64AtomicRmwSub { ref memarg } => self.translate_atomic_rmw(
10879                self.intrinsics.i64_ty,
10880                self.intrinsics.i64_ty,
10881                memarg,
10882                AtomicRMWBinOp::Sub,
10883                None,
10884            )?,
10885            Operator::I32AtomicRmw8AndU { ref memarg } => self.translate_atomic_rmw(
10886                self.intrinsics.i32_ty,
10887                self.intrinsics.i8_ty,
10888                memarg,
10889                AtomicRMWBinOp::And,
10890                Some(ExtraInfo::arithmetic_f32()),
10891            )?,
10892            Operator::I32AtomicRmw16AndU { ref memarg } => self.translate_atomic_rmw(
10893                self.intrinsics.i32_ty,
10894                self.intrinsics.i16_ty,
10895                memarg,
10896                AtomicRMWBinOp::And,
10897                Some(ExtraInfo::arithmetic_f32()),
10898            )?,
10899            Operator::I32AtomicRmwAnd { ref memarg } => self.translate_atomic_rmw(
10900                self.intrinsics.i32_ty,
10901                self.intrinsics.i32_ty,
10902                memarg,
10903                AtomicRMWBinOp::And,
10904                None,
10905            )?,
10906            Operator::I64AtomicRmw8AndU { ref memarg } => self.translate_atomic_rmw(
10907                self.intrinsics.i64_ty,
10908                self.intrinsics.i8_ty,
10909                memarg,
10910                AtomicRMWBinOp::And,
10911                Some(ExtraInfo::arithmetic_f64()),
10912            )?,
10913            Operator::I64AtomicRmw16AndU { ref memarg } => self.translate_atomic_rmw(
10914                self.intrinsics.i64_ty,
10915                self.intrinsics.i16_ty,
10916                memarg,
10917                AtomicRMWBinOp::And,
10918                Some(ExtraInfo::arithmetic_f64()),
10919            )?,
10920            Operator::I64AtomicRmw32AndU { ref memarg } => self.translate_atomic_rmw(
10921                self.intrinsics.i64_ty,
10922                self.intrinsics.i32_ty,
10923                memarg,
10924                AtomicRMWBinOp::And,
10925                Some(ExtraInfo::arithmetic_f64()),
10926            )?,
10927            Operator::I64AtomicRmwAnd { ref memarg } => self.translate_atomic_rmw(
10928                self.intrinsics.i64_ty,
10929                self.intrinsics.i64_ty,
10930                memarg,
10931                AtomicRMWBinOp::And,
10932                None,
10933            )?,
10934            Operator::I32AtomicRmw8OrU { ref memarg } => self.translate_atomic_rmw(
10935                self.intrinsics.i32_ty,
10936                self.intrinsics.i8_ty,
10937                memarg,
10938                AtomicRMWBinOp::Or,
10939                Some(ExtraInfo::arithmetic_f32()),
10940            )?,
10941            Operator::I32AtomicRmw16OrU { ref memarg } => self.translate_atomic_rmw(
10942                self.intrinsics.i32_ty,
10943                self.intrinsics.i16_ty,
10944                memarg,
10945                AtomicRMWBinOp::Or,
10946                Some(ExtraInfo::arithmetic_f32()),
10947            )?,
10948            Operator::I32AtomicRmwOr { ref memarg } => self.translate_atomic_rmw(
10949                self.intrinsics.i32_ty,
10950                self.intrinsics.i32_ty,
10951                memarg,
10952                AtomicRMWBinOp::Or,
10953                Some(ExtraInfo::arithmetic_f32()),
10954            )?,
10955            Operator::I64AtomicRmw8OrU { ref memarg } => self.translate_atomic_rmw(
10956                self.intrinsics.i64_ty,
10957                self.intrinsics.i8_ty,
10958                memarg,
10959                AtomicRMWBinOp::Or,
10960                Some(ExtraInfo::arithmetic_f64()),
10961            )?,
10962            Operator::I64AtomicRmw16OrU { ref memarg } => self.translate_atomic_rmw(
10963                self.intrinsics.i64_ty,
10964                self.intrinsics.i16_ty,
10965                memarg,
10966                AtomicRMWBinOp::Or,
10967                Some(ExtraInfo::arithmetic_f64()),
10968            )?,
10969            Operator::I64AtomicRmw32OrU { ref memarg } => self.translate_atomic_rmw(
10970                self.intrinsics.i64_ty,
10971                self.intrinsics.i32_ty,
10972                memarg,
10973                AtomicRMWBinOp::Or,
10974                Some(ExtraInfo::arithmetic_f64()),
10975            )?,
10976            Operator::I64AtomicRmwOr { ref memarg } => self.translate_atomic_rmw(
10977                self.intrinsics.i64_ty,
10978                self.intrinsics.i64_ty,
10979                memarg,
10980                AtomicRMWBinOp::Or,
10981                None,
10982            )?,
10983            Operator::I32AtomicRmw8XorU { ref memarg } => self.translate_atomic_rmw(
10984                self.intrinsics.i32_ty,
10985                self.intrinsics.i8_ty,
10986                memarg,
10987                AtomicRMWBinOp::Xor,
10988                Some(ExtraInfo::arithmetic_f32()),
10989            )?,
10990            Operator::I32AtomicRmw16XorU { ref memarg } => self.translate_atomic_rmw(
10991                self.intrinsics.i32_ty,
10992                self.intrinsics.i16_ty,
10993                memarg,
10994                AtomicRMWBinOp::Xor,
10995                Some(ExtraInfo::arithmetic_f32()),
10996            )?,
10997            Operator::I32AtomicRmwXor { ref memarg } => self.translate_atomic_rmw(
10998                self.intrinsics.i32_ty,
10999                self.intrinsics.i32_ty,
11000                memarg,
11001                AtomicRMWBinOp::Xor,
11002                None,
11003            )?,
11004            Operator::I64AtomicRmw8XorU { ref memarg } => self.translate_atomic_rmw(
11005                self.intrinsics.i64_ty,
11006                self.intrinsics.i8_ty,
11007                memarg,
11008                AtomicRMWBinOp::Xor,
11009                Some(ExtraInfo::arithmetic_f64()),
11010            )?,
11011            Operator::I64AtomicRmw16XorU { ref memarg } => self.translate_atomic_rmw(
11012                self.intrinsics.i64_ty,
11013                self.intrinsics.i16_ty,
11014                memarg,
11015                AtomicRMWBinOp::Xor,
11016                Some(ExtraInfo::arithmetic_f64()),
11017            )?,
11018            Operator::I64AtomicRmw32XorU { ref memarg } => self.translate_atomic_rmw(
11019                self.intrinsics.i64_ty,
11020                self.intrinsics.i32_ty,
11021                memarg,
11022                AtomicRMWBinOp::Xor,
11023                Some(ExtraInfo::arithmetic_f64()),
11024            )?,
11025            Operator::I64AtomicRmwXor { ref memarg } => self.translate_atomic_rmw(
11026                self.intrinsics.i64_ty,
11027                self.intrinsics.i64_ty,
11028                memarg,
11029                AtomicRMWBinOp::Xor,
11030                None,
11031            )?,
11032            Operator::I32AtomicRmw8XchgU { ref memarg } => self.translate_atomic_rmw(
11033                self.intrinsics.i32_ty,
11034                self.intrinsics.i8_ty,
11035                memarg,
11036                AtomicRMWBinOp::Xchg,
11037                Some(ExtraInfo::arithmetic_f32()),
11038            )?,
11039            Operator::I32AtomicRmw16XchgU { ref memarg } => self.translate_atomic_rmw(
11040                self.intrinsics.i32_ty,
11041                self.intrinsics.i16_ty,
11042                memarg,
11043                AtomicRMWBinOp::Xchg,
11044                Some(ExtraInfo::arithmetic_f32()),
11045            )?,
11046            Operator::I32AtomicRmwXchg { ref memarg } => self.translate_atomic_rmw(
11047                self.intrinsics.i32_ty,
11048                self.intrinsics.i32_ty,
11049                memarg,
11050                AtomicRMWBinOp::Xchg,
11051                None,
11052            )?,
11053            Operator::I64AtomicRmw8XchgU { ref memarg } => self.translate_atomic_rmw(
11054                self.intrinsics.i64_ty,
11055                self.intrinsics.i8_ty,
11056                memarg,
11057                AtomicRMWBinOp::Xchg,
11058                Some(ExtraInfo::arithmetic_f64()),
11059            )?,
11060            Operator::I64AtomicRmw16XchgU { ref memarg } => self.translate_atomic_rmw(
11061                self.intrinsics.i64_ty,
11062                self.intrinsics.i16_ty,
11063                memarg,
11064                AtomicRMWBinOp::Xchg,
11065                Some(ExtraInfo::arithmetic_f64()),
11066            )?,
11067            Operator::I64AtomicRmw32XchgU { ref memarg } => self.translate_atomic_rmw(
11068                self.intrinsics.i64_ty,
11069                self.intrinsics.i32_ty,
11070                memarg,
11071                AtomicRMWBinOp::Xchg,
11072                Some(ExtraInfo::arithmetic_f64()),
11073            )?,
11074            Operator::I64AtomicRmwXchg { ref memarg } => self.translate_atomic_rmw(
11075                self.intrinsics.i64_ty,
11076                self.intrinsics.i64_ty,
11077                memarg,
11078                AtomicRMWBinOp::Xchg,
11079                None,
11080            )?,
11081            Operator::I32AtomicRmw8CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11082                self.intrinsics.i32_ty,
11083                self.intrinsics.i8_ty,
11084                memarg,
11085                Some(ExtraInfo::arithmetic_f32()),
11086            )?,
11087            Operator::I32AtomicRmw16CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11088                self.intrinsics.i32_ty,
11089                self.intrinsics.i16_ty,
11090                memarg,
11091                Some(ExtraInfo::arithmetic_f32()),
11092            )?,
11093            Operator::I32AtomicRmwCmpxchg { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11094                self.intrinsics.i32_ty,
11095                self.intrinsics.i32_ty,
11096                memarg,
11097                None,
11098            )?,
11099            Operator::I64AtomicRmw8CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11100                self.intrinsics.i64_ty,
11101                self.intrinsics.i8_ty,
11102                memarg,
11103                Some(ExtraInfo::arithmetic_f64()),
11104            )?,
11105            Operator::I64AtomicRmw16CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11106                self.intrinsics.i64_ty,
11107                self.intrinsics.i16_ty,
11108                memarg,
11109                Some(ExtraInfo::arithmetic_f64()),
11110            )?,
11111            Operator::I64AtomicRmw32CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11112                self.intrinsics.i64_ty,
11113                self.intrinsics.i32_ty,
11114                memarg,
11115                Some(ExtraInfo::arithmetic_f64()),
11116            )?,
11117            Operator::I64AtomicRmwCmpxchg { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11118                self.intrinsics.i64_ty,
11119                self.intrinsics.i64_ty,
11120                memarg,
11121                None,
11122            )?,
11123            Operator::MemoryAtomicWait32 { memarg } => {
11124                let memory_index = MemoryIndex::from_u32(memarg.memory);
11125                let (dst, val, timeout) = self.state.pop3()?;
11126                let wait32_fn_ptr = self.ctx.memory_wait32(memory_index, self.intrinsics)?;
11127                let ret = err!(
11128                    self.builder.build_indirect_call(
11129                        self.intrinsics.memory_wait32_ty,
11130                        wait32_fn_ptr,
11131                        &[
11132                            vmctx.as_basic_value_enum().into(),
11133                            self.intrinsics
11134                                .i32_ty
11135                                .const_int(memarg.memory as u64, false)
11136                                .into(),
11137                            dst.into(),
11138                            val.into(),
11139                            timeout.into(),
11140                        ],
11141                        "",
11142                    )
11143                );
11144                self.state.push1(ret.try_as_basic_value().unwrap_basic());
11145            }
11146            Operator::MemoryAtomicWait64 { memarg } => {
11147                let memory_index = MemoryIndex::from_u32(memarg.memory);
11148                let (dst, val, timeout) = self.state.pop3()?;
11149                let wait64_fn_ptr = self.ctx.memory_wait64(memory_index, self.intrinsics)?;
11150                let ret = err!(
11151                    self.builder.build_indirect_call(
11152                        self.intrinsics.memory_wait64_ty,
11153                        wait64_fn_ptr,
11154                        &[
11155                            vmctx.as_basic_value_enum().into(),
11156                            self.intrinsics
11157                                .i32_ty
11158                                .const_int(memarg.memory as u64, false)
11159                                .into(),
11160                            dst.into(),
11161                            val.into(),
11162                            timeout.into(),
11163                        ],
11164                        "",
11165                    )
11166                );
11167                self.state.push1(ret.try_as_basic_value().unwrap_basic());
11168            }
11169            Operator::MemoryAtomicNotify { memarg } => {
11170                let memory_index = MemoryIndex::from_u32(memarg.memory);
11171                let (dst, count) = self.state.pop2()?;
11172                let notify_fn_ptr = self.ctx.memory_notify(memory_index, self.intrinsics)?;
11173                let cnt = err!(
11174                    self.builder.build_indirect_call(
11175                        self.intrinsics.memory_notify_ty,
11176                        notify_fn_ptr,
11177                        &[
11178                            vmctx.as_basic_value_enum().into(),
11179                            self.intrinsics
11180                                .i32_ty
11181                                .const_int(memarg.memory as u64, false)
11182                                .into(),
11183                            dst.into(),
11184                            count.into(),
11185                        ],
11186                        "",
11187                    )
11188                );
11189                self.state.push1(cnt.try_as_basic_value().unwrap_basic());
11190            }
11191            _ => unreachable!(),
11192        }
11193        Ok(())
11194    }
11195
11196    // Reference types.
11197    // https://github.com/WebAssembly/reference-types/blob/master/proposals/reference-types/Overview.md
11198    fn translate_reference_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11199        match op {
11200            Operator::RefNull { hty } => {
11201                let ty = err!(wpheaptype_to_type(hty));
11202                let ty = type_to_llvm(self.intrinsics, ty)?;
11203                self.state.push1(ty.const_zero());
11204            }
11205            Operator::RefIsNull => {
11206                let value = self.state.pop1()?;
11207                let is_null = match value {
11208                    BasicValueEnum::IntValue(value) => err!(self.builder.build_int_compare(
11209                        IntPredicate::EQ,
11210                        value,
11211                        value.get_type().const_zero(),
11212                        "",
11213                    )),
11214                    BasicValueEnum::PointerValue(value) => {
11215                        err!(self.builder.build_is_null(value, ""))
11216                    }
11217                    _ => unreachable!("ref.is_null only accepts reference types"),
11218                };
11219                let is_null = err!(self.builder.build_int_z_extend(
11220                    is_null,
11221                    self.intrinsics.i32_ty,
11222                    ""
11223                ));
11224                self.state.push1(is_null);
11225            }
11226            Operator::RefFunc { function_index } => {
11227                let index = self
11228                    .intrinsics
11229                    .i32_ty
11230                    .const_int(function_index.into(), false);
11231                let value = self
11232                    .build_call_with_param_attributes(
11233                        self.intrinsics.func_ref,
11234                        &[self.ctx.basic().into(), index.into()],
11235                        "",
11236                    )?
11237                    .try_as_basic_value()
11238                    .unwrap_basic();
11239                self.state.push1(value);
11240            }
11241            _ => unreachable!(),
11242        }
11243        Ok(())
11244    }
11245
11246    // Table operators.
11247    fn translate_table_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11248        match op {
11249            Operator::TableGet { table } => {
11250                let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
11251                let elem = self.state.pop1()?;
11252                let table_get = if self
11253                    .wasm_module
11254                    .local_table_index(TableIndex::from_u32(table))
11255                    .is_some()
11256                {
11257                    self.intrinsics.table_get
11258                } else {
11259                    self.intrinsics.imported_table_get
11260                };
11261                let value = self
11262                    .build_call_with_param_attributes(
11263                        table_get,
11264                        &[self.ctx.basic().into(), table_index.into(), elem.into()],
11265                        "",
11266                    )?
11267                    .try_as_basic_value()
11268                    .unwrap_basic();
11269                let value = err!(
11270                    self.builder.build_bit_cast(
11271                        value,
11272                        type_to_llvm(
11273                            self.intrinsics,
11274                            self.wasm_module
11275                                .tables
11276                                .get(TableIndex::from_u32(table))
11277                                .unwrap()
11278                                .ty,
11279                        )?,
11280                        "",
11281                    )
11282                );
11283                self.state.push1(value);
11284            }
11285            Operator::TableSet { table } => {
11286                let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
11287                let (elem, value) = self.state.pop2()?;
11288                let value = err!(
11289                    self.builder
11290                        .build_bit_cast(value, self.intrinsics.ptr_ty, "")
11291                );
11292                let table_set = if self
11293                    .wasm_module
11294                    .local_table_index(TableIndex::from_u32(table))
11295                    .is_some()
11296                {
11297                    self.intrinsics.table_set
11298                } else {
11299                    self.intrinsics.imported_table_set
11300                };
11301                self.build_call_with_param_attributes(
11302                    table_set,
11303                    &[
11304                        self.ctx.basic().into(),
11305                        table_index.into(),
11306                        elem.into(),
11307                        value.into(),
11308                    ],
11309                    "",
11310                )?;
11311            }
11312            Operator::TableCopy {
11313                dst_table,
11314                src_table,
11315            } => {
11316                let (dst, src, len) = self.state.pop3()?;
11317                let dst_table = self.intrinsics.i32_ty.const_int(dst_table as u64, false);
11318                let src_table = self.intrinsics.i32_ty.const_int(src_table as u64, false);
11319                self.build_call_with_param_attributes(
11320                    self.intrinsics.table_copy,
11321                    &[
11322                        self.ctx.basic().into(),
11323                        dst_table.into(),
11324                        src_table.into(),
11325                        dst.into(),
11326                        src.into(),
11327                        len.into(),
11328                    ],
11329                    "",
11330                )?;
11331            }
11332            Operator::TableInit { elem_index, table } => {
11333                let (dst, src, len) = self.state.pop3()?;
11334                let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
11335                let table = self.intrinsics.i32_ty.const_int(table as u64, false);
11336                self.build_call_with_param_attributes(
11337                    self.intrinsics.table_init,
11338                    &[
11339                        self.ctx.basic().into(),
11340                        table.into(),
11341                        segment.into(),
11342                        dst.into(),
11343                        src.into(),
11344                        len.into(),
11345                    ],
11346                    "",
11347                )?;
11348            }
11349            Operator::ElemDrop { elem_index } => {
11350                let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
11351                self.build_call_with_param_attributes(
11352                    self.intrinsics.elem_drop,
11353                    &[self.ctx.basic().into(), segment.into()],
11354                    "",
11355                )?;
11356            }
11357            Operator::TableFill { table } => {
11358                let table = self.intrinsics.i32_ty.const_int(table as u64, false);
11359                let (start, elem, len) = self.state.pop3()?;
11360                let elem = err!(
11361                    self.builder
11362                        .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
11363                );
11364                self.build_call_with_param_attributes(
11365                    self.intrinsics.table_fill,
11366                    &[
11367                        self.ctx.basic().into(),
11368                        table.into(),
11369                        start.into(),
11370                        elem.into(),
11371                        len.into(),
11372                    ],
11373                    "",
11374                )?;
11375            }
11376            Operator::TableGrow { table } => {
11377                let (elem, delta) = self.state.pop2()?;
11378                let elem = err!(
11379                    self.builder
11380                        .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
11381                );
11382                let (table_grow, table_index) = if let Some(local_table_index) = self
11383                    .wasm_module
11384                    .local_table_index(TableIndex::from_u32(table))
11385                {
11386                    (self.intrinsics.table_grow, local_table_index.as_u32())
11387                } else {
11388                    (self.intrinsics.imported_table_grow, table)
11389                };
11390                let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11391                let size = self
11392                    .build_call_with_param_attributes(
11393                        table_grow,
11394                        &[
11395                            self.ctx.basic().into(),
11396                            elem.into(),
11397                            delta.into(),
11398                            table_index.into(),
11399                        ],
11400                        "",
11401                    )?
11402                    .try_as_basic_value()
11403                    .unwrap_basic();
11404                self.state.push1(size);
11405            }
11406            Operator::TableSize { table } => {
11407                let (table_size, table_index) = if let Some(local_table_index) = self
11408                    .wasm_module
11409                    .local_table_index(TableIndex::from_u32(table))
11410                {
11411                    (self.intrinsics.table_size, local_table_index.as_u32())
11412                } else {
11413                    (self.intrinsics.imported_table_size, table)
11414                };
11415                let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11416                let size = self
11417                    .build_call_with_param_attributes(
11418                        table_size,
11419                        &[self.ctx.basic().into(), table_index.into()],
11420                        "",
11421                    )?
11422                    .try_as_basic_value()
11423                    .unwrap_basic();
11424                self.state.push1(size);
11425            }
11426            _ => unreachable!(),
11427        }
11428        Ok(())
11429    }
11430
11431    // Exception handling.
11432    // https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md
11433    fn translate_eh_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11434        match op {
11435            Operator::TryTable { try_table } => {
11436                let current_block = self
11437                    .builder
11438                    .get_insert_block()
11439                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
11440
11441                self.builder.position_at_end(current_block);
11442
11443                let end_block = self.context.append_basic_block(self.function, "try_end");
11444
11445                let end_phis = {
11446                    self.builder.position_at_end(end_block);
11447
11448                    let phis = self
11449                        .module_translation
11450                        .blocktype_params_results(&try_table.ty)?
11451                        .1
11452                        .iter()
11453                        .map(|&wp_ty| {
11454                            err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
11455                                type_to_llvm(self.intrinsics, wasm_ty)
11456                                    .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
11457                            })
11458                        })
11459                        .collect::<Result<_, _>>()?;
11460
11461                    self.builder.position_at_end(current_block);
11462                    phis
11463                };
11464
11465                // Collect unique catches. It is not a "hard" error on the wasm side,
11466                // but LLVM will definitely complain about having the same identifier
11467                // match two different branches in the switch below.
11468                let catches: Vec<_> = try_table
11469                    .catches
11470                    .into_iter()
11471                    .unique_by(|v| match v {
11472                        Catch::One { tag, .. } | Catch::OneRef { tag, .. } => *tag as i32,
11473                        Catch::All { .. } | Catch::AllRef { .. } => CATCH_ALL_TAG_VALUE,
11474                    })
11475                    .collect();
11476
11477                // Build the landing pad.
11478                let null = self.intrinsics.ptr_ty.const_zero();
11479
11480                let mut catch_tag_values = vec![];
11481                let mut lpad_clauses: Vec<BasicValueEnum<'ctx>> = catches
11482                    .iter()
11483                    .map(|catch| match catch {
11484                        Catch::All { .. } | Catch::AllRef { .. } => {
11485                            catch_tag_values.push(CATCH_ALL_TAG_VALUE as u32);
11486                            Ok(null.into())
11487                        }
11488                        Catch::One { tag, .. } | Catch::OneRef { tag, .. } => {
11489                            catch_tag_values.push(*tag);
11490                            Ok(self.get_or_insert_tag_type_info_global(*tag as i32))
11491                        }
11492                    })
11493                    .collect::<Result<Vec<BasicValueEnum<'ctx>>, CompileError>>()?;
11494
11495                // Since jumping between landingpads is not possible, we need to collect
11496                // all tags from outer try_tables as well to build a clause for *every*
11497                // possible tag that might be caught.
11498                let mut outer_catch_blocks = vec![];
11499                for outer_landingpad in self.state.landingpads.iter().rev() {
11500                    for catch_info @ TagCatchInfo { tag, .. } in &outer_landingpad.tags {
11501                        if !catch_tag_values.contains(tag) {
11502                            catch_tag_values.push(*tag);
11503                            lpad_clauses.push(if *tag as i32 == CATCH_ALL_TAG_VALUE {
11504                                null.into()
11505                            } else {
11506                                *self.tags_cache.get(&(*tag as i32)).expect(
11507                                    "If a previous try_table encountered a tag, \
11508                                    it should be in the cache",
11509                                )
11510                            });
11511                            outer_catch_blocks.push(*catch_info);
11512                        }
11513                    }
11514                }
11515
11516                // If there are no catch clauses, we have to skip everything, since
11517                // an lpad without catch clauses is invalid (and won't ever be jumped
11518                // to anyway)
11519                let mut maybe_lpad_block = None;
11520                let mut catch_blocks = vec![];
11521                if !lpad_clauses.is_empty() {
11522                    let lpad_block = self.context.append_basic_block(self.function, "catch");
11523                    let catch_all_block =
11524                        self.context.append_basic_block(self.function, "catch_all");
11525                    let catch_specific_block = self
11526                        .context
11527                        .append_basic_block(self.function, "catch_specific");
11528                    let catch_end_block =
11529                        self.context.append_basic_block(self.function, "catch_end");
11530                    let rethrow_block = self.context.append_basic_block(self.function, "rethrow");
11531
11532                    self.builder.position_at_end(lpad_block);
11533
11534                    let res = err!(self.builder.build_landing_pad(
11535                        self.intrinsics.lpad_exception_ty,
11536                        self.intrinsics.personality,
11537                        &lpad_clauses,
11538                        false,
11539                        "exc_struct",
11540                    ));
11541
11542                    let res = res.into_struct_value();
11543
11544                    let uw_exc = err!(self.builder.build_extract_value(res, 0, "exc_ptr"));
11545                    let pre_selector =
11546                        err!(self.builder.build_extract_value(res, 1, "pre_selector"));
11547
11548                    // The pre-selector can be either 0 (for catch-all) or 1 (for a
11549                    // specific, but as-yet-unknown tag).
11550                    let pre_selector_is_zero = err!(self.builder.build_int_compare(
11551                        IntPredicate::EQ,
11552                        pre_selector.into_int_value(),
11553                        self.intrinsics.i32_zero,
11554                        "pre_selector_is_zero"
11555                    ));
11556                    err!(self.builder.build_conditional_branch(
11557                        pre_selector_is_zero,
11558                        catch_all_block,
11559                        catch_specific_block
11560                    ));
11561
11562                    self.builder.position_at_end(catch_all_block);
11563                    err!(self.builder.build_unconditional_branch(catch_end_block));
11564
11565                    self.builder.position_at_end(catch_specific_block);
11566                    let selector_value = self.build_call_with_param_attributes(
11567                        self.intrinsics.personality2,
11568                        &[self.ctx.basic().into(), uw_exc.into()],
11569                        "selector",
11570                    )?;
11571                    err!(self.builder.build_unconditional_branch(catch_end_block));
11572
11573                    self.builder.position_at_end(catch_end_block);
11574                    let selector = err!(self.builder.build_phi(self.intrinsics.i32_ty, "selector"));
11575                    selector.add_incoming(&[
11576                        (
11577                            &self
11578                                .intrinsics
11579                                .i32_ty
11580                                .const_int(CATCH_ALL_TAG_VALUE as u64, false),
11581                            catch_all_block,
11582                        ),
11583                        (
11584                            &selector_value
11585                                .try_as_basic_value()
11586                                .unwrap_basic()
11587                                .into_int_value(),
11588                            catch_specific_block,
11589                        ),
11590                    ]);
11591
11592                    // Now we're done looking at the exception, it's time to deallocate and get
11593                    // the exnref out of it. When an exception is caught, "rethrowing" simply
11594                    // means starting another unwind by calling _Unwind_RaiseException with the
11595                    // same exception bits. Instead of keeping the same exception around, we
11596                    // deallocate the exception once it's caught, and if we need to rethrow, we
11597                    // just re-allocate a new exception.
11598                    //
11599                    // Note that this is different from how it's done in C++ land, where the
11600                    // exception object is kept around for rethrowing; this discrepancy exists
11601                    // because in C++, exception handling is lexical (i.e. there's an implicit
11602                    // "current exception" in catch blocks) whereas in WASM, you rethrow with
11603                    // an exnref that may very well have come from somewhere else; consider this
11604                    // (badly implemented and erroneous) pseudo-module:
11605                    //
11606                    // (module
11607                    //   (global $e (mut exnref) (ref.null exn))
11608                    //   ;; Store the given exnref, return the previous one
11609                    //   (func $delay_exnref (param exnref) (result exnref)
11610                    //     (global.get $e)
11611                    //     (local.get 0)
11612                    //     (global.set $e)
11613                    //   )
11614                    //   (func foo
11615                    //     (block $catch (result exnref)
11616                    //       (try_table (catch_all_ref $catch)
11617                    //         ...
11618                    //       )
11619                    //     )
11620                    //     (call $delay_exnref) ;; store the exnref caught above
11621                    //     throw_ref ;; throw the previous exnref
11622                    //   )
11623                    // )
11624                    //
11625                    // Here, it's impossible to reuse the same exception object since the
11626                    // exnref given to throw_ref is a different one than the one we caught
11627                    // with the try_table.
11628                    //
11629                    // Another difference is that C++ exceptions may well carry lots of data
11630                    // around; a WASM exception is just an exnref, backed by a u32, which is
11631                    // just 4 bytes, and is cheap to reallocate. C++ exceptions may also carry
11632                    // things with dtors around; another thing that doesn't exist in WASM.
11633                    //
11634                    // All of this is to say that putting exception deallocation and exnref
11635                    // retrieval in the same function has been a very deliberate choice.
11636                    let uw_exc = uw_exc.into_pointer_value();
11637                    let exnref = self.build_call_with_param_attributes(
11638                        self.intrinsics.exception_into_exnref,
11639                        &[uw_exc.into()],
11640                        "exnref",
11641                    )?;
11642
11643                    let exnref = exnref.try_as_basic_value().unwrap_basic().into_int_value();
11644                    let selector = selector.as_basic_value().into_int_value();
11645
11646                    for catch in catches.iter() {
11647                        match catch {
11648                            Catch::All { label } => {
11649                                let b = self
11650                                    .context
11651                                    .append_basic_block(self.function, "catch_all_clause");
11652                                self.builder.position_at_end(b);
11653                                let frame = self.state.frame_at_depth(*label)?;
11654
11655                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11656
11657                                self.builder.position_at_end(catch_end_block);
11658                                catch_blocks.push((b, None));
11659                            }
11660                            Catch::One { tag, label } => {
11661                                let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
11662                                let signature = &self.wasm_module.signatures[tag_idx];
11663                                let params = signature.params();
11664
11665                                let b = self.context.append_basic_block(
11666                                    self.function,
11667                                    format!("catch_one_clause_{tag}").as_str(),
11668                                );
11669                                self.builder.position_at_end(b);
11670
11671                                let exnref_phi = err!(
11672                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11673                                );
11674                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11675
11676                                // Get the payload pointer.
11677                                let exn_payload_ptr = err!(self.builder.build_direct_call(
11678                                    self.intrinsics.read_exnref,
11679                                    &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
11680                                    "exn_ptr",
11681                                ));
11682                                let exn_payload_ptr = exn_payload_ptr
11683                                    .try_as_basic_value()
11684                                    .unwrap_basic()
11685                                    .into_pointer_value();
11686
11687                                // Read each value from the data ptr.
11688                                let values = params
11689                                    .iter()
11690                                    .enumerate()
11691                                    .map(|(i, v)| {
11692                                        let name = format!("value_{i}");
11693                                        let ptr = err!(unsafe {
11694                                            self.builder.build_gep(
11695                                                self.intrinsics.i128_ty,
11696                                                exn_payload_ptr,
11697                                                &[self
11698                                                    .intrinsics
11699                                                    .i32_ty
11700                                                    .const_int(i as u64, false)],
11701                                                format!("{name}_ptr").as_str(),
11702                                            )
11703                                        });
11704                                        err_nt!(self.builder.build_load(
11705                                            type_to_llvm(self.intrinsics, *v)?,
11706                                            ptr,
11707                                            &name,
11708                                        ))
11709                                    })
11710                                    .collect::<Result<Vec<_>, CompileError>>()?;
11711
11712                                let frame = self.state.frame_at_depth(*label)?;
11713
11714                                for (phi, value) in frame.phis().iter().zip(values.iter()) {
11715                                    phi.add_incoming(&[(value, b)])
11716                                }
11717
11718                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11719
11720                                self.builder.position_at_end(catch_end_block);
11721                                catch_blocks.push((b, Some(exnref_phi)));
11722                            }
11723                            Catch::OneRef { label, tag } => {
11724                                let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
11725                                let signature = &self.wasm_module.signatures[tag_idx];
11726                                let params = signature.params();
11727
11728                                let b = self.context.append_basic_block(
11729                                    self.function,
11730                                    format!("catch_one_ref_clause_{tag}").as_str(),
11731                                );
11732                                self.builder.position_at_end(b);
11733
11734                                let exnref_phi = err!(
11735                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11736                                );
11737                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11738
11739                                // Get the payload pointer.
11740                                let exn_payload_ptr = err!(self.builder.build_direct_call(
11741                                    self.intrinsics.read_exnref,
11742                                    &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
11743                                    "exn_ptr",
11744                                ));
11745                                let exn_payload_ptr = exn_payload_ptr
11746                                    .try_as_basic_value()
11747                                    .unwrap_basic()
11748                                    .into_pointer_value();
11749
11750                                // Read each value from the data ptr.
11751                                let mut values = params
11752                                    .iter()
11753                                    .enumerate()
11754                                    .map(|(i, v)| {
11755                                        let name = format!("value_{i}");
11756                                        let ptr = err!(unsafe {
11757                                            self.builder.build_gep(
11758                                                self.intrinsics.i128_ty,
11759                                                exn_payload_ptr,
11760                                                &[self
11761                                                    .intrinsics
11762                                                    .i32_ty
11763                                                    .const_int(i as u64, false)],
11764                                                format!("{name}_ptr").as_str(),
11765                                            )
11766                                        });
11767                                        err_nt!(self.builder.build_load(
11768                                            type_to_llvm(self.intrinsics, *v)?,
11769                                            ptr,
11770                                            &name,
11771                                        ))
11772                                    })
11773                                    .collect::<Result<Vec<_>, CompileError>>()?;
11774
11775                                values.push(exnref_phi.as_basic_value());
11776
11777                                let frame = self.state.frame_at_depth(*label)?;
11778
11779                                for (phi, value) in frame.phis().iter().zip(values.iter()) {
11780                                    phi.add_incoming(&[(value, b)])
11781                                }
11782
11783                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11784
11785                                self.builder.position_at_end(catch_end_block);
11786                                catch_blocks.push((b, Some(exnref_phi)));
11787                            }
11788                            Catch::AllRef { label } => {
11789                                let b = self
11790                                    .context
11791                                    .append_basic_block(self.function, "catch_all_ref_clause");
11792                                self.builder.position_at_end(b);
11793
11794                                let exnref_phi = err!(
11795                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11796                                );
11797                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11798
11799                                let frame = self.state.frame_at_depth(*label)?;
11800
11801                                let phis = frame.phis();
11802
11803                                assert_eq!(phis.len(), 1);
11804                                phis[0].add_incoming(&[(&exnref_phi.as_basic_value(), b)]);
11805
11806                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11807
11808                                self.builder.position_at_end(catch_end_block);
11809                                catch_blocks.push((b, Some(exnref_phi)));
11810                            }
11811                        }
11812                    }
11813
11814                    for catch_info in &outer_catch_blocks {
11815                        if let Some(phi) = catch_info.exnref_phi {
11816                            phi.add_incoming(&[(&exnref, catch_end_block)]);
11817                        }
11818                    }
11819
11820                    err!(
11821                        self.builder.build_switch(
11822                            selector,
11823                            rethrow_block,
11824                            catch_blocks
11825                                .iter()
11826                                .enumerate()
11827                                .map(|(i, v)| (
11828                                    self.intrinsics
11829                                        .i32_ty
11830                                        .const_int(catch_tag_values[i] as _, false),
11831                                    v.0
11832                                ))
11833                                .chain(outer_catch_blocks.iter().map(|catch_info| (
11834                                    self.intrinsics.i32_ty.const_int(catch_info.tag as _, false),
11835                                    catch_info.catch_block
11836                                )))
11837                                .collect::<Vec<_>>()
11838                                .as_slice()
11839                        )
11840                    );
11841
11842                    // -- end
11843
11844                    // -- The rethrow block
11845                    self.builder.position_at_end(rethrow_block);
11846
11847                    self.build_call_with_param_attributes(
11848                        self.intrinsics.throw,
11849                        &[self.ctx.basic().into(), exnref.into()],
11850                        "rethrow",
11851                    )?;
11852                    // can't reach after an explicit throw!
11853                    err!(self.builder.build_unreachable());
11854
11855                    maybe_lpad_block = Some(lpad_block);
11856                }
11857
11858                // Move back to current block
11859                self.builder.position_at_end(current_block);
11860
11861                // Note: catch_tag_values also contains outer tags, but zipping with
11862                // catch_blocks will let us ignore the extra ones.
11863                let catch_tags_and_blocks = catch_tag_values
11864                    .into_iter()
11865                    .zip(catch_blocks)
11866                    .map(|(tag, (block, exnref_phi))| TagCatchInfo {
11867                        tag,
11868                        catch_block: block,
11869                        exnref_phi,
11870                    })
11871                    .collect::<Vec<_>>();
11872                self.state.push_landingpad(
11873                    maybe_lpad_block,
11874                    end_block,
11875                    end_phis,
11876                    &catch_tags_and_blocks,
11877                    self.module_translation
11878                        .blocktype_params_results(&try_table.ty)?
11879                        .0
11880                        .len(),
11881                );
11882            }
11883            Operator::Throw { tag_index } => {
11884                let current_block = self
11885                    .builder
11886                    .get_insert_block()
11887                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
11888
11889                let sig_index = self.wasm_module.tags[TagIndex::from_u32(tag_index)];
11890                let signature = &self.wasm_module.signatures[sig_index];
11891                let params = signature.params();
11892                let values = self.state.popn_save_extra(params.len())?;
11893
11894                values.iter().enumerate().try_for_each(|(i, (v, _))| {
11895                    let t = type_to_llvm(self.intrinsics, params[i])?;
11896                    if t != v.get_type() {
11897                        return Err(CompileError::Codegen(format!(
11898                            "Incompatible types: {:?} != {:?}",
11899                            t,
11900                            v.get_type()
11901                        )));
11902                    }
11903
11904                    Ok(())
11905                })?;
11906
11907                // Allocate the necessary bytes for the exception.
11908                let exnref = err!(
11909                    self.builder.build_direct_call(
11910                        self.intrinsics.alloc_exception,
11911                        &[
11912                            self.ctx.basic().into(),
11913                            self.intrinsics
11914                                .i32_ty
11915                                .const_int(tag_index as _, false)
11916                                .into()
11917                        ],
11918                        "exnref",
11919                    )
11920                );
11921                let exnref = exnref.try_as_basic_value().unwrap_basic();
11922
11923                let exn_payload_ptr = err!(self.builder.build_direct_call(
11924                    self.intrinsics.read_exnref,
11925                    &[self.ctx.basic().into(), exnref.into()],
11926                    "exn_ptr",
11927                ));
11928                let exn_payload_ptr = exn_payload_ptr
11929                    .try_as_basic_value()
11930                    .unwrap_basic()
11931                    .into_pointer_value();
11932
11933                for (i, value) in values.into_iter().enumerate() {
11934                    let ptr = err!(unsafe {
11935                        self.builder.build_gep(
11936                            self.intrinsics.i128_ty,
11937                            exn_payload_ptr,
11938                            &[self.intrinsics.i32_ty.const_int(i as u64, false)],
11939                            format!("value_{i}_ptr").as_str(),
11940                        )
11941                    });
11942                    err!(self.builder.build_store(ptr, value.0));
11943                }
11944
11945                if let Some(pad) = self.state.get_innermost_landingpad() {
11946                    let unreachable_block = self
11947                        .context
11948                        .append_basic_block(self.function, "_throw_unreachable");
11949
11950                    err!(self.builder.build_invoke(
11951                        self.intrinsics.throw,
11952                        &[self.ctx.basic(), exnref],
11953                        unreachable_block,
11954                        pad,
11955                        "throw",
11956                    ));
11957
11958                    self.builder.position_at_end(unreachable_block);
11959                    // can't reach after an explicit throw!
11960                    err!(self.builder.build_unreachable());
11961
11962                    self.builder.position_at_end(current_block);
11963                } else {
11964                    self.build_call_with_param_attributes(
11965                        self.intrinsics.throw,
11966                        &[self.ctx.basic().into(), exnref.into()],
11967                        "throw",
11968                    )?;
11969                    // can't reach after an explicit throw!
11970                    err!(self.builder.build_unreachable());
11971                }
11972
11973                self.state.reachable = false;
11974            }
11975            Operator::ThrowRef => {
11976                let current_block = self
11977                    .builder
11978                    .get_insert_block()
11979                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
11980
11981                let exnref = self.state.pop1()?;
11982
11983                if let Some(pad) = self.state.get_innermost_landingpad() {
11984                    let unreachable_block = self
11985                        .context
11986                        .append_basic_block(self.function, "_rethrow_unreachable");
11987
11988                    err!(self.builder.build_invoke(
11989                        self.intrinsics.throw,
11990                        &[self.ctx.basic(), exnref],
11991                        unreachable_block,
11992                        pad,
11993                        "throw",
11994                    ));
11995
11996                    self.builder.position_at_end(unreachable_block);
11997                    // can't reach after an explicit throw!
11998                    err!(self.builder.build_unreachable());
11999
12000                    self.builder.position_at_end(current_block);
12001                } else {
12002                    self.build_call_with_param_attributes(
12003                        self.intrinsics.throw,
12004                        &[self.ctx.basic().into(), exnref.into()],
12005                        "throw",
12006                    )?;
12007                    // can't reach after an explicit throw!
12008                    err!(self.builder.build_unreachable());
12009                }
12010
12011                self.state.reachable = false;
12012            }
12013            _ => unreachable!(),
12014        }
12015        Ok(())
12016    }
12017
12018    fn translate_operator(&mut self, op: Operator, _source_loc: u32) -> Result<(), CompileError> {
12019        //let opcode_offset: Option<usize> = None;
12020
12021        if !self.state.reachable {
12022            match op {
12023                Operator::Block { blockty: _ }
12024                | Operator::Loop { blockty: _ }
12025                | Operator::If { blockty: _ }
12026                | Operator::TryTable { .. } => {
12027                    self.unreachable_depth += 1;
12028                    return Ok(());
12029                }
12030                Operator::Else => {
12031                    if self.unreachable_depth != 0 {
12032                        return Ok(());
12033                    }
12034                }
12035                Operator::End => {
12036                    if self.unreachable_depth != 0 {
12037                        self.unreachable_depth -= 1;
12038                        return Ok(());
12039                    }
12040                }
12041                _ => {
12042                    return Ok(());
12043                }
12044            }
12045        }
12046
12047        match op {
12048            Operator::Block { .. }
12049            | Operator::Loop { .. }
12050            | Operator::Br { .. }
12051            | Operator::BrIf { .. }
12052            | Operator::BrTable { .. }
12053            | Operator::If { .. }
12054            | Operator::Else
12055            | Operator::End
12056            | Operator::Return
12057            | Operator::Unreachable => {
12058                self.translate_control_flow_operator(op)?;
12059            }
12060            Operator::Nop
12061            | Operator::Drop
12062            | Operator::I32Const { .. }
12063            | Operator::I64Const { .. }
12064            | Operator::F32Const { .. }
12065            | Operator::F64Const { .. }
12066            | Operator::V128Const { .. }
12067            | Operator::I8x16Splat
12068            | Operator::I16x8Splat
12069            | Operator::I32x4Splat
12070            | Operator::I64x2Splat
12071            | Operator::F32x4Splat
12072            | Operator::F64x2Splat
12073            | Operator::LocalGet { .. }
12074            | Operator::LocalSet { .. }
12075            | Operator::LocalTee { .. }
12076            | Operator::GlobalGet { .. }
12077            | Operator::GlobalSet { .. }
12078            | Operator::Call { .. }
12079            | Operator::ReturnCall { .. }
12080            | Operator::CallIndirect { .. }
12081            | Operator::ReturnCallIndirect { .. }
12082            | Operator::TypedSelect { .. }
12083            | Operator::Select => {
12084                self.translate_basic_operator(op)?;
12085            }
12086            Operator::I32Add
12087            | Operator::I64Add
12088            | Operator::I8x16Add
12089            | Operator::I16x8Add
12090            | Operator::I16x8ExtAddPairwiseI8x16S
12091            | Operator::I16x8ExtAddPairwiseI8x16U
12092            | Operator::I32x4Add
12093            | Operator::I32x4ExtAddPairwiseI16x8S
12094            | Operator::I32x4ExtAddPairwiseI16x8U
12095            | Operator::I64x2Add
12096            | Operator::I8x16AddSatS
12097            | Operator::I16x8AddSatS
12098            | Operator::I8x16AddSatU
12099            | Operator::I16x8AddSatU
12100            | Operator::I32Sub
12101            | Operator::I64Sub
12102            | Operator::I8x16Sub
12103            | Operator::I16x8Sub
12104            | Operator::I32x4Sub
12105            | Operator::I64x2Sub
12106            | Operator::I8x16SubSatS
12107            | Operator::I16x8SubSatS
12108            | Operator::I8x16SubSatU
12109            | Operator::I16x8SubSatU
12110            | Operator::I32Mul
12111            | Operator::I64Mul
12112            | Operator::I16x8Mul
12113            | Operator::I32x4Mul
12114            | Operator::I64x2Mul
12115            | Operator::I16x8RelaxedQ15mulrS
12116            | Operator::I16x8Q15MulrSatS
12117            | Operator::I16x8ExtMulLowI8x16S
12118            | Operator::I16x8ExtMulLowI8x16U
12119            | Operator::I16x8ExtMulHighI8x16S
12120            | Operator::I16x8ExtMulHighI8x16U
12121            | Operator::I32x4ExtMulLowI16x8S
12122            | Operator::I32x4ExtMulLowI16x8U
12123            | Operator::I32x4ExtMulHighI16x8S
12124            | Operator::I32x4ExtMulHighI16x8U
12125            | Operator::I64x2ExtMulLowI32x4S
12126            | Operator::I64x2ExtMulLowI32x4U
12127            | Operator::I64x2ExtMulHighI32x4S
12128            | Operator::I64x2ExtMulHighI32x4U
12129            | Operator::I32x4DotI16x8S
12130            | Operator::I16x8RelaxedDotI8x16I7x16S
12131            | Operator::I32x4RelaxedDotI8x16I7x16AddS
12132            | Operator::I32DivS
12133            | Operator::I64DivS
12134            | Operator::I32DivU
12135            | Operator::I64DivU
12136            | Operator::I32RemS
12137            | Operator::I64RemS
12138            | Operator::I32RemU
12139            | Operator::I64RemU
12140            | Operator::I32And
12141            | Operator::I64And
12142            | Operator::V128And
12143            | Operator::I32Or
12144            | Operator::I64Or
12145            | Operator::V128Or
12146            | Operator::I32Xor
12147            | Operator::I64Xor
12148            | Operator::V128Xor
12149            | Operator::V128AndNot
12150            | Operator::I8x16RelaxedLaneselect
12151            | Operator::I16x8RelaxedLaneselect
12152            | Operator::I32x4RelaxedLaneselect
12153            | Operator::I64x2RelaxedLaneselect
12154            | Operator::V128Bitselect
12155            | Operator::I8x16Bitmask
12156            | Operator::I16x8Bitmask
12157            | Operator::I32x4Bitmask
12158            | Operator::I64x2Bitmask
12159            | Operator::I32Shl
12160            | Operator::I64Shl
12161            | Operator::I8x16Shl
12162            | Operator::I16x8Shl
12163            | Operator::I32x4Shl
12164            | Operator::I64x2Shl
12165            | Operator::I32ShrS
12166            | Operator::I64ShrS
12167            | Operator::I8x16ShrS
12168            | Operator::I16x8ShrS
12169            | Operator::I32x4ShrS
12170            | Operator::I64x2ShrS
12171            | Operator::I32ShrU
12172            | Operator::I64ShrU
12173            | Operator::I8x16ShrU
12174            | Operator::I16x8ShrU
12175            | Operator::I32x4ShrU
12176            | Operator::I64x2ShrU
12177            | Operator::I32Rotl
12178            | Operator::I64Rotl
12179            | Operator::I32Rotr
12180            | Operator::I64Rotr
12181            | Operator::I32Clz
12182            | Operator::I64Clz
12183            | Operator::I32Ctz
12184            | Operator::I64Ctz
12185            | Operator::I8x16Popcnt
12186            | Operator::I32Popcnt
12187            | Operator::I64Popcnt
12188            | Operator::I32Eqz
12189            | Operator::I64Eqz
12190            | Operator::I8x16Abs
12191            | Operator::I16x8Abs
12192            | Operator::I32x4Abs
12193            | Operator::I64x2Abs
12194            | Operator::I8x16MinS
12195            | Operator::I8x16MinU
12196            | Operator::I8x16MaxS
12197            | Operator::I8x16MaxU
12198            | Operator::I16x8MinS
12199            | Operator::I16x8MinU
12200            | Operator::I16x8MaxS
12201            | Operator::I16x8MaxU
12202            | Operator::I32x4MinS
12203            | Operator::I32x4MinU
12204            | Operator::I32x4MaxS
12205            | Operator::I32x4MaxU
12206            | Operator::I8x16AvgrU
12207            | Operator::I16x8AvgrU
12208            | Operator::I64Add128
12209            | Operator::I64Sub128
12210            | Operator::I64MulWideS
12211            | Operator::I64MulWideU => self.translate_integer_arithmetic_operator(op)?,
12212            Operator::F32Add
12213            | Operator::F64Add
12214            | Operator::F32x4Add
12215            | Operator::F64x2Add
12216            | Operator::F32Sub
12217            | Operator::F64Sub
12218            | Operator::F32x4Sub
12219            | Operator::F64x2Sub
12220            | Operator::F32Mul
12221            | Operator::F64Mul
12222            | Operator::F32x4Mul
12223            | Operator::F32x4RelaxedMadd
12224            | Operator::F32x4RelaxedNmadd
12225            | Operator::F64x2Mul
12226            | Operator::F64x2RelaxedMadd
12227            | Operator::F64x2RelaxedNmadd
12228            | Operator::F32Div
12229            | Operator::F64Div
12230            | Operator::F32x4Div
12231            | Operator::F64x2Div
12232            | Operator::F32Sqrt
12233            | Operator::F64Sqrt
12234            | Operator::F32x4Sqrt
12235            | Operator::F64x2Sqrt
12236            | Operator::F32Min
12237            | Operator::F64Min
12238            | Operator::F32x4RelaxedMin
12239            | Operator::F32x4Min
12240            | Operator::F32x4PMin
12241            | Operator::F64x2RelaxedMin
12242            | Operator::F64x2Min
12243            | Operator::F64x2PMin
12244            | Operator::F32Max
12245            | Operator::F64Max
12246            | Operator::F32x4RelaxedMax
12247            | Operator::F32x4Max
12248            | Operator::F32x4PMax
12249            | Operator::F64x2RelaxedMax
12250            | Operator::F64x2Max
12251            | Operator::F64x2PMax
12252            | Operator::F32Ceil
12253            | Operator::F32x4Ceil
12254            | Operator::F64Ceil
12255            | Operator::F64x2Ceil
12256            | Operator::F32Floor
12257            | Operator::F32x4Floor
12258            | Operator::F64Floor
12259            | Operator::F64x2Floor
12260            | Operator::F32Trunc
12261            | Operator::F32x4Trunc
12262            | Operator::F64Trunc
12263            | Operator::F64x2Trunc
12264            | Operator::F32Nearest
12265            | Operator::F32x4Nearest
12266            | Operator::F64Nearest
12267            | Operator::F64x2Nearest
12268            | Operator::F32Abs
12269            | Operator::F64Abs
12270            | Operator::F32x4Abs
12271            | Operator::F64x2Abs
12272            | Operator::F32x4Neg
12273            | Operator::F64x2Neg
12274            | Operator::F32Neg
12275            | Operator::F64Neg
12276            | Operator::F32Copysign
12277            | Operator::F64Copysign => self.translate_floating_point_arithmetic_operator(op)?,
12278            Operator::I32Eq
12279            | Operator::I64Eq
12280            | Operator::I8x16Eq
12281            | Operator::I16x8Eq
12282            | Operator::I32x4Eq
12283            | Operator::I64x2Eq
12284            | Operator::I32Ne
12285            | Operator::I64Ne
12286            | Operator::I8x16Ne
12287            | Operator::I16x8Ne
12288            | Operator::I32x4Ne
12289            | Operator::I64x2Ne
12290            | Operator::I32LtS
12291            | Operator::I64LtS
12292            | Operator::I8x16LtS
12293            | Operator::I16x8LtS
12294            | Operator::I32x4LtS
12295            | Operator::I64x2LtS
12296            | Operator::I32LtU
12297            | Operator::I64LtU
12298            | Operator::I8x16LtU
12299            | Operator::I16x8LtU
12300            | Operator::I32x4LtU
12301            | Operator::I32LeS
12302            | Operator::I64LeS
12303            | Operator::I8x16LeS
12304            | Operator::I16x8LeS
12305            | Operator::I32x4LeS
12306            | Operator::I64x2LeS
12307            | Operator::I32LeU
12308            | Operator::I64LeU
12309            | Operator::I8x16LeU
12310            | Operator::I16x8LeU
12311            | Operator::I32x4LeU
12312            | Operator::I32GtS
12313            | Operator::I64GtS
12314            | Operator::I8x16GtS
12315            | Operator::I16x8GtS
12316            | Operator::I32x4GtS
12317            | Operator::I64x2GtS
12318            | Operator::I32GtU
12319            | Operator::I64GtU
12320            | Operator::I8x16GtU
12321            | Operator::I16x8GtU
12322            | Operator::I32x4GtU
12323            | Operator::I32GeS
12324            | Operator::I64GeS
12325            | Operator::I8x16GeS
12326            | Operator::I16x8GeS
12327            | Operator::I32x4GeS
12328            | Operator::I64x2GeS
12329            | Operator::I32GeU
12330            | Operator::I64GeU
12331            | Operator::I8x16GeU
12332            | Operator::I16x8GeU
12333            | Operator::I32x4GeU => self.translate_integer_comparison_operator(op)?,
12334            Operator::F32Eq
12335            | Operator::F64Eq
12336            | Operator::F32x4Eq
12337            | Operator::F64x2Eq
12338            | Operator::F32Ne
12339            | Operator::F64Ne
12340            | Operator::F32x4Ne
12341            | Operator::F64x2Ne
12342            | Operator::F32Lt
12343            | Operator::F64Lt
12344            | Operator::F32x4Lt
12345            | Operator::F64x2Lt
12346            | Operator::F32Le
12347            | Operator::F64Le
12348            | Operator::F32x4Le
12349            | Operator::F64x2Le
12350            | Operator::F32Gt
12351            | Operator::F64Gt
12352            | Operator::F32x4Gt
12353            | Operator::F64x2Gt
12354            | Operator::F32Ge
12355            | Operator::F64Ge
12356            | Operator::F32x4Ge
12357            | Operator::F64x2Ge => self.translate_floating_point_comparison_operator(op)?,
12358            Operator::I32WrapI64
12359            | Operator::I64ExtendI32S
12360            | Operator::I64ExtendI32U
12361            | Operator::I16x8ExtendLowI8x16S
12362            | Operator::I16x8ExtendHighI8x16S
12363            | Operator::I16x8ExtendLowI8x16U
12364            | Operator::I16x8ExtendHighI8x16U
12365            | Operator::I32x4ExtendLowI16x8S
12366            | Operator::I32x4ExtendHighI16x8S
12367            | Operator::I32x4ExtendLowI16x8U
12368            | Operator::I32x4ExtendHighI16x8U
12369            | Operator::I64x2ExtendLowI32x4U
12370            | Operator::I64x2ExtendLowI32x4S
12371            | Operator::I64x2ExtendHighI32x4U
12372            | Operator::I64x2ExtendHighI32x4S
12373            | Operator::I8x16NarrowI16x8S
12374            | Operator::I8x16NarrowI16x8U
12375            | Operator::I16x8NarrowI32x4S
12376            | Operator::I16x8NarrowI32x4U
12377            | Operator::I32x4RelaxedTruncF32x4S
12378            | Operator::I32x4TruncSatF32x4S
12379            | Operator::I32x4RelaxedTruncF32x4U
12380            | Operator::I32x4TruncSatF32x4U
12381            | Operator::I32x4RelaxedTruncF64x2SZero
12382            | Operator::I32x4RelaxedTruncF64x2UZero
12383            | Operator::I32x4TruncSatF64x2SZero
12384            | Operator::I32x4TruncSatF64x2UZero
12385            | Operator::I32TruncF32S
12386            | Operator::I32TruncF64S
12387            | Operator::I32TruncSatF32S
12388            | Operator::I32TruncSatF64S
12389            | Operator::I64TruncF32S
12390            | Operator::I64TruncF64S
12391            | Operator::I64TruncSatF32S
12392            | Operator::I64TruncSatF64S
12393            | Operator::I32TruncF32U
12394            | Operator::I32TruncF64U
12395            | Operator::I32TruncSatF32U
12396            | Operator::I32TruncSatF64U
12397            | Operator::I64TruncF32U
12398            | Operator::I64TruncF64U
12399            | Operator::I64TruncSatF32U
12400            | Operator::I64TruncSatF64U
12401            | Operator::F32DemoteF64
12402            | Operator::F64PromoteF32
12403            | Operator::F32ConvertI32S
12404            | Operator::F32ConvertI64S
12405            | Operator::F64ConvertI32S
12406            | Operator::F64ConvertI64S
12407            | Operator::F32ConvertI32U
12408            | Operator::F32ConvertI64U
12409            | Operator::F64ConvertI32U
12410            | Operator::F64ConvertI64U
12411            | Operator::F32x4ConvertI32x4S
12412            | Operator::F32x4ConvertI32x4U
12413            | Operator::F64x2ConvertLowI32x4S
12414            | Operator::F64x2ConvertLowI32x4U
12415            | Operator::F64x2PromoteLowF32x4
12416            | Operator::F32x4DemoteF64x2Zero
12417            | Operator::I32ReinterpretF32
12418            | Operator::I64ReinterpretF64
12419            | Operator::F32ReinterpretI32
12420            | Operator::F64ReinterpretI64 => self.translate_conversion_operator(op)?,
12421            Operator::I32Extend8S
12422            | Operator::I32Extend16S
12423            | Operator::I64Extend8S
12424            | Operator::I64Extend16S
12425            | Operator::I64Extend32S => self.translate_sign_extension_operator(op)?,
12426            Operator::I32Load { .. }
12427            | Operator::I64Load { .. }
12428            | Operator::F32Load { .. }
12429            | Operator::F64Load { .. }
12430            | Operator::V128Load { .. }
12431            | Operator::V128Load8Lane { .. }
12432            | Operator::V128Load16Lane { .. }
12433            | Operator::V128Load32Lane { .. }
12434            | Operator::V128Load64Lane { .. }
12435            | Operator::I32Store { .. }
12436            | Operator::I64Store { .. }
12437            | Operator::F32Store { .. }
12438            | Operator::F64Store { .. }
12439            | Operator::V128Store { .. }
12440            | Operator::V128Store8Lane { .. }
12441            | Operator::V128Store16Lane { .. }
12442            | Operator::V128Store32Lane { .. }
12443            | Operator::V128Store64Lane { .. }
12444            | Operator::I32Load8S { .. }
12445            | Operator::I32Load16S { .. }
12446            | Operator::I64Load8S { .. }
12447            | Operator::I64Load16S { .. }
12448            | Operator::I64Load32S { .. }
12449            | Operator::I32Load8U { .. }
12450            | Operator::I32Load16U { .. }
12451            | Operator::I64Load8U { .. }
12452            | Operator::I64Load16U { .. }
12453            | Operator::I64Load32U { .. }
12454            | Operator::I32Store8 { .. }
12455            | Operator::I64Store8 { .. }
12456            | Operator::I32Store16 { .. }
12457            | Operator::I64Store16 { .. }
12458            | Operator::I64Store32 { .. }
12459            | Operator::I8x16Neg
12460            | Operator::I16x8Neg
12461            | Operator::I32x4Neg
12462            | Operator::I64x2Neg
12463            | Operator::V128Not
12464            | Operator::V128AnyTrue
12465            | Operator::I8x16AllTrue
12466            | Operator::I16x8AllTrue
12467            | Operator::I32x4AllTrue
12468            | Operator::I64x2AllTrue
12469            | Operator::I8x16ExtractLaneS { .. }
12470            | Operator::I8x16ExtractLaneU { .. }
12471            | Operator::I16x8ExtractLaneS { .. }
12472            | Operator::I16x8ExtractLaneU { .. }
12473            | Operator::I32x4ExtractLane { .. }
12474            | Operator::I64x2ExtractLane { .. }
12475            | Operator::F32x4ExtractLane { .. }
12476            | Operator::F64x2ExtractLane { .. }
12477            | Operator::I8x16ReplaceLane { .. }
12478            | Operator::I16x8ReplaceLane { .. }
12479            | Operator::I32x4ReplaceLane { .. }
12480            | Operator::I64x2ReplaceLane { .. }
12481            | Operator::F32x4ReplaceLane { .. }
12482            | Operator::F64x2ReplaceLane { .. }
12483            | Operator::I8x16RelaxedSwizzle
12484            | Operator::I8x16Swizzle
12485            | Operator::I8x16Shuffle { .. }
12486            | Operator::V128Load8x8S { .. }
12487            | Operator::V128Load8x8U { .. }
12488            | Operator::V128Load16x4S { .. }
12489            | Operator::V128Load16x4U { .. }
12490            | Operator::V128Load32x2S { .. }
12491            | Operator::V128Load32x2U { .. }
12492            | Operator::V128Load32Zero { .. }
12493            | Operator::V128Load64Zero { .. }
12494            | Operator::V128Load8Splat { .. }
12495            | Operator::V128Load16Splat { .. }
12496            | Operator::V128Load32Splat { .. }
12497            | Operator::V128Load64Splat { .. }
12498            | Operator::MemoryGrow { .. }
12499            | Operator::MemorySize { .. }
12500            | Operator::MemoryInit { .. }
12501            | Operator::DataDrop { .. }
12502            | Operator::MemoryCopy { .. }
12503            | Operator::MemoryFill { .. } => self.translate_memory_operator(op)?,
12504            Operator::AtomicFence { .. }
12505            | Operator::I32AtomicLoad { .. }
12506            | Operator::I64AtomicLoad { .. }
12507            | Operator::I32AtomicLoad8U { .. }
12508            | Operator::I32AtomicLoad16U { .. }
12509            | Operator::I64AtomicLoad8U { .. }
12510            | Operator::I64AtomicLoad16U { .. }
12511            | Operator::I64AtomicLoad32U { .. }
12512            | Operator::I32AtomicStore { .. }
12513            | Operator::I64AtomicStore { .. }
12514            | Operator::I32AtomicStore8 { .. }
12515            | Operator::I64AtomicStore8 { .. }
12516            | Operator::I32AtomicStore16 { .. }
12517            | Operator::I64AtomicStore16 { .. }
12518            | Operator::I64AtomicStore32 { .. }
12519            | Operator::I32AtomicRmw8AddU { .. }
12520            | Operator::I32AtomicRmw16AddU { .. }
12521            | Operator::I32AtomicRmwAdd { .. }
12522            | Operator::I64AtomicRmw8AddU { .. }
12523            | Operator::I64AtomicRmw16AddU { .. }
12524            | Operator::I64AtomicRmw32AddU { .. }
12525            | Operator::I64AtomicRmwAdd { .. }
12526            | Operator::I32AtomicRmw8SubU { .. }
12527            | Operator::I32AtomicRmw16SubU { .. }
12528            | Operator::I32AtomicRmwSub { .. }
12529            | Operator::I64AtomicRmw8SubU { .. }
12530            | Operator::I64AtomicRmw16SubU { .. }
12531            | Operator::I64AtomicRmw32SubU { .. }
12532            | Operator::I64AtomicRmwSub { .. }
12533            | Operator::I32AtomicRmw8AndU { .. }
12534            | Operator::I32AtomicRmw16AndU { .. }
12535            | Operator::I32AtomicRmwAnd { .. }
12536            | Operator::I64AtomicRmw8AndU { .. }
12537            | Operator::I64AtomicRmw16AndU { .. }
12538            | Operator::I64AtomicRmw32AndU { .. }
12539            | Operator::I64AtomicRmwAnd { .. }
12540            | Operator::I32AtomicRmw8OrU { .. }
12541            | Operator::I32AtomicRmw16OrU { .. }
12542            | Operator::I32AtomicRmwOr { .. }
12543            | Operator::I64AtomicRmw8OrU { .. }
12544            | Operator::I64AtomicRmw16OrU { .. }
12545            | Operator::I64AtomicRmw32OrU { .. }
12546            | Operator::I64AtomicRmwOr { .. }
12547            | Operator::I32AtomicRmw8XorU { .. }
12548            | Operator::I32AtomicRmw16XorU { .. }
12549            | Operator::I32AtomicRmwXor { .. }
12550            | Operator::I64AtomicRmw8XorU { .. }
12551            | Operator::I64AtomicRmw16XorU { .. }
12552            | Operator::I64AtomicRmw32XorU { .. }
12553            | Operator::I64AtomicRmwXor { .. }
12554            | Operator::I32AtomicRmw8XchgU { .. }
12555            | Operator::I32AtomicRmw16XchgU { .. }
12556            | Operator::I32AtomicRmwXchg { .. }
12557            | Operator::I64AtomicRmw8XchgU { .. }
12558            | Operator::I64AtomicRmw16XchgU { .. }
12559            | Operator::I64AtomicRmw32XchgU { .. }
12560            | Operator::I64AtomicRmwXchg { .. }
12561            | Operator::I32AtomicRmw8CmpxchgU { .. }
12562            | Operator::I32AtomicRmw16CmpxchgU { .. }
12563            | Operator::I32AtomicRmwCmpxchg { .. }
12564            | Operator::I64AtomicRmw8CmpxchgU { .. }
12565            | Operator::I64AtomicRmw16CmpxchgU { .. }
12566            | Operator::I64AtomicRmw32CmpxchgU { .. }
12567            | Operator::I64AtomicRmwCmpxchg { .. }
12568            | Operator::MemoryAtomicWait32 { .. }
12569            | Operator::MemoryAtomicWait64 { .. }
12570            | Operator::MemoryAtomicNotify { .. } => self.translate_atomic_memory_operator(op)?,
12571            Operator::RefNull { .. } | Operator::RefIsNull | Operator::RefFunc { .. } => {
12572                self.translate_reference_operator(op)?;
12573            }
12574            Operator::TableGet { .. }
12575            | Operator::TableSet { .. }
12576            | Operator::TableCopy { .. }
12577            | Operator::TableInit { .. }
12578            | Operator::ElemDrop { .. }
12579            | Operator::TableFill { .. }
12580            | Operator::TableGrow { .. }
12581            | Operator::TableSize { .. } => self.translate_table_operator(op)?,
12582            Operator::TryTable { .. } | Operator::Throw { .. } | Operator::ThrowRef => {
12583                self.translate_eh_operator(op)?;
12584            }
12585            _ => {
12586                return Err(CompileError::Codegen(format!(
12587                    "Operator {op:?} unimplemented",
12588                )));
12589            }
12590        }
12591
12592        Ok(())
12593    }
12594
12595    fn build_call_with_param_attributes(
12596        &self,
12597        function: FunctionValue<'ctx>,
12598        args: &[BasicMetadataValueEnum<'ctx>],
12599        name: &str,
12600    ) -> Result<CallSiteValue<'ctx>, CompileError> {
12601        let call = self
12602            .builder
12603            .build_call(function, args, name)
12604            .map_err(|e| CompileError::Codegen(e.to_string()))?;
12605
12606        // https://five-embeddev.com/riscv-user-isa-manual/Priv-v1.12/rv64.html
12607        // > The compiler and calling convention maintain an invariant that all 32-bit values are held in a sign-extended format in 64-bit registers.
12608        // > Even 32-bit unsigned integers extend bit 31 into bits 63 through 32. Consequently, conversion between unsigned and signed 32-bit integers
12609        // > is a no-op, as is conversion from a signed 32-bit integer to a signed 64-bit integer.
12610        if matches!(
12611            self.target_triple.architecture,
12612            Architecture::Riscv32(..) | Architecture::Riscv64(..)
12613        ) {
12614            let param_types = function.get_type().get_param_types();
12615            for (i, ty) in param_types.into_iter().enumerate() {
12616                if ty == self.context.i32_type().into() {
12617                    call.add_attribute(
12618                        AttributeLoc::Param(i as u32),
12619                        self.context
12620                            .create_enum_attribute(Attribute::get_named_enum_kind_id("signext"), 0),
12621                    );
12622                    call.add_attribute(
12623                        AttributeLoc::Param(i as u32),
12624                        self.context
12625                            .create_enum_attribute(Attribute::get_named_enum_kind_id("noundef"), 0),
12626                    );
12627                }
12628            }
12629        }
12630
12631        Ok(call)
12632    }
12633}
12634
12635fn is_f32_arithmetic(bits: u32) -> bool {
12636    // Mask off sign bit.
12637    let bits = bits & 0x7FFF_FFFF;
12638    bits < 0x7FC0_0000
12639}
12640
12641fn is_f64_arithmetic(bits: u64) -> bool {
12642    // Mask off sign bit.
12643    let bits = bits & 0x7FFF_FFFF_FFFF_FFFF;
12644    bits < 0x7FF8_0000_0000_0000
12645}