wasmer_compiler_llvm/translator/
code.rs

1use std::collections::HashMap;
2
3use super::{
4    intrinsics::{
5        CtxType, FunctionCache, GlobalCache, Intrinsics, MemoryCache, tbaa_label, type_to_llvm,
6    },
7    // stackmap::{StackmapEntry, StackmapEntryKind, StackmapRegistry, ValueSemantic},
8    state::{ControlFrame, ExtraInfo, IfElseState, State, TagCatchInfo},
9};
10use crate::{compiler::ModuleBasedSymbolRegistry, config::OptimizationStyle};
11use enumset::EnumSet;
12use inkwell::{
13    AddressSpace, AtomicOrdering, AtomicRMWBinOp, DLLStorageClass, FloatPredicate, IntPredicate,
14    attributes::{Attribute, AttributeLoc},
15    builder::Builder,
16    context::Context,
17    module::{Linkage, Module},
18    passes::PassBuilderOptions,
19    targets::{FileType, TargetMachine},
20    types::{BasicType, BasicTypeEnum, FloatMathType, IntType, PointerType, VectorType},
21    values::{
22        BasicMetadataValueEnum, BasicValue, BasicValueEnum, CallSiteValue, FloatValue,
23        FunctionValue, InstructionOpcode, InstructionValue, IntValue, LLVMTailCallKind, PhiValue,
24        PointerValue, VectorValue,
25    },
26};
27use itertools::Itertools;
28use smallvec::SmallVec;
29use target_lexicon::{Architecture, BinaryFormat, OperatingSystem, Triple};
30use wasmer_compiler::WASM_LARGE_FUNCTION_THRESHOLD;
31
32use crate::{
33    abi::{Abi, get_abi},
34    config::LLVM,
35    error::{err, err_nt},
36    object_file::{CompiledFunction, load_object_file},
37};
38use wasmer_compiler::{
39    CANONICAL_NAN_F32, CANONICAL_NAN_F64, FunctionBinaryReader, FunctionBodyData,
40    GEF32_LEQ_I32_MAX, GEF32_LEQ_I64_MAX, GEF32_LEQ_U32_MAX, GEF32_LEQ_U64_MAX, GEF64_LEQ_I32_MAX,
41    GEF64_LEQ_I64_MAX, GEF64_LEQ_U32_MAX, GEF64_LEQ_U64_MAX, LEF32_GEQ_I32_MIN, LEF32_GEQ_I64_MIN,
42    LEF32_GEQ_U32_MIN, LEF32_GEQ_U64_MIN, LEF64_GEQ_I32_MIN, LEF64_GEQ_I64_MIN, LEF64_GEQ_U32_MIN,
43    LEF64_GEQ_U64_MIN, MiddlewareBinaryReader, ModuleMiddlewareChain, ModuleTranslationState,
44    from_binaryreadererror_wasmerror,
45    misc::CompiledKind,
46    types::{
47        relocation::RelocationTarget,
48        symbols::{Symbol, SymbolRegistry},
49    },
50    wasmparser::{Catch, MemArg, Operator},
51    wpheaptype_to_type, wptype_to_type,
52};
53use wasmer_types::{
54    CompileError, FunctionIndex, FunctionType, GlobalIndex, LocalFunctionIndex, MemoryIndex,
55    ModuleInfo, SignatureHash, SignatureIndex, TableIndex, Type, target::CpuFeature,
56};
57use wasmer_types::{TagIndex, entity::PrimaryMap};
58use wasmer_vm::{MemoryStyle, TableStyle, VMOffsets};
59
60const FUNCTION_SECTION_ELF: &str = "__TEXT,wasmer_function";
61const FUNCTION_SECTION_MACHO: &str = "__TEXT";
62const FUNCTION_SEGMENT_MACHO: &str = "wasmer_function";
63
64// Since we want to use module-local tag numbers for landing pads,
65// the catch-all tag can't be zero; we instead use i32::MAX, which
66// is hopefully large enough to not conflict with any real tag.
67// If you have 2 billion tags in a single module, you deserve what you get.
68// ( Arshia: that comment above is AI-generated... AI is savage XD )
69const CATCH_ALL_TAG_VALUE: i32 = i32::MAX;
70
71pub struct FuncTranslator {
72    ctx: Context,
73    target_triple: Triple,
74    target_machines: HashMap<OptimizationStyle, TargetMachine>,
75    abi: Box<dyn Abi>,
76    binary_fmt: BinaryFormat,
77    func_section: String,
78    pointer_width: u8,
79    cpu_features: EnumSet<CpuFeature>,
80    non_volatile_memory_ops: bool,
81    wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
82}
83
84impl wasmer_compiler::FuncTranslator for FuncTranslator {}
85
86impl FuncTranslator {
87    pub fn new(
88        target_triple: Triple,
89        target_machines: HashMap<OptimizationStyle, TargetMachine>,
90        binary_fmt: BinaryFormat,
91        pointer_width: u8,
92        cpu_features: EnumSet<CpuFeature>,
93        non_volatile_memory_ops: bool,
94        wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
95    ) -> Result<Self, CompileError> {
96        let abi_source_tm = target_machines
97            .get(&OptimizationStyle::ForSpeed)
98            .expect("target_machines must contain OptimizationStyle::ForSpeed");
99        let abi = get_abi(abi_source_tm);
100        Ok(Self {
101            ctx: Context::create(),
102            target_triple,
103            target_machines,
104            abi,
105            func_section: match binary_fmt {
106                BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
107                BinaryFormat::Macho => FUNCTION_SEGMENT_MACHO.to_string(),
108                _ => {
109                    return Err(CompileError::UnsupportedTarget(format!(
110                        "Unsupported binary format: {binary_fmt:?}"
111                    )));
112                }
113            },
114            binary_fmt,
115            pointer_width,
116            cpu_features,
117            non_volatile_memory_ops,
118            wasm_apply_data_relocs_fn_index,
119        })
120    }
121
122    #[allow(clippy::too_many_arguments)]
123    pub fn translate_to_module(
124        &self,
125        wasm_module: &ModuleInfo,
126        module_translation: &ModuleTranslationState,
127        signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
128        local_func_index: &LocalFunctionIndex,
129        function_body: &FunctionBodyData,
130        config: &LLVM,
131        memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
132        _table_styles: &PrimaryMap<TableIndex, TableStyle>,
133        symbol_registry: &dyn SymbolRegistry,
134        target: &Triple,
135        opt_style: OptimizationStyle,
136    ) -> Result<Module<'_>, CompileError> {
137        // The function type, used for the callbacks.
138        let func_index = wasm_module.func_index(*local_func_index);
139        let function =
140            CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
141        let function_name =
142            symbol_registry.symbol_to_name(Symbol::LocalFunction(*local_func_index));
143
144        // We can pass and use the heap pointer (memory #0) only and only if the memory static, that means
145        // the allocated heap is never moved to a different location.
146        let m0_is_enabled = memory_styles
147            .get(MemoryIndex::from_u32(0))
148            .is_some_and(|memory| matches!(memory, MemoryStyle::Static { .. }));
149
150        let module_name = match wasm_module.name.as_ref() {
151            None => format!("<anonymous module> function {function_name}"),
152            Some(module_name) => format!("module {module_name} function {function_name}"),
153        };
154        let module = self.ctx.create_module(module_name.as_str());
155
156        let target_machine = &self.target_machines.values().next().unwrap();
157        let target_triple = target_machine.get_triple();
158        let target_data = target_machine.get_target_data();
159        module.set_triple(&target_triple);
160        module.set_data_layout(&target_data.get_data_layout());
161        let wasm_fn_type = wasm_module
162            .signatures
163            .get(wasm_module.functions[func_index])
164            .unwrap();
165
166        let offsets = VMOffsets::new(self.pointer_width, wasm_module);
167        let intrinsics = Intrinsics::declare(
168            &module,
169            &self.ctx,
170            &target_data,
171            &self.target_triple,
172            &self.binary_fmt,
173        );
174        let (func_type, func_attrs) = self.abi.func_type_to_llvm(
175            &self.ctx,
176            &intrinsics,
177            Some(&offsets),
178            wasm_fn_type,
179            m0_is_enabled,
180        )?;
181
182        let func = module.add_function(&function_name, func_type, Some(Linkage::External));
183        for (attr, attr_loc) in &func_attrs {
184            func.add_attribute(*attr_loc, *attr);
185        }
186
187        if !matches!(target.operating_system, OperatingSystem::Windows) {
188            func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe);
189        }
190
191        func.add_attribute(AttributeLoc::Function, intrinsics.uwtable);
192        func.add_attribute(AttributeLoc::Function, intrinsics.frame_pointer);
193
194        let section = match self.binary_fmt {
195            BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
196            BinaryFormat::Macho => {
197                format!("{FUNCTION_SECTION_MACHO},{FUNCTION_SEGMENT_MACHO}")
198            }
199            _ => {
200                return Err(CompileError::UnsupportedTarget(format!(
201                    "Unsupported binary format: {:?}",
202                    self.binary_fmt
203                )));
204            }
205        };
206
207        func.set_personality_function(intrinsics.personality);
208        func.as_global_value().set_section(Some(&section));
209
210        func.set_linkage(Linkage::DLLExport);
211        func.as_global_value()
212            .set_dll_storage_class(DLLStorageClass::Export);
213
214        let entry = self.ctx.append_basic_block(func, "entry");
215        let start_of_code = self.ctx.append_basic_block(func, "start_of_code");
216        let return_ = self.ctx.append_basic_block(func, "return");
217        let alloca_builder = self.ctx.create_builder();
218        let cache_builder = self.ctx.create_builder();
219        let builder = self.ctx.create_builder();
220        cache_builder.position_at_end(entry);
221        let br = err!(cache_builder.build_unconditional_branch(start_of_code));
222        alloca_builder.position_before(&br);
223        cache_builder.position_before(&br);
224        builder.position_at_end(start_of_code);
225
226        let mut state = State::new();
227        builder.position_at_end(return_);
228        let phis: SmallVec<[PhiValue; 1]> = wasm_fn_type
229            .results()
230            .iter()
231            .map(|&wasm_ty| {
232                type_to_llvm(&intrinsics, wasm_ty).map(|ty| builder.build_phi(ty, "").unwrap())
233            })
234            .collect::<Result<_, _>>()?;
235        state.push_block(return_, phis, 0);
236        builder.position_at_end(start_of_code);
237
238        let mut reader = MiddlewareBinaryReader::new_with_offset(
239            function_body.data,
240            function_body.module_offset,
241        );
242        reader.set_middleware_chain(
243            config
244                .middlewares
245                .generate_function_middleware_chain(*local_func_index),
246        );
247
248        let mut params = vec![];
249        let first_param =
250            if func_type.get_return_type().is_none() && wasm_fn_type.results().len() > 1 {
251                if m0_is_enabled { 3 } else { 2 }
252            } else if m0_is_enabled {
253                2
254            } else {
255                1
256            };
257        let mut is_first_alloca = true;
258        let mut insert_alloca = |ty, name: String| -> Result<PointerValue, CompileError> {
259            let alloca = err!(alloca_builder.build_alloca(ty, &name));
260            if is_first_alloca {
261                alloca_builder.position_at(entry, &alloca.as_instruction_value().unwrap());
262                is_first_alloca = false;
263            }
264            Ok(alloca)
265        };
266
267        // Uncomment to print, at the start of the function, the function name.
268        // (poor man's debugger!)
269        //let func_name_str =
270        //    err!(alloca_builder.build_global_string_ptr(&function_name, "function_name"));
271        //
272        //_ = alloca_builder.build_call(
273        //    intrinsics.debug_str,
274        //    &[
275        //        func_name_str.as_pointer_value().into(),
276        //        intrinsics
277        //            .i32_ty
278        //            .const_int(function_name.len() as _, false)
279        //            .into(),
280        //    ],
281        //    "",
282        //);
283
284        for idx in 0..wasm_fn_type.params().len() {
285            let ty = wasm_fn_type.params()[idx];
286            let ty = type_to_llvm(&intrinsics, ty)?;
287            let value = func
288                .get_nth_param((idx as u32).checked_add(first_param).unwrap())
289                .unwrap();
290            let alloca = insert_alloca(ty, format!("param_{idx}"))?;
291            err!(cache_builder.build_store(alloca, value));
292            params.push((ty, alloca));
293        }
294
295        let mut locals = vec![];
296        let num_locals = reader.read_local_count()?;
297        for idx in 0..num_locals {
298            let (count, ty) = reader.read_local_decl()?;
299            let ty = err!(wptype_to_type(ty));
300            let ty = type_to_llvm(&intrinsics, ty)?;
301            for _ in 0..count {
302                let alloca = insert_alloca(ty, format!("local_{idx}"))?;
303                err!(cache_builder.build_store(alloca, ty.const_zero()));
304                locals.push((ty, alloca));
305            }
306        }
307
308        let mut params_locals = params.clone();
309        params_locals.extend(locals.iter().cloned());
310
311        let mut m0_param = None;
312
313        if m0_is_enabled {
314            let m0 = self.abi.get_m0_ptr_param(&func);
315            m0.set_name("m0_base_ptr");
316            m0_param = Some(m0);
317        }
318
319        let mut fcg = LLVMFunctionCodeGenerator {
320            m0_param,
321            context: &self.ctx,
322            builder,
323            alloca_builder,
324            intrinsics: &intrinsics,
325            state,
326            function: func,
327            locals: params_locals,
328            ctx: CtxType::new(
329                wasm_module,
330                &func,
331                &cache_builder,
332                &*self.abi,
333                self.pointer_width,
334                m0_param,
335            ),
336            unreachable_depth: 0,
337            memory_styles,
338            _table_styles,
339            module: &module,
340            module_translation,
341            signature_hashes,
342            wasm_module,
343            symbol_registry,
344            abi: &*self.abi,
345            config,
346            target_triple: self.target_triple.clone(),
347            tags_cache: HashMap::new(),
348            binary_fmt: self.binary_fmt,
349            cpu_features: self.cpu_features,
350            non_volatile_memory_ops: self.non_volatile_memory_ops,
351        };
352
353        fcg.ctx.add_func(
354            func_index,
355            func.as_global_value().as_pointer_value(),
356            func_type,
357            fcg.ctx.basic(),
358            &func_attrs,
359        );
360
361        while fcg.state.has_control_frames() {
362            let pos = reader.current_position() as u32;
363            let op = reader.read_operator()?;
364            fcg.translate_operator(op, pos)?;
365        }
366
367        fcg.finalize(wasm_fn_type)?;
368
369        if let Some(ref callbacks) = config.callbacks {
370            callbacks.preopt_ir(&function, &wasm_module.hash_string(), &module);
371        }
372
373        let mut passes = vec![];
374        if config.enable_verifier {
375            passes.push("verify");
376        }
377
378        match opt_style {
379            OptimizationStyle::Disabled => {
380                passes.push("default<O0>");
381            }
382            OptimizationStyle::ForSize => {
383                // Apparently, the default<Os> could be much slower compared to -O1.
384                passes.push("default<O1>");
385            }
386            OptimizationStyle::ForSpeed => {
387                passes.push("sccp");
388                passes.push("early-cse");
389                //passes.push("deadargelim");
390                passes.push("adce");
391                passes.push("sroa");
392                passes.push("aggressive-instcombine");
393                passes.push("jump-threading");
394                //passes.push("ipsccp");
395                passes.push("simplifycfg");
396                passes.push("reassociate");
397                passes.push("loop-rotate");
398                passes.push("indvars");
399                //passes.push("lcssa");
400                //passes.push("licm");
401                //passes.push("instcombine");
402                passes.push("sccp");
403                passes.push("reassociate");
404                passes.push("simplifycfg");
405                passes.push("gvn");
406                passes.push("memcpyopt");
407                passes.push("dse");
408                passes.push("dce");
409                //passes.push("instcombine");
410                passes.push("reassociate");
411                passes.push("simplifycfg");
412                passes.push("mem2reg");
413            }
414        }
415
416        module
417            .run_passes(
418                &passes.join(","),
419                target_machine,
420                PassBuilderOptions::create(),
421            )
422            .unwrap();
423
424        if let Some(ref callbacks) = config.callbacks {
425            callbacks.postopt_ir(&function, &wasm_module.hash_string(), &module);
426        }
427
428        Ok(module)
429    }
430
431    #[allow(clippy::too_many_arguments)]
432    pub fn translate(
433        &self,
434        wasm_module: &ModuleInfo,
435        module_translation: &ModuleTranslationState,
436        signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
437        local_func_index: &LocalFunctionIndex,
438        function_body: &FunctionBodyData,
439        config: &LLVM,
440        memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
441        table_styles: &PrimaryMap<TableIndex, TableStyle>,
442        symbol_registry: &ModuleBasedSymbolRegistry,
443        target: &Triple,
444    ) -> Result<CompiledFunction, CompileError> {
445        let func_index = wasm_module.func_index(*local_func_index);
446        let opt_style = if Some(func_index) == self.wasm_apply_data_relocs_fn_index {
447            // `__wasm_apply_data_relocs` can become a very large function made up
448            // mostly of loads and stores, and even `-O1` can spend significant
449            // time optimizing it.
450            OptimizationStyle::Disabled
451        } else if function_body.data.len() as u64 > WASM_LARGE_FUNCTION_THRESHOLD {
452            OptimizationStyle::ForSize
453        } else {
454            OptimizationStyle::ForSpeed
455        };
456        let module = self.translate_to_module(
457            wasm_module,
458            module_translation,
459            signature_hashes,
460            local_func_index,
461            function_body,
462            config,
463            memory_styles,
464            table_styles,
465            symbol_registry,
466            target,
467            opt_style,
468        )?;
469        let function =
470            CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
471
472        let target_machine = self.target_machines.get(&opt_style).unwrap();
473        let memory_buffer = target_machine
474            .write_to_memory_buffer(&module, FileType::Object)
475            .unwrap();
476
477        if let Some(ref callbacks) = config.callbacks {
478            let module_hash = wasm_module.hash().map(|m| m.to_string());
479            callbacks.obj_memory_buffer(&function, &module_hash, &memory_buffer);
480            let asm_buffer = target_machine
481                .write_to_memory_buffer(&module, FileType::Assembly)
482                .unwrap();
483            callbacks.asm_memory_buffer(&function, &module_hash, &asm_buffer)
484        }
485
486        let mem_buf_slice = memory_buffer.as_slice();
487
488        load_object_file(
489            mem_buf_slice,
490            &self.func_section,
491            RelocationTarget::LocalFunc(*local_func_index),
492            |name: &str| {
493                Ok({
494                    let name = if matches!(self.binary_fmt, BinaryFormat::Macho) {
495                        name.strip_prefix("_").unwrap_or(name)
496                    } else {
497                        name
498                    }
499                    .to_string();
500                    if let Some(Symbol::LocalFunction(local_func_index)) =
501                        symbol_registry.name_to_symbol(&name)
502                    {
503                        Some(RelocationTarget::LocalFunc(local_func_index))
504                    } else {
505                        None
506                    }
507                })
508            },
509            self.binary_fmt,
510        )
511    }
512}
513
514impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
515    // Create a vector where each lane contains the same value.
516    fn splat_vector(
517        &self,
518        value: BasicValueEnum<'ctx>,
519        vec_ty: VectorType<'ctx>,
520    ) -> Result<VectorValue<'ctx>, CompileError> {
521        // Use insert_element to insert the element into an undef vector, then use
522        // shuffle vector to copy that lane to all lanes.
523        err_nt!(
524            self.builder.build_shuffle_vector(
525                err!(self.builder.build_insert_element(
526                    vec_ty.get_undef(),
527                    value,
528                    self.intrinsics.i32_zero,
529                    "",
530                )),
531                vec_ty.get_undef(),
532                self.intrinsics
533                    .i32_ty
534                    .vec_type(vec_ty.get_size())
535                    .const_zero(),
536                "",
537            )
538        )
539    }
540
541    // Convert floating point vector to integer and saturate when out of range.
542    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
543    #[allow(clippy::too_many_arguments)]
544    fn trunc_sat<T: FloatMathType<'ctx>>(
545        &self,
546        fvec_ty: T,
547        ivec_ty: T::MathConvType,
548        lower_bound: u64, // Exclusive (least representable value)
549        upper_bound: u64, // Exclusive (greatest representable value)
550        int_min_value: u64,
551        int_max_value: u64,
552        value: IntValue<'ctx>,
553    ) -> Result<VectorValue<'ctx>, CompileError> {
554        // a) Compare vector with itself to identify NaN lanes.
555        // b) Compare vector with splat of inttofp(upper_bound) to identify
556        //    lanes that need to saturate to max.
557        // c) Compare vector with splat of inttofp(lower_bound) to identify
558        //    lanes that need to saturate to min.
559        // d) Use vector select (not shuffle) to pick from either the
560        //    splat vector or the input vector depending on whether the
561        //    comparison indicates that we have an unrepresentable value. Replace
562        //    unrepresentable values with zero.
563        // e) Now that the value is safe, fpto[su]i it.
564        // f) Use our previous comparison results to replace certain zeros with
565        //    int_min or int_max.
566
567        let fvec_ty = fvec_ty.as_basic_type_enum().into_vector_type();
568        let ivec_ty = ivec_ty.as_basic_type_enum().into_vector_type();
569        let fvec_element_ty = fvec_ty.get_element_type().into_float_type();
570        let ivec_element_ty = ivec_ty.get_element_type().into_int_type();
571
572        let is_signed = int_min_value != 0;
573        let int_min_value = self.splat_vector(
574            ivec_element_ty
575                .const_int(int_min_value, is_signed)
576                .as_basic_value_enum(),
577            ivec_ty,
578        )?;
579        let int_max_value = self.splat_vector(
580            ivec_element_ty
581                .const_int(int_max_value, is_signed)
582                .as_basic_value_enum(),
583            ivec_ty,
584        )?;
585        let lower_bound = if is_signed {
586            err!(self.builder.build_signed_int_to_float(
587                ivec_element_ty.const_int(lower_bound, is_signed),
588                fvec_element_ty,
589                "",
590            ))
591        } else {
592            err!(self.builder.build_unsigned_int_to_float(
593                ivec_element_ty.const_int(lower_bound, is_signed),
594                fvec_element_ty,
595                "",
596            ))
597        };
598        let upper_bound = if is_signed {
599            err!(self.builder.build_signed_int_to_float(
600                ivec_element_ty.const_int(upper_bound, is_signed),
601                fvec_element_ty,
602                "",
603            ))
604        } else {
605            err!(self.builder.build_unsigned_int_to_float(
606                ivec_element_ty.const_int(upper_bound, is_signed),
607                fvec_element_ty,
608                "",
609            ))
610        };
611
612        let value = err!(self.builder.build_bit_cast(value, fvec_ty, "")).into_vector_value();
613        let zero = fvec_ty.const_zero();
614        let lower_bound = self.splat_vector(lower_bound.as_basic_value_enum(), fvec_ty)?;
615        let upper_bound = self.splat_vector(upper_bound.as_basic_value_enum(), fvec_ty)?;
616        let nan_cmp =
617            err!(
618                self.builder
619                    .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
620            );
621        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
622            FloatPredicate::OGT,
623            value,
624            upper_bound,
625            "above_upper_bound",
626        ));
627        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
628            FloatPredicate::OLT,
629            value,
630            lower_bound,
631            "below_lower_bound",
632        ));
633        let not_representable = err!(self.builder.build_or(
634            err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
635            below_lower_bound_cmp,
636            "not_representable_as_int",
637        ));
638        let value =
639            err!(
640                self.builder
641                    .build_select(not_representable, zero, value, "safe_to_convert")
642            )
643            .into_vector_value();
644        let value = if is_signed {
645            self.builder
646                .build_float_to_signed_int(value, ivec_ty, "as_int")
647        } else {
648            self.builder
649                .build_float_to_unsigned_int(value, ivec_ty, "as_int")
650        };
651
652        let value = err!(value);
653        let value =
654            err!(
655                self.builder
656                    .build_select(above_upper_bound_cmp, int_max_value, value, "")
657            )
658            .into_vector_value();
659        err_nt!(
660            self.builder
661                .build_select(below_lower_bound_cmp, int_min_value, value, "")
662                .map(|v| v.into_vector_value())
663        )
664    }
665
666    // Convert floating point vector to integer and saturate when out of range.
667    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
668    #[allow(clippy::too_many_arguments)]
669    fn trunc_sat_into_int<T: FloatMathType<'ctx>>(
670        &self,
671        fvec_ty: T,
672        ivec_ty: T::MathConvType,
673        lower_bound: u64, // Exclusive (least representable value)
674        upper_bound: u64, // Exclusive (greatest representable value)
675        int_min_value: u64,
676        int_max_value: u64,
677        value: IntValue<'ctx>,
678    ) -> Result<IntValue<'ctx>, CompileError> {
679        let res = self.trunc_sat(
680            fvec_ty,
681            ivec_ty,
682            lower_bound,
683            upper_bound,
684            int_min_value,
685            int_max_value,
686            value,
687        )?;
688        err_nt!(
689            self.builder
690                .build_bit_cast(res, self.intrinsics.i128_ty, "")
691                .map(|v| v.into_int_value())
692        )
693    }
694
695    // Convert floating point vector to integer and saturate when out of range.
696    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
697    fn trunc_sat_scalar(
698        &self,
699        int_ty: IntType<'ctx>,
700        lower_bound: u64, // Exclusive (least representable value)
701        upper_bound: u64, // Exclusive (greatest representable value)
702        int_min_value: u64,
703        int_max_value: u64,
704        value: FloatValue<'ctx>,
705    ) -> Result<IntValue<'ctx>, CompileError> {
706        // TODO: this is a scalarized version of the process in trunc_sat. Either
707        // we should merge with trunc_sat, or we should simplify this function.
708
709        // a) Compare value with itself to identify NaN.
710        // b) Compare value inttofp(upper_bound) to identify values that need to
711        //    saturate to max.
712        // c) Compare value with inttofp(lower_bound) to identify values that need
713        //    to saturate to min.
714        // d) Use select to pick from either zero or the input vector depending on
715        //    whether the comparison indicates that we have an unrepresentable
716        //    value.
717        // e) Now that the value is safe, fpto[su]i it.
718        // f) Use our previous comparison results to replace certain zeros with
719        //    int_min or int_max.
720
721        let is_signed = int_min_value != 0;
722        let int_min_value = int_ty.const_int(int_min_value, is_signed);
723        let int_max_value = int_ty.const_int(int_max_value, is_signed);
724
725        let lower_bound = if is_signed {
726            err!(self.builder.build_signed_int_to_float(
727                int_ty.const_int(lower_bound, is_signed),
728                value.get_type(),
729                "",
730            ))
731        } else {
732            err!(self.builder.build_unsigned_int_to_float(
733                int_ty.const_int(lower_bound, is_signed),
734                value.get_type(),
735                "",
736            ))
737        };
738        let upper_bound = if is_signed {
739            err!(self.builder.build_signed_int_to_float(
740                int_ty.const_int(upper_bound, is_signed),
741                value.get_type(),
742                "",
743            ))
744        } else {
745            err!(self.builder.build_unsigned_int_to_float(
746                int_ty.const_int(upper_bound, is_signed),
747                value.get_type(),
748                "",
749            ))
750        };
751
752        let zero = value.get_type().const_zero();
753
754        let nan_cmp =
755            err!(
756                self.builder
757                    .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
758            );
759        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
760            FloatPredicate::OGT,
761            value,
762            upper_bound,
763            "above_upper_bound",
764        ));
765        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
766            FloatPredicate::OLT,
767            value,
768            lower_bound,
769            "below_lower_bound",
770        ));
771        let not_representable = err!(self.builder.build_or(
772            err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
773            below_lower_bound_cmp,
774            "not_representable_as_int",
775        ));
776        let value =
777            err!(
778                self.builder
779                    .build_select(not_representable, zero, value, "safe_to_convert")
780            )
781            .into_float_value();
782        let value = if is_signed {
783            err!(
784                self.builder
785                    .build_float_to_signed_int(value, int_ty, "as_int")
786            )
787        } else {
788            err!(
789                self.builder
790                    .build_float_to_unsigned_int(value, int_ty, "as_int")
791            )
792        };
793        let value =
794            err!(
795                self.builder
796                    .build_select(above_upper_bound_cmp, int_max_value, value, "")
797            )
798            .into_int_value();
799        let value =
800            err!(
801                self.builder
802                    .build_select(below_lower_bound_cmp, int_min_value, value, "")
803            )
804            .into_int_value();
805
806        err_nt!(
807            self.builder
808                .build_bit_cast(value, int_ty, "")
809                .map(|v| v.into_int_value())
810        )
811    }
812
813    fn trap_if_not_representable_as_int(
814        &self,
815        lower_bound: u64, // Inclusive (not a trapping value)
816        upper_bound: u64, // Inclusive (not a trapping value)
817        value: FloatValue<'ctx>,
818    ) -> Result<(), CompileError> {
819        let float_ty = value.get_type();
820        let int_ty = if float_ty == self.intrinsics.f32_ty {
821            self.intrinsics.i32_ty
822        } else {
823            self.intrinsics.i64_ty
824        };
825
826        let lower_bound = err!(self.builder.build_bit_cast(
827            int_ty.const_int(lower_bound, false),
828            float_ty,
829            ""
830        ))
831        .into_float_value();
832        let upper_bound = err!(self.builder.build_bit_cast(
833            int_ty.const_int(upper_bound, false),
834            float_ty,
835            ""
836        ))
837        .into_float_value();
838
839        // The 'U' in the float predicate is short for "unordered" which means that
840        // the comparison will compare true if either operand is a NaN. Thus, NaNs
841        // are out of bounds.
842        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
843            FloatPredicate::UGT,
844            value,
845            upper_bound,
846            "above_upper_bound",
847        ));
848        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
849            FloatPredicate::ULT,
850            value,
851            lower_bound,
852            "below_lower_bound",
853        ));
854        let out_of_bounds = err!(self.builder.build_or(
855            above_upper_bound_cmp,
856            below_lower_bound_cmp,
857            "out_of_bounds",
858        ));
859
860        let failure_block = self
861            .context
862            .append_basic_block(self.function, "conversion_failure_block");
863        let continue_block = self
864            .context
865            .append_basic_block(self.function, "conversion_success_block");
866
867        err!(
868            self.builder
869                .build_conditional_branch(out_of_bounds, failure_block, continue_block)
870        );
871        self.builder.position_at_end(failure_block);
872        let is_nan =
873            err!(
874                self.builder
875                    .build_float_compare(FloatPredicate::UNO, value, value, "is_nan")
876            );
877        let trap_code = err!(self.builder.build_select(
878            is_nan,
879            self.intrinsics.trap_bad_conversion_to_integer,
880            self.intrinsics.trap_illegal_arithmetic,
881            "",
882        ));
883        self.build_call_with_param_attributes(
884            self.intrinsics.throw_trap,
885            &[trap_code.into()],
886            "throw",
887        )?;
888        err!(self.builder.build_unreachable());
889        self.builder.position_at_end(continue_block);
890
891        Ok(())
892    }
893
894    fn trap_if_zero_or_overflow(
895        &self,
896        left: IntValue<'ctx>,
897        right: IntValue<'ctx>,
898    ) -> Result<(), CompileError> {
899        let int_type = left.get_type();
900
901        let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
902            let min_value = int_type.const_int(i32::MIN as u64, false);
903            let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
904            (min_value, neg_one_value)
905        } else if int_type == self.intrinsics.i64_ty {
906            let min_value = int_type.const_int(i64::MIN as u64, false);
907            let neg_one_value = int_type.const_int(-1i64 as u64, false);
908            (min_value, neg_one_value)
909        } else {
910            unreachable!()
911        };
912
913        let divisor_is_zero = err!(self.builder.build_int_compare(
914            IntPredicate::EQ,
915            right,
916            int_type.const_zero(),
917            "divisor_is_zero",
918        ));
919        let should_trap = err!(self.builder.build_or(
920            divisor_is_zero,
921            err!(self.builder.build_and(
922                err!(self.builder.build_int_compare(
923                    IntPredicate::EQ,
924                    left,
925                    min_value,
926                    "left_is_min"
927                )),
928                err!(self.builder.build_int_compare(
929                    IntPredicate::EQ,
930                    right,
931                    neg_one_value,
932                    "right_is_neg_one",
933                )),
934                "div_will_overflow",
935            )),
936            "div_should_trap",
937        ));
938
939        let should_trap = self
940            .build_call_with_param_attributes(
941                self.intrinsics.expect_i1,
942                &[
943                    should_trap.into(),
944                    self.intrinsics.i1_ty.const_zero().into(),
945                ],
946                "should_trap_expect",
947            )?
948            .try_as_basic_value()
949            .unwrap_basic()
950            .into_int_value();
951
952        let shouldnt_trap_block = self
953            .context
954            .append_basic_block(self.function, "shouldnt_trap_block");
955        let should_trap_block = self
956            .context
957            .append_basic_block(self.function, "should_trap_block");
958        err!(self.builder.build_conditional_branch(
959            should_trap,
960            should_trap_block,
961            shouldnt_trap_block
962        ));
963        self.builder.position_at_end(should_trap_block);
964        let trap_code = err!(self.builder.build_select(
965            divisor_is_zero,
966            self.intrinsics.trap_integer_division_by_zero,
967            self.intrinsics.trap_illegal_arithmetic,
968            "",
969        ));
970        err!(
971            self.builder
972                .build_call(self.intrinsics.throw_trap, &[trap_code.into()], "throw")
973        );
974        err!(self.builder.build_unreachable());
975        self.builder.position_at_end(shouldnt_trap_block);
976
977        Ok(())
978    }
979
980    fn trap_if_zero(&self, value: IntValue<'ctx>) -> Result<(), CompileError> {
981        let int_type = value.get_type();
982        let should_trap = err!(self.builder.build_int_compare(
983            IntPredicate::EQ,
984            value,
985            int_type.const_zero(),
986            "divisor_is_zero",
987        ));
988
989        let should_trap = self
990            .build_call_with_param_attributes(
991                self.intrinsics.expect_i1,
992                &[
993                    should_trap.into(),
994                    self.intrinsics.i1_ty.const_zero().into(),
995                ],
996                "should_trap_expect",
997            )?
998            .try_as_basic_value()
999            .unwrap_basic()
1000            .into_int_value();
1001
1002        let shouldnt_trap_block = self
1003            .context
1004            .append_basic_block(self.function, "shouldnt_trap_block");
1005        let should_trap_block = self
1006            .context
1007            .append_basic_block(self.function, "should_trap_block");
1008        err!(self.builder.build_conditional_branch(
1009            should_trap,
1010            should_trap_block,
1011            shouldnt_trap_block
1012        ));
1013        self.builder.position_at_end(should_trap_block);
1014        self.build_call_with_param_attributes(
1015            self.intrinsics.throw_trap,
1016            &[self.intrinsics.trap_integer_division_by_zero.into()],
1017            "throw",
1018        )?;
1019        err!(self.builder.build_unreachable());
1020        self.builder.position_at_end(shouldnt_trap_block);
1021
1022        Ok(())
1023    }
1024
1025    fn v128_into_int_vec(
1026        &self,
1027        value: BasicValueEnum<'ctx>,
1028        info: ExtraInfo,
1029        int_vec_ty: VectorType<'ctx>,
1030    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1031        let (value, info) = if self.config.enable_nan_canonicalization {
1032            if info.has_pending_f32_nan() {
1033                let value = err!(
1034                    self.builder
1035                        .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1036                );
1037                (self.canonicalize_nans(value)?, info.strip_pending())
1038            } else if info.has_pending_f64_nan() {
1039                let value = err!(
1040                    self.builder
1041                        .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1042                );
1043                (self.canonicalize_nans(value)?, info.strip_pending())
1044            } else {
1045                (value, info)
1046            }
1047        } else {
1048            (value, info)
1049        };
1050        Ok((
1051            err!(self.builder.build_bit_cast(value, int_vec_ty, "")).into_vector_value(),
1052            info,
1053        ))
1054    }
1055
1056    fn v128_into_i8x16(
1057        &self,
1058        value: BasicValueEnum<'ctx>,
1059        info: ExtraInfo,
1060    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1061        self.v128_into_int_vec(value, info, self.intrinsics.i8x16_ty)
1062    }
1063
1064    fn v128_into_i16x8(
1065        &self,
1066        value: BasicValueEnum<'ctx>,
1067        info: ExtraInfo,
1068    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1069        self.v128_into_int_vec(value, info, self.intrinsics.i16x8_ty)
1070    }
1071
1072    fn v128_into_i32x4(
1073        &self,
1074        value: BasicValueEnum<'ctx>,
1075        info: ExtraInfo,
1076    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1077        self.v128_into_int_vec(value, info, self.intrinsics.i32x4_ty)
1078    }
1079
1080    fn v128_into_i64x2(
1081        &self,
1082        value: BasicValueEnum<'ctx>,
1083        info: ExtraInfo,
1084    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1085        self.v128_into_int_vec(value, info, self.intrinsics.i64x2_ty)
1086    }
1087
1088    // If the value is pending a 64-bit canonicalization, do it now.
1089    // Return a f32x4 vector.
1090    fn v128_into_f32x4(
1091        &self,
1092        value: BasicValueEnum<'ctx>,
1093        info: ExtraInfo,
1094    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1095        let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f64_nan()
1096        {
1097            let value = err!(
1098                self.builder
1099                    .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1100            );
1101            (self.canonicalize_nans(value)?, info.strip_pending())
1102        } else {
1103            (value, info)
1104        };
1105        Ok((
1106            err!(
1107                self.builder
1108                    .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1109            )
1110            .into_vector_value(),
1111            info,
1112        ))
1113    }
1114
1115    // If the value is pending a 32-bit canonicalization, do it now.
1116    // Return a f64x2 vector.
1117    fn v128_into_f64x2(
1118        &self,
1119        value: BasicValueEnum<'ctx>,
1120        info: ExtraInfo,
1121    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1122        let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f32_nan()
1123        {
1124            let value = err!(
1125                self.builder
1126                    .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1127            );
1128            (self.canonicalize_nans(value)?, info.strip_pending())
1129        } else {
1130            (value, info)
1131        };
1132        Ok((
1133            err!(
1134                self.builder
1135                    .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1136            )
1137            .into_vector_value(),
1138            info,
1139        ))
1140    }
1141
1142    fn apply_pending_canonicalization(
1143        &self,
1144        value: BasicValueEnum<'ctx>,
1145        info: ExtraInfo,
1146    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1147        if !self.config.enable_nan_canonicalization {
1148            return Ok(value);
1149        }
1150
1151        if info.has_pending_f32_nan() {
1152            if value.get_type().is_vector_type()
1153                || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1154            {
1155                let ty = value.get_type();
1156                let value = err!(
1157                    self.builder
1158                        .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1159                );
1160                let value = self.canonicalize_nans(value)?;
1161                err_nt!(self.builder.build_bit_cast(value, ty, ""))
1162            } else {
1163                self.canonicalize_nans(value)
1164            }
1165        } else if info.has_pending_f64_nan() {
1166            if value.get_type().is_vector_type()
1167                || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1168            {
1169                let ty = value.get_type();
1170                let value = err!(
1171                    self.builder
1172                        .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1173                );
1174                let value = self.canonicalize_nans(value)?;
1175                err_nt!(self.builder.build_bit_cast(value, ty, ""))
1176            } else {
1177                self.canonicalize_nans(value)
1178            }
1179        } else {
1180            Ok(value)
1181        }
1182    }
1183
1184    // Replaces any NaN with the canonical QNaN, otherwise leaves the value alone.
1185    fn canonicalize_nans(
1186        &self,
1187        value: BasicValueEnum<'ctx>,
1188    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1189        if !self.config.enable_nan_canonicalization {
1190            return Ok(value);
1191        }
1192
1193        let f_ty = value.get_type();
1194        if f_ty.is_vector_type() {
1195            let value = value.into_vector_value();
1196            let f_ty = f_ty.into_vector_type();
1197            let zero = f_ty.const_zero();
1198            let nan_cmp =
1199                err!(
1200                    self.builder
1201                        .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1202                );
1203            let canonical_qnan = f_ty
1204                .get_element_type()
1205                .into_float_type()
1206                .const_float(f64::NAN);
1207            let canonical_qnan = self.splat_vector(canonical_qnan.as_basic_value_enum(), f_ty)?;
1208            err_nt!(
1209                self.builder
1210                    .build_select(nan_cmp, canonical_qnan, value, "")
1211                    .map(|v| v.as_basic_value_enum())
1212            )
1213        } else {
1214            let value = value.into_float_value();
1215            let f_ty = f_ty.into_float_type();
1216            let zero = f_ty.const_zero();
1217            let nan_cmp =
1218                err!(
1219                    self.builder
1220                        .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1221                );
1222            let canonical_qnan = f_ty.const_float(f64::NAN);
1223            err_nt!(
1224                self.builder
1225                    .build_select(nan_cmp, canonical_qnan, value, "")
1226                    .map(|v| v.as_basic_value_enum())
1227            )
1228        }
1229    }
1230
1231    // If this memory access must trap when out of bounds (i.e. it is a memory
1232    // access written in the user program as opposed to one used by our VM)
1233    // then mark that it can't be delete.
1234    fn mark_memaccess_nodelete(
1235        &mut self,
1236        memory_index: MemoryIndex,
1237        memaccess: InstructionValue<'ctx>,
1238    ) -> Result<(), CompileError> {
1239        if let MemoryCache::Static { base_ptr: _ } = self.ctx.memory(
1240            memory_index,
1241            self.intrinsics,
1242            self.module,
1243            self.memory_styles,
1244        )? {
1245            // The best we've got is `volatile`.
1246            memaccess.set_volatile(true).map_err(|err| {
1247                CompileError::Codegen(format!("could not set volatile on memory operation: {err}"))
1248            })
1249        } else {
1250            Ok(())
1251        }
1252    }
1253
1254    fn annotate_user_memaccess(
1255        &mut self,
1256        memory_index: MemoryIndex,
1257        _memarg: &MemArg,
1258        alignment: u32,
1259        memaccess: InstructionValue<'ctx>,
1260    ) -> Result<(), CompileError> {
1261        match memaccess.get_opcode() {
1262            InstructionOpcode::Load | InstructionOpcode::Store => {
1263                memaccess.set_alignment(alignment).unwrap();
1264            }
1265            _ => {}
1266        };
1267        if !self.non_volatile_memory_ops {
1268            self.mark_memaccess_nodelete(memory_index, memaccess)?;
1269        }
1270        tbaa_label(
1271            self.module,
1272            self.intrinsics,
1273            format!("memory {}", memory_index.as_u32()),
1274            memaccess,
1275        );
1276        Ok(())
1277    }
1278
1279    fn resolve_memory_ptr(
1280        &mut self,
1281        memory_index: MemoryIndex,
1282        memarg: &MemArg,
1283        ptr_ty: PointerType<'ctx>,
1284        var_offset: IntValue<'ctx>,
1285        value_size: usize,
1286    ) -> Result<PointerValue<'ctx>, CompileError> {
1287        let builder = &self.builder;
1288        let intrinsics = &self.intrinsics;
1289        let context = &self.context;
1290        let function = &self.function;
1291
1292        // Compute the offset into the storage.
1293        let imm_offset = intrinsics.i64_ty.const_int(memarg.offset, false);
1294        let var_offset = err!(builder.build_int_z_extend(var_offset, intrinsics.i64_ty, ""));
1295        let offset = err!(builder.build_int_add(var_offset, imm_offset, ""));
1296
1297        // Look up the memory base (as pointer) and bounds (as unsigned integer).
1298        let base_ptr = if let Some(m0) = self.m0_param {
1299            m0
1300        } else {
1301            match self
1302                .ctx
1303                .memory(memory_index, intrinsics, self.module, self.memory_styles)?
1304            {
1305                MemoryCache::Dynamic {
1306                    ptr_to_base_ptr,
1307                    ptr_to_current_length,
1308                } => {
1309                    // Bounds check it.
1310                    let minimum = self.wasm_module.memories[memory_index].minimum;
1311                    let value_size_v = intrinsics.i64_ty.const_int(value_size as u64, false);
1312                    let ptr_in_bounds = if offset.is_const() {
1313                        // When the offset is constant, if it's below the minimum
1314                        // memory size, we've statically shown that it's safe.
1315                        let load_offset_end =
1316                            offset.const_add(value_size_v).get_zero_extended_constant();
1317                        if load_offset_end.is_some_and(|load_offset_end| {
1318                            load_offset_end <= minimum.bytes().0 as u64
1319                        }) {
1320                            Some(intrinsics.i64_ty.const_int(1, false))
1321                        } else {
1322                            None
1323                        }
1324                    } else {
1325                        None
1326                    };
1327
1328                    let ptr_in_bounds = match ptr_in_bounds {
1329                        Some(ptr) => ptr,
1330                        None => {
1331                            let load_offset_end = err!(builder.build_int_add(
1332                                offset,
1333                                value_size_v,
1334                                "load_offset_end"
1335                            ));
1336
1337                            let current_length = err!(builder.build_load(
1338                                self.intrinsics.i32_ty,
1339                                ptr_to_current_length,
1340                                "current_length"
1341                            ))
1342                            .into_int_value();
1343                            tbaa_label(
1344                                self.module,
1345                                self.intrinsics,
1346                                format!("memory {} length", memory_index.as_u32()),
1347                                current_length.as_instruction_value().unwrap(),
1348                            );
1349                            let current_length = err!(builder.build_int_z_extend(
1350                                current_length,
1351                                intrinsics.i64_ty,
1352                                "current_length_zextd"
1353                            ));
1354
1355                            err!(builder.build_int_compare(
1356                                IntPredicate::ULE,
1357                                load_offset_end,
1358                                current_length,
1359                                "ptr_in_bounds",
1360                            ))
1361                        }
1362                    };
1363
1364                    if !ptr_in_bounds.is_constant_int()
1365                        || ptr_in_bounds.get_zero_extended_constant().unwrap() != 1
1366                    {
1367                        // LLVM may have folded this into 'i1 true' in which case we know
1368                        // the pointer is in bounds. LLVM may also have folded it into a
1369                        // constant expression, not known to be either true or false yet.
1370                        // If it's false, unknown-but-constant, or not-a-constant, emit a
1371                        // runtime bounds check. LLVM may yet succeed at optimizing it away.
1372                        let ptr_in_bounds = err!(self.build_call_with_param_attributes(
1373                            intrinsics.expect_i1,
1374                            &[
1375                                ptr_in_bounds.into(),
1376                                intrinsics.i1_ty.const_int(1, true).into(),
1377                            ],
1378                            "ptr_in_bounds_expect",
1379                        ))
1380                        .try_as_basic_value()
1381                        .unwrap_basic()
1382                        .into_int_value();
1383
1384                        let in_bounds_continue_block =
1385                            context.append_basic_block(*function, "in_bounds_continue_block");
1386                        let not_in_bounds_block =
1387                            context.append_basic_block(*function, "not_in_bounds_block");
1388                        err!(builder.build_conditional_branch(
1389                            ptr_in_bounds,
1390                            in_bounds_continue_block,
1391                            not_in_bounds_block,
1392                        ));
1393                        builder.position_at_end(not_in_bounds_block);
1394                        err!(self.build_call_with_param_attributes(
1395                            intrinsics.throw_trap,
1396                            &[intrinsics.trap_memory_oob.into()],
1397                            "throw",
1398                        ));
1399                        err!(builder.build_unreachable());
1400                        builder.position_at_end(in_bounds_continue_block);
1401                    }
1402                    let ptr_to_base =
1403                        err!(builder.build_load(intrinsics.ptr_ty, ptr_to_base_ptr, "ptr_to_base"))
1404                            .into_pointer_value();
1405                    tbaa_label(
1406                        self.module,
1407                        self.intrinsics,
1408                        format!("memory base_ptr {}", memory_index.as_u32()),
1409                        ptr_to_base.as_instruction_value().unwrap(),
1410                    );
1411                    ptr_to_base
1412                }
1413                MemoryCache::Static { base_ptr } => base_ptr,
1414            }
1415        };
1416        let value_ptr = unsafe {
1417            err!(builder.build_gep(self.intrinsics.i8_ty, base_ptr, &[offset], "mem_value_ptr"))
1418        };
1419        err_nt!(
1420            builder
1421                .build_bit_cast(value_ptr, ptr_ty, "mem_value")
1422                .map(|v| v.into_pointer_value())
1423        )
1424    }
1425
1426    fn trap_if_misaligned(
1427        &self,
1428        _memarg: &MemArg,
1429        ptr: PointerValue<'ctx>,
1430        align: u8,
1431    ) -> Result<(), CompileError> {
1432        if align <= 1 {
1433            return Ok(());
1434        }
1435        let value = err!(self.builder.build_ptr_to_int(
1436            ptr,
1437            self.intrinsics.i64_ty,
1438            "mischeck_value"
1439        ));
1440        let and = err!(self.builder.build_and(
1441            value,
1442            self.intrinsics.i64_ty.const_int((align - 1).into(), false),
1443            "misaligncheck",
1444        ));
1445        let aligned = err!(self.builder.build_int_compare(
1446            IntPredicate::EQ,
1447            and,
1448            self.intrinsics.i64_zero,
1449            "is_aligned"
1450        ));
1451        let aligned = self
1452            .build_call_with_param_attributes(
1453                self.intrinsics.expect_i1,
1454                &[
1455                    aligned.into(),
1456                    self.intrinsics.i1_ty.const_int(1, false).into(),
1457                ],
1458                "is_aligned_expect",
1459            )?
1460            .try_as_basic_value()
1461            .unwrap_basic()
1462            .into_int_value();
1463
1464        let continue_block = self
1465            .context
1466            .append_basic_block(self.function, "aligned_access_continue_block");
1467        let not_aligned_block = self
1468            .context
1469            .append_basic_block(self.function, "misaligned_trap_block");
1470        err!(
1471            self.builder
1472                .build_conditional_branch(aligned, continue_block, not_aligned_block)
1473        );
1474
1475        self.builder.position_at_end(not_aligned_block);
1476        self.build_call_with_param_attributes(
1477            self.intrinsics.throw_trap,
1478            &[self.intrinsics.trap_unaligned_atomic.into()],
1479            "throw",
1480        )?;
1481        err!(self.builder.build_unreachable());
1482
1483        self.builder.position_at_end(continue_block);
1484        Ok(())
1485    }
1486
1487    fn finalize(&mut self, wasm_fn_type: &FunctionType) -> Result<(), CompileError> {
1488        let func_type = self.function.get_type();
1489
1490        let results = self.state.popn_save_extra(wasm_fn_type.results().len())?;
1491        let results = err!(
1492            results
1493                .into_iter()
1494                .map(|(v, i)| self.apply_pending_canonicalization(v, i))
1495                .collect::<Result<Vec<_>, _>>()
1496        );
1497
1498        if wasm_fn_type.results().is_empty() {
1499            err!(self.builder.build_return(None));
1500        } else if self.abi.is_sret(wasm_fn_type)? {
1501            let sret = self
1502                .function
1503                .get_first_param()
1504                .unwrap()
1505                .into_pointer_value();
1506            let llvm_params: Vec<_> = wasm_fn_type
1507                .results()
1508                .iter()
1509                .map(|x| type_to_llvm(self.intrinsics, *x).unwrap())
1510                .collect();
1511            let mut struct_value = self
1512                .context
1513                .struct_type(llvm_params.as_slice(), false)
1514                .get_undef();
1515            for (idx, value) in results.into_iter().enumerate() {
1516                let value = err!(self.builder.build_bit_cast(
1517                    value,
1518                    type_to_llvm(self.intrinsics, wasm_fn_type.results()[idx])?,
1519                    "",
1520                ));
1521                struct_value =
1522                    err!(
1523                        self.builder
1524                            .build_insert_value(struct_value, value, idx as u32, "")
1525                    )
1526                    .into_struct_value();
1527            }
1528            err!(self.builder.build_store(sret, struct_value));
1529            err!(self.builder.build_return(None));
1530        } else {
1531            err!(
1532                self.builder
1533                    .build_return(Some(&self.abi.pack_values_for_register_return(
1534                        self.intrinsics,
1535                        &self.builder,
1536                        &results,
1537                        &func_type,
1538                    )?))
1539            );
1540        }
1541        Ok(())
1542    }
1543
1544    // Generates a global constant with the tag's module-local index, which can be used
1545    // as the "type info" of a catch clause.
1546    fn get_or_insert_tag_type_info_global(&mut self, tag: i32) -> BasicValueEnum<'ctx> {
1547        if let Some(tag) = self.tags_cache.get(&tag) {
1548            return *tag;
1549        }
1550
1551        let tag_ty = self
1552            .context
1553            .struct_type(&[self.intrinsics.i32_ty.into()], false);
1554        let tag_glbl = self.module.add_global(
1555            tag_ty,
1556            Some(AddressSpace::default()),
1557            &format!("__wasmer_eh_type_info_{tag}"),
1558        );
1559        tag_glbl.set_initializer(
1560            &tag_ty
1561                .const_named_struct(&[self.intrinsics.i32_ty.const_int(tag as _, false).into()])
1562                .as_basic_value_enum(),
1563        );
1564
1565        tag_glbl.set_linkage(Linkage::External);
1566        tag_glbl.set_constant(true);
1567        // Why set this to a specific section? On macOS it would land on a specifc read only data
1568        // section. GOT-based relocations will probably be generated with a non-zero addend, making
1569        // some EH-related intricacies not working.
1570        //
1571        // The general idea is that each tag has its own section, so the GOT-based relocation can
1572        // have a zero addend, i.e. the data of the tag is the first (and only) value in a specific
1573        // section we can target in relocations.
1574        if matches!(self.binary_fmt, target_lexicon::BinaryFormat::Macho) {
1575            tag_glbl.set_section(Some(&format!("{FUNCTION_SECTION_MACHO},_eh_ti_{tag}")));
1576        }
1577
1578        let tag_glbl = tag_glbl.as_basic_value_enum();
1579
1580        self.tags_cache.insert(tag, tag_glbl);
1581        tag_glbl
1582    }
1583
1584    fn emit_return_call(
1585        &mut self,
1586        call_site: CallSiteValue<'ctx>,
1587        callee_llvm_func_type: inkwell::types::FunctionType<'ctx>,
1588    ) -> Result<(), CompileError> {
1589        // This is an unintuitive spec corner case: a tail call must bypass all enclosing
1590        // try_table blocks in the function. See https://github.com/WebAssembly/exception-handling/issues/249.
1591        //
1592        // The LLVM MustTail is more restrictive than the one defined in the WebAssembly spec.
1593        // WebAssembly types alone are not enough here: the lowered ABI can add hidden arguments
1594        // like `m0` and `sret`, so we must compare the actual LLVM function types instead.
1595        let tail_call_kind = if self.function.get_type() == callee_llvm_func_type {
1596            LLVMTailCallKind::LLVMTailCallKindMustTail
1597        } else {
1598            LLVMTailCallKind::LLVMTailCallKindTail
1599        };
1600        call_site.set_tail_call_kind(tail_call_kind);
1601
1602        if self.function.get_type().get_return_type().is_none() {
1603            err!(self.builder.build_return(None));
1604        } else {
1605            let ret = call_site.try_as_basic_value();
1606            if ret.is_instruction() {
1607                return Err(CompileError::Codegen(
1608                    "return_call expected a non-void call result".to_string(),
1609                ));
1610            }
1611            err!(self.builder.build_return(Some(&ret.unwrap_basic())));
1612        }
1613        Ok(())
1614    }
1615
1616    // Return sret pointer if the functions needs the hidden argument for multiple return values.
1617    fn current_sret_ptr(&self, func_type: &FunctionType) -> Option<PointerValue<'ctx>> {
1618        self.abi.is_sret(func_type).ok().map(|_| {
1619            self.function
1620                .get_first_param()
1621                .unwrap()
1622                .into_pointer_value()
1623        })
1624    }
1625
1626    fn build_m0_indirect_call(
1627        &mut self,
1628        table_index: u32,
1629        ctx_ptr: PointerValue<'ctx>,
1630        func_type: &FunctionType,
1631        func_ptr: PointerValue<'ctx>,
1632        func_index: IntValue<'ctx>,
1633        is_return_call: bool,
1634    ) -> Result<(), CompileError> {
1635        let Some(m0) = self.m0_param else {
1636            return Err(CompileError::Codegen(
1637                "Call to build_m0_indirect_call without m0 parameter!".to_string(),
1638            ));
1639        };
1640
1641        let params = self.state.popn_save_extra(func_type.params().len())?;
1642
1643        let mut local_func_indices = vec![];
1644        let mut foreign_func_indices = vec![];
1645
1646        for t in &self.wasm_module.table_initializers {
1647            if t.table_index.as_u32() == table_index {
1648                for (func_in_table_idx, func_idx) in t.elements.iter().enumerate() {
1649                    if self.wasm_module.local_func_index(*func_idx).is_some() {
1650                        local_func_indices.push(func_in_table_idx)
1651                    } else {
1652                        foreign_func_indices.push(func_in_table_idx)
1653                    }
1654                }
1655                break;
1656            }
1657        }
1658
1659        let needs_switch = self.m0_param.is_some()
1660            && !local_func_indices.is_empty()
1661            && !foreign_func_indices.is_empty();
1662
1663        if needs_switch {
1664            let foreign_idx_block = self
1665                .context
1666                .append_basic_block(self.function, "foreign_call_block");
1667            let local_idx_block = self
1668                .context
1669                .append_basic_block(self.function, "local_call_block");
1670            let unreachable_indirect_call_branch_block = self
1671                .context
1672                .append_basic_block(self.function, "unreachable_indirect_call_branch");
1673
1674            let cont =
1675                (!is_return_call).then(|| self.context.append_basic_block(self.function, "cont"));
1676
1677            err!(
1678                self.builder.build_switch(
1679                    func_index,
1680                    unreachable_indirect_call_branch_block,
1681                    &local_func_indices
1682                        .into_iter()
1683                        .map(|v| (
1684                            self.intrinsics.i32_ty.const_int(v as _, false),
1685                            local_idx_block
1686                        ))
1687                        .chain(foreign_func_indices.into_iter().map(|v| (
1688                            self.intrinsics.i32_ty.const_int(v as _, false),
1689                            foreign_idx_block
1690                        )))
1691                        .collect::<Vec<_>>()
1692                )
1693            );
1694
1695            self.builder
1696                .position_at_end(unreachable_indirect_call_branch_block);
1697            err!(self.builder.build_unreachable());
1698
1699            //let current_block = self.builder.get_insert_block().unwrap();
1700            self.builder.position_at_end(local_idx_block);
1701            let (local_call_site, local_llvm_func_type) = self.build_indirect_call_with_params(
1702                ctx_ptr,
1703                func_type,
1704                func_ptr,
1705                Some(m0),
1706                is_return_call,
1707                &params,
1708            )?;
1709
1710            let local_rets = if is_return_call {
1711                self.emit_return_call(local_call_site, local_llvm_func_type)?;
1712                Vec::new()
1713            } else {
1714                let rets = self.abi.rets_from_call(
1715                    &self.builder,
1716                    self.intrinsics,
1717                    local_call_site,
1718                    func_type,
1719                )?;
1720                err!(
1721                    self.builder
1722                        .build_unconditional_branch(cont.expect("non-return call requires cont"))
1723                );
1724                rets
1725            };
1726
1727            self.builder.position_at_end(foreign_idx_block);
1728            let (foreign_call_site, foreign_llvm_func_type) = self
1729                .build_indirect_call_with_params(
1730                    ctx_ptr,
1731                    func_type,
1732                    func_ptr,
1733                    None,
1734                    is_return_call,
1735                    &params,
1736                )?;
1737
1738            let foreign_rets = if is_return_call {
1739                self.emit_return_call(foreign_call_site, foreign_llvm_func_type)?;
1740                Vec::new()
1741            } else {
1742                let rets = self.abi.rets_from_call(
1743                    &self.builder,
1744                    self.intrinsics,
1745                    foreign_call_site,
1746                    func_type,
1747                )?;
1748                err!(
1749                    self.builder
1750                        .build_unconditional_branch(cont.expect("non-return call requires cont"))
1751                );
1752                rets
1753            };
1754
1755            if is_return_call {
1756                return Ok(());
1757            }
1758
1759            self.builder
1760                .position_at_end(cont.expect("non-return call requires cont"));
1761
1762            for i in 0..foreign_rets.len() {
1763                let f_i = foreign_rets[i];
1764                let l_i = local_rets[i];
1765                let ty = f_i.get_type();
1766                let v = err!(self.builder.build_phi(ty, ""));
1767                v.add_incoming(&[(&f_i, foreign_idx_block), (&l_i, local_idx_block)]);
1768                self.state.push1(v.as_basic_value());
1769            }
1770        } else if foreign_func_indices.is_empty() {
1771            let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
1772                ctx_ptr,
1773                func_type,
1774                func_ptr,
1775                Some(m0),
1776                is_return_call,
1777                &params,
1778            )?;
1779
1780            if is_return_call {
1781                self.emit_return_call(call_site, llvm_func_type)?;
1782            } else {
1783                self.abi
1784                    .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
1785                    .iter()
1786                    .for_each(|ret| self.state.push1(*ret));
1787            }
1788        } else {
1789            let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
1790                ctx_ptr,
1791                func_type,
1792                func_ptr,
1793                None,
1794                is_return_call,
1795                &params,
1796            )?;
1797            if is_return_call {
1798                self.emit_return_call(call_site, llvm_func_type)?;
1799            } else {
1800                self.abi
1801                    .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
1802                    .iter()
1803                    .for_each(|ret| self.state.push1(*ret));
1804            }
1805        }
1806
1807        Ok(())
1808    }
1809
1810    fn build_indirect_call(
1811        &mut self,
1812        ctx_ptr: PointerValue<'ctx>,
1813        func_type: &FunctionType,
1814        func_ptr: PointerValue<'ctx>,
1815        m0_param: Option<PointerValue<'ctx>>,
1816        is_return_call: bool,
1817    ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
1818        let params = self.state.popn_save_extra(func_type.params().len())?;
1819        self.build_indirect_call_with_params(
1820            ctx_ptr,
1821            func_type,
1822            func_ptr,
1823            m0_param,
1824            is_return_call,
1825            &params,
1826        )
1827    }
1828
1829    fn build_indirect_call_with_params(
1830        &mut self,
1831        ctx_ptr: PointerValue<'ctx>,
1832        func_type: &FunctionType,
1833        func_ptr: PointerValue<'ctx>,
1834        m0_param: Option<PointerValue<'ctx>>,
1835        is_return_call: bool,
1836        params: &[(BasicValueEnum<'ctx>, ExtraInfo)],
1837    ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
1838        let (llvm_func_type, llvm_func_attrs) = self.abi.func_type_to_llvm(
1839            self.context,
1840            self.intrinsics,
1841            Some(self.ctx.get_offsets()),
1842            func_type,
1843            m0_param.is_some(),
1844        )?;
1845
1846        // Apply pending canonicalizations.
1847        let params = params
1848            .iter()
1849            .zip(func_type.params().iter())
1850            .map(|((v, info), wasm_ty)| match wasm_ty {
1851                Type::F32 => err_nt!(self.builder.build_bit_cast(
1852                    self.apply_pending_canonicalization(*v, *info)?,
1853                    self.intrinsics.f32_ty,
1854                    "",
1855                )),
1856                Type::F64 => err_nt!(self.builder.build_bit_cast(
1857                    self.apply_pending_canonicalization(*v, *info)?,
1858                    self.intrinsics.f64_ty,
1859                    "",
1860                )),
1861                Type::V128 => self.apply_pending_canonicalization(*v, *info),
1862                _ => Ok(*v),
1863            })
1864            .collect::<Result<Vec<_>, _>>()?;
1865
1866        let params = self.abi.args_to_call(
1867            &self.alloca_builder,
1868            func_type,
1869            &llvm_func_type,
1870            ctx_ptr,
1871            params.as_slice(),
1872            self.intrinsics,
1873            m0_param,
1874            is_return_call
1875                .then(|| self.current_sret_ptr(func_type))
1876                .flatten(),
1877        )?;
1878
1879        let typed_func_ptr = err!(self.builder.build_pointer_cast(
1880            func_ptr,
1881            self.context.ptr_type(AddressSpace::default()),
1882            "typed_func_ptr",
1883        ));
1884
1885        let call_site_local = self.build_indirect_call_or_invoke(
1886            llvm_func_type,
1887            typed_func_ptr,
1888            params.as_slice(),
1889            "then_block",
1890            is_return_call,
1891        )?;
1892        for (attr, attr_loc) in llvm_func_attrs {
1893            call_site_local.add_attribute(attr_loc, attr);
1894        }
1895
1896        Ok((call_site_local, llvm_func_type))
1897    }
1898
1899    fn build_indirect_call_or_invoke(
1900        &mut self,
1901        llvm_func_type: inkwell::types::FunctionType<'ctx>,
1902        func_ptr: PointerValue<'ctx>,
1903        params: &[BasicValueEnum<'ctx>],
1904        then_block_name: &str,
1905        is_return_call: bool,
1906    ) -> Result<CallSiteValue<'ctx>, CompileError> {
1907        // This is an unintuitive spec corner case: a tail call must bypass all enclosing
1908        // try_table blocks in the function. See https://github.com/WebAssembly/exception-handling/issues/249.
1909        if let Some(lpad) = self.state.get_innermost_landingpad()
1910            && !is_return_call
1911        {
1912            let then_block = self
1913                .context
1914                .append_basic_block(self.function, then_block_name);
1915
1916            let ret = err!(self.builder.build_indirect_invoke(
1917                llvm_func_type,
1918                func_ptr,
1919                params,
1920                then_block,
1921                lpad,
1922                "",
1923            ));
1924
1925            self.builder.position_at_end(then_block);
1926            Ok(ret)
1927        } else {
1928            let call_params = params
1929                .iter()
1930                .copied()
1931                .map(Into::into)
1932                .collect::<Vec<BasicMetadataValueEnum>>();
1933            Ok(err!(self.builder.build_indirect_call(
1934                llvm_func_type,
1935                func_ptr,
1936                call_params.as_slice(),
1937                ""
1938            )))
1939        }
1940    }
1941}
1942
1943pub struct LLVMFunctionCodeGenerator<'ctx, 'a> {
1944    m0_param: Option<PointerValue<'ctx>>,
1945    context: &'ctx Context,
1946    builder: Builder<'ctx>,
1947    alloca_builder: Builder<'ctx>,
1948    intrinsics: &'a Intrinsics<'ctx>,
1949    state: State<'ctx>,
1950    function: FunctionValue<'ctx>,
1951    locals: Vec<(BasicTypeEnum<'ctx>, PointerValue<'ctx>)>, // Contains params and locals
1952    ctx: CtxType<'ctx, 'a>,
1953    unreachable_depth: usize,
1954    memory_styles: &'a PrimaryMap<MemoryIndex, MemoryStyle>,
1955    _table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
1956    module: &'a Module<'ctx>,
1957    module_translation: &'a ModuleTranslationState,
1958    signature_hashes: &'a PrimaryMap<SignatureIndex, SignatureHash>,
1959    wasm_module: &'a ModuleInfo,
1960    symbol_registry: &'a dyn SymbolRegistry,
1961    abi: &'a dyn Abi,
1962    config: &'a LLVM,
1963    target_triple: Triple,
1964    tags_cache: HashMap<i32, BasicValueEnum<'ctx>>,
1965    binary_fmt: target_lexicon::BinaryFormat,
1966    cpu_features: EnumSet<CpuFeature>,
1967    non_volatile_memory_ops: bool,
1968}
1969
1970impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
1971    fn quiet_nan(&self, value: BasicValueEnum<'ctx>) -> Result<BasicValueEnum<'ctx>, CompileError> {
1972        let intrinsic = if value
1973            .get_type()
1974            .eq(&self.intrinsics.f32_ty.as_basic_type_enum())
1975        {
1976            Some(self.intrinsics.add_f32)
1977        } else if value
1978            .get_type()
1979            .eq(&self.intrinsics.f64_ty.as_basic_type_enum())
1980        {
1981            Some(self.intrinsics.add_f64)
1982        } else if value
1983            .get_type()
1984            .eq(&self.intrinsics.f32x4_ty.as_basic_type_enum())
1985        {
1986            Some(self.intrinsics.add_f32x4)
1987        } else if value
1988            .get_type()
1989            .eq(&self.intrinsics.f64x2_ty.as_basic_type_enum())
1990        {
1991            Some(self.intrinsics.add_f64x2)
1992        } else {
1993            None
1994        };
1995
1996        match intrinsic {
1997            Some(intrinsic) => err_nt!(
1998                self.builder
1999                    .build_call(
2000                        intrinsic,
2001                        &[
2002                            value.into(),
2003                            value.get_type().const_zero().into(),
2004                            self.intrinsics.fp_rounding_md,
2005                            self.intrinsics.fp_exception_md,
2006                        ],
2007                        "",
2008                    )
2009                    .map(|v| v.try_as_basic_value().unwrap_basic())
2010            ),
2011            None => Ok(value),
2012        }
2013    }
2014
2015    fn finalize_minmax_result(
2016        &self,
2017        value: BasicValueEnum<'ctx>,
2018    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
2019        let ty = value.get_type();
2020        if ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2021            || ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2022        {
2023            let value = value.into_float_value();
2024            let is_nan = err!(self.builder.build_float_compare(
2025                FloatPredicate::UNO,
2026                value,
2027                value,
2028                "res_is_nan"
2029            ));
2030            let quiet = self.quiet_nan(value.as_basic_value_enum())?;
2031            let result =
2032                err!(
2033                    self.builder
2034                        .build_select(is_nan, quiet, value.as_basic_value_enum(), "")
2035                );
2036            Ok(result.as_basic_value_enum())
2037        } else if ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum()) {
2038            let value = value.into_vector_value();
2039            let is_nan = self
2040                .build_call_with_param_attributes(
2041                    self.intrinsics.cmp_f32x4,
2042                    &[
2043                        value.into(),
2044                        value.into(),
2045                        self.intrinsics.fp_uno_md,
2046                        self.intrinsics.fp_exception_md,
2047                    ],
2048                    "",
2049                )?
2050                .try_as_basic_value()
2051                .unwrap_basic()
2052                .into_vector_value();
2053            let quiet = self
2054                .quiet_nan(value.as_basic_value_enum())?
2055                .into_vector_value();
2056            let result = err!(self.builder.build_select(
2057                is_nan,
2058                quiet.as_basic_value_enum(),
2059                value.as_basic_value_enum(),
2060                "",
2061            ));
2062            Ok(result.as_basic_value_enum())
2063        } else if ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum()) {
2064            let value = value.into_vector_value();
2065            let is_nan = self
2066                .build_call_with_param_attributes(
2067                    self.intrinsics.cmp_f64x2,
2068                    &[
2069                        value.into(),
2070                        value.into(),
2071                        self.intrinsics.fp_uno_md,
2072                        self.intrinsics.fp_exception_md,
2073                    ],
2074                    "",
2075                )?
2076                .try_as_basic_value()
2077                .unwrap_basic()
2078                .into_vector_value();
2079            let quiet = self
2080                .quiet_nan(value.as_basic_value_enum())?
2081                .into_vector_value();
2082            let result = err!(self.builder.build_select(
2083                is_nan,
2084                quiet.as_basic_value_enum(),
2085                value.as_basic_value_enum(),
2086                "",
2087            ));
2088            Ok(result.as_basic_value_enum())
2089        } else {
2090            Ok(value)
2091        }
2092    }
2093
2094    fn finalize_rounding_result(
2095        &self,
2096        value: BasicValueEnum<'ctx>,
2097        info: ExtraInfo,
2098    ) -> Result<(BasicValueEnum<'ctx>, ExtraInfo), CompileError> {
2099        let ty = value.get_type();
2100        let is_f32 = ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum());
2101        let is_f64 = ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum());
2102        let is_f32x4 = ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum());
2103        let is_f64x2 = ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum());
2104        debug_assert!(is_f32 || is_f64 || is_f32x4 || is_f64x2);
2105
2106        if matches!(
2107            self.target_triple.architecture,
2108            Architecture::Riscv32(..) | Architecture::Riscv64(..)
2109        ) {
2110            if is_f32 || is_f64 {
2111                let input = value.into_float_value();
2112                let is_nan = err!(self.builder.build_float_compare(
2113                    FloatPredicate::UNO,
2114                    input,
2115                    input,
2116                    "res_is_nan",
2117                ));
2118                let canonical_nan_bits = if is_f32 {
2119                    self.intrinsics
2120                        .i32_ty
2121                        .const_int(CANONICAL_NAN_F32 as _, false)
2122                } else {
2123                    self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false)
2124                };
2125                let canonical_nan = err!(self.builder.build_bit_cast(
2126                    canonical_nan_bits,
2127                    ty,
2128                    "canonical_nan",
2129                ));
2130                let res =
2131                    err!(
2132                        self.builder
2133                            .build_select(is_nan, canonical_nan, value, "canonical_nan",)
2134                    );
2135                Ok((res, info))
2136            } else if is_f32x4 {
2137                let value = value.into_vector_value();
2138                let is_nan = err!(self.builder.build_call(
2139                    self.intrinsics.cmp_f32x4,
2140                    &[
2141                        value.into(),
2142                        value.into(),
2143                        self.intrinsics.fp_uno_md,
2144                        self.intrinsics.fp_exception_md,
2145                    ],
2146                    "",
2147                ))
2148                .try_as_basic_value()
2149                .unwrap_basic()
2150                .into_vector_value();
2151                let canonical_nan_bits = self
2152                    .intrinsics
2153                    .i32_ty
2154                    .const_int(CANONICAL_NAN_F32 as _, false);
2155                let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 4]);
2156                let canonical_nan = err!(self.builder.build_bit_cast(
2157                    canonical_nan_bits,
2158                    self.intrinsics.f32x4_ty,
2159                    "canonical_nan",
2160                ));
2161                let res = err!(self.builder.build_select(
2162                    is_nan,
2163                    canonical_nan.as_basic_value_enum(),
2164                    value.as_basic_value_enum(),
2165                    "canonical_nan",
2166                ));
2167                Ok((res, info))
2168            } else {
2169                let value = value.into_vector_value();
2170                let is_nan = err!(self.builder.build_call(
2171                    self.intrinsics.cmp_f64x2,
2172                    &[
2173                        value.into(),
2174                        value.into(),
2175                        self.intrinsics.fp_uno_md,
2176                        self.intrinsics.fp_exception_md,
2177                    ],
2178                    "",
2179                ))
2180                .try_as_basic_value()
2181                .unwrap_basic()
2182                .into_vector_value();
2183                let canonical_nan_bits = self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false);
2184                let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 2]);
2185                let canonical_nan = err!(self.builder.build_bit_cast(
2186                    canonical_nan_bits,
2187                    self.intrinsics.f64x2_ty,
2188                    "canonical_nan",
2189                ));
2190                let res = err!(self.builder.build_select(
2191                    is_nan,
2192                    canonical_nan.as_basic_value_enum(),
2193                    value.as_basic_value_enum(),
2194                    "canonical_nan",
2195                ));
2196                Ok((res, info))
2197            }
2198        } else {
2199            Ok((
2200                value,
2201                (info
2202                    | if is_f32 || is_f32x4 {
2203                        ExtraInfo::pending_f32_nan()
2204                    } else {
2205                        ExtraInfo::pending_f64_nan()
2206                    })?,
2207            ))
2208        }
2209    }
2210
2211    fn translate_operator(&mut self, op: Operator, _source_loc: u32) -> Result<(), CompileError> {
2212        // TODO: remove this vmctx by moving everything into CtxType. Values
2213        // computed off vmctx usually benefit from caching.
2214        let vmctx = &self.ctx.basic().into_pointer_value();
2215
2216        //let opcode_offset: Option<usize> = None;
2217
2218        if !self.state.reachable {
2219            match op {
2220                Operator::Block { blockty: _ }
2221                | Operator::Loop { blockty: _ }
2222                | Operator::If { blockty: _ }
2223                | Operator::TryTable { .. } => {
2224                    self.unreachable_depth += 1;
2225                    return Ok(());
2226                }
2227                Operator::Else => {
2228                    if self.unreachable_depth != 0 {
2229                        return Ok(());
2230                    }
2231                }
2232                Operator::End => {
2233                    if self.unreachable_depth != 0 {
2234                        self.unreachable_depth -= 1;
2235                        return Ok(());
2236                    }
2237                }
2238                _ => {
2239                    return Ok(());
2240                }
2241            }
2242        }
2243
2244        match op {
2245            /***************************
2246             * Control Flow instructions.
2247             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#control-flow-instructions
2248             ***************************/
2249            Operator::Block { blockty } => {
2250                let current_block = self
2251                    .builder
2252                    .get_insert_block()
2253                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2254
2255                let end_block = self.context.append_basic_block(self.function, "end");
2256                self.builder.position_at_end(end_block);
2257
2258                let phis: SmallVec<[PhiValue<'ctx>; 1]> = self
2259                    .module_translation
2260                    .blocktype_params_results(&blockty)?
2261                    .1
2262                    .iter()
2263                    .map(|&wp_ty| {
2264                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2265                            type_to_llvm(self.intrinsics, wasm_ty)
2266                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2267                        })
2268                    })
2269                    .collect::<Result<_, _>>()?;
2270
2271                self.state.push_block(
2272                    end_block,
2273                    phis,
2274                    self.module_translation
2275                        .blocktype_params_results(&blockty)?
2276                        .0
2277                        .len(),
2278                );
2279                self.builder.position_at_end(current_block);
2280            }
2281            Operator::Loop { blockty } => {
2282                let loop_body = self.context.append_basic_block(self.function, "loop_body");
2283                let loop_next = self.context.append_basic_block(self.function, "loop_outer");
2284                let pre_loop_block = self.builder.get_insert_block().unwrap();
2285
2286                err!(self.builder.build_unconditional_branch(loop_body));
2287
2288                self.builder.position_at_end(loop_next);
2289                let blocktypes = self.module_translation.blocktype_params_results(&blockty)?;
2290                let phis = blocktypes
2291                    .1
2292                    .iter()
2293                    .map(|&wp_ty| {
2294                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2295                            type_to_llvm(self.intrinsics, wasm_ty)
2296                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2297                        })
2298                    })
2299                    .collect::<Result<_, _>>()?;
2300                self.builder.position_at_end(loop_body);
2301                let loop_phis: SmallVec<[PhiValue<'ctx>; 1]> = blocktypes
2302                    .0
2303                    .iter()
2304                    .map(|&wp_ty| {
2305                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2306                            type_to_llvm(self.intrinsics, wasm_ty)
2307                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2308                        })
2309                    })
2310                    .collect::<Result<_, _>>()?;
2311                for phi in loop_phis.iter().rev() {
2312                    let (value, info) = self.state.pop1_extra()?;
2313                    let value = self.apply_pending_canonicalization(value, info)?;
2314                    phi.add_incoming(&[(&value, pre_loop_block)]);
2315                }
2316                for phi in &loop_phis {
2317                    self.state.push1(phi.as_basic_value());
2318                }
2319
2320                let num_inputs = loop_phis.len();
2321                self.state
2322                    .push_loop(loop_body, loop_next, loop_phis, phis, num_inputs);
2323            }
2324            Operator::Br { relative_depth } => {
2325                let frame = self.state.frame_at_depth(relative_depth)?;
2326
2327                let current_block = self
2328                    .builder
2329                    .get_insert_block()
2330                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2331
2332                let phis = if frame.is_loop() {
2333                    frame.loop_body_phis()
2334                } else {
2335                    frame.phis()
2336                };
2337
2338                let len = phis.len();
2339                let values = self.state.peekn_extra(len)?;
2340                let values = values
2341                    .iter()
2342                    .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2343                    .collect::<Result<Vec<_>, _>>()?;
2344
2345                // For each result of the block we're branching to,
2346                // pop a value off the value stack and load it into
2347                // the corresponding phi.
2348                for (phi, value) in phis.iter().zip(values) {
2349                    phi.add_incoming(&[(&value, current_block)]);
2350                }
2351
2352                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2353
2354                self.state.popn(len)?;
2355                self.state.reachable = false;
2356            }
2357            Operator::BrIf { relative_depth } => {
2358                let cond = self.state.pop1()?;
2359                let frame = self.state.frame_at_depth(relative_depth)?;
2360
2361                let current_block = self
2362                    .builder
2363                    .get_insert_block()
2364                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2365
2366                let phis = if frame.is_loop() {
2367                    frame.loop_body_phis()
2368                } else {
2369                    frame.phis()
2370                };
2371
2372                let param_stack = self.state.peekn_extra(phis.len())?;
2373                let param_stack = param_stack
2374                    .iter()
2375                    .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2376                    .collect::<Result<Vec<_>, _>>()?;
2377
2378                for (phi, value) in phis.iter().zip(param_stack) {
2379                    phi.add_incoming(&[(&value, current_block)]);
2380                }
2381
2382                let else_block = self.context.append_basic_block(self.function, "else");
2383
2384                let cond_value = err!(self.builder.build_int_compare(
2385                    IntPredicate::NE,
2386                    cond.into_int_value(),
2387                    self.intrinsics.i32_zero,
2388                    "",
2389                ));
2390                err!(self.builder.build_conditional_branch(
2391                    cond_value,
2392                    *frame.br_dest(),
2393                    else_block
2394                ));
2395                self.builder.position_at_end(else_block);
2396            }
2397            Operator::BrTable { ref targets } => {
2398                let current_block = self
2399                    .builder
2400                    .get_insert_block()
2401                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2402
2403                let index = self.state.pop1()?;
2404
2405                let default_frame = self.state.frame_at_depth(targets.default())?;
2406
2407                let phis = if default_frame.is_loop() {
2408                    default_frame.loop_body_phis()
2409                } else {
2410                    default_frame.phis()
2411                };
2412                let args = self.state.peekn(phis.len())?;
2413
2414                for (phi, value) in phis.iter().zip(args.iter()) {
2415                    phi.add_incoming(&[(value, current_block)]);
2416                }
2417
2418                let cases: Vec<_> = targets
2419                    .targets()
2420                    .enumerate()
2421                    .map(|(case_index, depth)| {
2422                        let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
2423                        let frame_result: Result<&ControlFrame, CompileError> =
2424                            self.state.frame_at_depth(depth);
2425                        let frame = match frame_result {
2426                            Ok(v) => v,
2427                            Err(e) => return Err(e),
2428                        };
2429                        let case_index_literal =
2430                            self.context.i32_type().const_int(case_index as u64, false);
2431                        let phis = if frame.is_loop() {
2432                            frame.loop_body_phis()
2433                        } else {
2434                            frame.phis()
2435                        };
2436                        for (phi, value) in phis.iter().zip(args.iter()) {
2437                            phi.add_incoming(&[(value, current_block)]);
2438                        }
2439
2440                        Ok((case_index_literal, *frame.br_dest()))
2441                    })
2442                    .collect::<Result<_, _>>()?;
2443
2444                err!(self.builder.build_switch(
2445                    index.into_int_value(),
2446                    *default_frame.br_dest(),
2447                    &cases[..],
2448                ));
2449
2450                let args_len = args.len();
2451                self.state.popn(args_len)?;
2452                self.state.reachable = false;
2453            }
2454            Operator::If { blockty } => {
2455                let current_block = self
2456                    .builder
2457                    .get_insert_block()
2458                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2459                let if_then_block = self.context.append_basic_block(self.function, "if_then");
2460                let if_else_block = self.context.append_basic_block(self.function, "if_else");
2461                let end_block = self.context.append_basic_block(self.function, "if_end");
2462
2463                let end_phis = {
2464                    self.builder.position_at_end(end_block);
2465
2466                    let phis = self
2467                        .module_translation
2468                        .blocktype_params_results(&blockty)?
2469                        .1
2470                        .iter()
2471                        .map(|&wp_ty| {
2472                            err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2473                                type_to_llvm(self.intrinsics, wasm_ty)
2474                                    .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2475                            })
2476                        })
2477                        .collect::<Result<_, _>>()?;
2478
2479                    self.builder.position_at_end(current_block);
2480                    phis
2481                };
2482
2483                let cond = self.state.pop1()?;
2484
2485                let cond_value = err!(self.builder.build_int_compare(
2486                    IntPredicate::NE,
2487                    cond.into_int_value(),
2488                    self.intrinsics.i32_zero,
2489                    "",
2490                ));
2491
2492                err!(self.builder.build_conditional_branch(
2493                    cond_value,
2494                    if_then_block,
2495                    if_else_block
2496                ));
2497                self.builder.position_at_end(if_else_block);
2498                let block_param_types = self
2499                    .module_translation
2500                    .blocktype_params_results(&blockty)?
2501                    .0
2502                    .iter()
2503                    .map(|&wp_ty| {
2504                        err_nt!(wptype_to_type(wp_ty))
2505                            .and_then(|wasm_ty| type_to_llvm(self.intrinsics, wasm_ty))
2506                    })
2507                    .collect::<Result<Vec<_>, _>>()?;
2508                let else_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2509                    .iter()
2510                    .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2511                    .collect::<Result<SmallVec<_>, _>>()?;
2512                self.builder.position_at_end(if_then_block);
2513                let then_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2514                    .iter()
2515                    .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2516                    .collect::<Result<SmallVec<_>, _>>()?;
2517                for (else_phi, then_phi) in else_phis.iter().rev().zip(then_phis.iter().rev()) {
2518                    let (value, info) = self.state.pop1_extra()?;
2519                    let value = self.apply_pending_canonicalization(value, info)?;
2520                    else_phi.add_incoming(&[(&value, current_block)]);
2521                    then_phi.add_incoming(&[(&value, current_block)]);
2522                }
2523                for phi in then_phis.iter() {
2524                    self.state.push1(phi.as_basic_value());
2525                }
2526
2527                self.state.push_if(
2528                    if_then_block,
2529                    if_else_block,
2530                    end_block,
2531                    then_phis,
2532                    else_phis,
2533                    end_phis,
2534                    block_param_types.len(),
2535                );
2536            }
2537            Operator::Else => {
2538                if self.state.reachable {
2539                    let frame = self.state.frame_at_depth(0)?;
2540                    let current_block = self.builder.get_insert_block().ok_or_else(|| {
2541                        CompileError::Codegen("not currently in a block".to_string())
2542                    })?;
2543
2544                    for phi in frame.phis().to_vec().iter().rev() {
2545                        let (value, info) = self.state.pop1_extra()?;
2546                        let value = self.apply_pending_canonicalization(value, info)?;
2547                        phi.add_incoming(&[(&value, current_block)])
2548                    }
2549
2550                    let frame = self.state.frame_at_depth(0)?;
2551                    err!(self.builder.build_unconditional_branch(*frame.code_after()));
2552                }
2553
2554                let (if_else_block, if_else_state) = if let ControlFrame::IfElse {
2555                    if_else,
2556                    if_else_state,
2557                    ..
2558                } = self.state.frame_at_depth_mut(0)?
2559                {
2560                    (if_else, if_else_state)
2561                } else {
2562                    unreachable!()
2563                };
2564
2565                *if_else_state = IfElseState::Else;
2566
2567                self.builder.position_at_end(*if_else_block);
2568                self.state.reachable = true;
2569
2570                if let ControlFrame::IfElse { else_phis, .. } = self.state.frame_at_depth(0)? {
2571                    // Push our own 'else' phi nodes to the stack.
2572                    for phi in else_phis.clone().iter() {
2573                        self.state.push1(phi.as_basic_value());
2574                    }
2575                };
2576            }
2577
2578            Operator::End => {
2579                let frame = self.state.pop_frame()?;
2580                let current_block = self
2581                    .builder
2582                    .get_insert_block()
2583                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2584
2585                if self.state.reachable {
2586                    for phi in frame.phis().iter().rev() {
2587                        let (value, info) = self.state.pop1_extra()?;
2588                        let value = self.apply_pending_canonicalization(value, info)?;
2589                        phi.add_incoming(&[(&value, current_block)]);
2590                    }
2591
2592                    err!(self.builder.build_unconditional_branch(*frame.code_after()));
2593                }
2594
2595                if let ControlFrame::IfElse {
2596                    if_else,
2597                    next,
2598                    if_else_state: IfElseState::If,
2599                    else_phis,
2600                    ..
2601                } = &frame
2602                {
2603                    for (phi, else_phi) in frame.phis().iter().zip(else_phis.iter()) {
2604                        phi.add_incoming(&[(&else_phi.as_basic_value(), *if_else)]);
2605                    }
2606                    self.builder.position_at_end(*if_else);
2607                    err!(self.builder.build_unconditional_branch(*next));
2608                } else if let ControlFrame::Landingpad { .. } = &frame {
2609                    self.state.pop_landingpad();
2610                };
2611
2612                self.builder.position_at_end(*frame.code_after());
2613                self.state.reset_stack(&frame);
2614
2615                self.state.reachable = true;
2616
2617                // Push each phi value to the value stack.
2618                for phi in frame.phis() {
2619                    if phi.count_incoming() != 0 {
2620                        self.state.push1(phi.as_basic_value());
2621                    } else {
2622                        // TODO if there are no incoming phi values, it means
2623                        // this block has no predecessors, and we can skip it
2624                        // altogether. However, fixing this is non-trivial as
2625                        // some places in the code rely on code getting generated
2626                        // for unreachable end blocks. For now, we let LLVM remove
2627                        // the block during dead code elimination instead.
2628                        let basic_ty = phi.as_basic_value().get_type();
2629                        let placeholder_value = basic_ty.const_zero();
2630                        self.state.push1(placeholder_value);
2631                        phi.as_instruction().erase_from_basic_block();
2632                    }
2633                }
2634            }
2635            Operator::Return => {
2636                let current_block = self
2637                    .builder
2638                    .get_insert_block()
2639                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2640
2641                let frame = self.state.outermost_frame()?;
2642                for phi in frame.phis().to_vec().iter().rev() {
2643                    let (arg, info) = self.state.pop1_extra()?;
2644                    let arg = self.apply_pending_canonicalization(arg, info)?;
2645                    phi.add_incoming(&[(&arg, current_block)]);
2646                }
2647                let frame = self.state.outermost_frame()?;
2648                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2649
2650                self.state.reachable = false;
2651            }
2652
2653            Operator::Unreachable => {
2654                self.build_call_with_param_attributes(
2655                    self.intrinsics.throw_trap,
2656                    &[self.intrinsics.trap_unreachable.into()],
2657                    "throw",
2658                )?;
2659                err!(self.builder.build_unreachable());
2660
2661                self.state.reachable = false;
2662            }
2663
2664            /***************************
2665             * Basic instructions.
2666             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#basic-instructions
2667             ***************************/
2668            Operator::Nop => {
2669                // Do nothing.
2670            }
2671            Operator::Drop => {
2672                self.state.pop1()?;
2673            }
2674
2675            // Generate const values.
2676            Operator::I32Const { value } => {
2677                let i = self.intrinsics.i32_ty.const_int(value as u64, false);
2678                let info = if is_f32_arithmetic(value as u32) {
2679                    ExtraInfo::arithmetic_f32()
2680                } else {
2681                    Default::default()
2682                };
2683                self.state.push1_extra(i, info);
2684            }
2685            Operator::I64Const { value } => {
2686                let i = self.intrinsics.i64_ty.const_int(value as u64, false);
2687                let info = if is_f64_arithmetic(value as u64) {
2688                    ExtraInfo::arithmetic_f64()
2689                } else {
2690                    Default::default()
2691                };
2692                self.state.push1_extra(i, info);
2693            }
2694            Operator::F32Const { value } => {
2695                let bits = self.intrinsics.i32_ty.const_int(value.bits() as u64, false);
2696                let info = if is_f32_arithmetic(value.bits()) {
2697                    ExtraInfo::arithmetic_f32()
2698                } else {
2699                    Default::default()
2700                };
2701                let f = err!(
2702                    self.builder
2703                        .build_bit_cast(bits, self.intrinsics.f32_ty, "f")
2704                );
2705                self.state.push1_extra(f, info);
2706            }
2707            Operator::F64Const { value } => {
2708                let bits = self.intrinsics.i64_ty.const_int(value.bits(), false);
2709                let info = if is_f64_arithmetic(value.bits()) {
2710                    ExtraInfo::arithmetic_f64()
2711                } else {
2712                    Default::default()
2713                };
2714                let f = err!(
2715                    self.builder
2716                        .build_bit_cast(bits, self.intrinsics.f64_ty, "f")
2717                );
2718                self.state.push1_extra(f, info);
2719            }
2720            Operator::V128Const { value } => {
2721                let mut hi: [u8; 8] = Default::default();
2722                let mut lo: [u8; 8] = Default::default();
2723                hi.copy_from_slice(&value.bytes()[0..8]);
2724                lo.copy_from_slice(&value.bytes()[8..16]);
2725                let packed = [u64::from_le_bytes(hi), u64::from_le_bytes(lo)];
2726                let i = self
2727                    .intrinsics
2728                    .i128_ty
2729                    .const_int_arbitrary_precision(&packed);
2730                let mut quad1: [u8; 4] = Default::default();
2731                let mut quad2: [u8; 4] = Default::default();
2732                let mut quad3: [u8; 4] = Default::default();
2733                let mut quad4: [u8; 4] = Default::default();
2734                quad1.copy_from_slice(&value.bytes()[0..4]);
2735                quad2.copy_from_slice(&value.bytes()[4..8]);
2736                quad3.copy_from_slice(&value.bytes()[8..12]);
2737                quad4.copy_from_slice(&value.bytes()[12..16]);
2738                let mut info: ExtraInfo = Default::default();
2739                if is_f32_arithmetic(u32::from_le_bytes(quad1))
2740                    && is_f32_arithmetic(u32::from_le_bytes(quad2))
2741                    && is_f32_arithmetic(u32::from_le_bytes(quad3))
2742                    && is_f32_arithmetic(u32::from_le_bytes(quad4))
2743                {
2744                    info |= ExtraInfo::arithmetic_f32();
2745                }
2746                if is_f64_arithmetic(packed[0]) && is_f64_arithmetic(packed[1]) {
2747                    info |= ExtraInfo::arithmetic_f64();
2748                }
2749                self.state.push1_extra(i, info);
2750            }
2751
2752            Operator::I8x16Splat => {
2753                let (v, i) = self.state.pop1_extra()?;
2754                let v = v.into_int_value();
2755                let v = err!(
2756                    self.builder
2757                        .build_int_truncate(v, self.intrinsics.i8_ty, "")
2758                );
2759                let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
2760                let res = err!(
2761                    self.builder
2762                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
2763                );
2764                self.state.push1_extra(res, i);
2765            }
2766            Operator::I16x8Splat => {
2767                let (v, i) = self.state.pop1_extra()?;
2768                let v = v.into_int_value();
2769                let v = err!(
2770                    self.builder
2771                        .build_int_truncate(v, self.intrinsics.i16_ty, "")
2772                );
2773                let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
2774                let res = err!(
2775                    self.builder
2776                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
2777                );
2778                self.state.push1_extra(res, i);
2779            }
2780            Operator::I32x4Splat => {
2781                let (v, i) = self.state.pop1_extra()?;
2782                let res = self.splat_vector(v, self.intrinsics.i32x4_ty)?;
2783                let res = err!(
2784                    self.builder
2785                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
2786                );
2787                self.state.push1_extra(res, i);
2788            }
2789            Operator::I64x2Splat => {
2790                let (v, i) = self.state.pop1_extra()?;
2791                let res = self.splat_vector(v, self.intrinsics.i64x2_ty)?;
2792                let res = err!(
2793                    self.builder
2794                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
2795                );
2796                self.state.push1_extra(res, i);
2797            }
2798            Operator::F32x4Splat => {
2799                let (v, i) = self.state.pop1_extra()?;
2800                let res = self.splat_vector(v, self.intrinsics.f32x4_ty)?;
2801                let res = err!(
2802                    self.builder
2803                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
2804                );
2805                // The spec is unclear, we interpret splat as preserving NaN
2806                // payload bits.
2807                self.state.push1_extra(res, i);
2808            }
2809            Operator::F64x2Splat => {
2810                let (v, i) = self.state.pop1_extra()?;
2811                let res = self.splat_vector(v, self.intrinsics.f64x2_ty)?;
2812                let res = err!(
2813                    self.builder
2814                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
2815                );
2816                // The spec is unclear, we interpret splat as preserving NaN
2817                // payload bits.
2818                self.state.push1_extra(res, i);
2819            }
2820
2821            // Operate on self.locals.
2822            Operator::LocalGet { local_index } => {
2823                let (type_value, pointer_value) = self.locals[local_index as usize];
2824                let v = err!(self.builder.build_load(
2825                    type_value,
2826                    pointer_value,
2827                    &format!("local_{local_index}_get")
2828                ));
2829                tbaa_label(
2830                    self.module,
2831                    self.intrinsics,
2832                    format!("local {local_index}"),
2833                    v.as_instruction_value().unwrap(),
2834                );
2835                self.state.push1(v);
2836            }
2837            Operator::LocalSet { local_index } => {
2838                let pointer_value = self.locals[local_index as usize].1;
2839                let (v, i) = self.state.pop1_extra()?;
2840                let v = self.apply_pending_canonicalization(v, i)?;
2841                let store = err!(self.builder.build_store(pointer_value, v));
2842                tbaa_label(
2843                    self.module,
2844                    self.intrinsics,
2845                    format!("local {local_index}"),
2846                    store,
2847                );
2848            }
2849            Operator::LocalTee { local_index } => {
2850                let pointer_value = self.locals[local_index as usize].1;
2851                let (v, i) = self.state.peek1_extra()?;
2852                let v = self.apply_pending_canonicalization(v, i)?;
2853                let store = err!(self.builder.build_store(pointer_value, v));
2854                tbaa_label(
2855                    self.module,
2856                    self.intrinsics,
2857                    format!("local {local_index}"),
2858                    store,
2859                );
2860            }
2861
2862            Operator::GlobalGet { global_index } => {
2863                let global_index = GlobalIndex::from_u32(global_index);
2864                match self
2865                    .ctx
2866                    .global(global_index, self.intrinsics, self.module)?
2867                {
2868                    GlobalCache::Const { value } => {
2869                        self.state.push1(*value);
2870                    }
2871                    GlobalCache::Mut {
2872                        ptr_to_value,
2873                        value_type,
2874                    } => {
2875                        let value = err!(self.builder.build_load(*value_type, *ptr_to_value, ""));
2876                        tbaa_label(
2877                            self.module,
2878                            self.intrinsics,
2879                            format!("global {}", global_index.as_u32()),
2880                            value.as_instruction_value().unwrap(),
2881                        );
2882                        self.state.push1(value);
2883                    }
2884                }
2885            }
2886            Operator::GlobalSet { global_index } => {
2887                let global_index = GlobalIndex::from_u32(global_index);
2888                match self
2889                    .ctx
2890                    .global(global_index, self.intrinsics, self.module)?
2891                {
2892                    GlobalCache::Const { value: _ } => {
2893                        return Err(CompileError::Codegen(format!(
2894                            "global.set on immutable global index {}",
2895                            global_index.as_u32()
2896                        )));
2897                    }
2898                    GlobalCache::Mut { ptr_to_value, .. } => {
2899                        let ptr_to_value = *ptr_to_value;
2900                        let (value, info) = self.state.pop1_extra()?;
2901                        let value = self.apply_pending_canonicalization(value, info)?;
2902                        let store = err!(self.builder.build_store(ptr_to_value, value));
2903                        tbaa_label(
2904                            self.module,
2905                            self.intrinsics,
2906                            format!("global {}", global_index.as_u32()),
2907                            store,
2908                        );
2909                    }
2910                }
2911            }
2912
2913            // `TypedSelect` must be used for extern refs so ref counting should
2914            // be done with TypedSelect. But otherwise they're the same.
2915            Operator::TypedSelect { .. } | Operator::Select => {
2916                let ((v1, i1), (v2, i2), (cond, _)) = self.state.pop3_extra()?;
2917                // We don't bother canonicalizing 'cond' here because we only
2918                // compare it to zero, and that's invariant under
2919                // canonicalization.
2920
2921                // If the pending bits of v1 and v2 are the same, we can pass
2922                // them along to the result. Otherwise, apply pending
2923                // canonicalizations now.
2924                let (v1, i1, v2, i2) = if i1.has_pending_f32_nan() != i2.has_pending_f32_nan()
2925                    || i1.has_pending_f64_nan() != i2.has_pending_f64_nan()
2926                {
2927                    (
2928                        self.apply_pending_canonicalization(v1, i1)?,
2929                        i1.strip_pending(),
2930                        self.apply_pending_canonicalization(v2, i2)?,
2931                        i2.strip_pending(),
2932                    )
2933                } else {
2934                    (v1, i1, v2, i2)
2935                };
2936                let cond_value = err!(self.builder.build_int_compare(
2937                    IntPredicate::NE,
2938                    cond.into_int_value(),
2939                    self.intrinsics.i32_zero,
2940                    "",
2941                ));
2942                let res = err!(self.builder.build_select(cond_value, v1, v2, ""));
2943                let info = {
2944                    let mut info = (i1.strip_pending() & i2.strip_pending())?;
2945                    if i1.has_pending_f32_nan() {
2946                        debug_assert!(i2.has_pending_f32_nan());
2947                        info = (info | ExtraInfo::pending_f32_nan())?;
2948                    }
2949                    if i1.has_pending_f64_nan() {
2950                        debug_assert!(i2.has_pending_f64_nan());
2951                        info = (info | ExtraInfo::pending_f64_nan())?;
2952                    }
2953                    info
2954                };
2955                self.state.push1_extra(res, info);
2956            }
2957            Operator::Call { function_index } | Operator::ReturnCall { function_index } => {
2958                let is_return_call = matches!(op, Operator::ReturnCall { .. });
2959                let func_index = FunctionIndex::from_u32(function_index);
2960                let sigindex = &self.wasm_module.functions[func_index];
2961                let func_type = &self.wasm_module.signatures[*sigindex];
2962
2963                let FunctionCache {
2964                    func,
2965                    llvm_func_type,
2966                    vmctx: callee_vmctx,
2967                    imported_include_m0_param,
2968                    attrs,
2969                } = if let Some(local_func_index) = self.wasm_module.local_func_index(func_index) {
2970                    let function_name = self
2971                        .symbol_registry
2972                        .symbol_to_name(Symbol::LocalFunction(local_func_index));
2973
2974                    self.ctx.local_func(
2975                        local_func_index,
2976                        func_index,
2977                        self.intrinsics,
2978                        self.module,
2979                        self.context,
2980                        func_type,
2981                        &function_name,
2982                    )?
2983                } else {
2984                    self.ctx
2985                        .imported_func(func_index, self.intrinsics, self.context, func_type)?
2986                };
2987                let llvm_func_type = *llvm_func_type;
2988                let func = *func;
2989                let callee_vmctx = *callee_vmctx;
2990                let imported_include_m0_param = *imported_include_m0_param;
2991                let attrs = attrs.clone();
2992
2993                /*
2994                let func_ptr = self.llvm.functions.borrow_mut()[&func_index];
2995
2996                (params, func_ptr.as_global_value().as_pointer_value())
2997                */
2998                let params = self.state.popn_save_extra(func_type.params().len())?;
2999
3000                // Apply pending canonicalizations.
3001                let params = params
3002                    .iter()
3003                    .zip(func_type.params().iter())
3004                    .map(|((v, info), wasm_ty)| match wasm_ty {
3005                        Type::F32 => err_nt!(self.builder.build_bit_cast(
3006                            self.apply_pending_canonicalization(*v, *info)?,
3007                            self.intrinsics.f32_ty,
3008                            "",
3009                        )),
3010                        Type::F64 => err_nt!(self.builder.build_bit_cast(
3011                            self.apply_pending_canonicalization(*v, *info)?,
3012                            self.intrinsics.f64_ty,
3013                            "",
3014                        )),
3015                        Type::V128 => self.apply_pending_canonicalization(*v, *info),
3016                        _ => Ok(*v),
3017                    })
3018                    .collect::<Result<Vec<_>, _>>()?;
3019
3020                if let (Some(m0_param), Some(include_m0_param)) =
3021                    (self.m0_param, imported_include_m0_param)
3022                {
3023                    /* For imported functions, we must be careful about when to include `g0_param`:
3024                    imports from another Wasm module expect it, while host-function imports do not.
3025                    We intentionally not leverage tail-calls for such function calls. */
3026                    let (llvm_func_type_no_m0, llvm_func_attrs_no_m0) =
3027                        self.abi.func_type_to_llvm(
3028                            self.context,
3029                            self.intrinsics,
3030                            Some(self.ctx.get_offsets()),
3031                            func_type,
3032                            false,
3033                        )?;
3034                    let params_with_m0 = self.abi.args_to_call(
3035                        &self.alloca_builder,
3036                        func_type,
3037                        &llvm_func_type,
3038                        callee_vmctx.into_pointer_value(),
3039                        params.as_slice(),
3040                        self.intrinsics,
3041                        Some(m0_param),
3042                        is_return_call
3043                            .then(|| self.current_sret_ptr(func_type))
3044                            .flatten(),
3045                    )?;
3046                    let params_no_m0 = self.abi.args_to_call(
3047                        &self.alloca_builder,
3048                        func_type,
3049                        &llvm_func_type_no_m0,
3050                        callee_vmctx.into_pointer_value(),
3051                        params.as_slice(),
3052                        self.intrinsics,
3053                        None,
3054                        is_return_call
3055                            .then(|| self.current_sret_ptr(func_type))
3056                            .flatten(),
3057                    )?;
3058
3059                    let include_m0_call_block = self
3060                        .context
3061                        .append_basic_block(self.function, "call_block_with_m0");
3062                    let skip_m0_call_block =
3063                        self.context.append_basic_block(self.function, "call_block");
3064                    let call_cont = self.context.append_basic_block(self.function, "call_cont");
3065                    err!(self.builder.build_conditional_branch(
3066                        include_m0_param,
3067                        include_m0_call_block,
3068                        skip_m0_call_block,
3069                    ));
3070
3071                    self.builder.position_at_end(include_m0_call_block);
3072                    let call_site_with_m0 = self.build_indirect_call_or_invoke(
3073                        llvm_func_type,
3074                        func,
3075                        params_with_m0.as_slice(),
3076                        "then_block_with_m0",
3077                        is_return_call,
3078                    )?;
3079                    for (attr, attr_loc) in &attrs {
3080                        call_site_with_m0.add_attribute(*attr_loc, *attr);
3081                    }
3082                    let rets_with_m0 = self.abi.rets_from_call(
3083                        &self.builder,
3084                        self.intrinsics,
3085                        call_site_with_m0,
3086                        func_type,
3087                    )?;
3088                    let with_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3089                        CompileError::Codegen(
3090                            "missing insertion block after call with m0".to_string(),
3091                        )
3092                    })?;
3093                    err!(self.builder.build_unconditional_branch(call_cont));
3094
3095                    self.builder.position_at_end(skip_m0_call_block);
3096                    let call_site_no_m0 = self.build_indirect_call_or_invoke(
3097                        llvm_func_type_no_m0,
3098                        func,
3099                        params_no_m0.as_slice(),
3100                        "then_block",
3101                        is_return_call,
3102                    )?;
3103                    for (attr, attr_loc) in &llvm_func_attrs_no_m0 {
3104                        call_site_no_m0.add_attribute(*attr_loc, *attr);
3105                    }
3106                    let rets_no_m0 = self.abi.rets_from_call(
3107                        &self.builder,
3108                        self.intrinsics,
3109                        call_site_no_m0,
3110                        func_type,
3111                    )?;
3112                    let no_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3113                        CompileError::Codegen(
3114                            "missing insertion block after call without m0".to_string(),
3115                        )
3116                    })?;
3117                    err!(self.builder.build_unconditional_branch(call_cont));
3118
3119                    self.builder.position_at_end(call_cont);
3120                    for i in 0..rets_with_m0.len() {
3121                        let with_m0 = rets_with_m0[i];
3122                        let no_m0 = rets_no_m0[i];
3123                        let phi = err!(self.builder.build_phi(with_m0.get_type(), ""));
3124                        phi.add_incoming(&[(&with_m0, with_m0_pred), (&no_m0, no_m0_pred)]);
3125                        self.state.push1(phi.as_basic_value());
3126                    }
3127                } else {
3128                    let params = self.abi.args_to_call(
3129                        &self.alloca_builder,
3130                        func_type,
3131                        &llvm_func_type,
3132                        callee_vmctx.into_pointer_value(),
3133                        params.as_slice(),
3134                        self.intrinsics,
3135                        self.m0_param,
3136                        if is_return_call {
3137                            self.current_sret_ptr(func_type)
3138                        } else {
3139                            None
3140                        },
3141                    )?;
3142
3143                    let call_site = self.build_indirect_call_or_invoke(
3144                        llvm_func_type,
3145                        func,
3146                        params.as_slice(),
3147                        "then_block",
3148                        is_return_call,
3149                    )?;
3150                    for (attr, attr_loc) in attrs {
3151                        call_site.add_attribute(attr_loc, attr);
3152                    }
3153
3154                    if is_return_call {
3155                        self.emit_return_call(call_site, llvm_func_type)?;
3156                        self.state.reachable = false;
3157                    } else {
3158                        self.abi
3159                            .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3160                            .iter()
3161                            .for_each(|ret| self.state.push1(*ret));
3162                    }
3163                }
3164            }
3165            Operator::CallIndirect {
3166                type_index,
3167                table_index,
3168            }
3169            | Operator::ReturnCallIndirect {
3170                type_index,
3171                table_index,
3172            } => {
3173                let is_return_call = matches!(op, Operator::ReturnCallIndirect { .. });
3174                let sigindex = SignatureIndex::from_u32(type_index);
3175                let table_index = TableIndex::from_u32(table_index);
3176                let func_type = &self.wasm_module.signatures[sigindex];
3177                let table = self.wasm_module.tables.get(table_index).unwrap();
3178                let local_fixed_funcref_table = self
3179                    .wasm_module
3180                    .local_table_index(table_index)
3181                    .filter(|_| table.is_fixed_funcref_table());
3182                let expected_signature_hash = self
3183                    .intrinsics
3184                    .i32_ty
3185                    .const_int(u64::from(self.signature_hashes[sigindex].as_u32()), false);
3186
3187                let func_index = self.state.pop1()?.into_int_value();
3188                let generic_table = if local_fixed_funcref_table.is_none() {
3189                    Some(self.ctx.table(
3190                        table_index,
3191                        self.intrinsics,
3192                        self.module,
3193                        &self.builder,
3194                    )?)
3195                } else {
3196                    None
3197                };
3198
3199                let table_bound = if local_fixed_funcref_table.is_some() {
3200                    self.intrinsics
3201                        .i32_ty
3202                        .const_int(table.minimum.into(), false)
3203                } else {
3204                    let (_, table_bound) = *generic_table.as_ref().unwrap();
3205                    err!(self.builder.build_int_truncate(
3206                        table_bound,
3207                        self.intrinsics.i32_ty,
3208                        "truncated_table_bounds",
3209                    ))
3210                };
3211
3212                // First, check if the index is outside of the table bounds.
3213                let index_in_bounds = err!(self.builder.build_int_compare(
3214                    IntPredicate::ULT,
3215                    func_index,
3216                    table_bound,
3217                    "index_in_bounds",
3218                ));
3219
3220                let index_in_bounds = self
3221                    .build_call_with_param_attributes(
3222                        self.intrinsics.expect_i1,
3223                        &[
3224                            index_in_bounds.into(),
3225                            self.intrinsics.i1_ty.const_int(1, false).into(),
3226                        ],
3227                        "index_in_bounds_expect",
3228                    )?
3229                    .try_as_basic_value()
3230                    .unwrap_basic()
3231                    .into_int_value();
3232
3233                let in_bounds_continue_block = self
3234                    .context
3235                    .append_basic_block(self.function, "in_bounds_continue_block");
3236                let not_in_bounds_block = self
3237                    .context
3238                    .append_basic_block(self.function, "not_in_bounds_block");
3239                err!(self.builder.build_conditional_branch(
3240                    index_in_bounds,
3241                    in_bounds_continue_block,
3242                    not_in_bounds_block,
3243                ));
3244                self.builder.position_at_end(not_in_bounds_block);
3245                self.build_call_with_param_attributes(
3246                    self.intrinsics.throw_trap,
3247                    &[self.intrinsics.trap_table_access_oob.into()],
3248                    "throw",
3249                )?;
3250                err!(self.builder.build_unreachable());
3251                self.builder.position_at_end(in_bounds_continue_block);
3252
3253                let anyfunc_struct_ptr = if let Some(local_table_index) = local_fixed_funcref_table
3254                {
3255                    let anyfuncs = self.ctx.fixed_funcref_table_anyfuncs(
3256                        local_table_index,
3257                        self.intrinsics,
3258                        &self.builder,
3259                    )?;
3260                    unsafe {
3261                        err!(self.builder.build_in_bounds_gep(
3262                            self.intrinsics.anyfunc_ty,
3263                            anyfuncs,
3264                            &[func_index],
3265                            "anyfunc_struct_ptr",
3266                        ))
3267                    }
3268                } else {
3269                    let (table_base, _) = *generic_table.as_ref().unwrap();
3270
3271                    // We assume the table has the `funcref` (pointer to `anyfunc`)
3272                    // element type.
3273                    let casted_table_base = err!(self.builder.build_pointer_cast(
3274                        table_base,
3275                        self.context.ptr_type(AddressSpace::default()),
3276                        "casted_table_base",
3277                    ));
3278
3279                    let funcref_ptr = unsafe {
3280                        err!(self.builder.build_in_bounds_gep(
3281                            self.intrinsics.ptr_ty,
3282                            casted_table_base,
3283                            &[func_index],
3284                            "funcref_ptr",
3285                        ))
3286                    };
3287
3288                    // a funcref (pointer to `anyfunc`)
3289                    let anyfunc_struct_ptr = err!(self.builder.build_load(
3290                        self.intrinsics.ptr_ty,
3291                        funcref_ptr,
3292                        "anyfunc_struct_ptr",
3293                    ))
3294                    .into_pointer_value();
3295
3296                    if !table.readonly {
3297                        // trap if we're trying to call a null funcref
3298                        let funcref_not_null = err!(
3299                            self.builder
3300                                .build_is_not_null(anyfunc_struct_ptr, "null_funcref_check")
3301                        );
3302
3303                        let funcref_continue_deref_block = self
3304                            .context
3305                            .append_basic_block(self.function, "funcref_continue_deref_block");
3306
3307                        let funcref_is_null_block = self
3308                            .context
3309                            .append_basic_block(self.function, "funcref_is_null_block");
3310                        err!(self.builder.build_conditional_branch(
3311                            funcref_not_null,
3312                            funcref_continue_deref_block,
3313                            funcref_is_null_block,
3314                        ));
3315                        self.builder.position_at_end(funcref_is_null_block);
3316                        self.build_call_with_param_attributes(
3317                            self.intrinsics.throw_trap,
3318                            &[self.intrinsics.trap_call_indirect_null.into()],
3319                            "throw",
3320                        )?;
3321                        err!(self.builder.build_unreachable());
3322                        self.builder.position_at_end(funcref_continue_deref_block);
3323                    }
3324
3325                    anyfunc_struct_ptr
3326                };
3327
3328                // Load things from the anyfunc data structure.
3329                let sig_hash_ptr = self
3330                    .builder
3331                    .build_struct_gep(
3332                        self.intrinsics.anyfunc_ty,
3333                        anyfunc_struct_ptr,
3334                        1,
3335                        "sig_hash_ptr",
3336                    )
3337                    .unwrap();
3338                let func_ptr_ptr = self
3339                    .builder
3340                    .build_struct_gep(
3341                        self.intrinsics.anyfunc_ty,
3342                        anyfunc_struct_ptr,
3343                        0,
3344                        "func_ptr_ptr",
3345                    )
3346                    .unwrap();
3347                let (func_ptr, found_signature_hash) = (
3348                    err!(
3349                        self.builder
3350                            .build_load(self.intrinsics.ptr_ty, func_ptr_ptr, "func_ptr")
3351                    )
3352                    .into_pointer_value(),
3353                    err!(
3354                        self.builder
3355                            .build_load(self.intrinsics.i32_ty, sig_hash_ptr, "sig_hash")
3356                    )
3357                    .into_int_value(),
3358                );
3359
3360                // Next, check if the table element is initialized.
3361
3362                // TODO: we may not need this check anymore
3363                let elem_initialized = err!(self.builder.build_is_not_null(func_ptr, ""));
3364
3365                // Next, check if the signature id is correct.
3366
3367                let sig_hashes_equal = err!(self.builder.build_int_compare(
3368                    IntPredicate::EQ,
3369                    expected_signature_hash,
3370                    found_signature_hash,
3371                    "sig_hashes_equal",
3372                ));
3373
3374                let initialized_and_sig_hashes_match = err!(self.builder.build_and(
3375                    elem_initialized,
3376                    sig_hashes_equal,
3377                    ""
3378                ));
3379
3380                // Tell llvm that the expected and found signature hashes should match.
3381                let initialized_and_sig_hashes_match = self
3382                    .build_call_with_param_attributes(
3383                        self.intrinsics.expect_i1,
3384                        &[
3385                            initialized_and_sig_hashes_match.into(),
3386                            self.intrinsics.i1_ty.const_int(1, false).into(),
3387                        ],
3388                        "initialized_and_sig_hashes_match_expect",
3389                    )?
3390                    .try_as_basic_value()
3391                    .unwrap_basic()
3392                    .into_int_value();
3393
3394                let continue_block = self
3395                    .context
3396                    .append_basic_block(self.function, "continue_block");
3397                let sighashes_notequal_block = self
3398                    .context
3399                    .append_basic_block(self.function, "sighashes_notequal_block");
3400                err!(self.builder.build_conditional_branch(
3401                    initialized_and_sig_hashes_match,
3402                    continue_block,
3403                    sighashes_notequal_block,
3404                ));
3405
3406                self.builder.position_at_end(sighashes_notequal_block);
3407                let trap_code = err!(self.builder.build_select(
3408                    elem_initialized,
3409                    self.intrinsics.trap_call_indirect_sig,
3410                    self.intrinsics.trap_call_indirect_null,
3411                    "",
3412                ));
3413                self.build_call_with_param_attributes(
3414                    self.intrinsics.throw_trap,
3415                    &[trap_code.into()],
3416                    "throw",
3417                )?;
3418                err!(self.builder.build_unreachable());
3419                self.builder.position_at_end(continue_block);
3420
3421                let callee_vmctx = if table.readonly {
3422                    *vmctx
3423                } else {
3424                    let ctx_ptr_ptr = self
3425                        .builder
3426                        .build_struct_gep(
3427                            self.intrinsics.anyfunc_ty,
3428                            anyfunc_struct_ptr,
3429                            2,
3430                            "ctx_ptr_ptr",
3431                        )
3432                        .unwrap();
3433                    err!(
3434                        self.builder
3435                            .build_load(self.intrinsics.ptr_ty, ctx_ptr_ptr, "ctx_ptr")
3436                    )
3437                    .into_pointer_value()
3438                };
3439
3440                if self.m0_param.is_some() {
3441                    self.build_m0_indirect_call(
3442                        table_index.as_u32(),
3443                        callee_vmctx,
3444                        func_type,
3445                        func_ptr,
3446                        func_index,
3447                        is_return_call,
3448                    )?;
3449                } else {
3450                    let (call_site, llvm_func_type) = self.build_indirect_call(
3451                        callee_vmctx,
3452                        func_type,
3453                        func_ptr,
3454                        None,
3455                        is_return_call,
3456                    )?;
3457
3458                    if is_return_call {
3459                        self.emit_return_call(call_site, llvm_func_type)?;
3460                    } else {
3461                        self.abi
3462                            .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3463                            .iter()
3464                            .for_each(|ret| self.state.push1(*ret));
3465                    }
3466                }
3467
3468                if is_return_call {
3469                    self.state.reachable = false;
3470                }
3471            }
3472
3473            /***************************
3474             * Integer Arithmetic instructions.
3475             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-arithmetic-instructions
3476             ***************************/
3477            Operator::I32Add | Operator::I64Add => {
3478                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3479                let v1 = self.apply_pending_canonicalization(v1, i1)?;
3480                let v2 = self.apply_pending_canonicalization(v2, i2)?;
3481                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3482                let res = err!(self.builder.build_int_add(v1, v2, ""));
3483                self.state.push1(res);
3484            }
3485            Operator::I8x16Add => {
3486                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3487                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3488                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3489                let res = err!(self.builder.build_int_add(v1, v2, ""));
3490                let res = err!(
3491                    self.builder
3492                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3493                );
3494                self.state.push1(res);
3495            }
3496            Operator::I16x8Add => {
3497                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3498                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3499                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3500                let res = err!(self.builder.build_int_add(v1, v2, ""));
3501                let res = err!(
3502                    self.builder
3503                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3504                );
3505                self.state.push1(res);
3506            }
3507            Operator::I16x8ExtAddPairwiseI8x16S | Operator::I16x8ExtAddPairwiseI8x16U => {
3508                let extend_op = match op {
3509                    Operator::I16x8ExtAddPairwiseI8x16S => {
3510                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, "")
3511                    }
3512                    Operator::I16x8ExtAddPairwiseI8x16U => {
3513                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, "")
3514                    }
3515                    _ => unreachable!("Unhandled internal variant"),
3516                };
3517                let (v, i) = self.state.pop1_extra()?;
3518                let (v, _) = self.v128_into_i8x16(v, i)?;
3519
3520                let left = err!(self.builder.build_shuffle_vector(
3521                    v,
3522                    v.get_type().get_undef(),
3523                    VectorType::const_vector(&[
3524                        self.intrinsics.i32_consts[0],
3525                        self.intrinsics.i32_consts[2],
3526                        self.intrinsics.i32_consts[4],
3527                        self.intrinsics.i32_consts[6],
3528                        self.intrinsics.i32_consts[8],
3529                        self.intrinsics.i32_consts[10],
3530                        self.intrinsics.i32_consts[12],
3531                        self.intrinsics.i32_consts[14],
3532                    ]),
3533                    "",
3534                ));
3535                let left = err!(extend_op(self, left));
3536                let right = err!(self.builder.build_shuffle_vector(
3537                    v,
3538                    v.get_type().get_undef(),
3539                    VectorType::const_vector(&[
3540                        self.intrinsics.i32_consts[1],
3541                        self.intrinsics.i32_consts[3],
3542                        self.intrinsics.i32_consts[5],
3543                        self.intrinsics.i32_consts[7],
3544                        self.intrinsics.i32_consts[9],
3545                        self.intrinsics.i32_consts[11],
3546                        self.intrinsics.i32_consts[13],
3547                        self.intrinsics.i32_consts[15],
3548                    ]),
3549                    "",
3550                ));
3551                let right = err!(extend_op(self, right));
3552
3553                let res = err!(self.builder.build_int_add(left, right, ""));
3554                let res = err!(
3555                    self.builder
3556                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3557                );
3558                self.state.push1(res);
3559            }
3560            Operator::I32x4Add => {
3561                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3562                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3563                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3564                let res = err!(self.builder.build_int_add(v1, v2, ""));
3565                let res = err!(
3566                    self.builder
3567                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3568                );
3569                self.state.push1(res);
3570            }
3571            Operator::I32x4ExtAddPairwiseI16x8S | Operator::I32x4ExtAddPairwiseI16x8U => {
3572                let extend_op = match op {
3573                    Operator::I32x4ExtAddPairwiseI16x8S => {
3574                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
3575                    }
3576                    Operator::I32x4ExtAddPairwiseI16x8U => {
3577                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
3578                    }
3579                    _ => unreachable!("Unhandled internal variant"),
3580                };
3581                let (v, i) = self.state.pop1_extra()?;
3582                let (v, _) = self.v128_into_i16x8(v, i)?;
3583
3584                let left = err!(self.builder.build_shuffle_vector(
3585                    v,
3586                    v.get_type().get_undef(),
3587                    VectorType::const_vector(&[
3588                        self.intrinsics.i32_consts[0],
3589                        self.intrinsics.i32_consts[2],
3590                        self.intrinsics.i32_consts[4],
3591                        self.intrinsics.i32_consts[6],
3592                    ]),
3593                    "",
3594                ));
3595                let left = err!(extend_op(self, left));
3596                let right = err!(self.builder.build_shuffle_vector(
3597                    v,
3598                    v.get_type().get_undef(),
3599                    VectorType::const_vector(&[
3600                        self.intrinsics.i32_consts[1],
3601                        self.intrinsics.i32_consts[3],
3602                        self.intrinsics.i32_consts[5],
3603                        self.intrinsics.i32_consts[7],
3604                    ]),
3605                    "",
3606                ));
3607                let right = err!(extend_op(self, right));
3608
3609                let res = err!(self.builder.build_int_add(left, right, ""));
3610                let res = err!(
3611                    self.builder
3612                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3613                );
3614                self.state.push1(res);
3615            }
3616            Operator::I64x2Add => {
3617                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3618                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3619                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3620                let res = err!(self.builder.build_int_add(v1, v2, ""));
3621                let res = err!(
3622                    self.builder
3623                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3624                );
3625                self.state.push1(res);
3626            }
3627            Operator::I8x16AddSatS => {
3628                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3629                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3630                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3631                let res = self
3632                    .build_call_with_param_attributes(
3633                        self.intrinsics.sadd_sat_i8x16,
3634                        &[v1.into(), v2.into()],
3635                        "",
3636                    )?
3637                    .try_as_basic_value()
3638                    .unwrap_basic();
3639                let res = err!(
3640                    self.builder
3641                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3642                );
3643                self.state.push1(res);
3644            }
3645            Operator::I16x8AddSatS => {
3646                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3647                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3648                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3649                let res = self
3650                    .build_call_with_param_attributes(
3651                        self.intrinsics.sadd_sat_i16x8,
3652                        &[v1.into(), v2.into()],
3653                        "",
3654                    )?
3655                    .try_as_basic_value()
3656                    .unwrap_basic();
3657                let res = err!(
3658                    self.builder
3659                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3660                );
3661                self.state.push1(res);
3662            }
3663            Operator::I8x16AddSatU => {
3664                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3665                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3666                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3667                let res = self
3668                    .build_call_with_param_attributes(
3669                        self.intrinsics.uadd_sat_i8x16,
3670                        &[v1.into(), v2.into()],
3671                        "",
3672                    )?
3673                    .try_as_basic_value()
3674                    .unwrap_basic();
3675                let res = err!(
3676                    self.builder
3677                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3678                );
3679                self.state.push1(res);
3680            }
3681            Operator::I16x8AddSatU => {
3682                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3683                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3684                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3685                let res = self
3686                    .build_call_with_param_attributes(
3687                        self.intrinsics.uadd_sat_i16x8,
3688                        &[v1.into(), v2.into()],
3689                        "",
3690                    )?
3691                    .try_as_basic_value()
3692                    .unwrap_basic();
3693                let res = err!(
3694                    self.builder
3695                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3696                );
3697                self.state.push1(res);
3698            }
3699            Operator::I32Sub | Operator::I64Sub => {
3700                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3701                let v1 = self.apply_pending_canonicalization(v1, i1)?;
3702                let v2 = self.apply_pending_canonicalization(v2, i2)?;
3703                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3704                let res = err!(self.builder.build_int_sub(v1, v2, ""));
3705                self.state.push1(res);
3706            }
3707            Operator::I8x16Sub => {
3708                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3709                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3710                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3711                let res = err!(self.builder.build_int_sub(v1, v2, ""));
3712                let res = err!(
3713                    self.builder
3714                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3715                );
3716                self.state.push1(res);
3717            }
3718            Operator::I16x8Sub => {
3719                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3720                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3721                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3722                let res = err!(self.builder.build_int_sub(v1, v2, ""));
3723                let res = err!(
3724                    self.builder
3725                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3726                );
3727                self.state.push1(res);
3728            }
3729            Operator::I32x4Sub => {
3730                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3731                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3732                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3733                let res = err!(self.builder.build_int_sub(v1, v2, ""));
3734                let res = err!(
3735                    self.builder
3736                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3737                );
3738                self.state.push1(res);
3739            }
3740            Operator::I64x2Sub => {
3741                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3742                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3743                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3744                let res = err!(self.builder.build_int_sub(v1, v2, ""));
3745                let res = err!(
3746                    self.builder
3747                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3748                );
3749                self.state.push1(res);
3750            }
3751            Operator::I8x16SubSatS => {
3752                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3753                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3754                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3755                let res = self
3756                    .build_call_with_param_attributes(
3757                        self.intrinsics.ssub_sat_i8x16,
3758                        &[v1.into(), v2.into()],
3759                        "",
3760                    )?
3761                    .try_as_basic_value()
3762                    .unwrap_basic();
3763                let res = err!(
3764                    self.builder
3765                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3766                );
3767                self.state.push1(res);
3768            }
3769            Operator::I16x8SubSatS => {
3770                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3771                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3772                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3773                let res = self
3774                    .build_call_with_param_attributes(
3775                        self.intrinsics.ssub_sat_i16x8,
3776                        &[v1.into(), v2.into()],
3777                        "",
3778                    )?
3779                    .try_as_basic_value()
3780                    .unwrap_basic();
3781                let res = err!(
3782                    self.builder
3783                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3784                );
3785                self.state.push1(res);
3786            }
3787            Operator::I8x16SubSatU => {
3788                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3789                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3790                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3791                let res = self
3792                    .build_call_with_param_attributes(
3793                        self.intrinsics.usub_sat_i8x16,
3794                        &[v1.into(), v2.into()],
3795                        "",
3796                    )?
3797                    .try_as_basic_value()
3798                    .unwrap_basic();
3799                let res = err!(
3800                    self.builder
3801                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3802                );
3803                self.state.push1(res);
3804            }
3805            Operator::I16x8SubSatU => {
3806                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3807                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3808                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3809                let res = self
3810                    .build_call_with_param_attributes(
3811                        self.intrinsics.usub_sat_i16x8,
3812                        &[v1.into(), v2.into()],
3813                        "",
3814                    )?
3815                    .try_as_basic_value()
3816                    .unwrap_basic();
3817                let res = err!(
3818                    self.builder
3819                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3820                );
3821                self.state.push1(res);
3822            }
3823            Operator::I32Mul | Operator::I64Mul => {
3824                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3825                let v1 = self.apply_pending_canonicalization(v1, i1)?;
3826                let v2 = self.apply_pending_canonicalization(v2, i2)?;
3827                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3828                let res = err!(self.builder.build_int_mul(v1, v2, ""));
3829                self.state.push1(res);
3830            }
3831            Operator::I16x8Mul => {
3832                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3833                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3834                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3835                let res = err!(self.builder.build_int_mul(v1, v2, ""));
3836                let res = err!(
3837                    self.builder
3838                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3839                );
3840                self.state.push1(res);
3841            }
3842            Operator::I32x4Mul => {
3843                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3844                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3845                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3846                let res = err!(self.builder.build_int_mul(v1, v2, ""));
3847                let res = err!(
3848                    self.builder
3849                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3850                );
3851                self.state.push1(res);
3852            }
3853            Operator::I64x2Mul => {
3854                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3855                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3856                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3857                let res = err!(self.builder.build_int_mul(v1, v2, ""));
3858                let res = err!(
3859                    self.builder
3860                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3861                );
3862                self.state.push1(res);
3863            }
3864            Operator::I16x8RelaxedQ15mulrS if self.cpu_features.contains(CpuFeature::SSSE3) => {
3865                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3866                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3867                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3868                let res = self
3869                    .build_call_with_param_attributes(
3870                        self.intrinsics.x86_64.pmulhrsw128,
3871                        &[v1.into(), v2.into()],
3872                        "",
3873                    )?
3874                    .try_as_basic_value()
3875                    .unwrap_basic();
3876                let res = err!(
3877                    self.builder
3878                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3879                );
3880                self.state.push1(res);
3881            }
3882            Operator::I16x8Q15MulrSatS | Operator::I16x8RelaxedQ15mulrS => {
3883                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3884                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3885                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3886
3887                let max_value = self.intrinsics.i16_ty.const_int(i16::MAX as u64, false);
3888                let max_values = VectorType::const_vector(&[max_value; 8]);
3889
3890                let v1 = err!(
3891                    self.builder
3892                        .build_int_s_extend(v1, self.intrinsics.i32x8_ty, "")
3893                );
3894                let v2 = err!(
3895                    self.builder
3896                        .build_int_s_extend(v2, self.intrinsics.i32x8_ty, "")
3897                );
3898                let res = err!(self.builder.build_int_mul(v1, v2, ""));
3899
3900                // magic number specified by the spec
3901                let bit = self.intrinsics.i32_ty.const_int(0x4000, false);
3902                let bits = VectorType::const_vector(&[bit; 8]);
3903
3904                let res = err!(self.builder.build_int_add(res, bits, ""));
3905
3906                let fifteen = self.intrinsics.i32_consts[15];
3907                let fifteens = VectorType::const_vector(&[fifteen; 8]);
3908
3909                let res = err!(self.builder.build_right_shift(res, fifteens, true, ""));
3910                let saturate_up = {
3911                    let max_values = err!(self.builder.build_int_s_extend(
3912                        max_values,
3913                        self.intrinsics.i32x8_ty,
3914                        ""
3915                    ));
3916                    err!(
3917                        self.builder
3918                            .build_int_compare(IntPredicate::SGT, res, max_values, "")
3919                    )
3920                };
3921
3922                let res = err!(
3923                    self.builder
3924                        .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
3925                );
3926
3927                let res = err!(self.builder.build_select(saturate_up, max_values, res, ""))
3928                    .into_vector_value();
3929                let res = err!(
3930                    self.builder
3931                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3932                );
3933                self.state.push1(res);
3934            }
3935            Operator::I16x8ExtMulLowI8x16S
3936            | Operator::I16x8ExtMulLowI8x16U
3937            | Operator::I16x8ExtMulHighI8x16S
3938            | Operator::I16x8ExtMulHighI8x16U => {
3939                let extend_op = match op {
3940                    Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulHighI8x16S => {
3941                        |s: &Self, v| -> Result<VectorValue, CompileError> {
3942                            err_nt!(s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, ""))
3943                        }
3944                    }
3945                    Operator::I16x8ExtMulLowI8x16U | Operator::I16x8ExtMulHighI8x16U => {
3946                        |s: &Self, v| -> Result<VectorValue, CompileError> {
3947                            err_nt!(s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, ""))
3948                        }
3949                    }
3950                    _ => unreachable!("Unhandled internal variant"),
3951                };
3952                let shuffle_array = match op {
3953                    Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulLowI8x16U => [
3954                        self.intrinsics.i32_consts[0],
3955                        self.intrinsics.i32_consts[1],
3956                        self.intrinsics.i32_consts[2],
3957                        self.intrinsics.i32_consts[3],
3958                        self.intrinsics.i32_consts[4],
3959                        self.intrinsics.i32_consts[5],
3960                        self.intrinsics.i32_consts[6],
3961                        self.intrinsics.i32_consts[7],
3962                    ],
3963                    Operator::I16x8ExtMulHighI8x16S | Operator::I16x8ExtMulHighI8x16U => [
3964                        self.intrinsics.i32_consts[8],
3965                        self.intrinsics.i32_consts[9],
3966                        self.intrinsics.i32_consts[10],
3967                        self.intrinsics.i32_consts[11],
3968                        self.intrinsics.i32_consts[12],
3969                        self.intrinsics.i32_consts[13],
3970                        self.intrinsics.i32_consts[14],
3971                        self.intrinsics.i32_consts[15],
3972                    ],
3973                    _ => unreachable!("Unhandled internal variant"),
3974                };
3975                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3976                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3977                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3978                let val1 = err!(self.builder.build_shuffle_vector(
3979                    v1,
3980                    v1.get_type().get_undef(),
3981                    VectorType::const_vector(&shuffle_array),
3982                    "",
3983                ));
3984                let val1 = err!(extend_op(self, val1));
3985                let val2 = err!(self.builder.build_shuffle_vector(
3986                    v2,
3987                    v2.get_type().get_undef(),
3988                    VectorType::const_vector(&shuffle_array),
3989                    "",
3990                ));
3991                let val2 = err!(extend_op(self, val2));
3992                let res = err!(self.builder.build_int_mul(val1, val2, ""));
3993                let res = err!(
3994                    self.builder
3995                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3996                );
3997                self.state.push1(res);
3998            }
3999            Operator::I32x4ExtMulLowI16x8S
4000            | Operator::I32x4ExtMulLowI16x8U
4001            | Operator::I32x4ExtMulHighI16x8S
4002            | Operator::I32x4ExtMulHighI16x8U => {
4003                let extend_op = match op {
4004                    Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulHighI16x8S => {
4005                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
4006                    }
4007                    Operator::I32x4ExtMulLowI16x8U | Operator::I32x4ExtMulHighI16x8U => {
4008                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
4009                    }
4010                    _ => unreachable!("Unhandled internal variant"),
4011                };
4012                let shuffle_array = match op {
4013                    Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulLowI16x8U => [
4014                        self.intrinsics.i32_consts[0],
4015                        self.intrinsics.i32_consts[1],
4016                        self.intrinsics.i32_consts[2],
4017                        self.intrinsics.i32_consts[3],
4018                    ],
4019                    Operator::I32x4ExtMulHighI16x8S | Operator::I32x4ExtMulHighI16x8U => [
4020                        self.intrinsics.i32_consts[4],
4021                        self.intrinsics.i32_consts[5],
4022                        self.intrinsics.i32_consts[6],
4023                        self.intrinsics.i32_consts[7],
4024                    ],
4025                    _ => unreachable!("Unhandled internal variant"),
4026                };
4027                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4028                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4029                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4030                let val1 = err!(self.builder.build_shuffle_vector(
4031                    v1,
4032                    v1.get_type().get_undef(),
4033                    VectorType::const_vector(&shuffle_array),
4034                    "",
4035                ));
4036                let val1 = err!(extend_op(self, val1));
4037                let val2 = err!(self.builder.build_shuffle_vector(
4038                    v2,
4039                    v2.get_type().get_undef(),
4040                    VectorType::const_vector(&shuffle_array),
4041                    "",
4042                ));
4043                let val2 = err!(extend_op(self, val2));
4044                let res = err!(self.builder.build_int_mul(val1, val2, ""));
4045                let res = err!(
4046                    self.builder
4047                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4048                );
4049                self.state.push1(res);
4050            }
4051            Operator::I64x2ExtMulLowI32x4S
4052            | Operator::I64x2ExtMulLowI32x4U
4053            | Operator::I64x2ExtMulHighI32x4S
4054            | Operator::I64x2ExtMulHighI32x4U => {
4055                let extend_op = match op {
4056                    Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulHighI32x4S => {
4057                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
4058                    }
4059                    Operator::I64x2ExtMulLowI32x4U | Operator::I64x2ExtMulHighI32x4U => {
4060                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
4061                    }
4062                    _ => unreachable!("Unhandled internal variant"),
4063                };
4064                let shuffle_array = match op {
4065                    Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulLowI32x4U => {
4066                        [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
4067                    }
4068                    Operator::I64x2ExtMulHighI32x4S | Operator::I64x2ExtMulHighI32x4U => {
4069                        [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
4070                    }
4071                    _ => unreachable!("Unhandled internal variant"),
4072                };
4073                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4074                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4075                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4076                let val1 = err!(self.builder.build_shuffle_vector(
4077                    v1,
4078                    v1.get_type().get_undef(),
4079                    VectorType::const_vector(&shuffle_array),
4080                    "",
4081                ));
4082                let val1 = err!(extend_op(self, val1));
4083                let val2 = err!(self.builder.build_shuffle_vector(
4084                    v2,
4085                    v2.get_type().get_undef(),
4086                    VectorType::const_vector(&shuffle_array),
4087                    "",
4088                ));
4089                let val2 = err!(extend_op(self, val2));
4090                let res = err!(self.builder.build_int_mul(val1, val2, ""));
4091                let res = err!(
4092                    self.builder
4093                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4094                );
4095                self.state.push1(res);
4096            }
4097            Operator::I32x4DotI16x8S => {
4098                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4099                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4100                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4101                let low_i16 = [
4102                    self.intrinsics.i32_consts[0],
4103                    self.intrinsics.i32_consts[2],
4104                    self.intrinsics.i32_consts[4],
4105                    self.intrinsics.i32_consts[6],
4106                ];
4107                let high_i16 = [
4108                    self.intrinsics.i32_consts[1],
4109                    self.intrinsics.i32_consts[3],
4110                    self.intrinsics.i32_consts[5],
4111                    self.intrinsics.i32_consts[7],
4112                ];
4113                let v1_low = err!(self.builder.build_shuffle_vector(
4114                    v1,
4115                    v1.get_type().get_undef(),
4116                    VectorType::const_vector(&low_i16),
4117                    "",
4118                ));
4119                let v1_low = err!(self.builder.build_int_s_extend(
4120                    v1_low,
4121                    self.intrinsics.i32x4_ty,
4122                    ""
4123                ));
4124                let v1_high = err!(self.builder.build_shuffle_vector(
4125                    v1,
4126                    v1.get_type().get_undef(),
4127                    VectorType::const_vector(&high_i16),
4128                    "",
4129                ));
4130                let v1_high = err!(self.builder.build_int_s_extend(
4131                    v1_high,
4132                    self.intrinsics.i32x4_ty,
4133                    ""
4134                ));
4135                let v2_low = err!(self.builder.build_shuffle_vector(
4136                    v2,
4137                    v2.get_type().get_undef(),
4138                    VectorType::const_vector(&low_i16),
4139                    "",
4140                ));
4141                let v2_low = err!(self.builder.build_int_s_extend(
4142                    v2_low,
4143                    self.intrinsics.i32x4_ty,
4144                    ""
4145                ));
4146                let v2_high = err!(self.builder.build_shuffle_vector(
4147                    v2,
4148                    v2.get_type().get_undef(),
4149                    VectorType::const_vector(&high_i16),
4150                    "",
4151                ));
4152                let v2_high = err!(self.builder.build_int_s_extend(
4153                    v2_high,
4154                    self.intrinsics.i32x4_ty,
4155                    ""
4156                ));
4157                let low_product = err!(self.builder.build_int_mul(v1_low, v2_low, ""));
4158                let high_product = err!(self.builder.build_int_mul(v1_high, v2_high, ""));
4159
4160                let res = err!(self.builder.build_int_add(low_product, high_product, ""));
4161                let res = err!(
4162                    self.builder
4163                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4164                );
4165                self.state.push1(res);
4166            }
4167            Operator::I16x8RelaxedDotI8x16I7x16S
4168                if self.cpu_features.contains(CpuFeature::SSSE3) =>
4169            {
4170                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4171                let (a, _) = self.v128_into_i8x16(v1, i1)?;
4172                let (b, _) = self.v128_into_i8x16(v2, i2)?;
4173
4174                let res = self
4175                    .build_call_with_param_attributes(
4176                        self.intrinsics.x86_64.pmaddubsw128,
4177                        &[b.into(), a.into()],
4178                        "",
4179                    )?
4180                    .try_as_basic_value()
4181                    .unwrap_basic()
4182                    .into_vector_value();
4183                let res = err!(
4184                    self.builder
4185                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4186                );
4187                self.state.push1(res);
4188            }
4189            Operator::I16x8RelaxedDotI8x16I7x16S => {
4190                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4191                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4192                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4193
4194                let left_indices = [
4195                    self.intrinsics.i32_consts[0],
4196                    self.intrinsics.i32_consts[2],
4197                    self.intrinsics.i32_consts[4],
4198                    self.intrinsics.i32_consts[6],
4199                    self.intrinsics.i32_consts[8],
4200                    self.intrinsics.i32_consts[10],
4201                    self.intrinsics.i32_consts[12],
4202                    self.intrinsics.i32_consts[14],
4203                ];
4204                let right_indices = [
4205                    self.intrinsics.i32_consts[1],
4206                    self.intrinsics.i32_consts[3],
4207                    self.intrinsics.i32_consts[5],
4208                    self.intrinsics.i32_consts[7],
4209                    self.intrinsics.i32_consts[9],
4210                    self.intrinsics.i32_consts[11],
4211                    self.intrinsics.i32_consts[13],
4212                    self.intrinsics.i32_consts[15],
4213                ];
4214
4215                let v1_left = err!(self.builder.build_shuffle_vector(
4216                    v1,
4217                    v1.get_type().get_undef(),
4218                    VectorType::const_vector(&left_indices),
4219                    "",
4220                ));
4221                let v1_left = err!(self.builder.build_int_s_extend(
4222                    v1_left,
4223                    self.intrinsics.i16x8_ty,
4224                    ""
4225                ));
4226                let v1_right = err!(self.builder.build_shuffle_vector(
4227                    v1,
4228                    v1.get_type().get_undef(),
4229                    VectorType::const_vector(&right_indices),
4230                    "",
4231                ));
4232                let v1_right = err!(self.builder.build_int_s_extend(
4233                    v1_right,
4234                    self.intrinsics.i16x8_ty,
4235                    ""
4236                ));
4237
4238                let v2_left = err!(self.builder.build_shuffle_vector(
4239                    v2,
4240                    v2.get_type().get_undef(),
4241                    VectorType::const_vector(&left_indices),
4242                    "",
4243                ));
4244                let v2_left = err!(self.builder.build_int_s_extend(
4245                    v2_left,
4246                    self.intrinsics.i16x8_ty,
4247                    ""
4248                ));
4249                let v2_right = err!(self.builder.build_shuffle_vector(
4250                    v2,
4251                    v2.get_type().get_undef(),
4252                    VectorType::const_vector(&right_indices),
4253                    "",
4254                ));
4255                let v2_right = err!(self.builder.build_int_s_extend(
4256                    v2_right,
4257                    self.intrinsics.i16x8_ty,
4258                    ""
4259                ));
4260
4261                let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4262                let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4263                let res = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4264                let res = err!(
4265                    self.builder
4266                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4267                );
4268                self.state.push1(res);
4269            }
4270            Operator::I32x4RelaxedDotI8x16I7x16AddS
4271                if self.cpu_features.contains(CpuFeature::SSSE3) =>
4272            {
4273                let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4274                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4275                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4276                let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4277
4278                // PMADDUBSW computes pairwise u8*i8 with i16 saturation, which
4279                // is one of the valid relaxed dot-product behaviors.
4280                let dot16 = self
4281                    .build_call_with_param_attributes(
4282                        self.intrinsics.x86_64.pmaddubsw128,
4283                        &[v2.into(), v1.into()],
4284                        "",
4285                    )?
4286                    .try_as_basic_value()
4287                    .unwrap_basic()
4288                    .into_vector_value();
4289                let ones =
4290                    VectorType::const_vector(&[self.intrinsics.i16_ty.const_int(1, false); 8]);
4291                let dot32 = self
4292                    .build_call_with_param_attributes(
4293                        self.intrinsics.x86_64.pmaddwd128,
4294                        &[dot16.into(), ones.into()],
4295                        "",
4296                    )?
4297                    .try_as_basic_value()
4298                    .unwrap_basic()
4299                    .into_vector_value();
4300                let res = err!(self.builder.build_int_add(dot32, acc, ""));
4301                let res = err!(
4302                    self.builder
4303                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4304                );
4305                self.state.push1(res);
4306            }
4307            Operator::I32x4RelaxedDotI8x16I7x16AddS => {
4308                let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4309                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4310                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4311                let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4312
4313                let left_indices = [
4314                    self.intrinsics.i32_consts[0],
4315                    self.intrinsics.i32_consts[2],
4316                    self.intrinsics.i32_consts[4],
4317                    self.intrinsics.i32_consts[6],
4318                    self.intrinsics.i32_consts[8],
4319                    self.intrinsics.i32_consts[10],
4320                    self.intrinsics.i32_consts[12],
4321                    self.intrinsics.i32_consts[14],
4322                ];
4323                let right_indices = [
4324                    self.intrinsics.i32_consts[1],
4325                    self.intrinsics.i32_consts[3],
4326                    self.intrinsics.i32_consts[5],
4327                    self.intrinsics.i32_consts[7],
4328                    self.intrinsics.i32_consts[9],
4329                    self.intrinsics.i32_consts[11],
4330                    self.intrinsics.i32_consts[13],
4331                    self.intrinsics.i32_consts[15],
4332                ];
4333
4334                let v1_left = err!(self.builder.build_shuffle_vector(
4335                    v1,
4336                    v1.get_type().get_undef(),
4337                    VectorType::const_vector(&left_indices),
4338                    "",
4339                ));
4340                let v1_left = err!(self.builder.build_int_s_extend(
4341                    v1_left,
4342                    self.intrinsics.i16x8_ty,
4343                    ""
4344                ));
4345                let v1_right = err!(self.builder.build_shuffle_vector(
4346                    v1,
4347                    v1.get_type().get_undef(),
4348                    VectorType::const_vector(&right_indices),
4349                    "",
4350                ));
4351                let v1_right = err!(self.builder.build_int_s_extend(
4352                    v1_right,
4353                    self.intrinsics.i16x8_ty,
4354                    ""
4355                ));
4356
4357                let v2_left = err!(self.builder.build_shuffle_vector(
4358                    v2,
4359                    v2.get_type().get_undef(),
4360                    VectorType::const_vector(&left_indices),
4361                    "",
4362                ));
4363                let v2_left = err!(self.builder.build_int_s_extend(
4364                    v2_left,
4365                    self.intrinsics.i16x8_ty,
4366                    ""
4367                ));
4368                let v2_right = err!(self.builder.build_shuffle_vector(
4369                    v2,
4370                    v2.get_type().get_undef(),
4371                    VectorType::const_vector(&right_indices),
4372                    "",
4373                ));
4374                let v2_right = err!(self.builder.build_int_s_extend(
4375                    v2_right,
4376                    self.intrinsics.i16x8_ty,
4377                    ""
4378                ));
4379
4380                let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4381                let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4382                let dot16 = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4383
4384                let pair_left = err!(self.builder.build_shuffle_vector(
4385                    dot16,
4386                    dot16.get_type().get_undef(),
4387                    VectorType::const_vector(&[
4388                        self.intrinsics.i32_consts[0],
4389                        self.intrinsics.i32_consts[2],
4390                        self.intrinsics.i32_consts[4],
4391                        self.intrinsics.i32_consts[6],
4392                    ]),
4393                    "",
4394                ));
4395                let pair_left = err!(self.builder.build_int_s_extend(
4396                    pair_left,
4397                    self.intrinsics.i32x4_ty,
4398                    ""
4399                ));
4400                let pair_right = err!(self.builder.build_shuffle_vector(
4401                    dot16,
4402                    dot16.get_type().get_undef(),
4403                    VectorType::const_vector(&[
4404                        self.intrinsics.i32_consts[1],
4405                        self.intrinsics.i32_consts[3],
4406                        self.intrinsics.i32_consts[5],
4407                        self.intrinsics.i32_consts[7],
4408                    ]),
4409                    "",
4410                ));
4411                let pair_right = err!(self.builder.build_int_s_extend(
4412                    pair_right,
4413                    self.intrinsics.i32x4_ty,
4414                    ""
4415                ));
4416                let dot32 = err!(self.builder.build_int_add(pair_left, pair_right, ""));
4417                let res = err!(self.builder.build_int_add(dot32, acc, ""));
4418                let res = err!(
4419                    self.builder
4420                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4421                );
4422                self.state.push1(res);
4423            }
4424            Operator::I32DivS | Operator::I64DivS => {
4425                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4426                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4427                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4428                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4429
4430                self.trap_if_zero_or_overflow(v1, v2)?;
4431
4432                let res = err!(self.builder.build_int_signed_div(v1, v2, ""));
4433                self.state.push1(res);
4434            }
4435            Operator::I32DivU | Operator::I64DivU => {
4436                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4437                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4438                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4439                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4440
4441                self.trap_if_zero(v2)?;
4442
4443                let res = err!(self.builder.build_int_unsigned_div(v1, v2, ""));
4444                self.state.push1(res);
4445            }
4446            Operator::I32RemS | Operator::I64RemS => {
4447                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4448                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4449                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4450                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4451                let int_type = v1.get_type();
4452                let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
4453                    let min_value = int_type.const_int(i32::MIN as u64, false);
4454                    let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
4455                    (min_value, neg_one_value)
4456                } else if int_type == self.intrinsics.i64_ty {
4457                    let min_value = int_type.const_int(i64::MIN as u64, false);
4458                    let neg_one_value = int_type.const_int(-1i64 as u64, false);
4459                    (min_value, neg_one_value)
4460                } else {
4461                    unreachable!()
4462                };
4463
4464                self.trap_if_zero(v2)?;
4465
4466                // "Overflow also leads to undefined behavior; this is a rare
4467                // case, but can occur, for example, by taking the remainder of
4468                // a 32-bit division of -2147483648 by -1. (The remainder
4469                // doesn’t actually overflow, but this rule lets srem be
4470                // implemented using instructions that return both the result
4471                // of the division and the remainder.)"
4472                //   -- https://llvm.org/docs/LangRef.html#srem-instruction
4473                //
4474                // In Wasm, the i32.rem_s i32.const -2147483648 i32.const -1 is
4475                // i32.const 0. We implement this by swapping out the left value
4476                // for 0 in this case.
4477                let will_overflow = err!(self.builder.build_and(
4478                    err!(self.builder.build_int_compare(
4479                        IntPredicate::EQ,
4480                        v1,
4481                        min_value,
4482                        "left_is_min"
4483                    )),
4484                    err!(self.builder.build_int_compare(
4485                        IntPredicate::EQ,
4486                        v2,
4487                        neg_one_value,
4488                        "right_is_neg_one",
4489                    )),
4490                    "srem_will_overflow",
4491                ));
4492                let v1 =
4493                    err!(
4494                        self.builder
4495                            .build_select(will_overflow, int_type.const_zero(), v1, "")
4496                    )
4497                    .into_int_value();
4498                let res = err!(self.builder.build_int_signed_rem(v1, v2, ""));
4499                self.state.push1(res);
4500            }
4501            Operator::I32RemU | Operator::I64RemU => {
4502                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4503                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4504                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4505                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4506
4507                self.trap_if_zero(v2)?;
4508
4509                let res = err!(self.builder.build_int_unsigned_rem(v1, v2, ""));
4510                self.state.push1(res);
4511            }
4512            Operator::I32And | Operator::I64And | Operator::V128And => {
4513                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4514                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4515                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4516                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4517                let res = err!(self.builder.build_and(v1, v2, ""));
4518                self.state.push1(res);
4519            }
4520            Operator::I32Or | Operator::I64Or | Operator::V128Or => {
4521                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4522                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4523                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4524                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4525                let res = err!(self.builder.build_or(v1, v2, ""));
4526                self.state.push1(res);
4527            }
4528            Operator::I32Xor | Operator::I64Xor | Operator::V128Xor => {
4529                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4530                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4531                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4532                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4533                let res = err!(self.builder.build_xor(v1, v2, ""));
4534                self.state.push1(res);
4535            }
4536            Operator::V128AndNot => {
4537                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4538                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4539                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4540                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4541                let v2 = err!(self.builder.build_not(v2, ""));
4542                let res = err!(self.builder.build_and(v1, v2, ""));
4543                self.state.push1(res);
4544            }
4545            Operator::I8x16RelaxedLaneselect
4546            | Operator::I16x8RelaxedLaneselect
4547            | Operator::I32x4RelaxedLaneselect
4548            | Operator::I64x2RelaxedLaneselect
4549                if self.cpu_features.contains(CpuFeature::SSE41) =>
4550            {
4551                let ((v1, i1), (v2, i2), (mask, mask_info)) = self.state.pop3_extra()?;
4552                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4553                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4554                let mask = self.apply_pending_canonicalization(mask, mask_info)?;
4555
4556                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4557                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4558                let (mask, _) = self.v128_into_i8x16(mask, mask_info)?;
4559                let res = self
4560                    .build_call_with_param_attributes(
4561                        self.intrinsics.x86_64.pblendvb,
4562                        &[v2.into(), v1.into(), mask.into()],
4563                        "",
4564                    )?
4565                    .try_as_basic_value()
4566                    .unwrap_basic();
4567                let res = err!(
4568                    self.builder
4569                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4570                );
4571                self.state.push1(res);
4572            }
4573            Operator::I8x16RelaxedLaneselect
4574            | Operator::I16x8RelaxedLaneselect
4575            | Operator::I32x4RelaxedLaneselect
4576            | Operator::I64x2RelaxedLaneselect
4577            | Operator::V128Bitselect => {
4578                let ((v1, i1), (v2, i2), (cond, cond_info)) = self.state.pop3_extra()?;
4579                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4580                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4581                let cond = self.apply_pending_canonicalization(cond, cond_info)?;
4582                let v1 = err!(
4583                    self.builder
4584                        .build_bit_cast(v1, self.intrinsics.i1x128_ty, "")
4585                )
4586                .into_vector_value();
4587                let v2 = err!(
4588                    self.builder
4589                        .build_bit_cast(v2, self.intrinsics.i1x128_ty, "")
4590                )
4591                .into_vector_value();
4592                let cond = err!(
4593                    self.builder
4594                        .build_bit_cast(cond, self.intrinsics.i1x128_ty, "")
4595                )
4596                .into_vector_value();
4597                let res = err!(self.builder.build_select(cond, v1, v2, ""));
4598                let res = err!(
4599                    self.builder
4600                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4601                );
4602                self.state.push1(res);
4603            }
4604            Operator::I8x16Bitmask => {
4605                let (v, i) = self.state.pop1_extra()?;
4606                let (v, _) = self.v128_into_i8x16(v, i)?;
4607
4608                let zeros = self.intrinsics.i8x16_ty.const_zero();
4609                let res = err!(
4610                    self.builder
4611                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
4612                );
4613                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i16_ty, ""))
4614                    .into_int_value();
4615                let res = err!(
4616                    self.builder
4617                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4618                );
4619                self.state.push1(res);
4620            }
4621            Operator::I16x8Bitmask => {
4622                let (v, i) = self.state.pop1_extra()?;
4623                let (v, _) = self.v128_into_i16x8(v, i)?;
4624
4625                let zeros = self.intrinsics.i16x8_ty.const_zero();
4626                let res = err!(
4627                    self.builder
4628                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
4629                );
4630                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i8_ty, ""))
4631                    .into_int_value();
4632                let res = err!(
4633                    self.builder
4634                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4635                );
4636                self.state.push1(res);
4637            }
4638            Operator::I32x4Bitmask => {
4639                let (v, i) = self.state.pop1_extra()?;
4640                let (v, _) = self.v128_into_i32x4(v, i)?;
4641
4642                let zeros = self.intrinsics.i32x4_ty.const_zero();
4643                let res = err!(
4644                    self.builder
4645                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
4646                );
4647                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i4_ty, ""))
4648                    .into_int_value();
4649                let res = err!(
4650                    self.builder
4651                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4652                );
4653                self.state.push1(res);
4654            }
4655            Operator::I64x2Bitmask => {
4656                let (v, i) = self.state.pop1_extra()?;
4657                let (v, _) = self.v128_into_i64x2(v, i)?;
4658
4659                let zeros = self.intrinsics.i64x2_ty.const_zero();
4660                let res = err!(
4661                    self.builder
4662                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
4663                );
4664                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i2_ty, ""))
4665                    .into_int_value();
4666                let res = err!(
4667                    self.builder
4668                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4669                );
4670                self.state.push1(res);
4671            }
4672            Operator::I32Shl => {
4673                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4674                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4675                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4676                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4677                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4678                let v2 = err!(self.builder.build_and(v2, mask, ""));
4679                let res = err!(self.builder.build_left_shift(v1, v2, ""));
4680                self.state.push1(res);
4681            }
4682            Operator::I64Shl => {
4683                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4684                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4685                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4686                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4687                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4688                let v2 = err!(self.builder.build_and(v2, mask, ""));
4689                let res = err!(self.builder.build_left_shift(v1, v2, ""));
4690                self.state.push1(res);
4691            }
4692            Operator::I8x16Shl => {
4693                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4694                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4695                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4696                let v2 = v2.into_int_value();
4697                let v2 = err!(
4698                    self.builder
4699                        .build_and(v2, self.intrinsics.i32_consts[7], "")
4700                );
4701                let v2 = err!(
4702                    self.builder
4703                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
4704                );
4705                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
4706                let res = err!(self.builder.build_left_shift(v1, v2, ""));
4707                let res = err!(
4708                    self.builder
4709                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4710                );
4711                self.state.push1(res);
4712            }
4713            Operator::I16x8Shl => {
4714                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4715                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4716                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4717                let v2 = v2.into_int_value();
4718                let v2 = err!(
4719                    self.builder
4720                        .build_and(v2, self.intrinsics.i32_consts[15], "")
4721                );
4722                let v2 = err!(
4723                    self.builder
4724                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
4725                );
4726                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
4727                let res = err!(self.builder.build_left_shift(v1, v2, ""));
4728                let res = err!(
4729                    self.builder
4730                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4731                );
4732                self.state.push1(res);
4733            }
4734            Operator::I32x4Shl => {
4735                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4736                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4737                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4738                let v2 = v2.into_int_value();
4739                let v2 = err!(self.builder.build_and(
4740                    v2,
4741                    self.intrinsics.i32_ty.const_int(31, false),
4742                    ""
4743                ));
4744                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
4745                let res = err!(self.builder.build_left_shift(v1, v2, ""));
4746                let res = err!(
4747                    self.builder
4748                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4749                );
4750                self.state.push1(res);
4751            }
4752            Operator::I64x2Shl => {
4753                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4754                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4755                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4756                let v2 = v2.into_int_value();
4757                let v2 = err!(self.builder.build_and(
4758                    v2,
4759                    self.intrinsics.i32_ty.const_int(63, false),
4760                    ""
4761                ));
4762                let v2 = err!(
4763                    self.builder
4764                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
4765                );
4766                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
4767                let res = err!(self.builder.build_left_shift(v1, v2, ""));
4768                let res = err!(
4769                    self.builder
4770                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4771                );
4772                self.state.push1(res);
4773            }
4774            Operator::I32ShrS => {
4775                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4776                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4777                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4778                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4779                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4780                let v2 = err!(self.builder.build_and(v2, mask, ""));
4781                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4782                self.state.push1(res);
4783            }
4784            Operator::I64ShrS => {
4785                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4786                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4787                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4788                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4789                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4790                let v2 = err!(self.builder.build_and(v2, mask, ""));
4791                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4792                self.state.push1(res);
4793            }
4794            Operator::I8x16ShrS => {
4795                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4796                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4797                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4798                let v2 = v2.into_int_value();
4799                let v2 = err!(
4800                    self.builder
4801                        .build_and(v2, self.intrinsics.i32_consts[7], "")
4802                );
4803                let v2 = err!(
4804                    self.builder
4805                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
4806                );
4807                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
4808                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4809                let res = err!(
4810                    self.builder
4811                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4812                );
4813                self.state.push1(res);
4814            }
4815            Operator::I16x8ShrS => {
4816                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4817                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4818                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4819                let v2 = v2.into_int_value();
4820                let v2 = err!(
4821                    self.builder
4822                        .build_and(v2, self.intrinsics.i32_consts[15], "")
4823                );
4824                let v2 = err!(
4825                    self.builder
4826                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
4827                );
4828                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
4829                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4830                let res = err!(
4831                    self.builder
4832                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4833                );
4834                self.state.push1(res);
4835            }
4836            Operator::I32x4ShrS => {
4837                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4838                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4839                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4840                let v2 = v2.into_int_value();
4841                let v2 = err!(self.builder.build_and(
4842                    v2,
4843                    self.intrinsics.i32_ty.const_int(31, false),
4844                    ""
4845                ));
4846                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
4847                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4848                let res = err!(
4849                    self.builder
4850                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4851                );
4852                self.state.push1(res);
4853            }
4854            Operator::I64x2ShrS => {
4855                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4856                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4857                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4858                let v2 = v2.into_int_value();
4859                let v2 = err!(self.builder.build_and(
4860                    v2,
4861                    self.intrinsics.i32_ty.const_int(63, false),
4862                    ""
4863                ));
4864                let v2 = err!(
4865                    self.builder
4866                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
4867                );
4868                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
4869                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4870                let res = err!(
4871                    self.builder
4872                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4873                );
4874                self.state.push1(res);
4875            }
4876            Operator::I32ShrU => {
4877                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4878                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4879                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4880                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4881                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4882                let v2 = err!(self.builder.build_and(v2, mask, ""));
4883                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4884                self.state.push1(res);
4885            }
4886            Operator::I64ShrU => {
4887                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4888                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4889                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4890                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4891                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4892                let v2 = err!(self.builder.build_and(v2, mask, ""));
4893                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4894                self.state.push1(res);
4895            }
4896            Operator::I8x16ShrU => {
4897                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4898                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4899                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4900                let v2 = v2.into_int_value();
4901                let v2 = err!(
4902                    self.builder
4903                        .build_and(v2, self.intrinsics.i32_consts[7], "")
4904                );
4905                let v2 = err!(
4906                    self.builder
4907                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
4908                );
4909                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
4910                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4911                let res = err!(
4912                    self.builder
4913                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4914                );
4915                self.state.push1(res);
4916            }
4917            Operator::I16x8ShrU => {
4918                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4919                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4920                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4921                let v2 = v2.into_int_value();
4922                let v2 = err!(
4923                    self.builder
4924                        .build_and(v2, self.intrinsics.i32_consts[15], "")
4925                );
4926                let v2 = err!(
4927                    self.builder
4928                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
4929                );
4930                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
4931                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4932                let res = err!(
4933                    self.builder
4934                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4935                );
4936                self.state.push1(res);
4937            }
4938            Operator::I32x4ShrU => {
4939                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4940                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4941                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4942                let v2 = v2.into_int_value();
4943                let v2 = err!(self.builder.build_and(
4944                    v2,
4945                    self.intrinsics.i32_ty.const_int(31, false),
4946                    ""
4947                ));
4948                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
4949                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4950                let res = err!(
4951                    self.builder
4952                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4953                );
4954                self.state.push1(res);
4955            }
4956            Operator::I64x2ShrU => {
4957                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4958                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4959                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4960                let v2 = v2.into_int_value();
4961                let v2 = err!(self.builder.build_and(
4962                    v2,
4963                    self.intrinsics.i32_ty.const_int(63, false),
4964                    ""
4965                ));
4966                let v2 = err!(
4967                    self.builder
4968                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
4969                );
4970                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
4971                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4972                let res = err!(
4973                    self.builder
4974                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4975                );
4976                self.state.push1(res);
4977            }
4978            Operator::I32Rotl => {
4979                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4980                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4981                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4982                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4983                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4984                let v2 = err!(self.builder.build_and(v2, mask, ""));
4985                let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
4986                let rhs = {
4987                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
4988                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
4989                    err!(self.builder.build_right_shift(v1, rhs, false, ""))
4990                };
4991                let res = err!(self.builder.build_or(lhs, rhs, ""));
4992                self.state.push1(res);
4993            }
4994            Operator::I64Rotl => {
4995                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4996                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4997                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4998                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4999                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5000                let v2 = err!(self.builder.build_and(v2, mask, ""));
5001                let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5002                let rhs = {
5003                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5004                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5005                    err!(self.builder.build_right_shift(v1, rhs, false, ""))
5006                };
5007                let res = err!(self.builder.build_or(lhs, rhs, ""));
5008                self.state.push1(res);
5009            }
5010            Operator::I32Rotr => {
5011                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5012                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5013                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5014                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5015                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5016                let v2 = err!(self.builder.build_and(v2, mask, ""));
5017                let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5018                let rhs = {
5019                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5020                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5021                    err!(self.builder.build_left_shift(v1, rhs, ""))
5022                };
5023                let res = err!(self.builder.build_or(lhs, rhs, ""));
5024                self.state.push1(res);
5025            }
5026            Operator::I64Rotr => {
5027                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5028                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5029                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5030                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5031                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5032                let v2 = err!(self.builder.build_and(v2, mask, ""));
5033                let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5034                let rhs = {
5035                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5036                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5037                    err!(self.builder.build_left_shift(v1, rhs, ""))
5038                };
5039                let res = err!(self.builder.build_or(lhs, rhs, ""));
5040                self.state.push1(res);
5041            }
5042            Operator::I32Clz => {
5043                let (input, info) = self.state.pop1_extra()?;
5044                let input = self.apply_pending_canonicalization(input, info)?;
5045                let is_zero_undef = self.intrinsics.i1_zero;
5046                let res = self
5047                    .build_call_with_param_attributes(
5048                        self.intrinsics.ctlz_i32,
5049                        &[input.into(), is_zero_undef.into()],
5050                        "",
5051                    )?
5052                    .try_as_basic_value()
5053                    .unwrap_basic();
5054                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5055            }
5056            Operator::I64Clz => {
5057                let (input, info) = self.state.pop1_extra()?;
5058                let input = self.apply_pending_canonicalization(input, info)?;
5059                let is_zero_undef = self.intrinsics.i1_zero;
5060                let res = self
5061                    .build_call_with_param_attributes(
5062                        self.intrinsics.ctlz_i64,
5063                        &[input.into(), is_zero_undef.into()],
5064                        "",
5065                    )?
5066                    .try_as_basic_value()
5067                    .unwrap_basic();
5068                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5069            }
5070            Operator::I32Ctz => {
5071                let (input, info) = self.state.pop1_extra()?;
5072                let input = self.apply_pending_canonicalization(input, info)?;
5073                let is_zero_undef = self.intrinsics.i1_zero;
5074                let res = self
5075                    .build_call_with_param_attributes(
5076                        self.intrinsics.cttz_i32,
5077                        &[input.into(), is_zero_undef.into()],
5078                        "",
5079                    )?
5080                    .try_as_basic_value()
5081                    .unwrap_basic();
5082                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5083            }
5084            Operator::I64Ctz => {
5085                let (input, info) = self.state.pop1_extra()?;
5086                let input = self.apply_pending_canonicalization(input, info)?;
5087                let is_zero_undef = self.intrinsics.i1_zero;
5088                let res = self
5089                    .build_call_with_param_attributes(
5090                        self.intrinsics.cttz_i64,
5091                        &[input.into(), is_zero_undef.into()],
5092                        "",
5093                    )?
5094                    .try_as_basic_value()
5095                    .unwrap_basic();
5096                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5097            }
5098            Operator::I8x16Popcnt => {
5099                let (v, i) = self.state.pop1_extra()?;
5100                let (v, _) = self.v128_into_i8x16(v, i)?;
5101                let res = self
5102                    .build_call_with_param_attributes(self.intrinsics.ctpop_i8x16, &[v.into()], "")?
5103                    .try_as_basic_value()
5104                    .unwrap_basic();
5105                let res = err!(
5106                    self.builder
5107                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5108                );
5109                self.state.push1(res);
5110            }
5111            Operator::I32Popcnt => {
5112                let (input, info) = self.state.pop1_extra()?;
5113                let input = self.apply_pending_canonicalization(input, info)?;
5114                let res = self
5115                    .build_call_with_param_attributes(
5116                        self.intrinsics.ctpop_i32,
5117                        &[input.into()],
5118                        "",
5119                    )?
5120                    .try_as_basic_value()
5121                    .unwrap_basic();
5122                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5123            }
5124            Operator::I64Popcnt => {
5125                let (input, info) = self.state.pop1_extra()?;
5126                let input = self.apply_pending_canonicalization(input, info)?;
5127                let res = self
5128                    .build_call_with_param_attributes(
5129                        self.intrinsics.ctpop_i64,
5130                        &[input.into()],
5131                        "",
5132                    )?
5133                    .try_as_basic_value()
5134                    .unwrap_basic();
5135                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5136            }
5137            Operator::I32Eqz => {
5138                let input = self.state.pop1()?.into_int_value();
5139                let cond = err!(self.builder.build_int_compare(
5140                    IntPredicate::EQ,
5141                    input,
5142                    self.intrinsics.i32_zero,
5143                    "",
5144                ));
5145                let res = err!(
5146                    self.builder
5147                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5148                );
5149                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5150            }
5151            Operator::I64Eqz => {
5152                let input = self.state.pop1()?.into_int_value();
5153                let cond = err!(self.builder.build_int_compare(
5154                    IntPredicate::EQ,
5155                    input,
5156                    self.intrinsics.i64_zero,
5157                    "",
5158                ));
5159                let res = err!(
5160                    self.builder
5161                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5162                );
5163                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5164            }
5165            Operator::I8x16Abs => {
5166                let (v, i) = self.state.pop1_extra()?;
5167                let (v, _) = self.v128_into_i8x16(v, i)?;
5168
5169                let seven = self.intrinsics.i8_ty.const_int(7, false);
5170                let seven = VectorType::const_vector(&[seven; 16]);
5171                let all_sign_bits = err!(self.builder.build_right_shift(v, seven, true, ""));
5172                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5173                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5174                let res = err!(
5175                    self.builder
5176                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5177                );
5178                self.state.push1(res);
5179            }
5180            Operator::I16x8Abs => {
5181                let (v, i) = self.state.pop1_extra()?;
5182                let (v, _) = self.v128_into_i16x8(v, i)?;
5183
5184                let fifteen = self.intrinsics.i16_ty.const_int(15, false);
5185                let fifteen = VectorType::const_vector(&[fifteen; 8]);
5186                let all_sign_bits = err!(self.builder.build_right_shift(v, fifteen, true, ""));
5187                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5188                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5189                let res = err!(
5190                    self.builder
5191                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5192                );
5193                self.state.push1(res);
5194            }
5195            Operator::I32x4Abs => {
5196                let (v, i) = self.state.pop1_extra()?;
5197                let (v, _) = self.v128_into_i32x4(v, i)?;
5198
5199                let thirtyone = self.intrinsics.i32_ty.const_int(31, false);
5200                let thirtyone = VectorType::const_vector(&[thirtyone; 4]);
5201                let all_sign_bits = err!(self.builder.build_right_shift(v, thirtyone, true, ""));
5202                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5203                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5204                let res = err!(
5205                    self.builder
5206                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5207                );
5208                self.state.push1(res);
5209            }
5210            Operator::I64x2Abs => {
5211                let (v, i) = self.state.pop1_extra()?;
5212                let (v, _) = self.v128_into_i64x2(v, i)?;
5213
5214                let sixtythree = self.intrinsics.i64_ty.const_int(63, false);
5215                let sixtythree = VectorType::const_vector(&[sixtythree; 2]);
5216                let all_sign_bits = err!(self.builder.build_right_shift(v, sixtythree, true, ""));
5217                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5218                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5219                let res = err!(
5220                    self.builder
5221                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5222                );
5223                self.state.push1(res);
5224            }
5225            Operator::I8x16MinS => {
5226                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5227                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5228                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5229                let cmp = err!(
5230                    self.builder
5231                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5232                );
5233                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5234                let res = err!(
5235                    self.builder
5236                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5237                );
5238                self.state.push1(res);
5239            }
5240            Operator::I8x16MinU => {
5241                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5242                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5243                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5244                let cmp = err!(
5245                    self.builder
5246                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5247                );
5248                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5249                let res = err!(
5250                    self.builder
5251                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5252                );
5253                self.state.push1(res);
5254            }
5255            Operator::I8x16MaxS => {
5256                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5257                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5258                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5259                let cmp = err!(
5260                    self.builder
5261                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5262                );
5263                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5264                let res = err!(
5265                    self.builder
5266                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5267                );
5268                self.state.push1(res);
5269            }
5270            Operator::I8x16MaxU => {
5271                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5272                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5273                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5274                let cmp = err!(
5275                    self.builder
5276                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5277                );
5278                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5279                let res = err!(
5280                    self.builder
5281                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5282                );
5283                self.state.push1(res);
5284            }
5285            Operator::I16x8MinS => {
5286                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5287                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5288                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5289                let cmp = err!(
5290                    self.builder
5291                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5292                );
5293                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5294                let res = err!(
5295                    self.builder
5296                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5297                );
5298                self.state.push1(res);
5299            }
5300            Operator::I16x8MinU => {
5301                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5302                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5303                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5304                let cmp = err!(
5305                    self.builder
5306                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5307                );
5308                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5309                let res = err!(
5310                    self.builder
5311                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5312                );
5313                self.state.push1(res);
5314            }
5315            Operator::I16x8MaxS => {
5316                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5317                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5318                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5319                let cmp = err!(
5320                    self.builder
5321                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5322                );
5323                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5324                let res = err!(
5325                    self.builder
5326                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5327                );
5328                self.state.push1(res);
5329            }
5330            Operator::I16x8MaxU => {
5331                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5332                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5333                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5334                let cmp = err!(
5335                    self.builder
5336                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5337                );
5338                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5339                let res = err!(
5340                    self.builder
5341                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5342                );
5343                self.state.push1(res);
5344            }
5345            Operator::I32x4MinS => {
5346                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5347                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5348                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5349                let cmp = err!(
5350                    self.builder
5351                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5352                );
5353                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5354                let res = err!(
5355                    self.builder
5356                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5357                );
5358                self.state.push1(res);
5359            }
5360            Operator::I32x4MinU => {
5361                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5362                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5363                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5364                let cmp = err!(
5365                    self.builder
5366                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5367                );
5368                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5369                let res = err!(
5370                    self.builder
5371                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5372                );
5373                self.state.push1(res);
5374            }
5375            Operator::I32x4MaxS => {
5376                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5377                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5378                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5379                let cmp = err!(
5380                    self.builder
5381                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5382                );
5383                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5384                let res = err!(
5385                    self.builder
5386                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5387                );
5388                self.state.push1(res);
5389            }
5390            Operator::I32x4MaxU => {
5391                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5392                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5393                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5394                let cmp = err!(
5395                    self.builder
5396                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5397                );
5398                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5399                let res = err!(
5400                    self.builder
5401                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5402                );
5403                self.state.push1(res);
5404            }
5405            Operator::I8x16AvgrU => {
5406                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5407                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5408                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5409
5410                // This approach is faster on x86-64 when the PAVG[BW]
5411                // instructions are available. On other platforms, an alternative
5412                // implementation appears likely to outperform, described here:
5413                //   %a = or %v1, %v2
5414                //   %b = and %a, 1
5415                //   %v1 = lshr %v1, 1
5416                //   %v2 = lshr %v2, 1
5417                //   %sum = add %v1, %v2
5418                //   %res = add %sum, %b
5419
5420                let ext_ty = self.intrinsics.i16_ty.vec_type(16);
5421                let one = self.intrinsics.i16_ty.const_int(1, false);
5422                let one = VectorType::const_vector(&[one; 16]);
5423
5424                let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5425                let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5426                let res = err!(self.builder.build_int_add(
5427                    err!(self.builder.build_int_add(one, v1, "")),
5428                    v2,
5429                    ""
5430                ));
5431                let res = err!(self.builder.build_right_shift(res, one, false, ""));
5432                let res = err!(
5433                    self.builder
5434                        .build_int_truncate(res, self.intrinsics.i8x16_ty, "")
5435                );
5436                let res = err!(
5437                    self.builder
5438                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5439                );
5440                self.state.push1(res);
5441            }
5442            Operator::I16x8AvgrU => {
5443                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5444                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5445                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5446
5447                // This approach is faster on x86-64 when the PAVG[BW]
5448                // instructions are available. On other platforms, an alternative
5449                // implementation appears likely to outperform, described here:
5450                //   %a = or %v1, %v2
5451                //   %b = and %a, 1
5452                //   %v1 = lshr %v1, 1
5453                //   %v2 = lshr %v2, 1
5454                //   %sum = add %v1, %v2
5455                //   %res = add %sum, %b
5456
5457                let ext_ty = self.intrinsics.i32_ty.vec_type(8);
5458                let one = self.intrinsics.i32_consts[1];
5459                let one = VectorType::const_vector(&[one; 8]);
5460
5461                let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5462                let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5463                let res = err!(self.builder.build_int_add(
5464                    err!(self.builder.build_int_add(one, v1, "")),
5465                    v2,
5466                    ""
5467                ));
5468                let res = err!(self.builder.build_right_shift(res, one, false, ""));
5469                let res = err!(
5470                    self.builder
5471                        .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
5472                );
5473                let res = err!(
5474                    self.builder
5475                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5476                );
5477                self.state.push1(res);
5478            }
5479
5480            /***************************
5481             * Floating-Point Arithmetic instructions.
5482             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-arithmetic-instructions
5483             ***************************/
5484            Operator::F32Add => {
5485                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5486                let res = self
5487                    .build_call_with_param_attributes(
5488                        self.intrinsics.add_f32,
5489                        &[
5490                            v1.into(),
5491                            v2.into(),
5492                            self.intrinsics.fp_rounding_md,
5493                            self.intrinsics.fp_exception_md,
5494                        ],
5495                        "",
5496                    )?
5497                    .try_as_basic_value()
5498                    .unwrap_basic();
5499                self.state.push1_extra(
5500                    res,
5501                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5502                );
5503            }
5504            Operator::F64Add => {
5505                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5506                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5507                let res = self
5508                    .build_call_with_param_attributes(
5509                        self.intrinsics.add_f64,
5510                        &[
5511                            v1.into(),
5512                            v2.into(),
5513                            self.intrinsics.fp_rounding_md,
5514                            self.intrinsics.fp_exception_md,
5515                        ],
5516                        "",
5517                    )?
5518                    .try_as_basic_value()
5519                    .unwrap_basic();
5520                self.state.push1_extra(
5521                    res,
5522                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5523                );
5524            }
5525            Operator::F32x4Add => {
5526                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5527                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5528                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5529                let res = self
5530                    .build_call_with_param_attributes(
5531                        self.intrinsics.add_f32x4,
5532                        &[
5533                            v1.into(),
5534                            v2.into(),
5535                            self.intrinsics.fp_rounding_md,
5536                            self.intrinsics.fp_exception_md,
5537                        ],
5538                        "",
5539                    )?
5540                    .try_as_basic_value()
5541                    .unwrap_basic();
5542                let res = err!(
5543                    self.builder
5544                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5545                );
5546                self.state.push1_extra(
5547                    res,
5548                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5549                );
5550            }
5551            Operator::F64x2Add => {
5552                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5553                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5554                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5555                let res = self
5556                    .build_call_with_param_attributes(
5557                        self.intrinsics.add_f64x2,
5558                        &[
5559                            v1.into(),
5560                            v2.into(),
5561                            self.intrinsics.fp_rounding_md,
5562                            self.intrinsics.fp_exception_md,
5563                        ],
5564                        "",
5565                    )?
5566                    .try_as_basic_value()
5567                    .unwrap_basic();
5568                let res = err!(
5569                    self.builder
5570                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5571                );
5572                self.state.push1_extra(
5573                    res,
5574                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5575                );
5576            }
5577            Operator::F32Sub => {
5578                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5579                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5580                let res = self
5581                    .build_call_with_param_attributes(
5582                        self.intrinsics.sub_f32,
5583                        &[
5584                            v1.into(),
5585                            v2.into(),
5586                            self.intrinsics.fp_rounding_md,
5587                            self.intrinsics.fp_exception_md,
5588                        ],
5589                        "",
5590                    )?
5591                    .try_as_basic_value()
5592                    .unwrap_basic();
5593                self.state.push1_extra(
5594                    res,
5595                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5596                );
5597            }
5598            Operator::F64Sub => {
5599                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5600                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5601                let res = self
5602                    .build_call_with_param_attributes(
5603                        self.intrinsics.sub_f64,
5604                        &[
5605                            v1.into(),
5606                            v2.into(),
5607                            self.intrinsics.fp_rounding_md,
5608                            self.intrinsics.fp_exception_md,
5609                        ],
5610                        "",
5611                    )?
5612                    .try_as_basic_value()
5613                    .unwrap_basic();
5614                self.state.push1_extra(
5615                    res,
5616                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5617                );
5618            }
5619            Operator::F32x4Sub => {
5620                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5621                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5622                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5623                let res = self
5624                    .build_call_with_param_attributes(
5625                        self.intrinsics.sub_f32x4,
5626                        &[
5627                            v1.into(),
5628                            v2.into(),
5629                            self.intrinsics.fp_rounding_md,
5630                            self.intrinsics.fp_exception_md,
5631                        ],
5632                        "",
5633                    )?
5634                    .try_as_basic_value()
5635                    .unwrap_basic();
5636                let res = err!(
5637                    self.builder
5638                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5639                );
5640                self.state.push1_extra(
5641                    res,
5642                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5643                );
5644            }
5645            Operator::F64x2Sub => {
5646                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5647                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5648                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5649                let res = self
5650                    .build_call_with_param_attributes(
5651                        self.intrinsics.sub_f64x2,
5652                        &[
5653                            v1.into(),
5654                            v2.into(),
5655                            self.intrinsics.fp_rounding_md,
5656                            self.intrinsics.fp_exception_md,
5657                        ],
5658                        "",
5659                    )?
5660                    .try_as_basic_value()
5661                    .unwrap_basic();
5662                let res = err!(
5663                    self.builder
5664                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5665                );
5666                self.state.push1_extra(
5667                    res,
5668                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5669                );
5670            }
5671            Operator::F32Mul => {
5672                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5673                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5674                let res = self
5675                    .build_call_with_param_attributes(
5676                        self.intrinsics.mul_f32,
5677                        &[
5678                            v1.into(),
5679                            v2.into(),
5680                            self.intrinsics.fp_rounding_md,
5681                            self.intrinsics.fp_exception_md,
5682                        ],
5683                        "",
5684                    )?
5685                    .try_as_basic_value()
5686                    .unwrap_basic();
5687                self.state.push1_extra(
5688                    res,
5689                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5690                );
5691            }
5692            Operator::F64Mul => {
5693                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5694                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5695                let res = self
5696                    .build_call_with_param_attributes(
5697                        self.intrinsics.mul_f64,
5698                        &[
5699                            v1.into(),
5700                            v2.into(),
5701                            self.intrinsics.fp_rounding_md,
5702                            self.intrinsics.fp_exception_md,
5703                        ],
5704                        "",
5705                    )?
5706                    .try_as_basic_value()
5707                    .unwrap_basic();
5708                self.state.push1_extra(
5709                    res,
5710                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5711                );
5712            }
5713            Operator::F32x4Mul => {
5714                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5715                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5716                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5717                let res = self
5718                    .build_call_with_param_attributes(
5719                        self.intrinsics.mul_f32x4,
5720                        &[
5721                            v1.into(),
5722                            v2.into(),
5723                            self.intrinsics.fp_rounding_md,
5724                            self.intrinsics.fp_exception_md,
5725                        ],
5726                        "",
5727                    )?
5728                    .try_as_basic_value()
5729                    .unwrap_basic();
5730                let res = err!(
5731                    self.builder
5732                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5733                );
5734                self.state.push1_extra(
5735                    res,
5736                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5737                );
5738            }
5739            Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd
5740                if self.cpu_features.contains(CpuFeature::FMA) =>
5741            {
5742                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5743                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5744                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5745                let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
5746
5747                let v1 = match op {
5748                    Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5749                    _ => v1,
5750                };
5751                let res = self
5752                    .build_call_with_param_attributes(
5753                        self.intrinsics.muladd_f32x4,
5754                        &[
5755                            v1.into(),
5756                            v2.into(),
5757                            v3.into(),
5758                            self.intrinsics.fp_rounding_md,
5759                            self.intrinsics.fp_exception_md,
5760                        ],
5761                        "",
5762                    )?
5763                    .try_as_basic_value()
5764                    .unwrap_basic();
5765                let res = err!(
5766                    self.builder
5767                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5768                );
5769                let info = (i1.strip_pending() & i2.strip_pending())?;
5770                let info = (info & i3.strip_pending())?;
5771                let info = (info | ExtraInfo::pending_f32_nan())?;
5772                self.state.push1_extra(res, info);
5773            }
5774            Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd => {
5775                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5776                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5777                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5778                let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
5779
5780                let v1 = match op {
5781                    Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5782                    _ => v1,
5783                };
5784                let mul = self
5785                    .build_call_with_param_attributes(
5786                        self.intrinsics.mul_f32x4,
5787                        &[
5788                            v1.into(),
5789                            v2.into(),
5790                            self.intrinsics.fp_rounding_md,
5791                            self.intrinsics.fp_exception_md,
5792                        ],
5793                        "",
5794                    )?
5795                    .try_as_basic_value()
5796                    .unwrap_basic();
5797                let mul = mul.into_vector_value();
5798                let res = self
5799                    .build_call_with_param_attributes(
5800                        self.intrinsics.add_f32x4,
5801                        &[
5802                            mul.into(),
5803                            v3.into(),
5804                            self.intrinsics.fp_rounding_md,
5805                            self.intrinsics.fp_exception_md,
5806                        ],
5807                        "",
5808                    )?
5809                    .try_as_basic_value()
5810                    .unwrap_basic();
5811                let res = err!(
5812                    self.builder
5813                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5814                );
5815                let info = (i1.strip_pending() & i2.strip_pending())?;
5816                let info = (info & i3.strip_pending())?;
5817                let info = (info | ExtraInfo::pending_f32_nan())?;
5818                self.state.push1_extra(res, info);
5819            }
5820            Operator::F64x2Mul => {
5821                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5822                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5823                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5824                let res = self
5825                    .build_call_with_param_attributes(
5826                        self.intrinsics.mul_f64x2,
5827                        &[
5828                            v1.into(),
5829                            v2.into(),
5830                            self.intrinsics.fp_rounding_md,
5831                            self.intrinsics.fp_exception_md,
5832                        ],
5833                        "",
5834                    )?
5835                    .try_as_basic_value()
5836                    .unwrap_basic();
5837                let res = err!(
5838                    self.builder
5839                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5840                );
5841                self.state.push1_extra(
5842                    res,
5843                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5844                );
5845            }
5846            Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd
5847                if self.cpu_features.contains(CpuFeature::FMA) =>
5848            {
5849                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5850                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5851                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5852                let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
5853
5854                let v1 = match op {
5855                    Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5856                    _ => v1,
5857                };
5858                let res = self
5859                    .build_call_with_param_attributes(
5860                        self.intrinsics.muladd_f64x2,
5861                        &[
5862                            v1.into(),
5863                            v2.into(),
5864                            v3.into(),
5865                            self.intrinsics.fp_rounding_md,
5866                            self.intrinsics.fp_exception_md,
5867                        ],
5868                        "",
5869                    )?
5870                    .try_as_basic_value()
5871                    .unwrap_basic();
5872                let res = err!(
5873                    self.builder
5874                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5875                );
5876                let info = (i1.strip_pending() & i2.strip_pending())?;
5877                let info = (info & i3.strip_pending())?;
5878                let info = (info | ExtraInfo::pending_f64_nan())?;
5879                self.state.push1_extra(res, info);
5880            }
5881            Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd => {
5882                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5883                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5884                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5885                let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
5886
5887                let v1 = match op {
5888                    Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5889                    _ => v1,
5890                };
5891                let mul = self
5892                    .build_call_with_param_attributes(
5893                        self.intrinsics.mul_f64x2,
5894                        &[
5895                            v1.into(),
5896                            v2.into(),
5897                            self.intrinsics.fp_rounding_md,
5898                            self.intrinsics.fp_exception_md,
5899                        ],
5900                        "",
5901                    )?
5902                    .try_as_basic_value()
5903                    .unwrap_basic();
5904                let mul = mul.into_vector_value();
5905                let res = self
5906                    .build_call_with_param_attributes(
5907                        self.intrinsics.add_f64x2,
5908                        &[
5909                            mul.into(),
5910                            v3.into(),
5911                            self.intrinsics.fp_rounding_md,
5912                            self.intrinsics.fp_exception_md,
5913                        ],
5914                        "",
5915                    )?
5916                    .try_as_basic_value()
5917                    .unwrap_basic();
5918                let res = err!(
5919                    self.builder
5920                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5921                );
5922                let info = (i1.strip_pending() & i2.strip_pending())?;
5923                let info = (info & i3.strip_pending())?;
5924                let info = (info | ExtraInfo::pending_f64_nan())?;
5925                self.state.push1_extra(res, info);
5926            }
5927            Operator::F32Div => {
5928                let (v1, v2) = self.state.pop2()?;
5929                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5930                let res = self
5931                    .build_call_with_param_attributes(
5932                        self.intrinsics.div_f32,
5933                        &[
5934                            v1.into(),
5935                            v2.into(),
5936                            self.intrinsics.fp_rounding_md,
5937                            self.intrinsics.fp_exception_md,
5938                        ],
5939                        "",
5940                    )?
5941                    .try_as_basic_value()
5942                    .unwrap_basic();
5943                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
5944            }
5945            Operator::F64Div => {
5946                let (v1, v2) = self.state.pop2()?;
5947                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5948                let res = self
5949                    .build_call_with_param_attributes(
5950                        self.intrinsics.div_f64,
5951                        &[
5952                            v1.into(),
5953                            v2.into(),
5954                            self.intrinsics.fp_rounding_md,
5955                            self.intrinsics.fp_exception_md,
5956                        ],
5957                        "",
5958                    )?
5959                    .try_as_basic_value()
5960                    .unwrap_basic();
5961                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
5962            }
5963            Operator::F32x4Div => {
5964                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5965                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
5966                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
5967                let res = self
5968                    .build_call_with_param_attributes(
5969                        self.intrinsics.div_f32x4,
5970                        &[
5971                            v1.into(),
5972                            v2.into(),
5973                            self.intrinsics.fp_rounding_md,
5974                            self.intrinsics.fp_exception_md,
5975                        ],
5976                        "",
5977                    )?
5978                    .try_as_basic_value()
5979                    .unwrap_basic();
5980                let res = err!(
5981                    self.builder
5982                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5983                );
5984                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
5985            }
5986            Operator::F64x2Div => {
5987                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5988                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
5989                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
5990                let res = self
5991                    .build_call_with_param_attributes(
5992                        self.intrinsics.div_f64x2,
5993                        &[
5994                            v1.into(),
5995                            v2.into(),
5996                            self.intrinsics.fp_rounding_md,
5997                            self.intrinsics.fp_exception_md,
5998                        ],
5999                        "",
6000                    )?
6001                    .try_as_basic_value()
6002                    .unwrap_basic();
6003                let res = err!(
6004                    self.builder
6005                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6006                );
6007                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6008            }
6009            Operator::F32Sqrt => {
6010                let input = self.state.pop1()?;
6011                let res = self
6012                    .build_call_with_param_attributes(
6013                        self.intrinsics.sqrt_f32,
6014                        &[input.into()],
6015                        "",
6016                    )?
6017                    .try_as_basic_value()
6018                    .unwrap_basic();
6019                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6020            }
6021            Operator::F64Sqrt => {
6022                let input = self.state.pop1()?;
6023                let res = self
6024                    .build_call_with_param_attributes(
6025                        self.intrinsics.sqrt_f64,
6026                        &[input.into()],
6027                        "",
6028                    )?
6029                    .try_as_basic_value()
6030                    .unwrap_basic();
6031                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6032            }
6033            Operator::F32x4Sqrt => {
6034                let (v, i) = self.state.pop1_extra()?;
6035                let (v, _) = self.v128_into_f32x4(v, i)?;
6036                let res = self
6037                    .build_call_with_param_attributes(self.intrinsics.sqrt_f32x4, &[v.into()], "")?
6038                    .try_as_basic_value()
6039                    .unwrap_basic();
6040                let bits = err!(
6041                    self.builder
6042                        .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6043                );
6044                self.state.push1_extra(bits, ExtraInfo::pending_f32_nan());
6045            }
6046            Operator::F64x2Sqrt => {
6047                let (v, i) = self.state.pop1_extra()?;
6048                let (v, _) = self.v128_into_f64x2(v, i)?;
6049                let res = self
6050                    .build_call_with_param_attributes(self.intrinsics.sqrt_f64x2, &[v.into()], "")?
6051                    .try_as_basic_value()
6052                    .unwrap_basic();
6053                let bits = err!(
6054                    self.builder
6055                        .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6056                );
6057                self.state.push1(bits);
6058            }
6059            Operator::F32Min => {
6060                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6061                let lhs = self
6062                    .apply_pending_canonicalization(lhs, lhs_info)?
6063                    .into_float_value();
6064                let rhs = self
6065                    .apply_pending_canonicalization(rhs, rhs_info)?
6066                    .into_float_value();
6067
6068                let res = self
6069                    .build_call_with_param_attributes(
6070                        self.intrinsics.minimum_f32,
6071                        &[lhs.into(), rhs.into()],
6072                        "",
6073                    )?
6074                    .try_as_basic_value()
6075                    .unwrap_basic();
6076
6077                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6078                let res = res.into_float_value();
6079
6080                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6081            }
6082            Operator::F64Min => {
6083                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6084                let lhs = self
6085                    .apply_pending_canonicalization(lhs, lhs_info)?
6086                    .into_float_value();
6087                let rhs = self
6088                    .apply_pending_canonicalization(rhs, rhs_info)?
6089                    .into_float_value();
6090
6091                let res = self
6092                    .build_call_with_param_attributes(
6093                        self.intrinsics.minimum_f64,
6094                        &[lhs.into(), rhs.into()],
6095                        "",
6096                    )?
6097                    .try_as_basic_value()
6098                    .unwrap_basic();
6099
6100                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6101                let res = res.into_float_value();
6102
6103                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6104            }
6105            Operator::F32x4RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6106                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6107                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6108                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6109                let res = self
6110                    .build_call_with_param_attributes(
6111                        self.intrinsics.x86_64.min_ps,
6112                        &[v1.into(), v2.into()],
6113                        "",
6114                    )?
6115                    .try_as_basic_value()
6116                    .unwrap_basic();
6117                let res = err!(
6118                    self.builder
6119                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6120                );
6121                self.state.push1_extra(
6122                    res,
6123                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6124                );
6125            }
6126            Operator::F32x4Min | Operator::F32x4RelaxedMin => {
6127                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6128                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6129                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6130                let res = self
6131                    .build_call_with_param_attributes(
6132                        self.intrinsics.minimum_f32x4,
6133                        &[v1.into(), v2.into()],
6134                        "",
6135                    )?
6136                    .try_as_basic_value()
6137                    .unwrap_basic();
6138
6139                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6140                let res = res.into_vector_value();
6141
6142                let res = err!(
6143                    self.builder
6144                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6145                );
6146                self.state.push1_extra(
6147                    res,
6148                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6149                );
6150            }
6151            Operator::F32x4PMin => {
6152                // Pseudo-min: b < a ? b : a
6153                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6154                let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6155                let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6156                let cmp = err!(
6157                    self.builder
6158                        .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6159                );
6160                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6161                let res = err!(
6162                    self.builder
6163                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6164                );
6165                self.state.push1(res);
6166            }
6167            Operator::F64x2RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6168                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6169                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6170                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6171                let res = self
6172                    .build_call_with_param_attributes(
6173                        self.intrinsics.x86_64.min_pd,
6174                        &[v1.into(), v2.into()],
6175                        "",
6176                    )?
6177                    .try_as_basic_value()
6178                    .unwrap_basic();
6179                let res = err!(
6180                    self.builder
6181                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6182                );
6183                self.state.push1_extra(
6184                    res,
6185                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6186                );
6187            }
6188            Operator::F64x2Min | Operator::F64x2RelaxedMin => {
6189                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6190                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6191                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6192                let res = self
6193                    .build_call_with_param_attributes(
6194                        self.intrinsics.minimum_f64x2,
6195                        &[v1.into(), v2.into()],
6196                        "",
6197                    )?
6198                    .try_as_basic_value()
6199                    .unwrap_basic();
6200
6201                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6202                let res = res.into_vector_value();
6203
6204                let res = err!(
6205                    self.builder
6206                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6207                );
6208                self.state.push1_extra(
6209                    res,
6210                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6211                );
6212            }
6213            Operator::F64x2PMin => {
6214                // Pseudo-min: b < a ? b : a
6215                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6216                let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6217                let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6218                let cmp = err!(
6219                    self.builder
6220                        .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6221                );
6222                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6223                let res = err!(
6224                    self.builder
6225                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6226                );
6227                self.state.push1(res);
6228            }
6229            Operator::F32Max => {
6230                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6231                let lhs = self
6232                    .apply_pending_canonicalization(lhs, lhs_info)?
6233                    .into_float_value();
6234                let rhs = self
6235                    .apply_pending_canonicalization(rhs, rhs_info)?
6236                    .into_float_value();
6237
6238                let res = self
6239                    .build_call_with_param_attributes(
6240                        self.intrinsics.maximum_f32,
6241                        &[lhs.into(), rhs.into()],
6242                        "",
6243                    )?
6244                    .try_as_basic_value()
6245                    .unwrap_basic();
6246
6247                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6248                let res = res.into_float_value();
6249
6250                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6251            }
6252            Operator::F64Max => {
6253                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6254                let lhs = self
6255                    .apply_pending_canonicalization(lhs, lhs_info)?
6256                    .into_float_value();
6257                let rhs = self
6258                    .apply_pending_canonicalization(rhs, rhs_info)?
6259                    .into_float_value();
6260
6261                let res = self
6262                    .build_call_with_param_attributes(
6263                        self.intrinsics.maximum_f64,
6264                        &[lhs.into(), rhs.into()],
6265                        "",
6266                    )?
6267                    .try_as_basic_value()
6268                    .unwrap_basic();
6269
6270                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6271                let res = res.into_float_value();
6272
6273                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6274            }
6275            Operator::F32x4RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6276                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6277                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6278                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6279                let res = self
6280                    .build_call_with_param_attributes(
6281                        self.intrinsics.x86_64.max_ps,
6282                        &[v1.into(), v2.into()],
6283                        "",
6284                    )?
6285                    .try_as_basic_value()
6286                    .unwrap_basic();
6287                let res = err!(
6288                    self.builder
6289                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6290                );
6291                self.state.push1_extra(
6292                    res,
6293                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6294                );
6295            }
6296            Operator::F32x4Max | Operator::F32x4RelaxedMax => {
6297                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6298                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6299                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6300                let res = self
6301                    .build_call_with_param_attributes(
6302                        self.intrinsics.maximum_f32x4,
6303                        &[v1.into(), v2.into()],
6304                        "",
6305                    )?
6306                    .try_as_basic_value()
6307                    .unwrap_basic();
6308
6309                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6310                let res = res.into_vector_value();
6311
6312                let res = err!(
6313                    self.builder
6314                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6315                );
6316                self.state.push1_extra(
6317                    res,
6318                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6319                );
6320            }
6321            Operator::F32x4PMax => {
6322                // Pseudo-max: a < b ? b : a
6323                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6324                let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6325                let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6326                let cmp = err!(
6327                    self.builder
6328                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6329                );
6330                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6331
6332                let res = err!(
6333                    self.builder
6334                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6335                );
6336                self.state.push1(res);
6337            }
6338            Operator::F64x2RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6339                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6340                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6341                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6342                let res = self
6343                    .build_call_with_param_attributes(
6344                        self.intrinsics.x86_64.max_pd,
6345                        &[v1.into(), v2.into()],
6346                        "",
6347                    )?
6348                    .try_as_basic_value()
6349                    .unwrap_basic();
6350                let res = err!(
6351                    self.builder
6352                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6353                );
6354                self.state.push1_extra(
6355                    res,
6356                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6357                );
6358            }
6359            Operator::F64x2Max | Operator::F64x2RelaxedMax => {
6360                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6361                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6362                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6363                let res = self
6364                    .build_call_with_param_attributes(
6365                        self.intrinsics.maximum_f64x2,
6366                        &[v1.into(), v2.into()],
6367                        "",
6368                    )?
6369                    .try_as_basic_value()
6370                    .unwrap_basic();
6371
6372                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6373                let res = res.into_vector_value();
6374
6375                let res = err!(
6376                    self.builder
6377                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6378                );
6379                self.state.push1_extra(
6380                    res,
6381                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6382                );
6383            }
6384            Operator::F64x2PMax => {
6385                // Pseudo-max: a < b ? b : a
6386                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6387                let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6388                let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6389                let cmp = err!(
6390                    self.builder
6391                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6392                );
6393                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6394                let res = err!(
6395                    self.builder
6396                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6397                );
6398                self.state.push1(res);
6399            }
6400            Operator::F32Ceil => {
6401                let (input, info) = self.state.pop1_extra()?;
6402                let res = err!(self.build_call_with_param_attributes(
6403                    self.intrinsics.ceil_f32,
6404                    &[input.into()],
6405                    ""
6406                ))
6407                .try_as_basic_value()
6408                .unwrap_basic();
6409                let (res, info) = self.finalize_rounding_result(res, info)?;
6410                self.state.push1_extra(res, info);
6411            }
6412            Operator::F32x4Ceil => {
6413                let (v, i) = self.state.pop1_extra()?;
6414                let (v, _) = self.v128_into_f32x4(v, i)?;
6415                let res = err!(self.build_call_with_param_attributes(
6416                    self.intrinsics.ceil_f32x4,
6417                    &[v.into()],
6418                    ""
6419                ))
6420                .try_as_basic_value()
6421                .unwrap_basic();
6422                let (res, info) = self.finalize_rounding_result(res, i)?;
6423                let res = err!(
6424                    self.builder
6425                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6426                );
6427                self.state.push1_extra(res, info);
6428            }
6429            Operator::F64Ceil => {
6430                let (input, info) = self.state.pop1_extra()?;
6431                let res = err!(self.build_call_with_param_attributes(
6432                    self.intrinsics.ceil_f64,
6433                    &[input.into()],
6434                    ""
6435                ))
6436                .try_as_basic_value()
6437                .unwrap_basic();
6438                let (res, info) = self.finalize_rounding_result(res, info)?;
6439                self.state.push1_extra(res, info);
6440            }
6441            Operator::F64x2Ceil => {
6442                let (v, i) = self.state.pop1_extra()?;
6443                let (v, _) = self.v128_into_f64x2(v, i)?;
6444                let res = err!(self.build_call_with_param_attributes(
6445                    self.intrinsics.ceil_f64x2,
6446                    &[v.into()],
6447                    ""
6448                ))
6449                .try_as_basic_value()
6450                .unwrap_basic();
6451                let (res, info) = self.finalize_rounding_result(res, i)?;
6452                let res = err!(
6453                    self.builder
6454                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6455                );
6456                self.state.push1_extra(res, info);
6457            }
6458            Operator::F32Floor => {
6459                let (input, info) = self.state.pop1_extra()?;
6460                let res = err!(self.build_call_with_param_attributes(
6461                    self.intrinsics.floor_f32,
6462                    &[input.into()],
6463                    ""
6464                ))
6465                .try_as_basic_value()
6466                .unwrap_basic();
6467                let (res, info) = self.finalize_rounding_result(res, info)?;
6468                self.state.push1_extra(res, info);
6469            }
6470            Operator::F32x4Floor => {
6471                let (v, i) = self.state.pop1_extra()?;
6472                let (v, _) = self.v128_into_f32x4(v, i)?;
6473                let res = err!(self.build_call_with_param_attributes(
6474                    self.intrinsics.floor_f32x4,
6475                    &[v.into()],
6476                    ""
6477                ))
6478                .try_as_basic_value()
6479                .unwrap_basic();
6480                let (res, info) = self.finalize_rounding_result(res, i)?;
6481                let res = err!(
6482                    self.builder
6483                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6484                );
6485                self.state.push1_extra(res, info);
6486            }
6487            Operator::F64Floor => {
6488                let (input, info) = self.state.pop1_extra()?;
6489                let res = err!(self.build_call_with_param_attributes(
6490                    self.intrinsics.floor_f64,
6491                    &[input.into()],
6492                    ""
6493                ))
6494                .try_as_basic_value()
6495                .unwrap_basic();
6496                let (res, info) = self.finalize_rounding_result(res, info)?;
6497                self.state.push1_extra(res, info);
6498            }
6499            Operator::F64x2Floor => {
6500                let (v, i) = self.state.pop1_extra()?;
6501                let (v, _) = self.v128_into_f64x2(v, i)?;
6502                let res = err!(self.build_call_with_param_attributes(
6503                    self.intrinsics.floor_f64x2,
6504                    &[v.into()],
6505                    ""
6506                ))
6507                .try_as_basic_value()
6508                .unwrap_basic();
6509                let (res, info) = self.finalize_rounding_result(res, i)?;
6510                let res = err!(
6511                    self.builder
6512                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6513                );
6514                self.state.push1_extra(res, info);
6515            }
6516            Operator::F32Trunc => {
6517                let (v, info) = self.state.pop1_extra()?;
6518                let res = err!(
6519                    self.builder
6520                        .build_call(self.intrinsics.trunc_f32, &[v.into()], "")
6521                )
6522                .try_as_basic_value()
6523                .unwrap_basic();
6524                let (res, info) = self.finalize_rounding_result(res, info)?;
6525                self.state.push1_extra(res, info);
6526            }
6527            Operator::F32x4Trunc => {
6528                let (v, i) = self.state.pop1_extra()?;
6529                let (v, _) = self.v128_into_f32x4(v, i)?;
6530                let res = err!(self.build_call_with_param_attributes(
6531                    self.intrinsics.trunc_f32x4,
6532                    &[v.into()],
6533                    ""
6534                ))
6535                .try_as_basic_value()
6536                .unwrap_basic();
6537                let (res, info) = self.finalize_rounding_result(res, i)?;
6538                let res = err!(
6539                    self.builder
6540                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6541                );
6542                self.state.push1_extra(res, info);
6543            }
6544            Operator::F64Trunc => {
6545                let (v, info) = self.state.pop1_extra()?;
6546                let res = err!(
6547                    self.builder
6548                        .build_call(self.intrinsics.trunc_f64, &[v.into()], "")
6549                )
6550                .try_as_basic_value()
6551                .unwrap_basic();
6552                let (res, info) = self.finalize_rounding_result(res, info)?;
6553                self.state.push1_extra(res, info);
6554            }
6555            Operator::F64x2Trunc => {
6556                let (v, i) = self.state.pop1_extra()?;
6557                let (v, _) = self.v128_into_f64x2(v, i)?;
6558                let res = err!(self.build_call_with_param_attributes(
6559                    self.intrinsics.trunc_f64x2,
6560                    &[v.into()],
6561                    ""
6562                ))
6563                .try_as_basic_value()
6564                .unwrap_basic();
6565                let (res, info) = self.finalize_rounding_result(res, i)?;
6566                let res = err!(
6567                    self.builder
6568                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6569                );
6570                self.state.push1_extra(res, info);
6571            }
6572            Operator::F32Nearest => {
6573                let (v, info) = self.state.pop1_extra()?;
6574                let res = err!(self.build_call_with_param_attributes(
6575                    self.intrinsics.nearbyint_f32,
6576                    &[v.into()],
6577                    ""
6578                ))
6579                .try_as_basic_value()
6580                .unwrap_basic();
6581                let (res, info) = self.finalize_rounding_result(res, info)?;
6582                self.state.push1_extra(res, info);
6583            }
6584            Operator::F32x4Nearest => {
6585                let (v, i) = self.state.pop1_extra()?;
6586                let (v, _) = self.v128_into_f32x4(v, i)?;
6587                let res = err!(self.build_call_with_param_attributes(
6588                    self.intrinsics.nearbyint_f32x4,
6589                    &[v.into()],
6590                    ""
6591                ))
6592                .try_as_basic_value()
6593                .unwrap_basic();
6594                let (res, info) = self.finalize_rounding_result(res, i)?;
6595                let res = err!(
6596                    self.builder
6597                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6598                );
6599                self.state.push1_extra(res, info);
6600            }
6601            Operator::F64Nearest => {
6602                let (v, info) = self.state.pop1_extra()?;
6603                let res = err!(self.build_call_with_param_attributes(
6604                    self.intrinsics.nearbyint_f64,
6605                    &[v.into()],
6606                    ""
6607                ))
6608                .try_as_basic_value()
6609                .unwrap_basic();
6610                let (res, info) = self.finalize_rounding_result(res, info)?;
6611                self.state.push1_extra(res, info);
6612            }
6613            Operator::F64x2Nearest => {
6614                let (v, i) = self.state.pop1_extra()?;
6615                let (v, _) = self.v128_into_f64x2(v, i)?;
6616                let res = err!(self.build_call_with_param_attributes(
6617                    self.intrinsics.nearbyint_f64x2,
6618                    &[v.into()],
6619                    ""
6620                ))
6621                .try_as_basic_value()
6622                .unwrap_basic();
6623                let (res, info) = self.finalize_rounding_result(res, i)?;
6624                let res = err!(
6625                    self.builder
6626                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6627                );
6628                self.state.push1_extra(res, info);
6629            }
6630            Operator::F32Abs => {
6631                let (v, i) = self.state.pop1_extra()?;
6632                let v = self.apply_pending_canonicalization(v, i)?;
6633                let res = err!(
6634                    self.builder
6635                        .build_call(self.intrinsics.fabs_f32, &[v.into()], "")
6636                )
6637                .try_as_basic_value()
6638                .unwrap_basic();
6639                // The exact NaN returned by F32Abs is fully defined. Do not
6640                // adjust.
6641                self.state.push1_extra(res, i.strip_pending());
6642            }
6643            Operator::F64Abs => {
6644                let (v, i) = self.state.pop1_extra()?;
6645                let v = self.apply_pending_canonicalization(v, i)?;
6646                let res = err!(
6647                    self.builder
6648                        .build_call(self.intrinsics.fabs_f64, &[v.into()], "")
6649                )
6650                .try_as_basic_value()
6651                .unwrap_basic();
6652                // The exact NaN returned by F64Abs is fully defined. Do not
6653                // adjust.
6654                self.state.push1_extra(res, i.strip_pending());
6655            }
6656            Operator::F32x4Abs => {
6657                let (v, i) = self.state.pop1_extra()?;
6658                let v = err!(self.builder.build_bit_cast(
6659                    v.into_int_value(),
6660                    self.intrinsics.f32x4_ty,
6661                    ""
6662                ));
6663                let v = self.apply_pending_canonicalization(v, i)?;
6664                let res = self
6665                    .build_call_with_param_attributes(self.intrinsics.fabs_f32x4, &[v.into()], "")?
6666                    .try_as_basic_value()
6667                    .unwrap_basic();
6668                let res = err!(
6669                    self.builder
6670                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6671                );
6672                // The exact NaN returned by F32x4Abs is fully defined. Do not
6673                // adjust.
6674                self.state.push1_extra(res, i.strip_pending());
6675            }
6676            Operator::F64x2Abs => {
6677                let (v, i) = self.state.pop1_extra()?;
6678                let v = err!(self.builder.build_bit_cast(
6679                    v.into_int_value(),
6680                    self.intrinsics.f64x2_ty,
6681                    ""
6682                ));
6683                let v = self.apply_pending_canonicalization(v, i)?;
6684                let res = self
6685                    .build_call_with_param_attributes(self.intrinsics.fabs_f64x2, &[v.into()], "")?
6686                    .try_as_basic_value()
6687                    .unwrap_basic();
6688                let res = err!(
6689                    self.builder
6690                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6691                );
6692                // The exact NaN returned by F32x4Abs is fully defined. Do not
6693                // adjust.
6694                self.state.push1_extra(res, i.strip_pending());
6695            }
6696            Operator::F32x4Neg => {
6697                let (v, i) = self.state.pop1_extra()?;
6698                let v = err!(self.builder.build_bit_cast(
6699                    v.into_int_value(),
6700                    self.intrinsics.f32x4_ty,
6701                    ""
6702                ));
6703                let v = self
6704                    .apply_pending_canonicalization(v, i)?
6705                    .into_vector_value();
6706                let res = err!(self.builder.build_float_neg(v, ""));
6707                let res = err!(
6708                    self.builder
6709                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6710                );
6711                // The exact NaN returned by F32x4Neg is fully defined. Do not
6712                // adjust.
6713                self.state.push1_extra(res, i.strip_pending());
6714            }
6715            Operator::F64x2Neg => {
6716                let (v, i) = self.state.pop1_extra()?;
6717                let v = err!(self.builder.build_bit_cast(
6718                    v.into_int_value(),
6719                    self.intrinsics.f64x2_ty,
6720                    ""
6721                ));
6722                let v = self
6723                    .apply_pending_canonicalization(v, i)?
6724                    .into_vector_value();
6725                let res = err!(self.builder.build_float_neg(v, ""));
6726                let res = err!(
6727                    self.builder
6728                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6729                );
6730                // The exact NaN returned by F64x2Neg is fully defined. Do not
6731                // adjust.
6732                self.state.push1_extra(res, i.strip_pending());
6733            }
6734            Operator::F32Neg | Operator::F64Neg => {
6735                let (v, i) = self.state.pop1_extra()?;
6736                let v = self
6737                    .apply_pending_canonicalization(v, i)?
6738                    .into_float_value();
6739                let res = err!(self.builder.build_float_neg(v, ""));
6740                // The exact NaN returned by F32Neg and F64Neg are fully defined.
6741                // Do not adjust.
6742                self.state.push1_extra(res, i.strip_pending());
6743            }
6744            Operator::F32Copysign => {
6745                let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
6746                let mag = self.apply_pending_canonicalization(mag, mag_info)?;
6747                let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
6748                let res = self
6749                    .build_call_with_param_attributes(
6750                        self.intrinsics.copysign_f32,
6751                        &[mag.into(), sgn.into()],
6752                        "",
6753                    )?
6754                    .try_as_basic_value()
6755                    .unwrap_basic();
6756                // The exact NaN returned by F32Copysign is fully defined.
6757                // Do not adjust.
6758                self.state.push1_extra(res, mag_info.strip_pending());
6759            }
6760            Operator::F64Copysign => {
6761                let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
6762                let mag = self.apply_pending_canonicalization(mag, mag_info)?;
6763                let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
6764                let res = self
6765                    .build_call_with_param_attributes(
6766                        self.intrinsics.copysign_f64,
6767                        &[mag.into(), sgn.into()],
6768                        "",
6769                    )?
6770                    .try_as_basic_value()
6771                    .unwrap_basic();
6772                // The exact NaN returned by F32Copysign is fully defined.
6773                // Do not adjust.
6774                self.state.push1_extra(res, mag_info.strip_pending());
6775            }
6776
6777            /***************************
6778             * Integer Comparison instructions.
6779             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-comparison-instructions
6780             ***************************/
6781            Operator::I32Eq | Operator::I64Eq => {
6782                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6783                let v1 = self.apply_pending_canonicalization(v1, i1)?;
6784                let v2 = self.apply_pending_canonicalization(v2, i2)?;
6785                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6786                let cond = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6787                let res = err!(
6788                    self.builder
6789                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6790                );
6791                self.state.push1_extra(
6792                    res,
6793                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6794                );
6795            }
6796            Operator::I8x16Eq => {
6797                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6798                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6799                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6800                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6801                let res = err!(
6802                    self.builder
6803                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6804                );
6805                let res = err!(
6806                    self.builder
6807                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6808                );
6809                self.state.push1(res);
6810            }
6811            Operator::I16x8Eq => {
6812                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6813                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6814                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6815                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6816                let res = err!(
6817                    self.builder
6818                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6819                );
6820                let res = err!(
6821                    self.builder
6822                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6823                );
6824                self.state.push1(res);
6825            }
6826            Operator::I32x4Eq => {
6827                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6828                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6829                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6830                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6831                let res = err!(
6832                    self.builder
6833                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6834                );
6835                let res = err!(
6836                    self.builder
6837                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6838                );
6839                self.state.push1(res);
6840            }
6841            Operator::I64x2Eq => {
6842                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6843                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
6844                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
6845                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6846                let res = err!(
6847                    self.builder
6848                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
6849                );
6850                let res = err!(
6851                    self.builder
6852                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6853                );
6854                self.state.push1(res);
6855            }
6856            Operator::I32Ne | Operator::I64Ne => {
6857                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6858                let v1 = self.apply_pending_canonicalization(v1, i1)?;
6859                let v2 = self.apply_pending_canonicalization(v2, i2)?;
6860                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6861                let cond = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6862                let res = err!(
6863                    self.builder
6864                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6865                );
6866                self.state.push1_extra(
6867                    res,
6868                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6869                );
6870            }
6871            Operator::I8x16Ne => {
6872                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6873                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6874                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6875                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6876                let res = err!(
6877                    self.builder
6878                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6879                );
6880                let res = err!(
6881                    self.builder
6882                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6883                );
6884                self.state.push1(res);
6885            }
6886            Operator::I16x8Ne => {
6887                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6888                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6889                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6890                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6891                let res = err!(
6892                    self.builder
6893                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6894                );
6895                let res = err!(
6896                    self.builder
6897                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6898                );
6899                self.state.push1(res);
6900            }
6901            Operator::I32x4Ne => {
6902                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6903                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6904                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6905                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6906                let res = err!(
6907                    self.builder
6908                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6909                );
6910                let res = err!(
6911                    self.builder
6912                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6913                );
6914                self.state.push1(res);
6915            }
6916            Operator::I64x2Ne => {
6917                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6918                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
6919                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
6920                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6921                let res = err!(
6922                    self.builder
6923                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
6924                );
6925                let res = err!(
6926                    self.builder
6927                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6928                );
6929                self.state.push1(res);
6930            }
6931            Operator::I32LtS | Operator::I64LtS => {
6932                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6933                let v1 = self.apply_pending_canonicalization(v1, i1)?;
6934                let v2 = self.apply_pending_canonicalization(v2, i2)?;
6935                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6936                let cond = err!(
6937                    self.builder
6938                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
6939                );
6940                let res = err!(
6941                    self.builder
6942                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6943                );
6944                self.state.push1_extra(
6945                    res,
6946                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6947                );
6948            }
6949            Operator::I8x16LtS => {
6950                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6951                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6952                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6953                let res = err!(
6954                    self.builder
6955                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
6956                );
6957                let res = err!(
6958                    self.builder
6959                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6960                );
6961                let res = err!(
6962                    self.builder
6963                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6964                );
6965                self.state.push1(res);
6966            }
6967            Operator::I16x8LtS => {
6968                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6969                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6970                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6971                let res = err!(
6972                    self.builder
6973                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
6974                );
6975                let res = err!(
6976                    self.builder
6977                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6978                );
6979                let res = err!(
6980                    self.builder
6981                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6982                );
6983                self.state.push1(res);
6984            }
6985            Operator::I32x4LtS => {
6986                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6987                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6988                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6989                let res = err!(
6990                    self.builder
6991                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
6992                );
6993                let res = err!(
6994                    self.builder
6995                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6996                );
6997                let res = err!(
6998                    self.builder
6999                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7000                );
7001                self.state.push1(res);
7002            }
7003            Operator::I64x2LtS => {
7004                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7005                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7006                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7007                let res = err!(
7008                    self.builder
7009                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7010                );
7011                let res = err!(
7012                    self.builder
7013                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7014                );
7015                let res = err!(
7016                    self.builder
7017                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7018                );
7019                self.state.push1(res);
7020            }
7021            Operator::I32LtU | Operator::I64LtU => {
7022                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7023                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7024                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7025                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7026                let cond = err!(
7027                    self.builder
7028                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7029                );
7030                let res = err!(
7031                    self.builder
7032                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7033                );
7034                self.state.push1(res);
7035            }
7036            Operator::I8x16LtU => {
7037                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7038                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7039                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7040                let res = err!(
7041                    self.builder
7042                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7043                );
7044                let res = err!(
7045                    self.builder
7046                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7047                );
7048                let res = err!(
7049                    self.builder
7050                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7051                );
7052                self.state.push1(res);
7053            }
7054            Operator::I16x8LtU => {
7055                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7056                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7057                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7058                let res = err!(
7059                    self.builder
7060                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7061                );
7062                let res = err!(
7063                    self.builder
7064                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7065                );
7066                let res = err!(
7067                    self.builder
7068                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7069                );
7070                self.state.push1(res);
7071            }
7072            Operator::I32x4LtU => {
7073                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7074                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7075                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7076                let res = err!(
7077                    self.builder
7078                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7079                );
7080                let res = err!(
7081                    self.builder
7082                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7083                );
7084                let res = err!(
7085                    self.builder
7086                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7087                );
7088                self.state.push1(res);
7089            }
7090            Operator::I32LeS | Operator::I64LeS => {
7091                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7092                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7093                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7094                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7095                let cond = err!(
7096                    self.builder
7097                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7098                );
7099                let res = err!(
7100                    self.builder
7101                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7102                );
7103                self.state.push1_extra(
7104                    res,
7105                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7106                );
7107            }
7108            Operator::I8x16LeS => {
7109                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7110                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7111                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7112                let res = err!(
7113                    self.builder
7114                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7115                );
7116                let res = err!(
7117                    self.builder
7118                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7119                );
7120                let res = err!(
7121                    self.builder
7122                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7123                );
7124                self.state.push1(res);
7125            }
7126            Operator::I16x8LeS => {
7127                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7128                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7129                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7130                let res = err!(
7131                    self.builder
7132                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7133                );
7134                let res = err!(
7135                    self.builder
7136                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7137                );
7138                let res = err!(
7139                    self.builder
7140                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7141                );
7142                self.state.push1(res);
7143            }
7144            Operator::I32x4LeS => {
7145                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7146                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7147                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7148                let res = err!(
7149                    self.builder
7150                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7151                );
7152                let res = err!(
7153                    self.builder
7154                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7155                );
7156                let res = err!(
7157                    self.builder
7158                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7159                );
7160                self.state.push1(res);
7161            }
7162            Operator::I64x2LeS => {
7163                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7164                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7165                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7166                let res = err!(
7167                    self.builder
7168                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7169                );
7170                let res = err!(
7171                    self.builder
7172                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7173                );
7174                let res = err!(
7175                    self.builder
7176                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7177                );
7178                self.state.push1(res);
7179            }
7180            Operator::I32LeU | Operator::I64LeU => {
7181                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7182                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7183                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7184                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7185                let cond = err!(
7186                    self.builder
7187                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7188                );
7189                let res = err!(
7190                    self.builder
7191                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7192                );
7193                self.state.push1_extra(
7194                    res,
7195                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7196                );
7197            }
7198            Operator::I8x16LeU => {
7199                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7200                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7201                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7202                let res = err!(
7203                    self.builder
7204                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7205                );
7206                let res = err!(
7207                    self.builder
7208                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7209                );
7210                let res = err!(
7211                    self.builder
7212                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7213                );
7214                self.state.push1(res);
7215            }
7216            Operator::I16x8LeU => {
7217                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7218                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7219                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7220                let res = err!(
7221                    self.builder
7222                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7223                );
7224                let res = err!(
7225                    self.builder
7226                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7227                );
7228                let res = err!(
7229                    self.builder
7230                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7231                );
7232                self.state.push1(res);
7233            }
7234            Operator::I32x4LeU => {
7235                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7236                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7237                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7238                let res = err!(
7239                    self.builder
7240                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7241                );
7242                let res = err!(
7243                    self.builder
7244                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7245                );
7246                let res = err!(
7247                    self.builder
7248                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7249                );
7250                self.state.push1(res);
7251            }
7252            Operator::I32GtS | Operator::I64GtS => {
7253                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7254                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7255                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7256                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7257                let cond = err!(
7258                    self.builder
7259                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7260                );
7261                let res = err!(
7262                    self.builder
7263                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7264                );
7265                self.state.push1_extra(
7266                    res,
7267                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7268                );
7269            }
7270            Operator::I8x16GtS => {
7271                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7272                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7273                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7274                let res = err!(
7275                    self.builder
7276                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7277                );
7278                let res = err!(
7279                    self.builder
7280                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7281                );
7282                let res = err!(
7283                    self.builder
7284                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7285                );
7286                self.state.push1(res);
7287            }
7288            Operator::I16x8GtS => {
7289                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7290                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7291                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7292                let res = err!(
7293                    self.builder
7294                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7295                );
7296                let res = err!(
7297                    self.builder
7298                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7299                );
7300                let res = err!(
7301                    self.builder
7302                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7303                );
7304                self.state.push1(res);
7305            }
7306            Operator::I32x4GtS => {
7307                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7308                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7309                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7310                let res = err!(
7311                    self.builder
7312                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7313                );
7314                let res = err!(
7315                    self.builder
7316                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7317                );
7318                let res = err!(
7319                    self.builder
7320                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7321                );
7322                self.state.push1(res);
7323            }
7324            Operator::I64x2GtS => {
7325                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7326                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7327                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7328                let res = err!(
7329                    self.builder
7330                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7331                );
7332                let res = err!(
7333                    self.builder
7334                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7335                );
7336                let res = err!(
7337                    self.builder
7338                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7339                );
7340                self.state.push1(res);
7341            }
7342            Operator::I32GtU | Operator::I64GtU => {
7343                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7344                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7345                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7346                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7347                let cond = err!(
7348                    self.builder
7349                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
7350                );
7351                let res = err!(
7352                    self.builder
7353                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7354                );
7355                self.state.push1_extra(
7356                    res,
7357                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7358                );
7359            }
7360            Operator::I8x16GtU => {
7361                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7362                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7363                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7364                let res = err!(
7365                    self.builder
7366                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
7367                );
7368                let res = err!(
7369                    self.builder
7370                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7371                );
7372                let res = err!(
7373                    self.builder
7374                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7375                );
7376                self.state.push1(res);
7377            }
7378            Operator::I16x8GtU => {
7379                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7380                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7381                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7382                let res = err!(
7383                    self.builder
7384                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
7385                );
7386                let res = err!(
7387                    self.builder
7388                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7389                );
7390                let res = err!(
7391                    self.builder
7392                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7393                );
7394                self.state.push1(res);
7395            }
7396            Operator::I32x4GtU => {
7397                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7398                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7399                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7400                let res = err!(
7401                    self.builder
7402                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
7403                );
7404                let res = err!(
7405                    self.builder
7406                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7407                );
7408                let res = err!(
7409                    self.builder
7410                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7411                );
7412                self.state.push1(res);
7413            }
7414            Operator::I32GeS | Operator::I64GeS => {
7415                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7416                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7417                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7418                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7419                let cond = err!(
7420                    self.builder
7421                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7422                );
7423                let res = err!(
7424                    self.builder
7425                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7426                );
7427                self.state.push1(res);
7428            }
7429            Operator::I8x16GeS => {
7430                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7431                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7432                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7433                let res = err!(
7434                    self.builder
7435                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7436                );
7437                let res = err!(
7438                    self.builder
7439                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7440                );
7441                let res = err!(
7442                    self.builder
7443                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7444                );
7445                self.state.push1(res);
7446            }
7447            Operator::I16x8GeS => {
7448                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7449                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7450                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7451                let res = err!(
7452                    self.builder
7453                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7454                );
7455                let res = err!(
7456                    self.builder
7457                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7458                );
7459                let res = err!(
7460                    self.builder
7461                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7462                );
7463                self.state.push1(res);
7464            }
7465            Operator::I32x4GeS => {
7466                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7467                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7468                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7469                let res = err!(
7470                    self.builder
7471                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7472                );
7473                let res = err!(
7474                    self.builder
7475                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7476                );
7477                let res = err!(
7478                    self.builder
7479                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7480                );
7481                self.state.push1(res);
7482            }
7483            Operator::I64x2GeS => {
7484                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7485                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7486                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7487                let res = err!(
7488                    self.builder
7489                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7490                );
7491                let res = err!(
7492                    self.builder
7493                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7494                );
7495                let res = err!(
7496                    self.builder
7497                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7498                );
7499                self.state.push1(res);
7500            }
7501            Operator::I32GeU | Operator::I64GeU => {
7502                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7503                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7504                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7505                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7506                let cond = err!(
7507                    self.builder
7508                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
7509                );
7510                let res = err!(
7511                    self.builder
7512                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7513                );
7514                self.state.push1_extra(
7515                    res,
7516                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7517                );
7518            }
7519            Operator::I8x16GeU => {
7520                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7521                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7522                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7523                let res = err!(
7524                    self.builder
7525                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
7526                );
7527                let res = err!(
7528                    self.builder
7529                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7530                );
7531                let res = err!(
7532                    self.builder
7533                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7534                );
7535                self.state.push1(res);
7536            }
7537            Operator::I16x8GeU => {
7538                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7539                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7540                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7541                let res = err!(
7542                    self.builder
7543                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
7544                );
7545                let res = err!(
7546                    self.builder
7547                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7548                );
7549                let res = err!(
7550                    self.builder
7551                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7552                );
7553                self.state.push1(res);
7554            }
7555            Operator::I32x4GeU => {
7556                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7557                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7558                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7559                let res = err!(
7560                    self.builder
7561                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
7562                );
7563                let res = err!(
7564                    self.builder
7565                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7566                );
7567                let res = err!(
7568                    self.builder
7569                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7570                );
7571                self.state.push1(res);
7572            }
7573
7574            /***************************
7575             * Floating-Point Comparison instructions.
7576             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-comparison-instructions
7577             ***************************/
7578            Operator::F32Eq | Operator::F64Eq => {
7579                let (v1, v2) = self.state.pop2()?;
7580                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7581                let cond = err!(
7582                    self.builder
7583                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
7584                );
7585                let res = err!(
7586                    self.builder
7587                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7588                );
7589                self.state.push1_extra(
7590                    res,
7591                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7592                );
7593            }
7594            Operator::F32x4Eq => {
7595                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7596                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7597                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7598                let res = err!(
7599                    self.builder
7600                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
7601                );
7602                let res = err!(
7603                    self.builder
7604                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7605                );
7606                let res = err!(
7607                    self.builder
7608                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7609                );
7610                self.state.push1(res);
7611            }
7612            Operator::F64x2Eq => {
7613                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7614                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7615                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7616                let res = err!(
7617                    self.builder
7618                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
7619                );
7620                let res = err!(
7621                    self.builder
7622                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7623                );
7624                let res = err!(
7625                    self.builder
7626                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7627                );
7628                self.state.push1(res);
7629            }
7630            Operator::F32Ne | Operator::F64Ne => {
7631                let (v1, v2) = self.state.pop2()?;
7632                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7633                let cond = err!(
7634                    self.builder
7635                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
7636                );
7637                let res = err!(
7638                    self.builder
7639                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7640                );
7641                self.state.push1_extra(
7642                    res,
7643                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7644                );
7645            }
7646            Operator::F32x4Ne => {
7647                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7648                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7649                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7650                let res = err!(
7651                    self.builder
7652                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
7653                );
7654                let res = err!(
7655                    self.builder
7656                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7657                );
7658                let res = err!(
7659                    self.builder
7660                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7661                );
7662                self.state.push1(res);
7663            }
7664            Operator::F64x2Ne => {
7665                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7666                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7667                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7668                let res = err!(
7669                    self.builder
7670                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
7671                );
7672                let res = err!(
7673                    self.builder
7674                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7675                );
7676                let res = err!(
7677                    self.builder
7678                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7679                );
7680                self.state.push1(res);
7681            }
7682            Operator::F32Lt | Operator::F64Lt => {
7683                let (v1, v2) = self.state.pop2()?;
7684                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7685                let cond = err!(
7686                    self.builder
7687                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7688                );
7689                let res = err!(
7690                    self.builder
7691                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7692                );
7693                self.state.push1_extra(
7694                    res,
7695                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7696                );
7697            }
7698            Operator::F32x4Lt => {
7699                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7700                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7701                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7702                let res = err!(
7703                    self.builder
7704                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7705                );
7706                let res = err!(
7707                    self.builder
7708                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7709                );
7710                let res = err!(
7711                    self.builder
7712                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7713                );
7714                self.state.push1(res);
7715            }
7716            Operator::F64x2Lt => {
7717                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7718                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7719                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7720                let res = err!(
7721                    self.builder
7722                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7723                );
7724                let res = err!(
7725                    self.builder
7726                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7727                );
7728                let res = err!(
7729                    self.builder
7730                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7731                );
7732                self.state.push1(res);
7733            }
7734            Operator::F32Le | Operator::F64Le => {
7735                let (v1, v2) = self.state.pop2()?;
7736                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7737                let cond = err!(
7738                    self.builder
7739                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
7740                );
7741                let res = err!(
7742                    self.builder
7743                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7744                );
7745                self.state.push1_extra(
7746                    res,
7747                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7748                );
7749            }
7750            Operator::F32x4Le => {
7751                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7752                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7753                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7754                let res = err!(
7755                    self.builder
7756                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
7757                );
7758                let res = err!(
7759                    self.builder
7760                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7761                );
7762                let res = err!(
7763                    self.builder
7764                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7765                );
7766                self.state.push1(res);
7767            }
7768            Operator::F64x2Le => {
7769                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7770                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7771                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7772                let res = err!(
7773                    self.builder
7774                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
7775                );
7776                let res = err!(
7777                    self.builder
7778                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7779                );
7780                let res = err!(
7781                    self.builder
7782                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7783                );
7784                self.state.push1(res);
7785            }
7786            Operator::F32Gt | Operator::F64Gt => {
7787                let (v1, v2) = self.state.pop2()?;
7788                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7789                let cond = err!(
7790                    self.builder
7791                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
7792                );
7793                let res = err!(
7794                    self.builder
7795                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7796                );
7797                self.state.push1_extra(
7798                    res,
7799                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7800                );
7801            }
7802            Operator::F32x4Gt => {
7803                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7804                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7805                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7806                let res = err!(
7807                    self.builder
7808                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
7809                );
7810                let res = err!(
7811                    self.builder
7812                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7813                );
7814                let res = err!(
7815                    self.builder
7816                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7817                );
7818                self.state.push1(res);
7819            }
7820            Operator::F64x2Gt => {
7821                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7822                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7823                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7824                let res = err!(
7825                    self.builder
7826                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
7827                );
7828                let res = err!(
7829                    self.builder
7830                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7831                );
7832                let res = err!(
7833                    self.builder
7834                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7835                );
7836                self.state.push1(res);
7837            }
7838            Operator::F32Ge | Operator::F64Ge => {
7839                let (v1, v2) = self.state.pop2()?;
7840                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7841                let cond = err!(
7842                    self.builder
7843                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
7844                );
7845                let res = err!(
7846                    self.builder
7847                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7848                );
7849                self.state.push1_extra(
7850                    res,
7851                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7852                );
7853            }
7854            Operator::F32x4Ge => {
7855                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7856                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7857                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7858                let res = err!(
7859                    self.builder
7860                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
7861                );
7862                let res = err!(
7863                    self.builder
7864                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7865                );
7866                let res = err!(
7867                    self.builder
7868                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7869                );
7870                self.state.push1(res);
7871            }
7872            Operator::F64x2Ge => {
7873                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7874                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7875                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7876                let res = err!(
7877                    self.builder
7878                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
7879                );
7880                let res = err!(
7881                    self.builder
7882                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7883                );
7884                let res = err!(
7885                    self.builder
7886                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7887                );
7888                self.state.push1(res);
7889            }
7890
7891            /***************************
7892             * Conversion instructions.
7893             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#conversion-instructions
7894             ***************************/
7895            Operator::I32WrapI64 => {
7896                let (v, i) = self.state.pop1_extra()?;
7897                let v = self.apply_pending_canonicalization(v, i)?;
7898                let v = v.into_int_value();
7899                let res = err!(
7900                    self.builder
7901                        .build_int_truncate(v, self.intrinsics.i32_ty, "")
7902                );
7903                self.state.push1(res);
7904            }
7905            Operator::I64ExtendI32S => {
7906                let (v, i) = self.state.pop1_extra()?;
7907                let v = self.apply_pending_canonicalization(v, i)?;
7908                let v = v.into_int_value();
7909                let res = err!(
7910                    self.builder
7911                        .build_int_s_extend(v, self.intrinsics.i64_ty, "")
7912                );
7913                self.state.push1(res);
7914            }
7915            Operator::I64ExtendI32U => {
7916                let (v, i) = self.state.pop1_extra()?;
7917                let v = self.apply_pending_canonicalization(v, i)?;
7918                let v = v.into_int_value();
7919                let res = err!(
7920                    self.builder
7921                        .build_int_z_extend(v, self.intrinsics.i64_ty, "")
7922                );
7923                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
7924            }
7925            Operator::I16x8ExtendLowI8x16S => {
7926                let (v, i) = self.state.pop1_extra()?;
7927                let (v, _) = self.v128_into_i8x16(v, i)?;
7928                let low = err!(self.builder.build_shuffle_vector(
7929                    v,
7930                    v.get_type().get_undef(),
7931                    VectorType::const_vector(&[
7932                        self.intrinsics.i32_consts[0],
7933                        self.intrinsics.i32_consts[1],
7934                        self.intrinsics.i32_consts[2],
7935                        self.intrinsics.i32_consts[3],
7936                        self.intrinsics.i32_consts[4],
7937                        self.intrinsics.i32_consts[5],
7938                        self.intrinsics.i32_consts[6],
7939                        self.intrinsics.i32_consts[7],
7940                    ]),
7941                    "",
7942                ));
7943                let res = err!(
7944                    self.builder
7945                        .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
7946                );
7947                let res = err!(
7948                    self.builder
7949                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7950                );
7951                self.state.push1(res);
7952            }
7953            Operator::I16x8ExtendHighI8x16S => {
7954                let (v, i) = self.state.pop1_extra()?;
7955                let (v, _) = self.v128_into_i8x16(v, i)?;
7956                let low = err!(self.builder.build_shuffle_vector(
7957                    v,
7958                    v.get_type().get_undef(),
7959                    VectorType::const_vector(&[
7960                        self.intrinsics.i32_consts[8],
7961                        self.intrinsics.i32_consts[9],
7962                        self.intrinsics.i32_consts[10],
7963                        self.intrinsics.i32_consts[11],
7964                        self.intrinsics.i32_consts[12],
7965                        self.intrinsics.i32_consts[13],
7966                        self.intrinsics.i32_consts[14],
7967                        self.intrinsics.i32_consts[15],
7968                    ]),
7969                    "",
7970                ));
7971                let res = err!(
7972                    self.builder
7973                        .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
7974                );
7975                let res = err!(
7976                    self.builder
7977                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7978                );
7979                self.state.push1(res);
7980            }
7981            Operator::I16x8ExtendLowI8x16U => {
7982                let (v, i) = self.state.pop1_extra()?;
7983                let (v, _) = self.v128_into_i8x16(v, i)?;
7984                let low = err!(self.builder.build_shuffle_vector(
7985                    v,
7986                    v.get_type().get_undef(),
7987                    VectorType::const_vector(&[
7988                        self.intrinsics.i32_consts[0],
7989                        self.intrinsics.i32_consts[1],
7990                        self.intrinsics.i32_consts[2],
7991                        self.intrinsics.i32_consts[3],
7992                        self.intrinsics.i32_consts[4],
7993                        self.intrinsics.i32_consts[5],
7994                        self.intrinsics.i32_consts[6],
7995                        self.intrinsics.i32_consts[7],
7996                    ]),
7997                    "",
7998                ));
7999                let res = err!(
8000                    self.builder
8001                        .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8002                );
8003                let res = err!(
8004                    self.builder
8005                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8006                );
8007                self.state.push1(res);
8008            }
8009            Operator::I16x8ExtendHighI8x16U => {
8010                let (v, i) = self.state.pop1_extra()?;
8011                let (v, _) = self.v128_into_i8x16(v, i)?;
8012                let low = err!(self.builder.build_shuffle_vector(
8013                    v,
8014                    v.get_type().get_undef(),
8015                    VectorType::const_vector(&[
8016                        self.intrinsics.i32_consts[8],
8017                        self.intrinsics.i32_consts[9],
8018                        self.intrinsics.i32_consts[10],
8019                        self.intrinsics.i32_consts[11],
8020                        self.intrinsics.i32_consts[12],
8021                        self.intrinsics.i32_consts[13],
8022                        self.intrinsics.i32_consts[14],
8023                        self.intrinsics.i32_consts[15],
8024                    ]),
8025                    "",
8026                ));
8027                let res = err!(
8028                    self.builder
8029                        .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8030                );
8031                let res = err!(
8032                    self.builder
8033                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8034                );
8035                self.state.push1(res);
8036            }
8037            Operator::I32x4ExtendLowI16x8S => {
8038                let (v, i) = self.state.pop1_extra()?;
8039                let (v, _) = self.v128_into_i16x8(v, i)?;
8040                let low = err!(self.builder.build_shuffle_vector(
8041                    v,
8042                    v.get_type().get_undef(),
8043                    VectorType::const_vector(&[
8044                        self.intrinsics.i32_consts[0],
8045                        self.intrinsics.i32_consts[1],
8046                        self.intrinsics.i32_consts[2],
8047                        self.intrinsics.i32_consts[3],
8048                    ]),
8049                    "",
8050                ));
8051                let res = err!(
8052                    self.builder
8053                        .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8054                );
8055                let res = err!(
8056                    self.builder
8057                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8058                );
8059                self.state.push1(res);
8060            }
8061            Operator::I32x4ExtendHighI16x8S => {
8062                let (v, i) = self.state.pop1_extra()?;
8063                let (v, _) = self.v128_into_i16x8(v, i)?;
8064                let low = err!(self.builder.build_shuffle_vector(
8065                    v,
8066                    v.get_type().get_undef(),
8067                    VectorType::const_vector(&[
8068                        self.intrinsics.i32_consts[4],
8069                        self.intrinsics.i32_consts[5],
8070                        self.intrinsics.i32_consts[6],
8071                        self.intrinsics.i32_consts[7],
8072                    ]),
8073                    "",
8074                ));
8075                let res = err!(
8076                    self.builder
8077                        .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8078                );
8079                let res = err!(
8080                    self.builder
8081                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8082                );
8083                self.state.push1(res);
8084            }
8085            Operator::I32x4ExtendLowI16x8U => {
8086                let (v, i) = self.state.pop1_extra()?;
8087                let (v, _) = self.v128_into_i16x8(v, i)?;
8088                let low = err!(self.builder.build_shuffle_vector(
8089                    v,
8090                    v.get_type().get_undef(),
8091                    VectorType::const_vector(&[
8092                        self.intrinsics.i32_consts[0],
8093                        self.intrinsics.i32_consts[1],
8094                        self.intrinsics.i32_consts[2],
8095                        self.intrinsics.i32_consts[3],
8096                    ]),
8097                    "",
8098                ));
8099                let res = err!(
8100                    self.builder
8101                        .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8102                );
8103                let res = err!(
8104                    self.builder
8105                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8106                );
8107                self.state.push1(res);
8108            }
8109            Operator::I32x4ExtendHighI16x8U => {
8110                let (v, i) = self.state.pop1_extra()?;
8111                let (v, _) = self.v128_into_i16x8(v, i)?;
8112                let low = err!(self.builder.build_shuffle_vector(
8113                    v,
8114                    v.get_type().get_undef(),
8115                    VectorType::const_vector(&[
8116                        self.intrinsics.i32_consts[4],
8117                        self.intrinsics.i32_consts[5],
8118                        self.intrinsics.i32_consts[6],
8119                        self.intrinsics.i32_consts[7],
8120                    ]),
8121                    "",
8122                ));
8123                let res = err!(
8124                    self.builder
8125                        .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8126                );
8127                let res = err!(
8128                    self.builder
8129                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8130                );
8131                self.state.push1(res);
8132            }
8133            Operator::I64x2ExtendLowI32x4U
8134            | Operator::I64x2ExtendLowI32x4S
8135            | Operator::I64x2ExtendHighI32x4U
8136            | Operator::I64x2ExtendHighI32x4S => {
8137                let extend = match op {
8138                    Operator::I64x2ExtendLowI32x4U | Operator::I64x2ExtendHighI32x4U => {
8139                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
8140                    }
8141                    Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendHighI32x4S => {
8142                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
8143                    }
8144                    _ => unreachable!("Unhandled inner case"),
8145                };
8146                let indices = match op {
8147                    Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendLowI32x4U => {
8148                        [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
8149                    }
8150                    Operator::I64x2ExtendHighI32x4S | Operator::I64x2ExtendHighI32x4U => {
8151                        [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
8152                    }
8153                    _ => unreachable!("Unhandled inner case"),
8154                };
8155                let (v, i) = self.state.pop1_extra()?;
8156                let (v, _) = self.v128_into_i32x4(v, i)?;
8157                let low = err!(self.builder.build_shuffle_vector(
8158                    v,
8159                    v.get_type().get_undef(),
8160                    VectorType::const_vector(&indices),
8161                    "",
8162                ));
8163                let res = err!(extend(self, low));
8164                let res = err!(
8165                    self.builder
8166                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8167                );
8168                self.state.push1(res);
8169            }
8170            Operator::I8x16NarrowI16x8S => {
8171                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8172                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8173                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8174                let min = self.intrinsics.i16_ty.const_int(0xff80, false);
8175                let max = self.intrinsics.i16_ty.const_int(0x007f, false);
8176                let min = VectorType::const_vector(&[min; 8]);
8177                let max = VectorType::const_vector(&[max; 8]);
8178                let apply_min_clamp_v1 =
8179                    err!(
8180                        self.builder
8181                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8182                    );
8183                let apply_max_clamp_v1 =
8184                    err!(
8185                        self.builder
8186                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8187                    );
8188                let apply_min_clamp_v2 =
8189                    err!(
8190                        self.builder
8191                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8192                    );
8193                let apply_max_clamp_v2 =
8194                    err!(
8195                        self.builder
8196                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8197                    );
8198                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8199                    .into_vector_value();
8200                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8201                    .into_vector_value();
8202                let v1 = err!(self.builder.build_int_truncate(
8203                    v1,
8204                    self.intrinsics.i8_ty.vec_type(8),
8205                    ""
8206                ));
8207                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8208                    .into_vector_value();
8209                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8210                    .into_vector_value();
8211                let v2 = err!(self.builder.build_int_truncate(
8212                    v2,
8213                    self.intrinsics.i8_ty.vec_type(8),
8214                    ""
8215                ));
8216                let res = err!(self.builder.build_shuffle_vector(
8217                    v1,
8218                    v2,
8219                    VectorType::const_vector(&[
8220                        self.intrinsics.i32_consts[0],
8221                        self.intrinsics.i32_consts[1],
8222                        self.intrinsics.i32_consts[2],
8223                        self.intrinsics.i32_consts[3],
8224                        self.intrinsics.i32_consts[4],
8225                        self.intrinsics.i32_consts[5],
8226                        self.intrinsics.i32_consts[6],
8227                        self.intrinsics.i32_consts[7],
8228                        self.intrinsics.i32_consts[8],
8229                        self.intrinsics.i32_consts[9],
8230                        self.intrinsics.i32_consts[10],
8231                        self.intrinsics.i32_consts[11],
8232                        self.intrinsics.i32_consts[12],
8233                        self.intrinsics.i32_consts[13],
8234                        self.intrinsics.i32_consts[14],
8235                        self.intrinsics.i32_consts[15],
8236                    ]),
8237                    "",
8238                ));
8239                let res = err!(
8240                    self.builder
8241                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8242                );
8243                self.state.push1(res);
8244            }
8245            Operator::I8x16NarrowI16x8U => {
8246                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8247                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8248                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8249                let min = self.intrinsics.i16x8_ty.const_zero();
8250                let max = self.intrinsics.i16_ty.const_int(0x00ff, false);
8251                let max = VectorType::const_vector(&[max; 8]);
8252                let apply_min_clamp_v1 =
8253                    err!(
8254                        self.builder
8255                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8256                    );
8257                let apply_max_clamp_v1 =
8258                    err!(
8259                        self.builder
8260                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8261                    );
8262                let apply_min_clamp_v2 =
8263                    err!(
8264                        self.builder
8265                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8266                    );
8267                let apply_max_clamp_v2 =
8268                    err!(
8269                        self.builder
8270                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8271                    );
8272                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8273                    .into_vector_value();
8274                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8275                    .into_vector_value();
8276                let v1 = err!(self.builder.build_int_truncate(
8277                    v1,
8278                    self.intrinsics.i8_ty.vec_type(8),
8279                    ""
8280                ));
8281                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8282                    .into_vector_value();
8283                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8284                    .into_vector_value();
8285                let v2 = err!(self.builder.build_int_truncate(
8286                    v2,
8287                    self.intrinsics.i8_ty.vec_type(8),
8288                    ""
8289                ));
8290                let res = err!(self.builder.build_shuffle_vector(
8291                    v1,
8292                    v2,
8293                    VectorType::const_vector(&[
8294                        self.intrinsics.i32_consts[0],
8295                        self.intrinsics.i32_consts[1],
8296                        self.intrinsics.i32_consts[2],
8297                        self.intrinsics.i32_consts[3],
8298                        self.intrinsics.i32_consts[4],
8299                        self.intrinsics.i32_consts[5],
8300                        self.intrinsics.i32_consts[6],
8301                        self.intrinsics.i32_consts[7],
8302                        self.intrinsics.i32_consts[8],
8303                        self.intrinsics.i32_consts[9],
8304                        self.intrinsics.i32_consts[10],
8305                        self.intrinsics.i32_consts[11],
8306                        self.intrinsics.i32_consts[12],
8307                        self.intrinsics.i32_consts[13],
8308                        self.intrinsics.i32_consts[14],
8309                        self.intrinsics.i32_consts[15],
8310                    ]),
8311                    "",
8312                ));
8313                let res = err!(
8314                    self.builder
8315                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8316                );
8317                self.state.push1(res);
8318            }
8319            Operator::I16x8NarrowI32x4S => {
8320                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8321                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8322                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8323                let min = self.intrinsics.i32_ty.const_int(0xffff8000, false);
8324                let max = self.intrinsics.i32_ty.const_int(0x00007fff, false);
8325                let min = VectorType::const_vector(&[min; 4]);
8326                let max = VectorType::const_vector(&[max; 4]);
8327                let apply_min_clamp_v1 =
8328                    err!(
8329                        self.builder
8330                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8331                    );
8332                let apply_max_clamp_v1 =
8333                    err!(
8334                        self.builder
8335                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8336                    );
8337                let apply_min_clamp_v2 =
8338                    err!(
8339                        self.builder
8340                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8341                    );
8342                let apply_max_clamp_v2 =
8343                    err!(
8344                        self.builder
8345                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8346                    );
8347                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8348                    .into_vector_value();
8349                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8350                    .into_vector_value();
8351                let v1 = err!(self.builder.build_int_truncate(
8352                    v1,
8353                    self.intrinsics.i16_ty.vec_type(4),
8354                    ""
8355                ));
8356                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8357                    .into_vector_value();
8358                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8359                    .into_vector_value();
8360                let v2 = err!(self.builder.build_int_truncate(
8361                    v2,
8362                    self.intrinsics.i16_ty.vec_type(4),
8363                    ""
8364                ));
8365                let res = err!(self.builder.build_shuffle_vector(
8366                    v1,
8367                    v2,
8368                    VectorType::const_vector(&[
8369                        self.intrinsics.i32_consts[0],
8370                        self.intrinsics.i32_consts[1],
8371                        self.intrinsics.i32_consts[2],
8372                        self.intrinsics.i32_consts[3],
8373                        self.intrinsics.i32_consts[4],
8374                        self.intrinsics.i32_consts[5],
8375                        self.intrinsics.i32_consts[6],
8376                        self.intrinsics.i32_consts[7],
8377                    ]),
8378                    "",
8379                ));
8380                let res = err!(
8381                    self.builder
8382                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8383                );
8384                self.state.push1(res);
8385            }
8386            Operator::I16x8NarrowI32x4U => {
8387                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8388                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8389                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8390                let min = self.intrinsics.i32x4_ty.const_zero();
8391                let max = self.intrinsics.i32_ty.const_int(0xffff, false);
8392                let max = VectorType::const_vector(&[max; 4]);
8393                let apply_min_clamp_v1 =
8394                    err!(
8395                        self.builder
8396                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8397                    );
8398                let apply_max_clamp_v1 =
8399                    err!(
8400                        self.builder
8401                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8402                    );
8403                let apply_min_clamp_v2 =
8404                    err!(
8405                        self.builder
8406                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8407                    );
8408                let apply_max_clamp_v2 =
8409                    err!(
8410                        self.builder
8411                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8412                    );
8413                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8414                    .into_vector_value();
8415                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8416                    .into_vector_value();
8417                let v1 = err!(self.builder.build_int_truncate(
8418                    v1,
8419                    self.intrinsics.i16_ty.vec_type(4),
8420                    ""
8421                ));
8422                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8423                    .into_vector_value();
8424                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8425                    .into_vector_value();
8426                let v2 = err!(self.builder.build_int_truncate(
8427                    v2,
8428                    self.intrinsics.i16_ty.vec_type(4),
8429                    ""
8430                ));
8431                let res = err!(self.builder.build_shuffle_vector(
8432                    v1,
8433                    v2,
8434                    VectorType::const_vector(&[
8435                        self.intrinsics.i32_consts[0],
8436                        self.intrinsics.i32_consts[1],
8437                        self.intrinsics.i32_consts[2],
8438                        self.intrinsics.i32_consts[3],
8439                        self.intrinsics.i32_consts[4],
8440                        self.intrinsics.i32_consts[5],
8441                        self.intrinsics.i32_consts[6],
8442                        self.intrinsics.i32_consts[7],
8443                    ]),
8444                    "",
8445                ));
8446                let res = err!(
8447                    self.builder
8448                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8449                );
8450                self.state.push1(res);
8451            }
8452            Operator::I32x4RelaxedTruncF32x4S if self.cpu_features.contains(CpuFeature::SSE2) => {
8453                let (v, i) = self.state.pop1_extra()?;
8454                let (v, _) = self.v128_into_f32x4(v, i)?;
8455                let res = self
8456                    .build_call_with_param_attributes(
8457                        self.intrinsics.x86_64.cvttps2dq,
8458                        &[v.into()],
8459                        "",
8460                    )?
8461                    .try_as_basic_value()
8462                    .unwrap_basic();
8463                let res = err!(
8464                    self.builder
8465                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8466                );
8467                self.state.push1(res);
8468            }
8469            Operator::I32x4TruncSatF32x4S | Operator::I32x4RelaxedTruncF32x4S => {
8470                let (v, i) = self.state.pop1_extra()?;
8471                let v = self.apply_pending_canonicalization(v, i)?;
8472                let v = v.into_int_value();
8473                let res = self.trunc_sat_into_int(
8474                    self.intrinsics.f32x4_ty,
8475                    self.intrinsics.i32x4_ty,
8476                    LEF32_GEQ_I32_MIN,
8477                    GEF32_LEQ_I32_MAX,
8478                    i32::MIN as u64,
8479                    i32::MAX as u64,
8480                    v,
8481                )?;
8482                self.state.push1(res);
8483            }
8484            Operator::I32x4RelaxedTruncF32x4U
8485                if self.cpu_features.contains(CpuFeature::AVX512F)
8486                    && self.cpu_features.contains(CpuFeature::AVX512VL) =>
8487            {
8488                let (v, i) = self.state.pop1_extra()?;
8489                let (v, _) = self.v128_into_f32x4(v, i)?;
8490                let res = self
8491                    .build_call_with_param_attributes(
8492                        self.intrinsics.x86_64.cvtps2udq128,
8493                        &[
8494                            v.into(),
8495                            self.intrinsics.i32x4_ty.const_zero().into(),
8496                            self.intrinsics.i8_ty.const_int(0xff, false).into(),
8497                        ],
8498                        "",
8499                    )?
8500                    .try_as_basic_value()
8501                    .unwrap_basic();
8502                let res = err!(
8503                    self.builder
8504                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8505                );
8506                self.state.push1(res);
8507            }
8508            Operator::I32x4TruncSatF32x4U | Operator::I32x4RelaxedTruncF32x4U => {
8509                let (v, i) = self.state.pop1_extra()?;
8510                let v = self.apply_pending_canonicalization(v, i)?;
8511                let v = v.into_int_value();
8512                let res = self.trunc_sat_into_int(
8513                    self.intrinsics.f32x4_ty,
8514                    self.intrinsics.i32x4_ty,
8515                    LEF32_GEQ_U32_MIN,
8516                    GEF32_LEQ_U32_MAX,
8517                    u32::MIN as u64,
8518                    u32::MAX as u64,
8519                    v,
8520                )?;
8521                self.state.push1(res);
8522            }
8523            Operator::I32x4RelaxedTruncF64x2SZero
8524                if self.cpu_features.contains(CpuFeature::SSE2) =>
8525            {
8526                let (v, i) = self.state.pop1_extra()?;
8527                let (v, _) = self.v128_into_f64x2(v, i)?;
8528                let res = self
8529                    .build_call_with_param_attributes(
8530                        self.intrinsics.x86_64.cvtpd2dq,
8531                        &[v.into()],
8532                        "",
8533                    )?
8534                    .try_as_basic_value()
8535                    .unwrap_basic();
8536                let res = err!(
8537                    self.builder
8538                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8539                );
8540                self.state.push1(res);
8541            }
8542            Operator::I32x4RelaxedTruncF64x2UZero
8543                if self.cpu_features.contains(CpuFeature::AVX512F)
8544                    && self.cpu_features.contains(CpuFeature::AVX512VL) =>
8545            {
8546                let (v, i) = self.state.pop1_extra()?;
8547                let (v, _) = self.v128_into_f64x2(v, i)?;
8548                let res = self
8549                    .build_call_with_param_attributes(
8550                        self.intrinsics.x86_64.cvtpd2udq128,
8551                        &[
8552                            v.into(),
8553                            self.intrinsics.i32x4_ty.const_zero().into(),
8554                            self.intrinsics.i8_ty.const_int(0xff, false).into(),
8555                        ],
8556                        "",
8557                    )?
8558                    .try_as_basic_value()
8559                    .unwrap_basic();
8560                let res = err!(
8561                    self.builder
8562                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8563                );
8564                self.state.push1(res);
8565            }
8566            Operator::I32x4TruncSatF64x2SZero
8567            | Operator::I32x4TruncSatF64x2UZero
8568            | Operator::I32x4RelaxedTruncF64x2SZero
8569            | Operator::I32x4RelaxedTruncF64x2UZero => {
8570                let ((min, max), (cmp_min, cmp_max)) = match op {
8571                    Operator::I32x4TruncSatF64x2SZero => (
8572                        (i32::MIN as u64, i32::MAX as u64),
8573                        (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
8574                    ),
8575                    Operator::I32x4TruncSatF64x2UZero => (
8576                        (u32::MIN as u64, u32::MAX as u64),
8577                        (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
8578                    ),
8579                    Operator::I32x4RelaxedTruncF64x2SZero => (
8580                        (i32::MIN as u64, i32::MAX as u64),
8581                        (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
8582                    ),
8583                    Operator::I32x4RelaxedTruncF64x2UZero => (
8584                        (u32::MIN as u64, u32::MAX as u64),
8585                        (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
8586                    ),
8587                    _ => unreachable!("Unhandled internal variant"),
8588                };
8589                let (v, i) = self.state.pop1_extra()?;
8590                let v = self.apply_pending_canonicalization(v, i)?;
8591                let v = v.into_int_value();
8592                let res = self.trunc_sat(
8593                    self.intrinsics.f64x2_ty,
8594                    self.intrinsics.i32_ty.vec_type(2),
8595                    cmp_min,
8596                    cmp_max,
8597                    min,
8598                    max,
8599                    v,
8600                )?;
8601
8602                let zero = self.intrinsics.i32_consts[0];
8603                let zeros = VectorType::const_vector(&[zero; 2]);
8604                let res = err!(self.builder.build_shuffle_vector(
8605                    res,
8606                    zeros,
8607                    VectorType::const_vector(&[
8608                        self.intrinsics.i32_consts[0],
8609                        self.intrinsics.i32_consts[1],
8610                        self.intrinsics.i32_consts[2],
8611                        self.intrinsics.i32_consts[3],
8612                    ]),
8613                    "",
8614                ));
8615                let res = err!(
8616                    self.builder
8617                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8618                );
8619                self.state.push1(res);
8620            }
8621            // Operator::I64x2TruncSatF64x2S => {
8622            //     let (v, i) = self.state.pop1_extra()?;
8623            //     let v = self.apply_pending_canonicalization(v, i)?;
8624            //     let v = v.into_int_value();
8625            //     let res = self.trunc_sat_into_int(
8626            //         self.intrinsics.f64x2_ty,
8627            //         self.intrinsics.i64x2_ty,
8628            //         i64::MIN as u64,
8629            //         i64::MAX as u64,
8630            //         i64::MIN as u64,
8631            //         i64::MAX as u64,
8632            //         v,
8633            //     )?;
8634            //     self.state.push1(res);
8635            // }
8636            // Operator::I64x2TruncSatF64x2U => {
8637            //     let (v, i) = self.state.pop1_extra()?;
8638            //     let v = self.apply_pending_canonicalization(v, i)?;
8639            //     let v = v.into_int_value();
8640            //     let res = self.trunc_sat_into_int(
8641            //         self.intrinsics.f64x2_ty,
8642            //         self.intrinsics.i64x2_ty,
8643            //         u64::MIN,
8644            //         u64::MAX,
8645            //         u64::MIN,
8646            //         u64::MAX,
8647            //         v,
8648            //     )?;
8649            //     self.state.push1(res);
8650            // }
8651            Operator::I32TruncF32S => {
8652                let v1 = self.state.pop1()?.into_float_value();
8653                self.trap_if_not_representable_as_int(
8654                    0xcf000000, // -2147483600.0
8655                    0x4effffff, // 2147483500.0
8656                    v1,
8657                )?;
8658                let res = err!(self.builder.build_float_to_signed_int(
8659                    v1,
8660                    self.intrinsics.i32_ty,
8661                    ""
8662                ));
8663                self.state.push1(res);
8664            }
8665            Operator::I32TruncF64S => {
8666                let v1 = self.state.pop1()?.into_float_value();
8667                self.trap_if_not_representable_as_int(
8668                    0xc1e00000001fffff, // -2147483648.9999995
8669                    0x41dfffffffffffff, // 2147483647.9999998
8670                    v1,
8671                )?;
8672                let res = err!(self.builder.build_float_to_signed_int(
8673                    v1,
8674                    self.intrinsics.i32_ty,
8675                    ""
8676                ));
8677                self.state.push1(res);
8678            }
8679            Operator::I32TruncSatF32S => {
8680                let (v, i) = self.state.pop1_extra()?;
8681                let v = self.apply_pending_canonicalization(v, i)?;
8682                let v = v.into_float_value();
8683                let res = self.trunc_sat_scalar(
8684                    self.intrinsics.i32_ty,
8685                    LEF32_GEQ_I32_MIN,
8686                    GEF32_LEQ_I32_MAX,
8687                    i32::MIN as u32 as u64,
8688                    i32::MAX as u32 as u64,
8689                    v,
8690                )?;
8691                self.state.push1(res);
8692            }
8693            Operator::I32TruncSatF64S => {
8694                let (v, i) = self.state.pop1_extra()?;
8695                let v = self.apply_pending_canonicalization(v, i)?;
8696                let v = v.into_float_value();
8697                let res = self.trunc_sat_scalar(
8698                    self.intrinsics.i32_ty,
8699                    LEF64_GEQ_I32_MIN,
8700                    GEF64_LEQ_I32_MAX,
8701                    i32::MIN as u64,
8702                    i32::MAX as u64,
8703                    v,
8704                )?;
8705                self.state.push1(res);
8706            }
8707            Operator::I64TruncF32S => {
8708                let v1 = self.state.pop1()?.into_float_value();
8709                self.trap_if_not_representable_as_int(
8710                    0xdf000000, // -9223372000000000000.0
8711                    0x5effffff, // 9223371500000000000.0
8712                    v1,
8713                )?;
8714                let res = err!(self.builder.build_float_to_signed_int(
8715                    v1,
8716                    self.intrinsics.i64_ty,
8717                    ""
8718                ));
8719                self.state.push1(res);
8720            }
8721            Operator::I64TruncF64S => {
8722                let v1 = self.state.pop1()?.into_float_value();
8723                self.trap_if_not_representable_as_int(
8724                    0xc3e0000000000000, // -9223372036854776000.0
8725                    0x43dfffffffffffff, // 9223372036854775000.0
8726                    v1,
8727                )?;
8728                let res = err!(self.builder.build_float_to_signed_int(
8729                    v1,
8730                    self.intrinsics.i64_ty,
8731                    ""
8732                ));
8733                self.state.push1(res);
8734            }
8735            Operator::I64TruncSatF32S => {
8736                let (v, i) = self.state.pop1_extra()?;
8737                let v = self.apply_pending_canonicalization(v, i)?;
8738                let v = v.into_float_value();
8739                let res = self.trunc_sat_scalar(
8740                    self.intrinsics.i64_ty,
8741                    LEF32_GEQ_I64_MIN,
8742                    GEF32_LEQ_I64_MAX,
8743                    i64::MIN as u64,
8744                    i64::MAX as u64,
8745                    v,
8746                )?;
8747                self.state.push1(res);
8748            }
8749            Operator::I64TruncSatF64S => {
8750                let (v, i) = self.state.pop1_extra()?;
8751                let v = self.apply_pending_canonicalization(v, i)?;
8752                let v = v.into_float_value();
8753                let res = self.trunc_sat_scalar(
8754                    self.intrinsics.i64_ty,
8755                    LEF64_GEQ_I64_MIN,
8756                    GEF64_LEQ_I64_MAX,
8757                    i64::MIN as u64,
8758                    i64::MAX as u64,
8759                    v,
8760                )?;
8761                self.state.push1(res);
8762            }
8763            Operator::I32TruncF32U => {
8764                let v1 = self.state.pop1()?.into_float_value();
8765                self.trap_if_not_representable_as_int(
8766                    0xbf7fffff, // -0.99999994
8767                    0x4f7fffff, // 4294967000.0
8768                    v1,
8769                )?;
8770                let res = err!(self.builder.build_float_to_unsigned_int(
8771                    v1,
8772                    self.intrinsics.i32_ty,
8773                    ""
8774                ));
8775                self.state.push1(res);
8776            }
8777            Operator::I32TruncF64U => {
8778                let v1 = self.state.pop1()?.into_float_value();
8779                self.trap_if_not_representable_as_int(
8780                    0xbfefffffffffffff, // -0.9999999999999999
8781                    0x41efffffffffffff, // 4294967295.9999995
8782                    v1,
8783                )?;
8784                let res = err!(self.builder.build_float_to_unsigned_int(
8785                    v1,
8786                    self.intrinsics.i32_ty,
8787                    ""
8788                ));
8789                self.state.push1(res);
8790            }
8791            Operator::I32TruncSatF32U => {
8792                let (v, i) = self.state.pop1_extra()?;
8793                let v = self.apply_pending_canonicalization(v, i)?;
8794                let v = v.into_float_value();
8795                let res = self.trunc_sat_scalar(
8796                    self.intrinsics.i32_ty,
8797                    LEF32_GEQ_U32_MIN,
8798                    GEF32_LEQ_U32_MAX,
8799                    u32::MIN as u64,
8800                    u32::MAX as u64,
8801                    v,
8802                )?;
8803                self.state.push1(res);
8804            }
8805            Operator::I32TruncSatF64U => {
8806                let (v, i) = self.state.pop1_extra()?;
8807                let v = self.apply_pending_canonicalization(v, i)?;
8808                let v = v.into_float_value();
8809                let res = self.trunc_sat_scalar(
8810                    self.intrinsics.i32_ty,
8811                    LEF64_GEQ_U32_MIN,
8812                    GEF64_LEQ_U32_MAX,
8813                    u32::MIN as u64,
8814                    u32::MAX as u64,
8815                    v,
8816                )?;
8817                self.state.push1(res);
8818            }
8819            Operator::I64TruncF32U => {
8820                let v1 = self.state.pop1()?.into_float_value();
8821                self.trap_if_not_representable_as_int(
8822                    0xbf7fffff, // -0.99999994
8823                    0x5f7fffff, // 18446743000000000000.0
8824                    v1,
8825                )?;
8826                let res = err!(self.builder.build_float_to_unsigned_int(
8827                    v1,
8828                    self.intrinsics.i64_ty,
8829                    ""
8830                ));
8831                self.state.push1(res);
8832            }
8833            Operator::I64TruncF64U => {
8834                let v1 = self.state.pop1()?.into_float_value();
8835                self.trap_if_not_representable_as_int(
8836                    0xbfefffffffffffff, // -0.9999999999999999
8837                    0x43efffffffffffff, // 18446744073709550000.0
8838                    v1,
8839                )?;
8840                let res = err!(self.builder.build_float_to_unsigned_int(
8841                    v1,
8842                    self.intrinsics.i64_ty,
8843                    ""
8844                ));
8845                self.state.push1(res);
8846            }
8847            Operator::I64TruncSatF32U => {
8848                let (v, i) = self.state.pop1_extra()?;
8849                let v = self.apply_pending_canonicalization(v, i)?;
8850                let v = v.into_float_value();
8851                let res = self.trunc_sat_scalar(
8852                    self.intrinsics.i64_ty,
8853                    LEF32_GEQ_U64_MIN,
8854                    GEF32_LEQ_U64_MAX,
8855                    u64::MIN,
8856                    u64::MAX,
8857                    v,
8858                )?;
8859                self.state.push1(res);
8860            }
8861            Operator::I64TruncSatF64U => {
8862                let (v, i) = self.state.pop1_extra()?;
8863                let v = self.apply_pending_canonicalization(v, i)?;
8864                let v = v.into_float_value();
8865                let res = self.trunc_sat_scalar(
8866                    self.intrinsics.i64_ty,
8867                    LEF64_GEQ_U64_MIN,
8868                    GEF64_LEQ_U64_MAX,
8869                    u64::MIN,
8870                    u64::MAX,
8871                    v,
8872                )?;
8873                self.state.push1(res);
8874            }
8875            Operator::F32DemoteF64 => {
8876                let v = self.state.pop1()?;
8877                let v = v.into_float_value();
8878                let res = self
8879                    .build_call_with_param_attributes(
8880                        self.intrinsics.fptrunc_f64,
8881                        &[
8882                            v.into(),
8883                            self.intrinsics.fp_rounding_md,
8884                            self.intrinsics.fp_exception_md,
8885                        ],
8886                        "",
8887                    )?
8888                    .try_as_basic_value()
8889                    .unwrap_basic();
8890                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
8891            }
8892            Operator::F64PromoteF32 => {
8893                let v = self.state.pop1()?;
8894                let v = v.into_float_value();
8895                let res = self
8896                    .build_call_with_param_attributes(
8897                        self.intrinsics.fpext_f32,
8898                        &[v.into(), self.intrinsics.fp_exception_md],
8899                        "",
8900                    )?
8901                    .try_as_basic_value()
8902                    .unwrap_basic();
8903                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
8904            }
8905            Operator::F32ConvertI32S | Operator::F32ConvertI64S => {
8906                let (v, i) = self.state.pop1_extra()?;
8907                let v = self.apply_pending_canonicalization(v, i)?;
8908                let v = v.into_int_value();
8909                let res = err!(self.builder.build_signed_int_to_float(
8910                    v,
8911                    self.intrinsics.f32_ty,
8912                    ""
8913                ));
8914                self.state.push1(res);
8915            }
8916            Operator::F64ConvertI32S | Operator::F64ConvertI64S => {
8917                let (v, i) = self.state.pop1_extra()?;
8918                let v = self.apply_pending_canonicalization(v, i)?;
8919                let v = v.into_int_value();
8920                let res = err!(self.builder.build_signed_int_to_float(
8921                    v,
8922                    self.intrinsics.f64_ty,
8923                    ""
8924                ));
8925                self.state.push1(res);
8926            }
8927            Operator::F32ConvertI32U | Operator::F32ConvertI64U => {
8928                let (v, i) = self.state.pop1_extra()?;
8929                let v = self.apply_pending_canonicalization(v, i)?;
8930                let v = v.into_int_value();
8931                let res = err!(self.builder.build_unsigned_int_to_float(
8932                    v,
8933                    self.intrinsics.f32_ty,
8934                    ""
8935                ));
8936                self.state.push1(res);
8937            }
8938            Operator::F64ConvertI32U | Operator::F64ConvertI64U => {
8939                let (v, i) = self.state.pop1_extra()?;
8940                let v = self.apply_pending_canonicalization(v, i)?;
8941                let v = v.into_int_value();
8942                let res = err!(self.builder.build_unsigned_int_to_float(
8943                    v,
8944                    self.intrinsics.f64_ty,
8945                    ""
8946                ));
8947                self.state.push1(res);
8948            }
8949            Operator::F32x4ConvertI32x4S => {
8950                let v = self.state.pop1()?;
8951                let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
8952                    .into_vector_value();
8953                let res = err!(self.builder.build_signed_int_to_float(
8954                    v,
8955                    self.intrinsics.f32x4_ty,
8956                    ""
8957                ));
8958                let res = err!(
8959                    self.builder
8960                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8961                );
8962                self.state.push1(res);
8963            }
8964            Operator::F32x4ConvertI32x4U => {
8965                let v = self.state.pop1()?;
8966                let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
8967                    .into_vector_value();
8968                let res = err!(self.builder.build_unsigned_int_to_float(
8969                    v,
8970                    self.intrinsics.f32x4_ty,
8971                    ""
8972                ));
8973                let res = err!(
8974                    self.builder
8975                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8976                );
8977                self.state.push1(res);
8978            }
8979            Operator::F64x2ConvertLowI32x4S | Operator::F64x2ConvertLowI32x4U => {
8980                let extend = match op {
8981                    Operator::F64x2ConvertLowI32x4U => {
8982                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
8983                    }
8984                    Operator::F64x2ConvertLowI32x4S => {
8985                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
8986                    }
8987                    _ => unreachable!("Unhandled inner case"),
8988                };
8989                let (v, i) = self.state.pop1_extra()?;
8990                let (v, _) = self.v128_into_i32x4(v, i)?;
8991                let low = err!(self.builder.build_shuffle_vector(
8992                    v,
8993                    v.get_type().get_undef(),
8994                    VectorType::const_vector(&[
8995                        self.intrinsics.i32_consts[0],
8996                        self.intrinsics.i32_consts[1],
8997                    ]),
8998                    "",
8999                ));
9000                let res = err!(extend(self, low));
9001                let res = err!(self.builder.build_signed_int_to_float(
9002                    res,
9003                    self.intrinsics.f64x2_ty,
9004                    ""
9005                ));
9006                let res = err!(
9007                    self.builder
9008                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9009                );
9010                self.state.push1(res);
9011            }
9012            Operator::F64x2PromoteLowF32x4 => {
9013                let (v, i) = self.state.pop1_extra()?;
9014                let (v, _) = self.v128_into_f32x4(v, i)?;
9015                let low = err!(self.builder.build_shuffle_vector(
9016                    v,
9017                    v.get_type().get_undef(),
9018                    VectorType::const_vector(&[
9019                        self.intrinsics.i32_consts[0],
9020                        self.intrinsics.i32_consts[1],
9021                    ]),
9022                    "",
9023                ));
9024                let res = err!(
9025                    self.builder
9026                        .build_float_ext(low, self.intrinsics.f64x2_ty, "")
9027                );
9028                let res = err!(
9029                    self.builder
9030                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9031                );
9032                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9033            }
9034            Operator::F32x4DemoteF64x2Zero => {
9035                let (v, i) = self.state.pop1_extra()?;
9036                let (v, _) = self.v128_into_f64x2(v, i)?;
9037                let f32x2_ty = self.intrinsics.f32_ty.vec_type(2);
9038                let res = err!(self.builder.build_float_trunc(v, f32x2_ty, ""));
9039                let zeros = f32x2_ty.const_zero();
9040                let res = err!(self.builder.build_shuffle_vector(
9041                    res,
9042                    zeros,
9043                    VectorType::const_vector(&[
9044                        self.intrinsics.i32_consts[0],
9045                        self.intrinsics.i32_consts[1],
9046                        self.intrinsics.i32_consts[2],
9047                        self.intrinsics.i32_consts[3],
9048                    ]),
9049                    "",
9050                ));
9051                let res = err!(
9052                    self.builder
9053                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9054                );
9055                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9056            }
9057            // Operator::F64x2ConvertI64x2S => {
9058            //     let v = self.state.pop1()?;
9059            //     let v = self
9060            //         .builder
9061            //         .build_bit_cast(v, self.intrinsics.i64x2_ty, "")
9062            //         .into_vector_value();
9063            //     let res = self
9064            //         .builder
9065            //         .build_signed_int_to_float(v, self.intrinsics.f64x2_ty, "");
9066            //     let res = chck_err!(self.builder.build_bit_cast(res, self.intrinsics.i128_ty, ""));
9067            //     self.state.push1(res);
9068            // }
9069            // Operator::F64x2ConvertI64x2U => {
9070            //     let v = self.state.pop1()?;
9071            //     let v = self
9072            //         .builder
9073            //         .build_bit_cast(v, self.intrinsics.i64x2_ty, "")
9074            //         .into_vector_value();
9075            //     let res = self
9076            //         .builder
9077            //         .build_unsigned_int_to_float(v, self.intrinsics.f64x2_ty, "");
9078            //     let res = chck_err!(self.builder.build_bit_cast(res, self.intrinsics.i128_ty, ""));
9079            //     self.state.push1(res);
9080            // }
9081            Operator::I32ReinterpretF32 => {
9082                let (v, i) = self.state.pop1_extra()?;
9083                let v = self.apply_pending_canonicalization(v, i)?;
9084                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i32_ty, ""));
9085                self.state.push1_extra(ret, ExtraInfo::arithmetic_f32());
9086            }
9087            Operator::I64ReinterpretF64 => {
9088                let (v, i) = self.state.pop1_extra()?;
9089                let v = self.apply_pending_canonicalization(v, i)?;
9090                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i64_ty, ""));
9091                self.state.push1_extra(ret, ExtraInfo::arithmetic_f64());
9092            }
9093            Operator::F32ReinterpretI32 => {
9094                let (v, i) = self.state.pop1_extra()?;
9095                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f32_ty, ""));
9096                self.state.push1_extra(ret, i);
9097            }
9098            Operator::F64ReinterpretI64 => {
9099                let (v, i) = self.state.pop1_extra()?;
9100                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f64_ty, ""));
9101                self.state.push1_extra(ret, i);
9102            }
9103
9104            /***************************
9105             * Sign-extension operators.
9106             * https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md
9107             ***************************/
9108            Operator::I32Extend8S => {
9109                let value = self.state.pop1()?.into_int_value();
9110                let narrow_value = err!(self.builder.build_int_truncate(
9111                    value,
9112                    self.intrinsics.i8_ty,
9113                    ""
9114                ));
9115                let extended_value = err!(self.builder.build_int_s_extend(
9116                    narrow_value,
9117                    self.intrinsics.i32_ty,
9118                    ""
9119                ));
9120                self.state.push1(extended_value);
9121            }
9122            Operator::I32Extend16S => {
9123                let value = self.state.pop1()?.into_int_value();
9124                let narrow_value = err!(self.builder.build_int_truncate(
9125                    value,
9126                    self.intrinsics.i16_ty,
9127                    ""
9128                ));
9129                let extended_value = err!(self.builder.build_int_s_extend(
9130                    narrow_value,
9131                    self.intrinsics.i32_ty,
9132                    ""
9133                ));
9134                self.state.push1(extended_value);
9135            }
9136            Operator::I64Extend8S => {
9137                let value = self.state.pop1()?.into_int_value();
9138                let narrow_value = err!(self.builder.build_int_truncate(
9139                    value,
9140                    self.intrinsics.i8_ty,
9141                    ""
9142                ));
9143                let extended_value = err!(self.builder.build_int_s_extend(
9144                    narrow_value,
9145                    self.intrinsics.i64_ty,
9146                    ""
9147                ));
9148                self.state.push1(extended_value);
9149            }
9150            Operator::I64Extend16S => {
9151                let value = self.state.pop1()?.into_int_value();
9152                let narrow_value = err!(self.builder.build_int_truncate(
9153                    value,
9154                    self.intrinsics.i16_ty,
9155                    ""
9156                ));
9157                let extended_value = err!(self.builder.build_int_s_extend(
9158                    narrow_value,
9159                    self.intrinsics.i64_ty,
9160                    ""
9161                ));
9162                self.state.push1(extended_value);
9163            }
9164            Operator::I64Extend32S => {
9165                let value = self.state.pop1()?.into_int_value();
9166                let narrow_value = err!(self.builder.build_int_truncate(
9167                    value,
9168                    self.intrinsics.i32_ty,
9169                    ""
9170                ));
9171                let extended_value = err!(self.builder.build_int_s_extend(
9172                    narrow_value,
9173                    self.intrinsics.i64_ty,
9174                    ""
9175                ));
9176                self.state.push1(extended_value);
9177            }
9178
9179            /***************************
9180             * Load and Store instructions.
9181             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#load-and-store-instructions
9182             ***************************/
9183            Operator::I32Load { ref memarg } => {
9184                let offset = self.state.pop1()?.into_int_value();
9185                let memory_index = MemoryIndex::from_u32(0);
9186                let effective_address = self.resolve_memory_ptr(
9187                    memory_index,
9188                    memarg,
9189                    self.intrinsics.ptr_ty,
9190                    offset,
9191                    4,
9192                )?;
9193                let result = err!(self.builder.build_load(
9194                    self.intrinsics.i32_ty,
9195                    effective_address,
9196                    ""
9197                ));
9198                self.annotate_user_memaccess(
9199                    memory_index,
9200                    memarg,
9201                    1,
9202                    result.as_instruction_value().unwrap(),
9203                )?;
9204                self.state.push1(result);
9205            }
9206            Operator::I64Load { ref memarg } => {
9207                let offset = self.state.pop1()?.into_int_value();
9208                let memory_index = MemoryIndex::from_u32(0);
9209                let effective_address = self.resolve_memory_ptr(
9210                    memory_index,
9211                    memarg,
9212                    self.intrinsics.ptr_ty,
9213                    offset,
9214                    8,
9215                )?;
9216                let result = err!(self.builder.build_load(
9217                    self.intrinsics.i64_ty,
9218                    effective_address,
9219                    ""
9220                ));
9221                self.annotate_user_memaccess(
9222                    memory_index,
9223                    memarg,
9224                    1,
9225                    result.as_instruction_value().unwrap(),
9226                )?;
9227                self.state.push1(result);
9228            }
9229            Operator::F32Load { ref memarg } => {
9230                let offset = self.state.pop1()?.into_int_value();
9231                let memory_index = MemoryIndex::from_u32(0);
9232                let effective_address = self.resolve_memory_ptr(
9233                    memory_index,
9234                    memarg,
9235                    self.intrinsics.ptr_ty,
9236                    offset,
9237                    4,
9238                )?;
9239                let result = err!(self.builder.build_load(
9240                    self.intrinsics.f32_ty,
9241                    effective_address,
9242                    ""
9243                ));
9244                self.annotate_user_memaccess(
9245                    memory_index,
9246                    memarg,
9247                    1,
9248                    result.as_instruction_value().unwrap(),
9249                )?;
9250                self.state.push1(result);
9251            }
9252            Operator::F64Load { ref memarg } => {
9253                let offset = self.state.pop1()?.into_int_value();
9254                let memory_index = MemoryIndex::from_u32(0);
9255                let effective_address = self.resolve_memory_ptr(
9256                    memory_index,
9257                    memarg,
9258                    self.intrinsics.ptr_ty,
9259                    offset,
9260                    8,
9261                )?;
9262                let result = err!(self.builder.build_load(
9263                    self.intrinsics.f64_ty,
9264                    effective_address,
9265                    ""
9266                ));
9267                self.annotate_user_memaccess(
9268                    memory_index,
9269                    memarg,
9270                    1,
9271                    result.as_instruction_value().unwrap(),
9272                )?;
9273                self.state.push1(result);
9274            }
9275            Operator::V128Load { ref memarg } => {
9276                let offset = self.state.pop1()?.into_int_value();
9277                let memory_index = MemoryIndex::from_u32(0);
9278                let effective_address = self.resolve_memory_ptr(
9279                    memory_index,
9280                    memarg,
9281                    self.intrinsics.ptr_ty,
9282                    offset,
9283                    16,
9284                )?;
9285                let result = err!(self.builder.build_load(
9286                    self.intrinsics.i128_ty,
9287                    effective_address,
9288                    ""
9289                ));
9290                self.annotate_user_memaccess(
9291                    memory_index,
9292                    memarg,
9293                    1,
9294                    result.as_instruction_value().unwrap(),
9295                )?;
9296                self.state.push1(result);
9297            }
9298            Operator::V128Load8Lane { ref memarg, lane } => {
9299                let (v, i) = self.state.pop1_extra()?;
9300                let (v, _i) = self.v128_into_i8x16(v, i)?;
9301                let offset = self.state.pop1()?.into_int_value();
9302                let memory_index = MemoryIndex::from_u32(memarg.memory);
9303                let effective_address = self.resolve_memory_ptr(
9304                    memory_index,
9305                    memarg,
9306                    self.intrinsics.ptr_ty,
9307                    offset,
9308                    1,
9309                )?;
9310                let element = err!(self.builder.build_load(
9311                    self.intrinsics.i8_ty,
9312                    effective_address,
9313                    ""
9314                ));
9315                self.annotate_user_memaccess(
9316                    memory_index,
9317                    memarg,
9318                    1,
9319                    element.as_instruction_value().unwrap(),
9320                )?;
9321                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9322                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9323                let res = err!(
9324                    self.builder
9325                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9326                );
9327                self.state.push1(res);
9328            }
9329            Operator::V128Load16Lane { ref memarg, lane } => {
9330                let (v, i) = self.state.pop1_extra()?;
9331                let (v, i) = self.v128_into_i16x8(v, i)?;
9332                let offset = self.state.pop1()?.into_int_value();
9333                let memory_index = MemoryIndex::from_u32(memarg.memory);
9334                let effective_address = self.resolve_memory_ptr(
9335                    memory_index,
9336                    memarg,
9337                    self.intrinsics.ptr_ty,
9338                    offset,
9339                    2,
9340                )?;
9341                let element = err!(self.builder.build_load(
9342                    self.intrinsics.i16_ty,
9343                    effective_address,
9344                    ""
9345                ));
9346                self.annotate_user_memaccess(
9347                    memory_index,
9348                    memarg,
9349                    1,
9350                    element.as_instruction_value().unwrap(),
9351                )?;
9352                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9353                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9354                let res = err!(
9355                    self.builder
9356                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9357                );
9358                self.state.push1_extra(res, i);
9359            }
9360            Operator::V128Load32Lane { ref memarg, lane } => {
9361                let (v, i) = self.state.pop1_extra()?;
9362                let (v, i) = self.v128_into_i32x4(v, i)?;
9363                let offset = self.state.pop1()?.into_int_value();
9364                let memory_index = MemoryIndex::from_u32(memarg.memory);
9365                let effective_address = self.resolve_memory_ptr(
9366                    memory_index,
9367                    memarg,
9368                    self.intrinsics.ptr_ty,
9369                    offset,
9370                    4,
9371                )?;
9372                let element = err!(self.builder.build_load(
9373                    self.intrinsics.i32_ty,
9374                    effective_address,
9375                    ""
9376                ));
9377                self.annotate_user_memaccess(
9378                    memory_index,
9379                    memarg,
9380                    1,
9381                    element.as_instruction_value().unwrap(),
9382                )?;
9383                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9384                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9385                let res = err!(
9386                    self.builder
9387                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9388                );
9389                self.state.push1_extra(res, i);
9390            }
9391            Operator::V128Load64Lane { ref memarg, lane } => {
9392                let (v, i) = self.state.pop1_extra()?;
9393                let (v, i) = self.v128_into_i64x2(v, i)?;
9394                let offset = self.state.pop1()?.into_int_value();
9395                let memory_index = MemoryIndex::from_u32(memarg.memory);
9396                let effective_address = self.resolve_memory_ptr(
9397                    memory_index,
9398                    memarg,
9399                    self.intrinsics.ptr_ty,
9400                    offset,
9401                    8,
9402                )?;
9403                let element = err!(self.builder.build_load(
9404                    self.intrinsics.i64_ty,
9405                    effective_address,
9406                    ""
9407                ));
9408                self.annotate_user_memaccess(
9409                    memory_index,
9410                    memarg,
9411                    1,
9412                    element.as_instruction_value().unwrap(),
9413                )?;
9414                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9415                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9416                let res = err!(
9417                    self.builder
9418                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9419                );
9420                self.state.push1_extra(res, i);
9421            }
9422
9423            Operator::I32Store { ref memarg } => {
9424                let value = self.state.pop1()?;
9425                let offset = self.state.pop1()?.into_int_value();
9426                let memory_index = MemoryIndex::from_u32(0);
9427                let effective_address = self.resolve_memory_ptr(
9428                    memory_index,
9429                    memarg,
9430                    self.intrinsics.ptr_ty,
9431                    offset,
9432                    4,
9433                )?;
9434                let dead_load = err!(self.builder.build_load(
9435                    self.intrinsics.i32_ty,
9436                    effective_address,
9437                    ""
9438                ));
9439                self.annotate_user_memaccess(
9440                    memory_index,
9441                    memarg,
9442                    1,
9443                    dead_load.as_instruction_value().unwrap(),
9444                )?;
9445                let store = err!(self.builder.build_store(effective_address, value));
9446                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9447            }
9448            Operator::I64Store { ref memarg } => {
9449                let value = self.state.pop1()?;
9450                let offset = self.state.pop1()?.into_int_value();
9451                let memory_index = MemoryIndex::from_u32(0);
9452                let effective_address = self.resolve_memory_ptr(
9453                    memory_index,
9454                    memarg,
9455                    self.intrinsics.ptr_ty,
9456                    offset,
9457                    8,
9458                )?;
9459                let dead_load = err!(self.builder.build_load(
9460                    self.intrinsics.i64_ty,
9461                    effective_address,
9462                    ""
9463                ));
9464                self.annotate_user_memaccess(
9465                    memory_index,
9466                    memarg,
9467                    1,
9468                    dead_load.as_instruction_value().unwrap(),
9469                )?;
9470                let store = err!(self.builder.build_store(effective_address, value));
9471                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9472            }
9473            Operator::F32Store { ref memarg } => {
9474                let (v, i) = self.state.pop1_extra()?;
9475                let v = self.apply_pending_canonicalization(v, i)?;
9476                let offset = self.state.pop1()?.into_int_value();
9477                let memory_index = MemoryIndex::from_u32(0);
9478                let effective_address = self.resolve_memory_ptr(
9479                    memory_index,
9480                    memarg,
9481                    self.intrinsics.ptr_ty,
9482                    offset,
9483                    4,
9484                )?;
9485                let dead_load = err!(self.builder.build_load(
9486                    self.intrinsics.f32_ty,
9487                    effective_address,
9488                    ""
9489                ));
9490                self.annotate_user_memaccess(
9491                    memory_index,
9492                    memarg,
9493                    1,
9494                    dead_load.as_instruction_value().unwrap(),
9495                )?;
9496                let store = err!(self.builder.build_store(effective_address, v));
9497                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9498            }
9499            Operator::F64Store { ref memarg } => {
9500                let (v, i) = self.state.pop1_extra()?;
9501                let v = self.apply_pending_canonicalization(v, i)?;
9502                let offset = self.state.pop1()?.into_int_value();
9503                let memory_index = MemoryIndex::from_u32(0);
9504                let effective_address = self.resolve_memory_ptr(
9505                    memory_index,
9506                    memarg,
9507                    self.intrinsics.ptr_ty,
9508                    offset,
9509                    8,
9510                )?;
9511                let dead_load = err!(self.builder.build_load(
9512                    self.intrinsics.f64_ty,
9513                    effective_address,
9514                    ""
9515                ));
9516                self.annotate_user_memaccess(
9517                    memory_index,
9518                    memarg,
9519                    1,
9520                    dead_load.as_instruction_value().unwrap(),
9521                )?;
9522                let store = err!(self.builder.build_store(effective_address, v));
9523                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9524            }
9525            Operator::V128Store { ref memarg } => {
9526                let (v, i) = self.state.pop1_extra()?;
9527                let v = self.apply_pending_canonicalization(v, i)?;
9528                let offset = self.state.pop1()?.into_int_value();
9529                let memory_index = MemoryIndex::from_u32(0);
9530                let effective_address = self.resolve_memory_ptr(
9531                    memory_index,
9532                    memarg,
9533                    self.intrinsics.ptr_ty,
9534                    offset,
9535                    16,
9536                )?;
9537                let dead_load = err!(self.builder.build_load(
9538                    self.intrinsics.i128_ty,
9539                    effective_address,
9540                    ""
9541                ));
9542                self.annotate_user_memaccess(
9543                    memory_index,
9544                    memarg,
9545                    1,
9546                    dead_load.as_instruction_value().unwrap(),
9547                )?;
9548                let store = err!(self.builder.build_store(effective_address, v));
9549                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9550            }
9551            Operator::V128Store8Lane { ref memarg, lane } => {
9552                let (v, i) = self.state.pop1_extra()?;
9553                let (v, _i) = self.v128_into_i8x16(v, i)?;
9554                let offset = self.state.pop1()?.into_int_value();
9555                let memory_index = MemoryIndex::from_u32(memarg.memory);
9556
9557                let effective_address = self.resolve_memory_ptr(
9558                    memory_index,
9559                    memarg,
9560                    self.intrinsics.ptr_ty,
9561                    offset,
9562                    1,
9563                )?;
9564                let dead_load = err!(self.builder.build_load(
9565                    self.intrinsics.i8_ty,
9566                    effective_address,
9567                    ""
9568                ));
9569                self.annotate_user_memaccess(
9570                    memory_index,
9571                    memarg,
9572                    1,
9573                    dead_load.as_instruction_value().unwrap(),
9574                )?;
9575                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9576                let val = err!(self.builder.build_extract_element(v, idx, ""));
9577                let store = err!(self.builder.build_store(effective_address, val));
9578                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9579            }
9580            Operator::V128Store16Lane { ref memarg, lane } => {
9581                let (v, i) = self.state.pop1_extra()?;
9582                let (v, _i) = self.v128_into_i16x8(v, i)?;
9583                let offset = self.state.pop1()?.into_int_value();
9584                let memory_index = MemoryIndex::from_u32(memarg.memory);
9585
9586                let effective_address = self.resolve_memory_ptr(
9587                    memory_index,
9588                    memarg,
9589                    self.intrinsics.ptr_ty,
9590                    offset,
9591                    2,
9592                )?;
9593                let dead_load = err!(self.builder.build_load(
9594                    self.intrinsics.i16_ty,
9595                    effective_address,
9596                    ""
9597                ));
9598                self.annotate_user_memaccess(
9599                    memory_index,
9600                    memarg,
9601                    1,
9602                    dead_load.as_instruction_value().unwrap(),
9603                )?;
9604                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9605                let val = err!(self.builder.build_extract_element(v, idx, ""));
9606                let store = err!(self.builder.build_store(effective_address, val));
9607                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9608            }
9609            Operator::V128Store32Lane { ref memarg, lane } => {
9610                let (v, i) = self.state.pop1_extra()?;
9611                let (v, _i) = self.v128_into_i32x4(v, i)?;
9612                let offset = self.state.pop1()?.into_int_value();
9613                let memory_index = MemoryIndex::from_u32(memarg.memory);
9614
9615                let effective_address = self.resolve_memory_ptr(
9616                    memory_index,
9617                    memarg,
9618                    self.intrinsics.ptr_ty,
9619                    offset,
9620                    4,
9621                )?;
9622                let dead_load = err!(self.builder.build_load(
9623                    self.intrinsics.i32_ty,
9624                    effective_address,
9625                    ""
9626                ));
9627                self.annotate_user_memaccess(
9628                    memory_index,
9629                    memarg,
9630                    1,
9631                    dead_load.as_instruction_value().unwrap(),
9632                )?;
9633                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9634                let val = err!(self.builder.build_extract_element(v, idx, ""));
9635                let store = err!(self.builder.build_store(effective_address, val));
9636                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9637            }
9638            Operator::V128Store64Lane { ref memarg, lane } => {
9639                let (v, i) = self.state.pop1_extra()?;
9640                let (v, _i) = self.v128_into_i64x2(v, i)?;
9641                let offset = self.state.pop1()?.into_int_value();
9642                let memory_index = MemoryIndex::from_u32(memarg.memory);
9643
9644                let effective_address = self.resolve_memory_ptr(
9645                    memory_index,
9646                    memarg,
9647                    self.intrinsics.ptr_ty,
9648                    offset,
9649                    8,
9650                )?;
9651                let dead_load = err!(self.builder.build_load(
9652                    self.intrinsics.i64_ty,
9653                    effective_address,
9654                    ""
9655                ));
9656                self.annotate_user_memaccess(
9657                    memory_index,
9658                    memarg,
9659                    1,
9660                    dead_load.as_instruction_value().unwrap(),
9661                )?;
9662                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9663                let val = err!(self.builder.build_extract_element(v, idx, ""));
9664                let store = err!(self.builder.build_store(effective_address, val));
9665                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9666            }
9667            Operator::I32Load8S { ref memarg } => {
9668                let offset = self.state.pop1()?.into_int_value();
9669                let memory_index = MemoryIndex::from_u32(0);
9670                let effective_address = self.resolve_memory_ptr(
9671                    memory_index,
9672                    memarg,
9673                    self.intrinsics.ptr_ty,
9674                    offset,
9675                    1,
9676                )?;
9677                let narrow_result = err!(self.builder.build_load(
9678                    self.intrinsics.i8_ty,
9679                    effective_address,
9680                    ""
9681                ));
9682                self.annotate_user_memaccess(
9683                    memory_index,
9684                    memarg,
9685                    1,
9686                    narrow_result.as_instruction_value().unwrap(),
9687                )?;
9688                let result = err!(self.builder.build_int_s_extend(
9689                    narrow_result.into_int_value(),
9690                    self.intrinsics.i32_ty,
9691                    "",
9692                ));
9693                self.state.push1(result);
9694            }
9695            Operator::I32Load16S { ref memarg } => {
9696                let offset = self.state.pop1()?.into_int_value();
9697                let memory_index = MemoryIndex::from_u32(0);
9698                let effective_address = self.resolve_memory_ptr(
9699                    memory_index,
9700                    memarg,
9701                    self.intrinsics.ptr_ty,
9702                    offset,
9703                    2,
9704                )?;
9705                let narrow_result = err!(self.builder.build_load(
9706                    self.intrinsics.i16_ty,
9707                    effective_address,
9708                    ""
9709                ));
9710                self.annotate_user_memaccess(
9711                    memory_index,
9712                    memarg,
9713                    1,
9714                    narrow_result.as_instruction_value().unwrap(),
9715                )?;
9716                let result = err!(self.builder.build_int_s_extend(
9717                    narrow_result.into_int_value(),
9718                    self.intrinsics.i32_ty,
9719                    "",
9720                ));
9721                self.state.push1(result);
9722            }
9723            Operator::I64Load8S { ref memarg } => {
9724                let offset = self.state.pop1()?.into_int_value();
9725                let memory_index = MemoryIndex::from_u32(0);
9726                let effective_address = self.resolve_memory_ptr(
9727                    memory_index,
9728                    memarg,
9729                    self.intrinsics.ptr_ty,
9730                    offset,
9731                    1,
9732                )?;
9733                let narrow_result = err!(self.builder.build_load(
9734                    self.intrinsics.i8_ty,
9735                    effective_address,
9736                    ""
9737                ))
9738                .into_int_value();
9739                self.annotate_user_memaccess(
9740                    memory_index,
9741                    memarg,
9742                    1,
9743                    narrow_result.as_instruction_value().unwrap(),
9744                )?;
9745                let result = err!(self.builder.build_int_s_extend(
9746                    narrow_result,
9747                    self.intrinsics.i64_ty,
9748                    ""
9749                ));
9750                self.state.push1(result);
9751            }
9752            Operator::I64Load16S { ref memarg } => {
9753                let offset = self.state.pop1()?.into_int_value();
9754                let memory_index = MemoryIndex::from_u32(0);
9755                let effective_address = self.resolve_memory_ptr(
9756                    memory_index,
9757                    memarg,
9758                    self.intrinsics.ptr_ty,
9759                    offset,
9760                    2,
9761                )?;
9762                let narrow_result = err!(self.builder.build_load(
9763                    self.intrinsics.i16_ty,
9764                    effective_address,
9765                    ""
9766                ))
9767                .into_int_value();
9768                self.annotate_user_memaccess(
9769                    memory_index,
9770                    memarg,
9771                    1,
9772                    narrow_result.as_instruction_value().unwrap(),
9773                )?;
9774                let result = err!(self.builder.build_int_s_extend(
9775                    narrow_result,
9776                    self.intrinsics.i64_ty,
9777                    ""
9778                ));
9779                self.state.push1(result);
9780            }
9781            Operator::I64Load32S { ref memarg } => {
9782                let offset = self.state.pop1()?.into_int_value();
9783                let memory_index = MemoryIndex::from_u32(0);
9784                let effective_address = self.resolve_memory_ptr(
9785                    memory_index,
9786                    memarg,
9787                    self.intrinsics.ptr_ty,
9788                    offset,
9789                    4,
9790                )?;
9791                let narrow_result = err!(self.builder.build_load(
9792                    self.intrinsics.i32_ty,
9793                    effective_address,
9794                    ""
9795                ));
9796                self.annotate_user_memaccess(
9797                    memory_index,
9798                    memarg,
9799                    1,
9800                    narrow_result.as_instruction_value().unwrap(),
9801                )?;
9802                let result = err!(self.builder.build_int_s_extend(
9803                    narrow_result.into_int_value(),
9804                    self.intrinsics.i64_ty,
9805                    "",
9806                ));
9807                self.state.push1(result);
9808            }
9809
9810            Operator::I32Load8U { ref memarg } => {
9811                let offset = self.state.pop1()?.into_int_value();
9812                let memory_index = MemoryIndex::from_u32(0);
9813                let effective_address = self.resolve_memory_ptr(
9814                    memory_index,
9815                    memarg,
9816                    self.intrinsics.ptr_ty,
9817                    offset,
9818                    1,
9819                )?;
9820                let narrow_result = err!(self.builder.build_load(
9821                    self.intrinsics.i8_ty,
9822                    effective_address,
9823                    ""
9824                ));
9825                self.annotate_user_memaccess(
9826                    memory_index,
9827                    memarg,
9828                    1,
9829                    narrow_result.as_instruction_value().unwrap(),
9830                )?;
9831                let result = err!(self.builder.build_int_z_extend(
9832                    narrow_result.into_int_value(),
9833                    self.intrinsics.i32_ty,
9834                    "",
9835                ));
9836                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9837            }
9838            Operator::I32Load16U { ref memarg } => {
9839                let offset = self.state.pop1()?.into_int_value();
9840                let memory_index = MemoryIndex::from_u32(0);
9841                let effective_address = self.resolve_memory_ptr(
9842                    memory_index,
9843                    memarg,
9844                    self.intrinsics.ptr_ty,
9845                    offset,
9846                    2,
9847                )?;
9848                let narrow_result = err!(self.builder.build_load(
9849                    self.intrinsics.i16_ty,
9850                    effective_address,
9851                    ""
9852                ));
9853                self.annotate_user_memaccess(
9854                    memory_index,
9855                    memarg,
9856                    1,
9857                    narrow_result.as_instruction_value().unwrap(),
9858                )?;
9859                let result = err!(self.builder.build_int_z_extend(
9860                    narrow_result.into_int_value(),
9861                    self.intrinsics.i32_ty,
9862                    "",
9863                ));
9864                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9865            }
9866            Operator::I64Load8U { ref memarg } => {
9867                let offset = self.state.pop1()?.into_int_value();
9868                let memory_index = MemoryIndex::from_u32(0);
9869                let effective_address = self.resolve_memory_ptr(
9870                    memory_index,
9871                    memarg,
9872                    self.intrinsics.ptr_ty,
9873                    offset,
9874                    1,
9875                )?;
9876                let narrow_result = err!(self.builder.build_load(
9877                    self.intrinsics.i8_ty,
9878                    effective_address,
9879                    ""
9880                ));
9881                self.annotate_user_memaccess(
9882                    memory_index,
9883                    memarg,
9884                    1,
9885                    narrow_result.as_instruction_value().unwrap(),
9886                )?;
9887                let result = err!(self.builder.build_int_z_extend(
9888                    narrow_result.into_int_value(),
9889                    self.intrinsics.i64_ty,
9890                    "",
9891                ));
9892                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9893            }
9894            Operator::I64Load16U { ref memarg } => {
9895                let offset = self.state.pop1()?.into_int_value();
9896                let memory_index = MemoryIndex::from_u32(0);
9897                let effective_address = self.resolve_memory_ptr(
9898                    memory_index,
9899                    memarg,
9900                    self.intrinsics.ptr_ty,
9901                    offset,
9902                    2,
9903                )?;
9904                let narrow_result = err!(self.builder.build_load(
9905                    self.intrinsics.i16_ty,
9906                    effective_address,
9907                    ""
9908                ));
9909                self.annotate_user_memaccess(
9910                    memory_index,
9911                    memarg,
9912                    1,
9913                    narrow_result.as_instruction_value().unwrap(),
9914                )?;
9915                let result = err!(self.builder.build_int_z_extend(
9916                    narrow_result.into_int_value(),
9917                    self.intrinsics.i64_ty,
9918                    "",
9919                ));
9920                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9921            }
9922            Operator::I64Load32U { ref memarg } => {
9923                let offset = self.state.pop1()?.into_int_value();
9924                let memory_index = MemoryIndex::from_u32(0);
9925                let effective_address = self.resolve_memory_ptr(
9926                    memory_index,
9927                    memarg,
9928                    self.intrinsics.ptr_ty,
9929                    offset,
9930                    4,
9931                )?;
9932                let narrow_result = err!(self.builder.build_load(
9933                    self.intrinsics.i32_ty,
9934                    effective_address,
9935                    ""
9936                ));
9937                self.annotate_user_memaccess(
9938                    memory_index,
9939                    memarg,
9940                    1,
9941                    narrow_result.as_instruction_value().unwrap(),
9942                )?;
9943                let result = err!(self.builder.build_int_z_extend(
9944                    narrow_result.into_int_value(),
9945                    self.intrinsics.i64_ty,
9946                    "",
9947                ));
9948                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9949            }
9950
9951            Operator::I32Store8 { ref memarg } | Operator::I64Store8 { ref memarg } => {
9952                let value = self.state.pop1()?.into_int_value();
9953                let offset = self.state.pop1()?.into_int_value();
9954                let memory_index = MemoryIndex::from_u32(0);
9955                let effective_address = self.resolve_memory_ptr(
9956                    memory_index,
9957                    memarg,
9958                    self.intrinsics.ptr_ty,
9959                    offset,
9960                    1,
9961                )?;
9962                let dead_load = err!(self.builder.build_load(
9963                    self.intrinsics.i8_ty,
9964                    effective_address,
9965                    ""
9966                ));
9967                self.annotate_user_memaccess(
9968                    memory_index,
9969                    memarg,
9970                    1,
9971                    dead_load.as_instruction_value().unwrap(),
9972                )?;
9973                let narrow_value = err!(self.builder.build_int_truncate(
9974                    value,
9975                    self.intrinsics.i8_ty,
9976                    ""
9977                ));
9978                let store = err!(self.builder.build_store(effective_address, narrow_value));
9979                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9980            }
9981            Operator::I32Store16 { ref memarg } | Operator::I64Store16 { ref memarg } => {
9982                let value = self.state.pop1()?.into_int_value();
9983                let offset = self.state.pop1()?.into_int_value();
9984                let memory_index = MemoryIndex::from_u32(0);
9985                let effective_address = self.resolve_memory_ptr(
9986                    memory_index,
9987                    memarg,
9988                    self.intrinsics.ptr_ty,
9989                    offset,
9990                    2,
9991                )?;
9992                let dead_load = err!(self.builder.build_load(
9993                    self.intrinsics.i16_ty,
9994                    effective_address,
9995                    ""
9996                ));
9997                self.annotate_user_memaccess(
9998                    memory_index,
9999                    memarg,
10000                    1,
10001                    dead_load.as_instruction_value().unwrap(),
10002                )?;
10003                let narrow_value = err!(self.builder.build_int_truncate(
10004                    value,
10005                    self.intrinsics.i16_ty,
10006                    ""
10007                ));
10008                let store = err!(self.builder.build_store(effective_address, narrow_value));
10009                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
10010            }
10011            Operator::I64Store32 { ref memarg } => {
10012                let value = self.state.pop1()?.into_int_value();
10013                let offset = self.state.pop1()?.into_int_value();
10014                let memory_index = MemoryIndex::from_u32(0);
10015                let effective_address = self.resolve_memory_ptr(
10016                    memory_index,
10017                    memarg,
10018                    self.intrinsics.ptr_ty,
10019                    offset,
10020                    4,
10021                )?;
10022                let dead_load = err!(self.builder.build_load(
10023                    self.intrinsics.i32_ty,
10024                    effective_address,
10025                    ""
10026                ));
10027                self.annotate_user_memaccess(
10028                    memory_index,
10029                    memarg,
10030                    1,
10031                    dead_load.as_instruction_value().unwrap(),
10032                )?;
10033                let narrow_value = err!(self.builder.build_int_truncate(
10034                    value,
10035                    self.intrinsics.i32_ty,
10036                    ""
10037                ));
10038                let store = err!(self.builder.build_store(effective_address, narrow_value));
10039                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
10040            }
10041            Operator::I8x16Neg => {
10042                let (v, i) = self.state.pop1_extra()?;
10043                let (v, _) = self.v128_into_i8x16(v, i)?;
10044                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10045                let res = err!(
10046                    self.builder
10047                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10048                );
10049                self.state.push1(res);
10050            }
10051            Operator::I16x8Neg => {
10052                let (v, i) = self.state.pop1_extra()?;
10053                let (v, _) = self.v128_into_i16x8(v, i)?;
10054                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10055                let res = err!(
10056                    self.builder
10057                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10058                );
10059                self.state.push1(res);
10060            }
10061            Operator::I32x4Neg => {
10062                let (v, i) = self.state.pop1_extra()?;
10063                let (v, _) = self.v128_into_i32x4(v, i)?;
10064                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10065                let res = err!(
10066                    self.builder
10067                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10068                );
10069                self.state.push1(res);
10070            }
10071            Operator::I64x2Neg => {
10072                let (v, i) = self.state.pop1_extra()?;
10073                let (v, _) = self.v128_into_i64x2(v, i)?;
10074                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10075                let res = err!(
10076                    self.builder
10077                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10078                );
10079                self.state.push1(res);
10080            }
10081            Operator::V128Not => {
10082                let (v, i) = self.state.pop1_extra()?;
10083                let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10084                let res = err!(self.builder.build_not(v, ""));
10085                self.state.push1(res);
10086            }
10087            Operator::V128AnyTrue => {
10088                // | Operator::I64x2AnyTrue
10089                // Skip canonicalization, it never changes non-zero values to zero or vice versa.
10090                let v = self.state.pop1()?.into_int_value();
10091                let res = err!(self.builder.build_int_compare(
10092                    IntPredicate::NE,
10093                    v,
10094                    v.get_type().const_zero(),
10095                    "",
10096                ));
10097                let res = err!(
10098                    self.builder
10099                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10100                );
10101                self.state.push1_extra(
10102                    res,
10103                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10104                );
10105            }
10106            Operator::I8x16AllTrue
10107            | Operator::I16x8AllTrue
10108            | Operator::I32x4AllTrue
10109            | Operator::I64x2AllTrue => {
10110                let vec_ty = match op {
10111                    Operator::I8x16AllTrue => self.intrinsics.i8x16_ty,
10112                    Operator::I16x8AllTrue => self.intrinsics.i16x8_ty,
10113                    Operator::I32x4AllTrue => self.intrinsics.i32x4_ty,
10114                    Operator::I64x2AllTrue => self.intrinsics.i64x2_ty,
10115                    _ => unreachable!(),
10116                };
10117                let (v, i) = self.state.pop1_extra()?;
10118                let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10119                let lane_int_ty = self.context.custom_width_int_type(vec_ty.get_size());
10120                let vec = err!(self.builder.build_bit_cast(v, vec_ty, "vec")).into_vector_value();
10121                let mask = err!(self.builder.build_int_compare(
10122                    IntPredicate::NE,
10123                    vec,
10124                    vec_ty.const_zero(),
10125                    "mask",
10126                ));
10127                let cmask =
10128                    err!(self.builder.build_bit_cast(mask, lane_int_ty, "cmask")).into_int_value();
10129                let res = err!(self.builder.build_int_compare(
10130                    IntPredicate::EQ,
10131                    cmask,
10132                    lane_int_ty.const_int(u64::MAX, true),
10133                    "",
10134                ));
10135                let res = err!(
10136                    self.builder
10137                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10138                );
10139                self.state.push1_extra(
10140                    res,
10141                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10142                );
10143            }
10144            Operator::I8x16ExtractLaneS { lane } => {
10145                let (v, i) = self.state.pop1_extra()?;
10146                let (v, _) = self.v128_into_i8x16(v, i)?;
10147                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10148                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10149                let res = err!(
10150                    self.builder
10151                        .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10152                );
10153                self.state.push1(res);
10154            }
10155            Operator::I8x16ExtractLaneU { lane } => {
10156                let (v, i) = self.state.pop1_extra()?;
10157                let (v, _) = self.v128_into_i8x16(v, i)?;
10158                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10159                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10160                let res = err!(
10161                    self.builder
10162                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10163                );
10164                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10165            }
10166            Operator::I16x8ExtractLaneS { lane } => {
10167                let (v, i) = self.state.pop1_extra()?;
10168                let (v, _) = self.v128_into_i16x8(v, i)?;
10169                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10170                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10171                let res = err!(
10172                    self.builder
10173                        .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10174                );
10175                self.state.push1(res);
10176            }
10177            Operator::I16x8ExtractLaneU { lane } => {
10178                let (v, i) = self.state.pop1_extra()?;
10179                let (v, _) = self.v128_into_i16x8(v, i)?;
10180                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10181                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10182                let res = err!(
10183                    self.builder
10184                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10185                );
10186                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10187            }
10188            Operator::I32x4ExtractLane { lane } => {
10189                let (v, i) = self.state.pop1_extra()?;
10190                let (v, i) = self.v128_into_i32x4(v, i)?;
10191                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10192                let res = err!(self.builder.build_extract_element(v, idx, ""));
10193                self.state.push1_extra(res, i);
10194            }
10195            Operator::I64x2ExtractLane { lane } => {
10196                let (v, i) = self.state.pop1_extra()?;
10197                let (v, i) = self.v128_into_i64x2(v, i)?;
10198                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10199                let res = err!(self.builder.build_extract_element(v, idx, ""));
10200                self.state.push1_extra(res, i);
10201            }
10202            Operator::F32x4ExtractLane { lane } => {
10203                let (v, i) = self.state.pop1_extra()?;
10204                let (v, i) = self.v128_into_f32x4(v, i)?;
10205                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10206                let res = err!(self.builder.build_extract_element(v, idx, ""));
10207                self.state.push1_extra(res, i);
10208            }
10209            Operator::F64x2ExtractLane { lane } => {
10210                let (v, i) = self.state.pop1_extra()?;
10211                let (v, i) = self.v128_into_f64x2(v, i)?;
10212                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10213                let res = err!(self.builder.build_extract_element(v, idx, ""));
10214                self.state.push1_extra(res, i);
10215            }
10216            Operator::I8x16ReplaceLane { lane } => {
10217                let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10218                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10219                let v2 = v2.into_int_value();
10220                let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i8_ty, ""));
10221                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10222                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10223                let res = err!(
10224                    self.builder
10225                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10226                );
10227                self.state.push1(res);
10228            }
10229            Operator::I16x8ReplaceLane { lane } => {
10230                let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10231                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
10232                let v2 = v2.into_int_value();
10233                let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i16_ty, ""));
10234                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10235                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10236                let res = err!(
10237                    self.builder
10238                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10239                );
10240                self.state.push1(res);
10241            }
10242            Operator::I32x4ReplaceLane { lane } => {
10243                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10244                let (v1, i1) = self.v128_into_i32x4(v1, i1)?;
10245                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10246                let v2 = v2.into_int_value();
10247                let i2 = i2.strip_pending();
10248                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10249                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10250                let res = err!(
10251                    self.builder
10252                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10253                );
10254                self.state
10255                    .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f32())?);
10256            }
10257            Operator::I64x2ReplaceLane { lane } => {
10258                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10259                let (v1, i1) = self.v128_into_i64x2(v1, i1)?;
10260                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10261                let v2 = v2.into_int_value();
10262                let i2 = i2.strip_pending();
10263                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10264                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10265                let res = err!(
10266                    self.builder
10267                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10268                );
10269                self.state
10270                    .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f64())?);
10271            }
10272            Operator::F32x4ReplaceLane { lane } => {
10273                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10274                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
10275                let push_pending_f32_nan_to_result =
10276                    i1.has_pending_f32_nan() && i2.has_pending_f32_nan();
10277                let (v1, v2) = if !push_pending_f32_nan_to_result {
10278                    (
10279                        self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10280                            .into_vector_value(),
10281                        self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10282                            .into_float_value(),
10283                    )
10284                } else {
10285                    (v1, v2.into_float_value())
10286                };
10287                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10288                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10289                let res = err!(
10290                    self.builder
10291                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10292                );
10293                let info = if push_pending_f32_nan_to_result {
10294                    ExtraInfo::pending_f32_nan()
10295                } else {
10296                    (i1.strip_pending() & i2.strip_pending())?
10297                };
10298                self.state.push1_extra(res, info);
10299            }
10300            Operator::F64x2ReplaceLane { lane } => {
10301                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10302                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
10303                let push_pending_f64_nan_to_result =
10304                    i1.has_pending_f64_nan() && i2.has_pending_f64_nan();
10305                let (v1, v2) = if !push_pending_f64_nan_to_result {
10306                    (
10307                        self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10308                            .into_vector_value(),
10309                        self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10310                            .into_float_value(),
10311                    )
10312                } else {
10313                    (v1, v2.into_float_value())
10314                };
10315                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10316                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10317                let res = err!(
10318                    self.builder
10319                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10320                );
10321                let info = if push_pending_f64_nan_to_result {
10322                    ExtraInfo::pending_f64_nan()
10323                } else {
10324                    (i1.strip_pending() & i2.strip_pending())?
10325                };
10326                self.state.push1_extra(res, info);
10327            }
10328            Operator::I8x16RelaxedSwizzle if self.cpu_features.contains(CpuFeature::SSSE3) => {
10329                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10330                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10331                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10332
10333                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10334                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
10335                let res = self
10336                    .build_call_with_param_attributes(
10337                        self.intrinsics.x86_64.pshufb128,
10338                        &[v1.into(), v2.into()],
10339                        "",
10340                    )?
10341                    .try_as_basic_value()
10342                    .unwrap_basic();
10343                let res = err!(
10344                    self.builder
10345                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10346                );
10347                self.state.push1(res);
10348            }
10349            Operator::I8x16Swizzle | Operator::I8x16RelaxedSwizzle => {
10350                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10351                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10352                let v1 = err!(
10353                    self.builder
10354                        .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10355                )
10356                .into_vector_value();
10357                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10358                let v2 = err!(
10359                    self.builder
10360                        .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10361                )
10362                .into_vector_value();
10363                let lanes = self.intrinsics.i8_ty.const_int(16, false);
10364                let lanes =
10365                    self.splat_vector(lanes.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
10366                let mut res = self.intrinsics.i8x16_ty.get_undef();
10367                let idx_out_of_range = err!(self.builder.build_int_compare(
10368                    IntPredicate::UGE,
10369                    v2,
10370                    lanes,
10371                    "idx_out_of_range",
10372                ));
10373                let idx_clamped = err!(self.builder.build_select(
10374                    idx_out_of_range,
10375                    self.intrinsics.i8x16_ty.const_zero(),
10376                    v2,
10377                    "idx_clamped",
10378                ))
10379                .into_vector_value();
10380                for i in 0..16 {
10381                    let idx = err!(self.builder.build_extract_element(
10382                        idx_clamped,
10383                        self.intrinsics.i32_ty.const_int(i, false),
10384                        "idx",
10385                    ))
10386                    .into_int_value();
10387                    let replace_with_zero = err!(self.builder.build_extract_element(
10388                        idx_out_of_range,
10389                        self.intrinsics.i32_ty.const_int(i, false),
10390                        "replace_with_zero",
10391                    ))
10392                    .into_int_value();
10393                    let elem =
10394                        err!(self.builder.build_extract_element(v1, idx, "elem")).into_int_value();
10395                    let elem_or_zero = err!(self.builder.build_select(
10396                        replace_with_zero,
10397                        self.intrinsics.i8_zero,
10398                        elem,
10399                        "elem_or_zero",
10400                    ));
10401                    res = err!(self.builder.build_insert_element(
10402                        res,
10403                        elem_or_zero,
10404                        self.intrinsics.i32_ty.const_int(i, false),
10405                        "",
10406                    ));
10407                }
10408                let res = err!(
10409                    self.builder
10410                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10411                );
10412                self.state.push1(res);
10413            }
10414            Operator::I8x16Shuffle { lanes } => {
10415                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10416                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10417                let v1 = err!(
10418                    self.builder
10419                        .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10420                )
10421                .into_vector_value();
10422                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10423                let v2 = err!(
10424                    self.builder
10425                        .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10426                )
10427                .into_vector_value();
10428                let mask = VectorType::const_vector(
10429                    lanes
10430                        .iter()
10431                        .map(|l| self.intrinsics.i32_ty.const_int((*l).into(), false))
10432                        .collect::<Vec<IntValue>>()
10433                        .as_slice(),
10434                );
10435                let res = err!(self.builder.build_shuffle_vector(v1, v2, mask, ""));
10436                let res = err!(
10437                    self.builder
10438                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10439                );
10440                self.state.push1(res);
10441            }
10442            Operator::V128Load8x8S { ref memarg } => {
10443                let offset = self.state.pop1()?.into_int_value();
10444                let memory_index = MemoryIndex::from_u32(0);
10445                let effective_address = self.resolve_memory_ptr(
10446                    memory_index,
10447                    memarg,
10448                    self.intrinsics.ptr_ty,
10449                    offset,
10450                    8,
10451                )?;
10452                let v = err!(self.builder.build_load(
10453                    self.intrinsics.i64_ty,
10454                    effective_address,
10455                    ""
10456                ));
10457                let v = err!(
10458                    self.builder
10459                        .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10460                )
10461                .into_vector_value();
10462                let res = err!(
10463                    self.builder
10464                        .build_int_s_extend(v, self.intrinsics.i16x8_ty, "")
10465                );
10466                let res = err!(
10467                    self.builder
10468                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10469                );
10470                self.state.push1(res);
10471            }
10472            Operator::V128Load8x8U { ref memarg } => {
10473                let offset = self.state.pop1()?.into_int_value();
10474                let memory_index = MemoryIndex::from_u32(0);
10475                let effective_address = self.resolve_memory_ptr(
10476                    memory_index,
10477                    memarg,
10478                    self.intrinsics.ptr_ty,
10479                    offset,
10480                    8,
10481                )?;
10482                let v = err!(self.builder.build_load(
10483                    self.intrinsics.i64_ty,
10484                    effective_address,
10485                    ""
10486                ));
10487                let v = err!(
10488                    self.builder
10489                        .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10490                )
10491                .into_vector_value();
10492                let res = err!(
10493                    self.builder
10494                        .build_int_z_extend(v, self.intrinsics.i16x8_ty, "")
10495                );
10496                let res = err!(
10497                    self.builder
10498                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10499                );
10500                self.state.push1(res);
10501            }
10502            Operator::V128Load16x4S { ref memarg } => {
10503                let offset = self.state.pop1()?.into_int_value();
10504                let memory_index = MemoryIndex::from_u32(0);
10505                let effective_address = self.resolve_memory_ptr(
10506                    memory_index,
10507                    memarg,
10508                    self.intrinsics.ptr_ty,
10509                    offset,
10510                    8,
10511                )?;
10512                let v = err!(self.builder.build_load(
10513                    self.intrinsics.i64_ty,
10514                    effective_address,
10515                    ""
10516                ));
10517                let v = err!(self.builder.build_bit_cast(
10518                    v,
10519                    self.intrinsics.i16_ty.vec_type(4),
10520                    ""
10521                ))
10522                .into_vector_value();
10523                let res = err!(
10524                    self.builder
10525                        .build_int_s_extend(v, self.intrinsics.i32x4_ty, "")
10526                );
10527                let res = err!(
10528                    self.builder
10529                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10530                );
10531                self.state.push1(res);
10532            }
10533            Operator::V128Load16x4U { ref memarg } => {
10534                let offset = self.state.pop1()?.into_int_value();
10535                let memory_index = MemoryIndex::from_u32(0);
10536                let effective_address = self.resolve_memory_ptr(
10537                    memory_index,
10538                    memarg,
10539                    self.intrinsics.ptr_ty,
10540                    offset,
10541                    8,
10542                )?;
10543                let v = err!(self.builder.build_load(
10544                    self.intrinsics.i64_ty,
10545                    effective_address,
10546                    ""
10547                ));
10548                let v = err!(self.builder.build_bit_cast(
10549                    v,
10550                    self.intrinsics.i16_ty.vec_type(4),
10551                    ""
10552                ))
10553                .into_vector_value();
10554                let res = err!(
10555                    self.builder
10556                        .build_int_z_extend(v, self.intrinsics.i32x4_ty, "")
10557                );
10558                let res = err!(
10559                    self.builder
10560                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10561                );
10562                self.state.push1(res);
10563            }
10564            Operator::V128Load32x2S { ref memarg } => {
10565                let offset = self.state.pop1()?.into_int_value();
10566                let memory_index = MemoryIndex::from_u32(0);
10567                let effective_address = self.resolve_memory_ptr(
10568                    memory_index,
10569                    memarg,
10570                    self.intrinsics.ptr_ty,
10571                    offset,
10572                    8,
10573                )?;
10574                let v = err!(self.builder.build_load(
10575                    self.intrinsics.i64_ty,
10576                    effective_address,
10577                    ""
10578                ));
10579                let v = err!(self.builder.build_bit_cast(
10580                    v,
10581                    self.intrinsics.i32_ty.vec_type(2),
10582                    ""
10583                ))
10584                .into_vector_value();
10585                let res = err!(
10586                    self.builder
10587                        .build_int_s_extend(v, self.intrinsics.i64x2_ty, "")
10588                );
10589                let res = err!(
10590                    self.builder
10591                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10592                );
10593                self.state.push1(res);
10594            }
10595            Operator::V128Load32x2U { ref memarg } => {
10596                let offset = self.state.pop1()?.into_int_value();
10597                let memory_index = MemoryIndex::from_u32(0);
10598                let effective_address = self.resolve_memory_ptr(
10599                    memory_index,
10600                    memarg,
10601                    self.intrinsics.ptr_ty,
10602                    offset,
10603                    8,
10604                )?;
10605                let v = err!(self.builder.build_load(
10606                    self.intrinsics.i64_ty,
10607                    effective_address,
10608                    ""
10609                ));
10610                let v = err!(self.builder.build_bit_cast(
10611                    v,
10612                    self.intrinsics.i32_ty.vec_type(2),
10613                    ""
10614                ))
10615                .into_vector_value();
10616                let res = err!(
10617                    self.builder
10618                        .build_int_z_extend(v, self.intrinsics.i64x2_ty, "")
10619                );
10620                let res = err!(
10621                    self.builder
10622                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10623                );
10624                self.state.push1(res);
10625            }
10626            Operator::V128Load32Zero { ref memarg } => {
10627                let offset = self.state.pop1()?.into_int_value();
10628                let memory_index = MemoryIndex::from_u32(0);
10629                let effective_address = self.resolve_memory_ptr(
10630                    memory_index,
10631                    memarg,
10632                    self.intrinsics.ptr_ty,
10633                    offset,
10634                    4,
10635                )?;
10636                let elem = err!(self.builder.build_load(
10637                    self.intrinsics.i32_ty,
10638                    effective_address,
10639                    ""
10640                ));
10641                self.annotate_user_memaccess(
10642                    memory_index,
10643                    memarg,
10644                    1,
10645                    elem.as_instruction_value().unwrap(),
10646                )?;
10647                let res = err!(self.builder.build_int_z_extend(
10648                    elem.into_int_value(),
10649                    self.intrinsics.i128_ty,
10650                    "",
10651                ));
10652                self.state.push1(res);
10653            }
10654            Operator::V128Load64Zero { ref memarg } => {
10655                let offset = self.state.pop1()?.into_int_value();
10656                let memory_index = MemoryIndex::from_u32(0);
10657                let effective_address = self.resolve_memory_ptr(
10658                    memory_index,
10659                    memarg,
10660                    self.intrinsics.ptr_ty,
10661                    offset,
10662                    8,
10663                )?;
10664                let elem = err!(self.builder.build_load(
10665                    self.intrinsics.i64_ty,
10666                    effective_address,
10667                    ""
10668                ));
10669                self.annotate_user_memaccess(
10670                    memory_index,
10671                    memarg,
10672                    1,
10673                    elem.as_instruction_value().unwrap(),
10674                )?;
10675                let res = err!(self.builder.build_int_z_extend(
10676                    elem.into_int_value(),
10677                    self.intrinsics.i128_ty,
10678                    "",
10679                ));
10680                self.state.push1(res);
10681            }
10682            Operator::V128Load8Splat { ref memarg } => {
10683                let offset = self.state.pop1()?.into_int_value();
10684                let memory_index = MemoryIndex::from_u32(0);
10685                let effective_address = self.resolve_memory_ptr(
10686                    memory_index,
10687                    memarg,
10688                    self.intrinsics.ptr_ty,
10689                    offset,
10690                    1,
10691                )?;
10692                let elem = err!(self.builder.build_load(
10693                    self.intrinsics.i8_ty,
10694                    effective_address,
10695                    ""
10696                ));
10697                self.annotate_user_memaccess(
10698                    memory_index,
10699                    memarg,
10700                    1,
10701                    elem.as_instruction_value().unwrap(),
10702                )?;
10703                let res = self.splat_vector(elem, self.intrinsics.i8x16_ty)?;
10704                let res = err!(
10705                    self.builder
10706                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10707                );
10708                self.state.push1(res);
10709            }
10710            Operator::V128Load16Splat { ref memarg } => {
10711                let offset = self.state.pop1()?.into_int_value();
10712                let memory_index = MemoryIndex::from_u32(0);
10713                let effective_address = self.resolve_memory_ptr(
10714                    memory_index,
10715                    memarg,
10716                    self.intrinsics.ptr_ty,
10717                    offset,
10718                    2,
10719                )?;
10720                let elem = err!(self.builder.build_load(
10721                    self.intrinsics.i16_ty,
10722                    effective_address,
10723                    ""
10724                ));
10725                self.annotate_user_memaccess(
10726                    memory_index,
10727                    memarg,
10728                    1,
10729                    elem.as_instruction_value().unwrap(),
10730                )?;
10731                let res = self.splat_vector(elem, self.intrinsics.i16x8_ty)?;
10732                let res = err!(
10733                    self.builder
10734                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10735                );
10736                self.state.push1(res);
10737            }
10738            Operator::V128Load32Splat { ref memarg } => {
10739                let offset = self.state.pop1()?.into_int_value();
10740                let memory_index = MemoryIndex::from_u32(0);
10741                let effective_address = self.resolve_memory_ptr(
10742                    memory_index,
10743                    memarg,
10744                    self.intrinsics.ptr_ty,
10745                    offset,
10746                    4,
10747                )?;
10748                let elem = err!(self.builder.build_load(
10749                    self.intrinsics.i32_ty,
10750                    effective_address,
10751                    ""
10752                ));
10753                self.annotate_user_memaccess(
10754                    memory_index,
10755                    memarg,
10756                    1,
10757                    elem.as_instruction_value().unwrap(),
10758                )?;
10759                let res = self.splat_vector(elem, self.intrinsics.i32x4_ty)?;
10760                let res = err!(
10761                    self.builder
10762                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10763                );
10764                self.state.push1(res);
10765            }
10766            Operator::V128Load64Splat { ref memarg } => {
10767                let offset = self.state.pop1()?.into_int_value();
10768                let memory_index = MemoryIndex::from_u32(0);
10769                let effective_address = self.resolve_memory_ptr(
10770                    memory_index,
10771                    memarg,
10772                    self.intrinsics.ptr_ty,
10773                    offset,
10774                    8,
10775                )?;
10776                let elem = err!(self.builder.build_load(
10777                    self.intrinsics.i64_ty,
10778                    effective_address,
10779                    ""
10780                ));
10781                self.annotate_user_memaccess(
10782                    memory_index,
10783                    memarg,
10784                    1,
10785                    elem.as_instruction_value().unwrap(),
10786                )?;
10787                let res = self.splat_vector(elem, self.intrinsics.i64x2_ty)?;
10788                let res = err!(
10789                    self.builder
10790                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10791                );
10792                self.state.push1(res);
10793            }
10794            Operator::AtomicFence => {
10795                // Fence is a nop.
10796                //
10797                // Fence was added to preserve information about fences from
10798                // source languages. If in the future Wasm extends the memory
10799                // model, and if we hadn't recorded what fences used to be there,
10800                // it would lead to data races that weren't present in the
10801                // original source language.
10802            }
10803            Operator::I32AtomicLoad { ref memarg } => {
10804                let offset = self.state.pop1()?.into_int_value();
10805                let memory_index = MemoryIndex::from_u32(0);
10806                let effective_address = self.resolve_memory_ptr(
10807                    memory_index,
10808                    memarg,
10809                    self.intrinsics.ptr_ty,
10810                    offset,
10811                    4,
10812                )?;
10813                self.trap_if_misaligned(memarg, effective_address, 4)?;
10814                let result = err!(self.builder.build_load(
10815                    self.intrinsics.i32_ty,
10816                    effective_address,
10817                    "atomic_load"
10818                ));
10819                let load = result.as_instruction_value().unwrap();
10820                self.annotate_user_memaccess(memory_index, memarg, 4, load)?;
10821                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10822                    .unwrap();
10823                self.state.push1(result);
10824            }
10825            Operator::I64AtomicLoad { ref memarg } => {
10826                let offset = self.state.pop1()?.into_int_value();
10827                let memory_index = MemoryIndex::from_u32(0);
10828                let effective_address = self.resolve_memory_ptr(
10829                    memory_index,
10830                    memarg,
10831                    self.intrinsics.ptr_ty,
10832                    offset,
10833                    8,
10834                )?;
10835                self.trap_if_misaligned(memarg, effective_address, 8)?;
10836                let result = err!(self.builder.build_load(
10837                    self.intrinsics.i64_ty,
10838                    effective_address,
10839                    ""
10840                ));
10841                let load = result.as_instruction_value().unwrap();
10842                self.annotate_user_memaccess(memory_index, memarg, 8, load)?;
10843                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10844                    .unwrap();
10845                self.state.push1(result);
10846            }
10847            Operator::I32AtomicLoad8U { ref memarg } => {
10848                let offset = self.state.pop1()?.into_int_value();
10849                let memory_index = MemoryIndex::from_u32(0);
10850                let effective_address = self.resolve_memory_ptr(
10851                    memory_index,
10852                    memarg,
10853                    self.intrinsics.ptr_ty,
10854                    offset,
10855                    1,
10856                )?;
10857                self.trap_if_misaligned(memarg, effective_address, 1)?;
10858                let narrow_result = err!(self.builder.build_load(
10859                    self.intrinsics.i8_ty,
10860                    effective_address,
10861                    ""
10862                ))
10863                .into_int_value();
10864                let load = narrow_result.as_instruction_value().unwrap();
10865                self.annotate_user_memaccess(memory_index, memarg, 1, load)?;
10866                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10867                    .unwrap();
10868                let result = err!(self.builder.build_int_z_extend(
10869                    narrow_result,
10870                    self.intrinsics.i32_ty,
10871                    ""
10872                ));
10873                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10874            }
10875            Operator::I32AtomicLoad16U { ref memarg } => {
10876                let offset = self.state.pop1()?.into_int_value();
10877                let memory_index = MemoryIndex::from_u32(0);
10878                let effective_address = self.resolve_memory_ptr(
10879                    memory_index,
10880                    memarg,
10881                    self.intrinsics.ptr_ty,
10882                    offset,
10883                    2,
10884                )?;
10885                self.trap_if_misaligned(memarg, effective_address, 2)?;
10886                let narrow_result = err!(self.builder.build_load(
10887                    self.intrinsics.i16_ty,
10888                    effective_address,
10889                    ""
10890                ))
10891                .into_int_value();
10892                let load = narrow_result.as_instruction_value().unwrap();
10893                self.annotate_user_memaccess(memory_index, memarg, 2, load)?;
10894                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10895                    .unwrap();
10896                let result = err!(self.builder.build_int_z_extend(
10897                    narrow_result,
10898                    self.intrinsics.i32_ty,
10899                    ""
10900                ));
10901                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10902            }
10903            Operator::I64AtomicLoad8U { ref memarg } => {
10904                let offset = self.state.pop1()?.into_int_value();
10905                let memory_index = MemoryIndex::from_u32(0);
10906                let effective_address = self.resolve_memory_ptr(
10907                    memory_index,
10908                    memarg,
10909                    self.intrinsics.ptr_ty,
10910                    offset,
10911                    1,
10912                )?;
10913                self.trap_if_misaligned(memarg, effective_address, 1)?;
10914                let narrow_result = err!(self.builder.build_load(
10915                    self.intrinsics.i8_ty,
10916                    effective_address,
10917                    ""
10918                ))
10919                .into_int_value();
10920                let load = narrow_result.as_instruction_value().unwrap();
10921                self.annotate_user_memaccess(memory_index, memarg, 1, load)?;
10922                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10923                    .unwrap();
10924                let result = err!(self.builder.build_int_z_extend(
10925                    narrow_result,
10926                    self.intrinsics.i64_ty,
10927                    ""
10928                ));
10929                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10930            }
10931            Operator::I64AtomicLoad16U { ref memarg } => {
10932                let offset = self.state.pop1()?.into_int_value();
10933                let memory_index = MemoryIndex::from_u32(0);
10934                let effective_address = self.resolve_memory_ptr(
10935                    memory_index,
10936                    memarg,
10937                    self.intrinsics.ptr_ty,
10938                    offset,
10939                    2,
10940                )?;
10941                self.trap_if_misaligned(memarg, effective_address, 2)?;
10942                let narrow_result = err!(self.builder.build_load(
10943                    self.intrinsics.i16_ty,
10944                    effective_address,
10945                    ""
10946                ))
10947                .into_int_value();
10948                let load = narrow_result.as_instruction_value().unwrap();
10949                self.annotate_user_memaccess(memory_index, memarg, 2, load)?;
10950                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10951                    .unwrap();
10952                let result = err!(self.builder.build_int_z_extend(
10953                    narrow_result,
10954                    self.intrinsics.i64_ty,
10955                    ""
10956                ));
10957                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10958            }
10959            Operator::I64AtomicLoad32U { ref memarg } => {
10960                let offset = self.state.pop1()?.into_int_value();
10961                let memory_index = MemoryIndex::from_u32(0);
10962                let effective_address = self.resolve_memory_ptr(
10963                    memory_index,
10964                    memarg,
10965                    self.intrinsics.ptr_ty,
10966                    offset,
10967                    4,
10968                )?;
10969                self.trap_if_misaligned(memarg, effective_address, 4)?;
10970                let narrow_result = err!(self.builder.build_load(
10971                    self.intrinsics.i32_ty,
10972                    effective_address,
10973                    ""
10974                ))
10975                .into_int_value();
10976                let load = narrow_result.as_instruction_value().unwrap();
10977                self.annotate_user_memaccess(memory_index, memarg, 4, load)?;
10978                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10979                    .unwrap();
10980                let result = err!(self.builder.build_int_z_extend(
10981                    narrow_result,
10982                    self.intrinsics.i64_ty,
10983                    ""
10984                ));
10985                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10986            }
10987            Operator::I32AtomicStore { ref memarg } => {
10988                let value = self.state.pop1()?;
10989                let offset = self.state.pop1()?.into_int_value();
10990                let memory_index = MemoryIndex::from_u32(0);
10991                let effective_address = self.resolve_memory_ptr(
10992                    memory_index,
10993                    memarg,
10994                    self.intrinsics.ptr_ty,
10995                    offset,
10996                    4,
10997                )?;
10998                self.trap_if_misaligned(memarg, effective_address, 4)?;
10999                let store = err!(self.builder.build_store(effective_address, value));
11000                self.annotate_user_memaccess(memory_index, memarg, 4, store)?;
11001                store
11002                    .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
11003                    .unwrap();
11004            }
11005            Operator::I64AtomicStore { ref memarg } => {
11006                let value = self.state.pop1()?;
11007                let offset = self.state.pop1()?.into_int_value();
11008                let memory_index = MemoryIndex::from_u32(0);
11009                let effective_address = self.resolve_memory_ptr(
11010                    memory_index,
11011                    memarg,
11012                    self.intrinsics.ptr_ty,
11013                    offset,
11014                    8,
11015                )?;
11016                self.trap_if_misaligned(memarg, effective_address, 8)?;
11017                let store = err!(self.builder.build_store(effective_address, value));
11018                self.annotate_user_memaccess(memory_index, memarg, 8, store)?;
11019                store
11020                    .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
11021                    .unwrap();
11022            }
11023            Operator::I32AtomicStore8 { ref memarg } | Operator::I64AtomicStore8 { ref memarg } => {
11024                let value = self.state.pop1()?.into_int_value();
11025                let offset = self.state.pop1()?.into_int_value();
11026                let memory_index = MemoryIndex::from_u32(0);
11027                let effective_address = self.resolve_memory_ptr(
11028                    memory_index,
11029                    memarg,
11030                    self.intrinsics.ptr_ty,
11031                    offset,
11032                    1,
11033                )?;
11034                self.trap_if_misaligned(memarg, effective_address, 1)?;
11035                let narrow_value = err!(self.builder.build_int_truncate(
11036                    value,
11037                    self.intrinsics.i8_ty,
11038                    ""
11039                ));
11040                let store = err!(self.builder.build_store(effective_address, narrow_value));
11041                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
11042                store
11043                    .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
11044                    .unwrap();
11045            }
11046            Operator::I32AtomicStore16 { ref memarg }
11047            | Operator::I64AtomicStore16 { ref memarg } => {
11048                let value = self.state.pop1()?.into_int_value();
11049                let offset = self.state.pop1()?.into_int_value();
11050                let memory_index = MemoryIndex::from_u32(0);
11051                let effective_address = self.resolve_memory_ptr(
11052                    memory_index,
11053                    memarg,
11054                    self.intrinsics.ptr_ty,
11055                    offset,
11056                    2,
11057                )?;
11058                self.trap_if_misaligned(memarg, effective_address, 2)?;
11059                let narrow_value = err!(self.builder.build_int_truncate(
11060                    value,
11061                    self.intrinsics.i16_ty,
11062                    ""
11063                ));
11064                let store = err!(self.builder.build_store(effective_address, narrow_value));
11065                self.annotate_user_memaccess(memory_index, memarg, 2, store)?;
11066                store
11067                    .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
11068                    .unwrap();
11069            }
11070            Operator::I64AtomicStore32 { ref memarg } => {
11071                let value = self.state.pop1()?.into_int_value();
11072                let offset = self.state.pop1()?.into_int_value();
11073                let memory_index = MemoryIndex::from_u32(0);
11074                let effective_address = self.resolve_memory_ptr(
11075                    memory_index,
11076                    memarg,
11077                    self.intrinsics.ptr_ty,
11078                    offset,
11079                    4,
11080                )?;
11081                self.trap_if_misaligned(memarg, effective_address, 4)?;
11082                let narrow_value = err!(self.builder.build_int_truncate(
11083                    value,
11084                    self.intrinsics.i32_ty,
11085                    ""
11086                ));
11087                let store = err!(self.builder.build_store(effective_address, narrow_value));
11088                self.annotate_user_memaccess(memory_index, memarg, 4, store)?;
11089                store
11090                    .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
11091                    .unwrap();
11092            }
11093            Operator::I32AtomicRmw8AddU { ref memarg } => {
11094                let value = self.state.pop1()?.into_int_value();
11095                let offset = self.state.pop1()?.into_int_value();
11096                let memory_index = MemoryIndex::from_u32(0);
11097                let effective_address = self.resolve_memory_ptr(
11098                    memory_index,
11099                    memarg,
11100                    self.intrinsics.ptr_ty,
11101                    offset,
11102                    1,
11103                )?;
11104                self.trap_if_misaligned(memarg, effective_address, 1)?;
11105                let narrow_value = err!(self.builder.build_int_truncate(
11106                    value,
11107                    self.intrinsics.i8_ty,
11108                    ""
11109                ));
11110                let old = self
11111                    .builder
11112                    .build_atomicrmw(
11113                        AtomicRMWBinOp::Add,
11114                        effective_address,
11115                        narrow_value,
11116                        AtomicOrdering::SequentiallyConsistent,
11117                    )
11118                    .unwrap();
11119                tbaa_label(
11120                    self.module,
11121                    self.intrinsics,
11122                    format!("memory {}", memory_index.as_u32()),
11123                    old.as_instruction_value().unwrap(),
11124                );
11125                let old = err!(
11126                    self.builder
11127                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11128                );
11129                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11130            }
11131            Operator::I32AtomicRmw16AddU { ref memarg } => {
11132                let value = self.state.pop1()?.into_int_value();
11133                let offset = self.state.pop1()?.into_int_value();
11134                let memory_index = MemoryIndex::from_u32(0);
11135                let effective_address = self.resolve_memory_ptr(
11136                    memory_index,
11137                    memarg,
11138                    self.intrinsics.ptr_ty,
11139                    offset,
11140                    2,
11141                )?;
11142                self.trap_if_misaligned(memarg, effective_address, 2)?;
11143                let narrow_value = err!(self.builder.build_int_truncate(
11144                    value,
11145                    self.intrinsics.i16_ty,
11146                    ""
11147                ));
11148                let old = self
11149                    .builder
11150                    .build_atomicrmw(
11151                        AtomicRMWBinOp::Add,
11152                        effective_address,
11153                        narrow_value,
11154                        AtomicOrdering::SequentiallyConsistent,
11155                    )
11156                    .unwrap();
11157                tbaa_label(
11158                    self.module,
11159                    self.intrinsics,
11160                    format!("memory {}", memory_index.as_u32()),
11161                    old.as_instruction_value().unwrap(),
11162                );
11163                let old = err!(
11164                    self.builder
11165                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11166                );
11167                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11168            }
11169            Operator::I32AtomicRmwAdd { ref memarg } => {
11170                let value = self.state.pop1()?.into_int_value();
11171                let offset = self.state.pop1()?.into_int_value();
11172                let memory_index = MemoryIndex::from_u32(0);
11173                let effective_address = self.resolve_memory_ptr(
11174                    memory_index,
11175                    memarg,
11176                    self.intrinsics.ptr_ty,
11177                    offset,
11178                    4,
11179                )?;
11180                self.trap_if_misaligned(memarg, effective_address, 4)?;
11181                let old = self
11182                    .builder
11183                    .build_atomicrmw(
11184                        AtomicRMWBinOp::Add,
11185                        effective_address,
11186                        value,
11187                        AtomicOrdering::SequentiallyConsistent,
11188                    )
11189                    .unwrap();
11190                tbaa_label(
11191                    self.module,
11192                    self.intrinsics,
11193                    format!("memory {}", memory_index.as_u32()),
11194                    old.as_instruction_value().unwrap(),
11195                );
11196                self.state.push1(old);
11197            }
11198            Operator::I64AtomicRmw8AddU { ref memarg } => {
11199                let value = self.state.pop1()?.into_int_value();
11200                let offset = self.state.pop1()?.into_int_value();
11201                let memory_index = MemoryIndex::from_u32(0);
11202                let effective_address = self.resolve_memory_ptr(
11203                    memory_index,
11204                    memarg,
11205                    self.intrinsics.ptr_ty,
11206                    offset,
11207                    1,
11208                )?;
11209                self.trap_if_misaligned(memarg, effective_address, 1)?;
11210                let narrow_value = err!(self.builder.build_int_truncate(
11211                    value,
11212                    self.intrinsics.i8_ty,
11213                    ""
11214                ));
11215                let old = self
11216                    .builder
11217                    .build_atomicrmw(
11218                        AtomicRMWBinOp::Add,
11219                        effective_address,
11220                        narrow_value,
11221                        AtomicOrdering::SequentiallyConsistent,
11222                    )
11223                    .unwrap();
11224                self.annotate_user_memaccess(
11225                    memory_index,
11226                    memarg,
11227                    0,
11228                    old.as_instruction_value().unwrap(),
11229                )?;
11230                let old = err!(
11231                    self.builder
11232                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11233                );
11234                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11235            }
11236            Operator::I64AtomicRmw16AddU { ref memarg } => {
11237                let value = self.state.pop1()?.into_int_value();
11238                let offset = self.state.pop1()?.into_int_value();
11239                let memory_index = MemoryIndex::from_u32(0);
11240                let effective_address = self.resolve_memory_ptr(
11241                    memory_index,
11242                    memarg,
11243                    self.intrinsics.ptr_ty,
11244                    offset,
11245                    2,
11246                )?;
11247                self.trap_if_misaligned(memarg, effective_address, 2)?;
11248                let narrow_value = err!(self.builder.build_int_truncate(
11249                    value,
11250                    self.intrinsics.i16_ty,
11251                    ""
11252                ));
11253                let old = self
11254                    .builder
11255                    .build_atomicrmw(
11256                        AtomicRMWBinOp::Add,
11257                        effective_address,
11258                        narrow_value,
11259                        AtomicOrdering::SequentiallyConsistent,
11260                    )
11261                    .unwrap();
11262                self.annotate_user_memaccess(
11263                    memory_index,
11264                    memarg,
11265                    0,
11266                    old.as_instruction_value().unwrap(),
11267                )?;
11268                let old = err!(
11269                    self.builder
11270                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11271                );
11272                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11273            }
11274            Operator::I64AtomicRmw32AddU { ref memarg } => {
11275                let value = self.state.pop1()?.into_int_value();
11276                let offset = self.state.pop1()?.into_int_value();
11277                let memory_index = MemoryIndex::from_u32(0);
11278                let effective_address = self.resolve_memory_ptr(
11279                    memory_index,
11280                    memarg,
11281                    self.intrinsics.ptr_ty,
11282                    offset,
11283                    4,
11284                )?;
11285                self.trap_if_misaligned(memarg, effective_address, 4)?;
11286                let narrow_value = err!(self.builder.build_int_truncate(
11287                    value,
11288                    self.intrinsics.i32_ty,
11289                    ""
11290                ));
11291                let old = self
11292                    .builder
11293                    .build_atomicrmw(
11294                        AtomicRMWBinOp::Add,
11295                        effective_address,
11296                        narrow_value,
11297                        AtomicOrdering::SequentiallyConsistent,
11298                    )
11299                    .unwrap();
11300                self.annotate_user_memaccess(
11301                    memory_index,
11302                    memarg,
11303                    0,
11304                    old.as_instruction_value().unwrap(),
11305                )?;
11306                let old = err!(
11307                    self.builder
11308                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11309                );
11310                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11311            }
11312            Operator::I64AtomicRmwAdd { ref memarg } => {
11313                let value = self.state.pop1()?.into_int_value();
11314                let offset = self.state.pop1()?.into_int_value();
11315                let memory_index = MemoryIndex::from_u32(0);
11316                let effective_address = self.resolve_memory_ptr(
11317                    memory_index,
11318                    memarg,
11319                    self.intrinsics.ptr_ty,
11320                    offset,
11321                    8,
11322                )?;
11323                self.trap_if_misaligned(memarg, effective_address, 8)?;
11324                let old = self
11325                    .builder
11326                    .build_atomicrmw(
11327                        AtomicRMWBinOp::Add,
11328                        effective_address,
11329                        value,
11330                        AtomicOrdering::SequentiallyConsistent,
11331                    )
11332                    .unwrap();
11333                self.annotate_user_memaccess(
11334                    memory_index,
11335                    memarg,
11336                    0,
11337                    old.as_instruction_value().unwrap(),
11338                )?;
11339                self.state.push1(old);
11340            }
11341            Operator::I32AtomicRmw8SubU { ref memarg } => {
11342                let value = self.state.pop1()?.into_int_value();
11343                let offset = self.state.pop1()?.into_int_value();
11344                let memory_index = MemoryIndex::from_u32(0);
11345                let effective_address = self.resolve_memory_ptr(
11346                    memory_index,
11347                    memarg,
11348                    self.intrinsics.ptr_ty,
11349                    offset,
11350                    1,
11351                )?;
11352                self.trap_if_misaligned(memarg, effective_address, 1)?;
11353                let narrow_value = err!(self.builder.build_int_truncate(
11354                    value,
11355                    self.intrinsics.i8_ty,
11356                    ""
11357                ));
11358                let old = self
11359                    .builder
11360                    .build_atomicrmw(
11361                        AtomicRMWBinOp::Sub,
11362                        effective_address,
11363                        narrow_value,
11364                        AtomicOrdering::SequentiallyConsistent,
11365                    )
11366                    .unwrap();
11367                self.annotate_user_memaccess(
11368                    memory_index,
11369                    memarg,
11370                    0,
11371                    old.as_instruction_value().unwrap(),
11372                )?;
11373                let old = err!(
11374                    self.builder
11375                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11376                );
11377                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11378            }
11379            Operator::I32AtomicRmw16SubU { ref memarg } => {
11380                let value = self.state.pop1()?.into_int_value();
11381                let offset = self.state.pop1()?.into_int_value();
11382                let memory_index = MemoryIndex::from_u32(0);
11383                let effective_address = self.resolve_memory_ptr(
11384                    memory_index,
11385                    memarg,
11386                    self.intrinsics.ptr_ty,
11387                    offset,
11388                    2,
11389                )?;
11390                self.trap_if_misaligned(memarg, effective_address, 2)?;
11391                let narrow_value = err!(self.builder.build_int_truncate(
11392                    value,
11393                    self.intrinsics.i16_ty,
11394                    ""
11395                ));
11396                let old = self
11397                    .builder
11398                    .build_atomicrmw(
11399                        AtomicRMWBinOp::Sub,
11400                        effective_address,
11401                        narrow_value,
11402                        AtomicOrdering::SequentiallyConsistent,
11403                    )
11404                    .unwrap();
11405                self.annotate_user_memaccess(
11406                    memory_index,
11407                    memarg,
11408                    0,
11409                    old.as_instruction_value().unwrap(),
11410                )?;
11411                let old = err!(
11412                    self.builder
11413                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11414                );
11415                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11416            }
11417            Operator::I32AtomicRmwSub { ref memarg } => {
11418                let value = self.state.pop1()?.into_int_value();
11419                let offset = self.state.pop1()?.into_int_value();
11420                let memory_index = MemoryIndex::from_u32(0);
11421                let effective_address = self.resolve_memory_ptr(
11422                    memory_index,
11423                    memarg,
11424                    self.intrinsics.ptr_ty,
11425                    offset,
11426                    4,
11427                )?;
11428                self.trap_if_misaligned(memarg, effective_address, 4)?;
11429                let old = self
11430                    .builder
11431                    .build_atomicrmw(
11432                        AtomicRMWBinOp::Sub,
11433                        effective_address,
11434                        value,
11435                        AtomicOrdering::SequentiallyConsistent,
11436                    )
11437                    .unwrap();
11438                self.annotate_user_memaccess(
11439                    memory_index,
11440                    memarg,
11441                    0,
11442                    old.as_instruction_value().unwrap(),
11443                )?;
11444                self.state.push1(old);
11445            }
11446            Operator::I64AtomicRmw8SubU { ref memarg } => {
11447                let value = self.state.pop1()?.into_int_value();
11448                let offset = self.state.pop1()?.into_int_value();
11449                let memory_index = MemoryIndex::from_u32(0);
11450                let effective_address = self.resolve_memory_ptr(
11451                    memory_index,
11452                    memarg,
11453                    self.intrinsics.ptr_ty,
11454                    offset,
11455                    1,
11456                )?;
11457                self.trap_if_misaligned(memarg, effective_address, 1)?;
11458                let narrow_value = err!(self.builder.build_int_truncate(
11459                    value,
11460                    self.intrinsics.i8_ty,
11461                    ""
11462                ));
11463                let old = self
11464                    .builder
11465                    .build_atomicrmw(
11466                        AtomicRMWBinOp::Sub,
11467                        effective_address,
11468                        narrow_value,
11469                        AtomicOrdering::SequentiallyConsistent,
11470                    )
11471                    .unwrap();
11472                self.annotate_user_memaccess(
11473                    memory_index,
11474                    memarg,
11475                    0,
11476                    old.as_instruction_value().unwrap(),
11477                )?;
11478                let old = err!(
11479                    self.builder
11480                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11481                );
11482                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11483            }
11484            Operator::I64AtomicRmw16SubU { ref memarg } => {
11485                let value = self.state.pop1()?.into_int_value();
11486                let offset = self.state.pop1()?.into_int_value();
11487                let memory_index = MemoryIndex::from_u32(0);
11488                let effective_address = self.resolve_memory_ptr(
11489                    memory_index,
11490                    memarg,
11491                    self.intrinsics.ptr_ty,
11492                    offset,
11493                    2,
11494                )?;
11495                self.trap_if_misaligned(memarg, effective_address, 2)?;
11496                let narrow_value = err!(self.builder.build_int_truncate(
11497                    value,
11498                    self.intrinsics.i16_ty,
11499                    ""
11500                ));
11501                let old = self
11502                    .builder
11503                    .build_atomicrmw(
11504                        AtomicRMWBinOp::Sub,
11505                        effective_address,
11506                        narrow_value,
11507                        AtomicOrdering::SequentiallyConsistent,
11508                    )
11509                    .unwrap();
11510                self.annotate_user_memaccess(
11511                    memory_index,
11512                    memarg,
11513                    0,
11514                    old.as_instruction_value().unwrap(),
11515                )?;
11516                let old = err!(
11517                    self.builder
11518                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11519                );
11520                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11521            }
11522            Operator::I64AtomicRmw32SubU { ref memarg } => {
11523                let value = self.state.pop1()?.into_int_value();
11524                let offset = self.state.pop1()?.into_int_value();
11525                let memory_index = MemoryIndex::from_u32(0);
11526                let effective_address = self.resolve_memory_ptr(
11527                    memory_index,
11528                    memarg,
11529                    self.intrinsics.ptr_ty,
11530                    offset,
11531                    4,
11532                )?;
11533                self.trap_if_misaligned(memarg, effective_address, 4)?;
11534                let narrow_value = err!(self.builder.build_int_truncate(
11535                    value,
11536                    self.intrinsics.i32_ty,
11537                    ""
11538                ));
11539                let old = self
11540                    .builder
11541                    .build_atomicrmw(
11542                        AtomicRMWBinOp::Sub,
11543                        effective_address,
11544                        narrow_value,
11545                        AtomicOrdering::SequentiallyConsistent,
11546                    )
11547                    .unwrap();
11548                self.annotate_user_memaccess(
11549                    memory_index,
11550                    memarg,
11551                    0,
11552                    old.as_instruction_value().unwrap(),
11553                )?;
11554                let old = err!(
11555                    self.builder
11556                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11557                );
11558                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11559            }
11560            Operator::I64AtomicRmwSub { ref memarg } => {
11561                let value = self.state.pop1()?.into_int_value();
11562                let offset = self.state.pop1()?.into_int_value();
11563                let memory_index = MemoryIndex::from_u32(0);
11564                let effective_address = self.resolve_memory_ptr(
11565                    memory_index,
11566                    memarg,
11567                    self.intrinsics.ptr_ty,
11568                    offset,
11569                    8,
11570                )?;
11571                self.trap_if_misaligned(memarg, effective_address, 8)?;
11572                let old = self
11573                    .builder
11574                    .build_atomicrmw(
11575                        AtomicRMWBinOp::Sub,
11576                        effective_address,
11577                        value,
11578                        AtomicOrdering::SequentiallyConsistent,
11579                    )
11580                    .unwrap();
11581                self.annotate_user_memaccess(
11582                    memory_index,
11583                    memarg,
11584                    0,
11585                    old.as_instruction_value().unwrap(),
11586                )?;
11587                self.state.push1(old);
11588            }
11589            Operator::I32AtomicRmw8AndU { ref memarg } => {
11590                let value = self.state.pop1()?.into_int_value();
11591                let offset = self.state.pop1()?.into_int_value();
11592                let memory_index = MemoryIndex::from_u32(0);
11593                let effective_address = self.resolve_memory_ptr(
11594                    memory_index,
11595                    memarg,
11596                    self.intrinsics.ptr_ty,
11597                    offset,
11598                    1,
11599                )?;
11600                self.trap_if_misaligned(memarg, effective_address, 1)?;
11601                let narrow_value = err!(self.builder.build_int_truncate(
11602                    value,
11603                    self.intrinsics.i8_ty,
11604                    ""
11605                ));
11606                let old = self
11607                    .builder
11608                    .build_atomicrmw(
11609                        AtomicRMWBinOp::And,
11610                        effective_address,
11611                        narrow_value,
11612                        AtomicOrdering::SequentiallyConsistent,
11613                    )
11614                    .unwrap();
11615                self.annotate_user_memaccess(
11616                    memory_index,
11617                    memarg,
11618                    0,
11619                    old.as_instruction_value().unwrap(),
11620                )?;
11621                let old = err!(
11622                    self.builder
11623                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11624                );
11625                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11626            }
11627            Operator::I32AtomicRmw16AndU { ref memarg } => {
11628                let value = self.state.pop1()?.into_int_value();
11629                let offset = self.state.pop1()?.into_int_value();
11630                let memory_index = MemoryIndex::from_u32(0);
11631                let effective_address = self.resolve_memory_ptr(
11632                    memory_index,
11633                    memarg,
11634                    self.intrinsics.ptr_ty,
11635                    offset,
11636                    2,
11637                )?;
11638                self.trap_if_misaligned(memarg, effective_address, 2)?;
11639                let narrow_value = err!(self.builder.build_int_truncate(
11640                    value,
11641                    self.intrinsics.i16_ty,
11642                    ""
11643                ));
11644                let old = self
11645                    .builder
11646                    .build_atomicrmw(
11647                        AtomicRMWBinOp::And,
11648                        effective_address,
11649                        narrow_value,
11650                        AtomicOrdering::SequentiallyConsistent,
11651                    )
11652                    .unwrap();
11653                self.annotate_user_memaccess(
11654                    memory_index,
11655                    memarg,
11656                    0,
11657                    old.as_instruction_value().unwrap(),
11658                )?;
11659                let old = err!(
11660                    self.builder
11661                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11662                );
11663                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11664            }
11665            Operator::I32AtomicRmwAnd { ref memarg } => {
11666                let value = self.state.pop1()?.into_int_value();
11667                let offset = self.state.pop1()?.into_int_value();
11668                let memory_index = MemoryIndex::from_u32(0);
11669                let effective_address = self.resolve_memory_ptr(
11670                    memory_index,
11671                    memarg,
11672                    self.intrinsics.ptr_ty,
11673                    offset,
11674                    4,
11675                )?;
11676                self.trap_if_misaligned(memarg, effective_address, 4)?;
11677                let old = self
11678                    .builder
11679                    .build_atomicrmw(
11680                        AtomicRMWBinOp::And,
11681                        effective_address,
11682                        value,
11683                        AtomicOrdering::SequentiallyConsistent,
11684                    )
11685                    .unwrap();
11686                self.annotate_user_memaccess(
11687                    memory_index,
11688                    memarg,
11689                    0,
11690                    old.as_instruction_value().unwrap(),
11691                )?;
11692                self.state.push1(old);
11693            }
11694            Operator::I64AtomicRmw8AndU { ref memarg } => {
11695                let value = self.state.pop1()?.into_int_value();
11696                let offset = self.state.pop1()?.into_int_value();
11697                let memory_index = MemoryIndex::from_u32(0);
11698                let effective_address = self.resolve_memory_ptr(
11699                    memory_index,
11700                    memarg,
11701                    self.intrinsics.ptr_ty,
11702                    offset,
11703                    1,
11704                )?;
11705                self.trap_if_misaligned(memarg, effective_address, 1)?;
11706                let narrow_value = err!(self.builder.build_int_truncate(
11707                    value,
11708                    self.intrinsics.i8_ty,
11709                    ""
11710                ));
11711                let old = self
11712                    .builder
11713                    .build_atomicrmw(
11714                        AtomicRMWBinOp::And,
11715                        effective_address,
11716                        narrow_value,
11717                        AtomicOrdering::SequentiallyConsistent,
11718                    )
11719                    .unwrap();
11720                self.annotate_user_memaccess(
11721                    memory_index,
11722                    memarg,
11723                    0,
11724                    old.as_instruction_value().unwrap(),
11725                )?;
11726                let old = err!(
11727                    self.builder
11728                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11729                );
11730                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11731            }
11732            Operator::I64AtomicRmw16AndU { ref memarg } => {
11733                let value = self.state.pop1()?.into_int_value();
11734                let offset = self.state.pop1()?.into_int_value();
11735                let memory_index = MemoryIndex::from_u32(0);
11736                let effective_address = self.resolve_memory_ptr(
11737                    memory_index,
11738                    memarg,
11739                    self.intrinsics.ptr_ty,
11740                    offset,
11741                    2,
11742                )?;
11743                self.trap_if_misaligned(memarg, effective_address, 2)?;
11744                let narrow_value = err!(self.builder.build_int_truncate(
11745                    value,
11746                    self.intrinsics.i16_ty,
11747                    ""
11748                ));
11749                let old = self
11750                    .builder
11751                    .build_atomicrmw(
11752                        AtomicRMWBinOp::And,
11753                        effective_address,
11754                        narrow_value,
11755                        AtomicOrdering::SequentiallyConsistent,
11756                    )
11757                    .unwrap();
11758                self.annotate_user_memaccess(
11759                    memory_index,
11760                    memarg,
11761                    0,
11762                    old.as_instruction_value().unwrap(),
11763                )?;
11764                let old = err!(
11765                    self.builder
11766                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11767                );
11768                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11769            }
11770            Operator::I64AtomicRmw32AndU { ref memarg } => {
11771                let value = self.state.pop1()?.into_int_value();
11772                let offset = self.state.pop1()?.into_int_value();
11773                let memory_index = MemoryIndex::from_u32(0);
11774                let effective_address = self.resolve_memory_ptr(
11775                    memory_index,
11776                    memarg,
11777                    self.intrinsics.ptr_ty,
11778                    offset,
11779                    4,
11780                )?;
11781                self.trap_if_misaligned(memarg, effective_address, 4)?;
11782                let narrow_value = err!(self.builder.build_int_truncate(
11783                    value,
11784                    self.intrinsics.i32_ty,
11785                    ""
11786                ));
11787                let old = self
11788                    .builder
11789                    .build_atomicrmw(
11790                        AtomicRMWBinOp::And,
11791                        effective_address,
11792                        narrow_value,
11793                        AtomicOrdering::SequentiallyConsistent,
11794                    )
11795                    .unwrap();
11796                self.annotate_user_memaccess(
11797                    memory_index,
11798                    memarg,
11799                    0,
11800                    old.as_instruction_value().unwrap(),
11801                )?;
11802                let old = err!(
11803                    self.builder
11804                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11805                );
11806                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11807            }
11808            Operator::I64AtomicRmwAnd { ref memarg } => {
11809                let value = self.state.pop1()?.into_int_value();
11810                let offset = self.state.pop1()?.into_int_value();
11811                let memory_index = MemoryIndex::from_u32(0);
11812                let effective_address = self.resolve_memory_ptr(
11813                    memory_index,
11814                    memarg,
11815                    self.intrinsics.ptr_ty,
11816                    offset,
11817                    8,
11818                )?;
11819                self.trap_if_misaligned(memarg, effective_address, 8)?;
11820                let old = self
11821                    .builder
11822                    .build_atomicrmw(
11823                        AtomicRMWBinOp::And,
11824                        effective_address,
11825                        value,
11826                        AtomicOrdering::SequentiallyConsistent,
11827                    )
11828                    .unwrap();
11829                self.annotate_user_memaccess(
11830                    memory_index,
11831                    memarg,
11832                    0,
11833                    old.as_instruction_value().unwrap(),
11834                )?;
11835                self.state.push1(old);
11836            }
11837            Operator::I32AtomicRmw8OrU { ref memarg } => {
11838                let value = self.state.pop1()?.into_int_value();
11839                let offset = self.state.pop1()?.into_int_value();
11840                let memory_index = MemoryIndex::from_u32(0);
11841                let effective_address = self.resolve_memory_ptr(
11842                    memory_index,
11843                    memarg,
11844                    self.intrinsics.ptr_ty,
11845                    offset,
11846                    1,
11847                )?;
11848                self.trap_if_misaligned(memarg, effective_address, 1)?;
11849                let narrow_value = err!(self.builder.build_int_truncate(
11850                    value,
11851                    self.intrinsics.i8_ty,
11852                    ""
11853                ));
11854                let old = self
11855                    .builder
11856                    .build_atomicrmw(
11857                        AtomicRMWBinOp::Or,
11858                        effective_address,
11859                        narrow_value,
11860                        AtomicOrdering::SequentiallyConsistent,
11861                    )
11862                    .unwrap();
11863                self.annotate_user_memaccess(
11864                    memory_index,
11865                    memarg,
11866                    0,
11867                    old.as_instruction_value().unwrap(),
11868                )?;
11869                let old = err!(
11870                    self.builder
11871                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11872                );
11873                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11874            }
11875            Operator::I32AtomicRmw16OrU { ref memarg } => {
11876                let value = self.state.pop1()?.into_int_value();
11877                let offset = self.state.pop1()?.into_int_value();
11878                let memory_index = MemoryIndex::from_u32(0);
11879                let effective_address = self.resolve_memory_ptr(
11880                    memory_index,
11881                    memarg,
11882                    self.intrinsics.ptr_ty,
11883                    offset,
11884                    2,
11885                )?;
11886                self.trap_if_misaligned(memarg, effective_address, 2)?;
11887                let narrow_value = err!(self.builder.build_int_truncate(
11888                    value,
11889                    self.intrinsics.i16_ty,
11890                    ""
11891                ));
11892                let old = self
11893                    .builder
11894                    .build_atomicrmw(
11895                        AtomicRMWBinOp::Or,
11896                        effective_address,
11897                        narrow_value,
11898                        AtomicOrdering::SequentiallyConsistent,
11899                    )
11900                    .unwrap();
11901                self.annotate_user_memaccess(
11902                    memory_index,
11903                    memarg,
11904                    0,
11905                    old.as_instruction_value().unwrap(),
11906                )?;
11907                let old = err!(
11908                    self.builder
11909                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11910                );
11911                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11912            }
11913            Operator::I32AtomicRmwOr { ref memarg } => {
11914                let value = self.state.pop1()?.into_int_value();
11915                let offset = self.state.pop1()?.into_int_value();
11916                let memory_index = MemoryIndex::from_u32(0);
11917                let effective_address = self.resolve_memory_ptr(
11918                    memory_index,
11919                    memarg,
11920                    self.intrinsics.ptr_ty,
11921                    offset,
11922                    4,
11923                )?;
11924                self.trap_if_misaligned(memarg, effective_address, 4)?;
11925                let old = self
11926                    .builder
11927                    .build_atomicrmw(
11928                        AtomicRMWBinOp::Or,
11929                        effective_address,
11930                        value,
11931                        AtomicOrdering::SequentiallyConsistent,
11932                    )
11933                    .unwrap();
11934                self.annotate_user_memaccess(
11935                    memory_index,
11936                    memarg,
11937                    0,
11938                    old.as_instruction_value().unwrap(),
11939                )?;
11940                let old = err!(
11941                    self.builder
11942                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11943                );
11944                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11945            }
11946            Operator::I64AtomicRmw8OrU { ref memarg } => {
11947                let value = self.state.pop1()?.into_int_value();
11948                let offset = self.state.pop1()?.into_int_value();
11949                let memory_index = MemoryIndex::from_u32(0);
11950                let effective_address = self.resolve_memory_ptr(
11951                    memory_index,
11952                    memarg,
11953                    self.intrinsics.ptr_ty,
11954                    offset,
11955                    1,
11956                )?;
11957                self.trap_if_misaligned(memarg, effective_address, 1)?;
11958                let narrow_value = err!(self.builder.build_int_truncate(
11959                    value,
11960                    self.intrinsics.i8_ty,
11961                    ""
11962                ));
11963                let old = self
11964                    .builder
11965                    .build_atomicrmw(
11966                        AtomicRMWBinOp::Or,
11967                        effective_address,
11968                        narrow_value,
11969                        AtomicOrdering::SequentiallyConsistent,
11970                    )
11971                    .unwrap();
11972                self.annotate_user_memaccess(
11973                    memory_index,
11974                    memarg,
11975                    0,
11976                    old.as_instruction_value().unwrap(),
11977                )?;
11978                let old = err!(
11979                    self.builder
11980                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11981                );
11982                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11983            }
11984            Operator::I64AtomicRmw16OrU { ref memarg } => {
11985                let value = self.state.pop1()?.into_int_value();
11986                let offset = self.state.pop1()?.into_int_value();
11987                let memory_index = MemoryIndex::from_u32(0);
11988                let effective_address = self.resolve_memory_ptr(
11989                    memory_index,
11990                    memarg,
11991                    self.intrinsics.ptr_ty,
11992                    offset,
11993                    2,
11994                )?;
11995                self.trap_if_misaligned(memarg, effective_address, 2)?;
11996                let narrow_value = err!(self.builder.build_int_truncate(
11997                    value,
11998                    self.intrinsics.i16_ty,
11999                    ""
12000                ));
12001                let old = self
12002                    .builder
12003                    .build_atomicrmw(
12004                        AtomicRMWBinOp::Or,
12005                        effective_address,
12006                        narrow_value,
12007                        AtomicOrdering::SequentiallyConsistent,
12008                    )
12009                    .unwrap();
12010                self.annotate_user_memaccess(
12011                    memory_index,
12012                    memarg,
12013                    0,
12014                    old.as_instruction_value().unwrap(),
12015                )?;
12016                let old = err!(
12017                    self.builder
12018                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12019                );
12020                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12021            }
12022            Operator::I64AtomicRmw32OrU { ref memarg } => {
12023                let value = self.state.pop1()?.into_int_value();
12024                let offset = self.state.pop1()?.into_int_value();
12025                let memory_index = MemoryIndex::from_u32(0);
12026                let effective_address = self.resolve_memory_ptr(
12027                    memory_index,
12028                    memarg,
12029                    self.intrinsics.ptr_ty,
12030                    offset,
12031                    4,
12032                )?;
12033                self.trap_if_misaligned(memarg, effective_address, 4)?;
12034                let narrow_value = err!(self.builder.build_int_truncate(
12035                    value,
12036                    self.intrinsics.i32_ty,
12037                    ""
12038                ));
12039                let old = self
12040                    .builder
12041                    .build_atomicrmw(
12042                        AtomicRMWBinOp::Or,
12043                        effective_address,
12044                        narrow_value,
12045                        AtomicOrdering::SequentiallyConsistent,
12046                    )
12047                    .unwrap();
12048                self.annotate_user_memaccess(
12049                    memory_index,
12050                    memarg,
12051                    0,
12052                    old.as_instruction_value().unwrap(),
12053                )?;
12054                let old = err!(
12055                    self.builder
12056                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12057                );
12058                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12059            }
12060            Operator::I64AtomicRmwOr { ref memarg } => {
12061                let value = self.state.pop1()?.into_int_value();
12062                let offset = self.state.pop1()?.into_int_value();
12063                let memory_index = MemoryIndex::from_u32(0);
12064                let effective_address = self.resolve_memory_ptr(
12065                    memory_index,
12066                    memarg,
12067                    self.intrinsics.ptr_ty,
12068                    offset,
12069                    8,
12070                )?;
12071                self.trap_if_misaligned(memarg, effective_address, 8)?;
12072                let old = self
12073                    .builder
12074                    .build_atomicrmw(
12075                        AtomicRMWBinOp::Or,
12076                        effective_address,
12077                        value,
12078                        AtomicOrdering::SequentiallyConsistent,
12079                    )
12080                    .unwrap();
12081                self.annotate_user_memaccess(
12082                    memory_index,
12083                    memarg,
12084                    0,
12085                    old.as_instruction_value().unwrap(),
12086                )?;
12087                self.state.push1(old);
12088            }
12089            Operator::I32AtomicRmw8XorU { ref memarg } => {
12090                let value = self.state.pop1()?.into_int_value();
12091                let offset = self.state.pop1()?.into_int_value();
12092                let memory_index = MemoryIndex::from_u32(0);
12093                let effective_address = self.resolve_memory_ptr(
12094                    memory_index,
12095                    memarg,
12096                    self.intrinsics.ptr_ty,
12097                    offset,
12098                    1,
12099                )?;
12100                self.trap_if_misaligned(memarg, effective_address, 2)?;
12101                let narrow_value = err!(self.builder.build_int_truncate(
12102                    value,
12103                    self.intrinsics.i8_ty,
12104                    ""
12105                ));
12106                let old = self
12107                    .builder
12108                    .build_atomicrmw(
12109                        AtomicRMWBinOp::Xor,
12110                        effective_address,
12111                        narrow_value,
12112                        AtomicOrdering::SequentiallyConsistent,
12113                    )
12114                    .unwrap();
12115                self.annotate_user_memaccess(
12116                    memory_index,
12117                    memarg,
12118                    0,
12119                    old.as_instruction_value().unwrap(),
12120                )?;
12121                let old = err!(
12122                    self.builder
12123                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12124                );
12125                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12126            }
12127            Operator::I32AtomicRmw16XorU { ref memarg } => {
12128                let value = self.state.pop1()?.into_int_value();
12129                let offset = self.state.pop1()?.into_int_value();
12130                let memory_index = MemoryIndex::from_u32(0);
12131                let effective_address = self.resolve_memory_ptr(
12132                    memory_index,
12133                    memarg,
12134                    self.intrinsics.ptr_ty,
12135                    offset,
12136                    2,
12137                )?;
12138                self.trap_if_misaligned(memarg, effective_address, 2)?;
12139                let narrow_value = err!(self.builder.build_int_truncate(
12140                    value,
12141                    self.intrinsics.i16_ty,
12142                    ""
12143                ));
12144                let old = self
12145                    .builder
12146                    .build_atomicrmw(
12147                        AtomicRMWBinOp::Xor,
12148                        effective_address,
12149                        narrow_value,
12150                        AtomicOrdering::SequentiallyConsistent,
12151                    )
12152                    .unwrap();
12153                self.annotate_user_memaccess(
12154                    memory_index,
12155                    memarg,
12156                    0,
12157                    old.as_instruction_value().unwrap(),
12158                )?;
12159                let old = err!(
12160                    self.builder
12161                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12162                );
12163                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12164            }
12165            Operator::I32AtomicRmwXor { ref memarg } => {
12166                let value = self.state.pop1()?.into_int_value();
12167                let offset = self.state.pop1()?.into_int_value();
12168                let memory_index = MemoryIndex::from_u32(0);
12169                let effective_address = self.resolve_memory_ptr(
12170                    memory_index,
12171                    memarg,
12172                    self.intrinsics.ptr_ty,
12173                    offset,
12174                    4,
12175                )?;
12176                self.trap_if_misaligned(memarg, effective_address, 4)?;
12177                let old = self
12178                    .builder
12179                    .build_atomicrmw(
12180                        AtomicRMWBinOp::Xor,
12181                        effective_address,
12182                        value,
12183                        AtomicOrdering::SequentiallyConsistent,
12184                    )
12185                    .unwrap();
12186                self.annotate_user_memaccess(
12187                    memory_index,
12188                    memarg,
12189                    0,
12190                    old.as_instruction_value().unwrap(),
12191                )?;
12192                self.state.push1(old);
12193            }
12194            Operator::I64AtomicRmw8XorU { ref memarg } => {
12195                let value = self.state.pop1()?.into_int_value();
12196                let offset = self.state.pop1()?.into_int_value();
12197                let memory_index = MemoryIndex::from_u32(0);
12198                let effective_address = self.resolve_memory_ptr(
12199                    memory_index,
12200                    memarg,
12201                    self.intrinsics.ptr_ty,
12202                    offset,
12203                    1,
12204                )?;
12205                self.trap_if_misaligned(memarg, effective_address, 1)?;
12206                let narrow_value = err!(self.builder.build_int_truncate(
12207                    value,
12208                    self.intrinsics.i8_ty,
12209                    ""
12210                ));
12211                let old = self
12212                    .builder
12213                    .build_atomicrmw(
12214                        AtomicRMWBinOp::Xor,
12215                        effective_address,
12216                        narrow_value,
12217                        AtomicOrdering::SequentiallyConsistent,
12218                    )
12219                    .unwrap();
12220                self.annotate_user_memaccess(
12221                    memory_index,
12222                    memarg,
12223                    0,
12224                    old.as_instruction_value().unwrap(),
12225                )?;
12226                let old = err!(
12227                    self.builder
12228                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12229                );
12230                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12231            }
12232            Operator::I64AtomicRmw16XorU { ref memarg } => {
12233                let value = self.state.pop1()?.into_int_value();
12234                let offset = self.state.pop1()?.into_int_value();
12235                let memory_index = MemoryIndex::from_u32(0);
12236                let effective_address = self.resolve_memory_ptr(
12237                    memory_index,
12238                    memarg,
12239                    self.intrinsics.ptr_ty,
12240                    offset,
12241                    2,
12242                )?;
12243                self.trap_if_misaligned(memarg, effective_address, 2)?;
12244                let narrow_value = err!(self.builder.build_int_truncate(
12245                    value,
12246                    self.intrinsics.i16_ty,
12247                    ""
12248                ));
12249                let old = self
12250                    .builder
12251                    .build_atomicrmw(
12252                        AtomicRMWBinOp::Xor,
12253                        effective_address,
12254                        narrow_value,
12255                        AtomicOrdering::SequentiallyConsistent,
12256                    )
12257                    .unwrap();
12258                self.annotate_user_memaccess(
12259                    memory_index,
12260                    memarg,
12261                    0,
12262                    old.as_instruction_value().unwrap(),
12263                )?;
12264                let old = err!(
12265                    self.builder
12266                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12267                );
12268                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12269            }
12270            Operator::I64AtomicRmw32XorU { ref memarg } => {
12271                let value = self.state.pop1()?.into_int_value();
12272                let offset = self.state.pop1()?.into_int_value();
12273                let memory_index = MemoryIndex::from_u32(0);
12274                let effective_address = self.resolve_memory_ptr(
12275                    memory_index,
12276                    memarg,
12277                    self.intrinsics.ptr_ty,
12278                    offset,
12279                    4,
12280                )?;
12281                self.trap_if_misaligned(memarg, effective_address, 4)?;
12282                let narrow_value = err!(self.builder.build_int_truncate(
12283                    value,
12284                    self.intrinsics.i32_ty,
12285                    ""
12286                ));
12287                let old = self
12288                    .builder
12289                    .build_atomicrmw(
12290                        AtomicRMWBinOp::Xor,
12291                        effective_address,
12292                        narrow_value,
12293                        AtomicOrdering::SequentiallyConsistent,
12294                    )
12295                    .unwrap();
12296                self.annotate_user_memaccess(
12297                    memory_index,
12298                    memarg,
12299                    0,
12300                    old.as_instruction_value().unwrap(),
12301                )?;
12302                let old = err!(
12303                    self.builder
12304                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12305                );
12306                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12307            }
12308            Operator::I64AtomicRmwXor { ref memarg } => {
12309                let value = self.state.pop1()?.into_int_value();
12310                let offset = self.state.pop1()?.into_int_value();
12311                let memory_index = MemoryIndex::from_u32(0);
12312                let effective_address = self.resolve_memory_ptr(
12313                    memory_index,
12314                    memarg,
12315                    self.intrinsics.ptr_ty,
12316                    offset,
12317                    8,
12318                )?;
12319                self.trap_if_misaligned(memarg, effective_address, 8)?;
12320                let old = self
12321                    .builder
12322                    .build_atomicrmw(
12323                        AtomicRMWBinOp::Xor,
12324                        effective_address,
12325                        value,
12326                        AtomicOrdering::SequentiallyConsistent,
12327                    )
12328                    .unwrap();
12329                self.annotate_user_memaccess(
12330                    memory_index,
12331                    memarg,
12332                    0,
12333                    old.as_instruction_value().unwrap(),
12334                )?;
12335                self.state.push1(old);
12336            }
12337            Operator::I32AtomicRmw8XchgU { ref memarg } => {
12338                let value = self.state.pop1()?.into_int_value();
12339                let offset = self.state.pop1()?.into_int_value();
12340                let memory_index = MemoryIndex::from_u32(0);
12341                let effective_address = self.resolve_memory_ptr(
12342                    memory_index,
12343                    memarg,
12344                    self.intrinsics.ptr_ty,
12345                    offset,
12346                    1,
12347                )?;
12348                self.trap_if_misaligned(memarg, effective_address, 1)?;
12349                let narrow_value = err!(self.builder.build_int_truncate(
12350                    value,
12351                    self.intrinsics.i8_ty,
12352                    ""
12353                ));
12354                let old = self
12355                    .builder
12356                    .build_atomicrmw(
12357                        AtomicRMWBinOp::Xchg,
12358                        effective_address,
12359                        narrow_value,
12360                        AtomicOrdering::SequentiallyConsistent,
12361                    )
12362                    .unwrap();
12363                self.annotate_user_memaccess(
12364                    memory_index,
12365                    memarg,
12366                    0,
12367                    old.as_instruction_value().unwrap(),
12368                )?;
12369                let old = err!(
12370                    self.builder
12371                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12372                );
12373                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12374            }
12375            Operator::I32AtomicRmw16XchgU { ref memarg } => {
12376                let value = self.state.pop1()?.into_int_value();
12377                let offset = self.state.pop1()?.into_int_value();
12378                let memory_index = MemoryIndex::from_u32(0);
12379                let effective_address = self.resolve_memory_ptr(
12380                    memory_index,
12381                    memarg,
12382                    self.intrinsics.ptr_ty,
12383                    offset,
12384                    2,
12385                )?;
12386                self.trap_if_misaligned(memarg, effective_address, 2)?;
12387                let narrow_value = err!(self.builder.build_int_truncate(
12388                    value,
12389                    self.intrinsics.i16_ty,
12390                    ""
12391                ));
12392                let old = self
12393                    .builder
12394                    .build_atomicrmw(
12395                        AtomicRMWBinOp::Xchg,
12396                        effective_address,
12397                        narrow_value,
12398                        AtomicOrdering::SequentiallyConsistent,
12399                    )
12400                    .unwrap();
12401                self.annotate_user_memaccess(
12402                    memory_index,
12403                    memarg,
12404                    0,
12405                    old.as_instruction_value().unwrap(),
12406                )?;
12407                let old = err!(
12408                    self.builder
12409                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12410                );
12411                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12412            }
12413            Operator::I32AtomicRmwXchg { ref memarg } => {
12414                let value = self.state.pop1()?.into_int_value();
12415                let offset = self.state.pop1()?.into_int_value();
12416                let memory_index = MemoryIndex::from_u32(0);
12417                let effective_address = self.resolve_memory_ptr(
12418                    memory_index,
12419                    memarg,
12420                    self.intrinsics.ptr_ty,
12421                    offset,
12422                    4,
12423                )?;
12424                self.trap_if_misaligned(memarg, effective_address, 4)?;
12425                let old = self
12426                    .builder
12427                    .build_atomicrmw(
12428                        AtomicRMWBinOp::Xchg,
12429                        effective_address,
12430                        value,
12431                        AtomicOrdering::SequentiallyConsistent,
12432                    )
12433                    .unwrap();
12434                self.annotate_user_memaccess(
12435                    memory_index,
12436                    memarg,
12437                    0,
12438                    old.as_instruction_value().unwrap(),
12439                )?;
12440                self.state.push1(old);
12441            }
12442            Operator::I64AtomicRmw8XchgU { ref memarg } => {
12443                let value = self.state.pop1()?.into_int_value();
12444                let offset = self.state.pop1()?.into_int_value();
12445                let memory_index = MemoryIndex::from_u32(0);
12446                let effective_address = self.resolve_memory_ptr(
12447                    memory_index,
12448                    memarg,
12449                    self.intrinsics.ptr_ty,
12450                    offset,
12451                    1,
12452                )?;
12453                self.trap_if_misaligned(memarg, effective_address, 1)?;
12454                let narrow_value = err!(self.builder.build_int_truncate(
12455                    value,
12456                    self.intrinsics.i8_ty,
12457                    ""
12458                ));
12459                let old = self
12460                    .builder
12461                    .build_atomicrmw(
12462                        AtomicRMWBinOp::Xchg,
12463                        effective_address,
12464                        narrow_value,
12465                        AtomicOrdering::SequentiallyConsistent,
12466                    )
12467                    .unwrap();
12468                self.annotate_user_memaccess(
12469                    memory_index,
12470                    memarg,
12471                    0,
12472                    old.as_instruction_value().unwrap(),
12473                )?;
12474                let old = err!(
12475                    self.builder
12476                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12477                );
12478                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12479            }
12480            Operator::I64AtomicRmw16XchgU { ref memarg } => {
12481                let value = self.state.pop1()?.into_int_value();
12482                let offset = self.state.pop1()?.into_int_value();
12483                let memory_index = MemoryIndex::from_u32(0);
12484                let effective_address = self.resolve_memory_ptr(
12485                    memory_index,
12486                    memarg,
12487                    self.intrinsics.ptr_ty,
12488                    offset,
12489                    2,
12490                )?;
12491                self.trap_if_misaligned(memarg, effective_address, 2)?;
12492                let narrow_value = err!(self.builder.build_int_truncate(
12493                    value,
12494                    self.intrinsics.i16_ty,
12495                    ""
12496                ));
12497                let old = self
12498                    .builder
12499                    .build_atomicrmw(
12500                        AtomicRMWBinOp::Xchg,
12501                        effective_address,
12502                        narrow_value,
12503                        AtomicOrdering::SequentiallyConsistent,
12504                    )
12505                    .unwrap();
12506                self.annotate_user_memaccess(
12507                    memory_index,
12508                    memarg,
12509                    0,
12510                    old.as_instruction_value().unwrap(),
12511                )?;
12512                let old = err!(
12513                    self.builder
12514                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12515                );
12516                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12517            }
12518            Operator::I64AtomicRmw32XchgU { ref memarg } => {
12519                let value = self.state.pop1()?.into_int_value();
12520                let offset = self.state.pop1()?.into_int_value();
12521                let memory_index = MemoryIndex::from_u32(0);
12522                let effective_address = self.resolve_memory_ptr(
12523                    memory_index,
12524                    memarg,
12525                    self.intrinsics.ptr_ty,
12526                    offset,
12527                    4,
12528                )?;
12529                self.trap_if_misaligned(memarg, effective_address, 4)?;
12530                let narrow_value = err!(self.builder.build_int_truncate(
12531                    value,
12532                    self.intrinsics.i32_ty,
12533                    ""
12534                ));
12535                let old = self
12536                    .builder
12537                    .build_atomicrmw(
12538                        AtomicRMWBinOp::Xchg,
12539                        effective_address,
12540                        narrow_value,
12541                        AtomicOrdering::SequentiallyConsistent,
12542                    )
12543                    .unwrap();
12544                self.annotate_user_memaccess(
12545                    memory_index,
12546                    memarg,
12547                    0,
12548                    old.as_instruction_value().unwrap(),
12549                )?;
12550                let old = err!(
12551                    self.builder
12552                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12553                );
12554                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12555            }
12556            Operator::I64AtomicRmwXchg { ref memarg } => {
12557                let value = self.state.pop1()?.into_int_value();
12558                let offset = self.state.pop1()?.into_int_value();
12559                let memory_index = MemoryIndex::from_u32(0);
12560                let effective_address = self.resolve_memory_ptr(
12561                    memory_index,
12562                    memarg,
12563                    self.intrinsics.ptr_ty,
12564                    offset,
12565                    8,
12566                )?;
12567                self.trap_if_misaligned(memarg, effective_address, 8)?;
12568                let old = self
12569                    .builder
12570                    .build_atomicrmw(
12571                        AtomicRMWBinOp::Xchg,
12572                        effective_address,
12573                        value,
12574                        AtomicOrdering::SequentiallyConsistent,
12575                    )
12576                    .unwrap();
12577                self.annotate_user_memaccess(
12578                    memory_index,
12579                    memarg,
12580                    0,
12581                    old.as_instruction_value().unwrap(),
12582                )?;
12583                self.state.push1(old);
12584            }
12585            Operator::I32AtomicRmw8CmpxchgU { ref memarg } => {
12586                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12587                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12588                let new = self.apply_pending_canonicalization(new, new_info)?;
12589                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12590                let offset = self.state.pop1()?.into_int_value();
12591                let memory_index = MemoryIndex::from_u32(0);
12592                let effective_address = self.resolve_memory_ptr(
12593                    memory_index,
12594                    memarg,
12595                    self.intrinsics.ptr_ty,
12596                    offset,
12597                    1,
12598                )?;
12599                self.trap_if_misaligned(memarg, effective_address, 1)?;
12600                let narrow_cmp = err!(self.builder.build_int_truncate(
12601                    cmp,
12602                    self.intrinsics.i8_ty,
12603                    ""
12604                ));
12605                let narrow_new = err!(self.builder.build_int_truncate(
12606                    new,
12607                    self.intrinsics.i8_ty,
12608                    ""
12609                ));
12610                let old = self
12611                    .builder
12612                    .build_cmpxchg(
12613                        effective_address,
12614                        narrow_cmp,
12615                        narrow_new,
12616                        AtomicOrdering::SequentiallyConsistent,
12617                        AtomicOrdering::SequentiallyConsistent,
12618                    )
12619                    .unwrap();
12620                self.annotate_user_memaccess(
12621                    memory_index,
12622                    memarg,
12623                    0,
12624                    old.as_instruction_value().unwrap(),
12625                )?;
12626                let old = self
12627                    .builder
12628                    .build_extract_value(old, 0, "")
12629                    .unwrap()
12630                    .into_int_value();
12631                let old = err!(
12632                    self.builder
12633                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12634                );
12635                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12636            }
12637            Operator::I32AtomicRmw16CmpxchgU { ref memarg } => {
12638                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12639                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12640                let new = self.apply_pending_canonicalization(new, new_info)?;
12641                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12642                let offset = self.state.pop1()?.into_int_value();
12643                let memory_index = MemoryIndex::from_u32(0);
12644                let effective_address = self.resolve_memory_ptr(
12645                    memory_index,
12646                    memarg,
12647                    self.intrinsics.ptr_ty,
12648                    offset,
12649                    2,
12650                )?;
12651                self.trap_if_misaligned(memarg, effective_address, 2)?;
12652                let narrow_cmp = err!(self.builder.build_int_truncate(
12653                    cmp,
12654                    self.intrinsics.i16_ty,
12655                    ""
12656                ));
12657                let narrow_new = err!(self.builder.build_int_truncate(
12658                    new,
12659                    self.intrinsics.i16_ty,
12660                    ""
12661                ));
12662                let old = self
12663                    .builder
12664                    .build_cmpxchg(
12665                        effective_address,
12666                        narrow_cmp,
12667                        narrow_new,
12668                        AtomicOrdering::SequentiallyConsistent,
12669                        AtomicOrdering::SequentiallyConsistent,
12670                    )
12671                    .unwrap();
12672                self.annotate_user_memaccess(
12673                    memory_index,
12674                    memarg,
12675                    0,
12676                    old.as_instruction_value().unwrap(),
12677                )?;
12678                let old = self
12679                    .builder
12680                    .build_extract_value(old, 0, "")
12681                    .unwrap()
12682                    .into_int_value();
12683                let old = err!(
12684                    self.builder
12685                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12686                );
12687                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12688            }
12689            Operator::I32AtomicRmwCmpxchg { ref memarg } => {
12690                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12691                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12692                let new = self.apply_pending_canonicalization(new, new_info)?;
12693                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12694                let offset = self.state.pop1()?.into_int_value();
12695                let memory_index = MemoryIndex::from_u32(0);
12696                let effective_address = self.resolve_memory_ptr(
12697                    memory_index,
12698                    memarg,
12699                    self.intrinsics.ptr_ty,
12700                    offset,
12701                    4,
12702                )?;
12703                self.trap_if_misaligned(memarg, effective_address, 4)?;
12704                let old = self
12705                    .builder
12706                    .build_cmpxchg(
12707                        effective_address,
12708                        cmp,
12709                        new,
12710                        AtomicOrdering::SequentiallyConsistent,
12711                        AtomicOrdering::SequentiallyConsistent,
12712                    )
12713                    .unwrap();
12714                self.annotate_user_memaccess(
12715                    memory_index,
12716                    memarg,
12717                    0,
12718                    old.as_instruction_value().unwrap(),
12719                )?;
12720                let old = err!(self.builder.build_extract_value(old, 0, ""));
12721                self.state.push1(old);
12722            }
12723            Operator::I64AtomicRmw8CmpxchgU { ref memarg } => {
12724                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12725                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12726                let new = self.apply_pending_canonicalization(new, new_info)?;
12727                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12728                let offset = self.state.pop1()?.into_int_value();
12729                let memory_index = MemoryIndex::from_u32(0);
12730                let effective_address = self.resolve_memory_ptr(
12731                    memory_index,
12732                    memarg,
12733                    self.intrinsics.ptr_ty,
12734                    offset,
12735                    1,
12736                )?;
12737                self.trap_if_misaligned(memarg, effective_address, 1)?;
12738                let narrow_cmp = err!(self.builder.build_int_truncate(
12739                    cmp,
12740                    self.intrinsics.i8_ty,
12741                    ""
12742                ));
12743                let narrow_new = err!(self.builder.build_int_truncate(
12744                    new,
12745                    self.intrinsics.i8_ty,
12746                    ""
12747                ));
12748                let old = self
12749                    .builder
12750                    .build_cmpxchg(
12751                        effective_address,
12752                        narrow_cmp,
12753                        narrow_new,
12754                        AtomicOrdering::SequentiallyConsistent,
12755                        AtomicOrdering::SequentiallyConsistent,
12756                    )
12757                    .unwrap();
12758                self.annotate_user_memaccess(
12759                    memory_index,
12760                    memarg,
12761                    0,
12762                    old.as_instruction_value().unwrap(),
12763                )?;
12764                let old = self
12765                    .builder
12766                    .build_extract_value(old, 0, "")
12767                    .unwrap()
12768                    .into_int_value();
12769                let old = err!(
12770                    self.builder
12771                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12772                );
12773                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12774            }
12775            Operator::I64AtomicRmw16CmpxchgU { ref memarg } => {
12776                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12777                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12778                let new = self.apply_pending_canonicalization(new, new_info)?;
12779                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12780                let offset = self.state.pop1()?.into_int_value();
12781                let memory_index = MemoryIndex::from_u32(0);
12782                let effective_address = self.resolve_memory_ptr(
12783                    memory_index,
12784                    memarg,
12785                    self.intrinsics.ptr_ty,
12786                    offset,
12787                    2,
12788                )?;
12789                self.trap_if_misaligned(memarg, effective_address, 2)?;
12790                let narrow_cmp = err!(self.builder.build_int_truncate(
12791                    cmp,
12792                    self.intrinsics.i16_ty,
12793                    ""
12794                ));
12795                let narrow_new = err!(self.builder.build_int_truncate(
12796                    new,
12797                    self.intrinsics.i16_ty,
12798                    ""
12799                ));
12800                let old = self
12801                    .builder
12802                    .build_cmpxchg(
12803                        effective_address,
12804                        narrow_cmp,
12805                        narrow_new,
12806                        AtomicOrdering::SequentiallyConsistent,
12807                        AtomicOrdering::SequentiallyConsistent,
12808                    )
12809                    .unwrap();
12810                self.annotate_user_memaccess(
12811                    memory_index,
12812                    memarg,
12813                    0,
12814                    old.as_instruction_value().unwrap(),
12815                )?;
12816                let old = self
12817                    .builder
12818                    .build_extract_value(old, 0, "")
12819                    .unwrap()
12820                    .into_int_value();
12821                let old = err!(
12822                    self.builder
12823                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12824                );
12825                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12826            }
12827            Operator::I64AtomicRmw32CmpxchgU { ref memarg } => {
12828                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12829                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12830                let new = self.apply_pending_canonicalization(new, new_info)?;
12831                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12832                let offset = self.state.pop1()?.into_int_value();
12833                let memory_index = MemoryIndex::from_u32(0);
12834                let effective_address = self.resolve_memory_ptr(
12835                    memory_index,
12836                    memarg,
12837                    self.intrinsics.ptr_ty,
12838                    offset,
12839                    4,
12840                )?;
12841                self.trap_if_misaligned(memarg, effective_address, 4)?;
12842                let narrow_cmp = err!(self.builder.build_int_truncate(
12843                    cmp,
12844                    self.intrinsics.i32_ty,
12845                    ""
12846                ));
12847                let narrow_new = err!(self.builder.build_int_truncate(
12848                    new,
12849                    self.intrinsics.i32_ty,
12850                    ""
12851                ));
12852                let old = self
12853                    .builder
12854                    .build_cmpxchg(
12855                        effective_address,
12856                        narrow_cmp,
12857                        narrow_new,
12858                        AtomicOrdering::SequentiallyConsistent,
12859                        AtomicOrdering::SequentiallyConsistent,
12860                    )
12861                    .unwrap();
12862                self.annotate_user_memaccess(
12863                    memory_index,
12864                    memarg,
12865                    0,
12866                    old.as_instruction_value().unwrap(),
12867                )?;
12868                let old = self
12869                    .builder
12870                    .build_extract_value(old, 0, "")
12871                    .unwrap()
12872                    .into_int_value();
12873                let old = err!(
12874                    self.builder
12875                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12876                );
12877                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12878            }
12879            Operator::I64AtomicRmwCmpxchg { ref memarg } => {
12880                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12881                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12882                let new = self.apply_pending_canonicalization(new, new_info)?;
12883                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12884                let offset = self.state.pop1()?.into_int_value();
12885                let memory_index = MemoryIndex::from_u32(0);
12886                let effective_address = self.resolve_memory_ptr(
12887                    memory_index,
12888                    memarg,
12889                    self.intrinsics.ptr_ty,
12890                    offset,
12891                    8,
12892                )?;
12893                self.trap_if_misaligned(memarg, effective_address, 8)?;
12894                let old = self
12895                    .builder
12896                    .build_cmpxchg(
12897                        effective_address,
12898                        cmp,
12899                        new,
12900                        AtomicOrdering::SequentiallyConsistent,
12901                        AtomicOrdering::SequentiallyConsistent,
12902                    )
12903                    .unwrap();
12904                self.annotate_user_memaccess(
12905                    memory_index,
12906                    memarg,
12907                    0,
12908                    old.as_instruction_value().unwrap(),
12909                )?;
12910                let old = err!(self.builder.build_extract_value(old, 0, ""));
12911                self.state.push1(old);
12912            }
12913
12914            Operator::MemoryGrow { mem } => {
12915                let memory_index = MemoryIndex::from_u32(mem);
12916                let delta = self.state.pop1()?;
12917                let grow_fn_ptr = self.ctx.memory_grow(memory_index, self.intrinsics)?;
12918                let grow = err!(self.builder.build_indirect_call(
12919                    self.intrinsics.memory_grow_ty,
12920                    grow_fn_ptr,
12921                    &[
12922                        vmctx.as_basic_value_enum().into(),
12923                        delta.into(),
12924                        self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
12925                    ],
12926                    "",
12927                ));
12928                self.state.push1(grow.try_as_basic_value().unwrap_basic());
12929            }
12930            Operator::MemorySize { mem } => {
12931                let memory_index = MemoryIndex::from_u32(mem);
12932                let size_fn_ptr = self.ctx.memory_size(memory_index, self.intrinsics)?;
12933                let size = err!(self.builder.build_indirect_call(
12934                    self.intrinsics.memory_size_ty,
12935                    size_fn_ptr,
12936                    &[
12937                        vmctx.as_basic_value_enum().into(),
12938                        self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
12939                    ],
12940                    "",
12941                ));
12942                //size.add_attribute(AttributeLoc::Function, self.intrinsics.readonly);
12943                self.state.push1(size.try_as_basic_value().unwrap_basic());
12944            }
12945            Operator::MemoryInit { data_index, mem } => {
12946                let (dest, src, len) = self.state.pop3()?;
12947                let mem = self.intrinsics.i32_ty.const_int(mem.into(), false);
12948                let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
12949                self.build_call_with_param_attributes(
12950                    self.intrinsics.memory_init,
12951                    &[
12952                        vmctx.as_basic_value_enum().into(),
12953                        mem.into(),
12954                        segment.into(),
12955                        dest.into(),
12956                        src.into(),
12957                        len.into(),
12958                    ],
12959                    "",
12960                )?;
12961            }
12962            Operator::DataDrop { data_index } => {
12963                let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
12964                self.build_call_with_param_attributes(
12965                    self.intrinsics.data_drop,
12966                    &[vmctx.as_basic_value_enum().into(), segment.into()],
12967                    "",
12968                )?;
12969            }
12970            Operator::MemoryCopy { dst_mem, src_mem } => {
12971                // ignored until we support multiple memories
12972                let _dst = dst_mem;
12973                let (memory_copy, src) = if let Some(local_memory_index) = self
12974                    .wasm_module
12975                    .local_memory_index(MemoryIndex::from_u32(src_mem))
12976                {
12977                    (self.intrinsics.memory_copy, local_memory_index.as_u32())
12978                } else {
12979                    (self.intrinsics.imported_memory_copy, src_mem)
12980                };
12981
12982                let (dest_pos, src_pos, len) = self.state.pop3()?;
12983                let src_index = self.intrinsics.i32_ty.const_int(src.into(), false);
12984                self.build_call_with_param_attributes(
12985                    memory_copy,
12986                    &[
12987                        vmctx.as_basic_value_enum().into(),
12988                        src_index.into(),
12989                        dest_pos.into(),
12990                        src_pos.into(),
12991                        len.into(),
12992                    ],
12993                    "",
12994                )?;
12995            }
12996            Operator::MemoryFill { mem } => {
12997                let (memory_fill, mem) = if let Some(local_memory_index) = self
12998                    .wasm_module
12999                    .local_memory_index(MemoryIndex::from_u32(mem))
13000                {
13001                    (self.intrinsics.memory_fill, local_memory_index.as_u32())
13002                } else {
13003                    (self.intrinsics.imported_memory_fill, mem)
13004                };
13005
13006                let (dst, val, len) = self.state.pop3()?;
13007                let mem_index = self.intrinsics.i32_ty.const_int(mem.into(), false);
13008                self.build_call_with_param_attributes(
13009                    memory_fill,
13010                    &[
13011                        vmctx.as_basic_value_enum().into(),
13012                        mem_index.into(),
13013                        dst.into(),
13014                        val.into(),
13015                        len.into(),
13016                    ],
13017                    "",
13018                )?;
13019            }
13020            /***************************
13021             * Reference types.
13022             * https://github.com/WebAssembly/reference-types/blob/master/proposals/reference-types/Overview.md
13023             ***************************/
13024            Operator::RefNull { hty } => {
13025                let ty = err!(wpheaptype_to_type(hty));
13026                let ty = type_to_llvm(self.intrinsics, ty)?;
13027                self.state.push1(ty.const_zero());
13028            }
13029            Operator::RefIsNull => {
13030                let value = self.state.pop1()?.into_pointer_value();
13031                let is_null = err!(self.builder.build_is_null(value, ""));
13032                let is_null = err!(self.builder.build_int_z_extend(
13033                    is_null,
13034                    self.intrinsics.i32_ty,
13035                    ""
13036                ));
13037                self.state.push1(is_null);
13038            }
13039            Operator::RefFunc { function_index } => {
13040                let index = self
13041                    .intrinsics
13042                    .i32_ty
13043                    .const_int(function_index.into(), false);
13044                let value = self
13045                    .build_call_with_param_attributes(
13046                        self.intrinsics.func_ref,
13047                        &[self.ctx.basic().into(), index.into()],
13048                        "",
13049                    )?
13050                    .try_as_basic_value()
13051                    .unwrap_basic();
13052                self.state.push1(value);
13053            }
13054            Operator::TableGet { table } => {
13055                let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
13056                let elem = self.state.pop1()?;
13057                let table_get = if self
13058                    .wasm_module
13059                    .local_table_index(TableIndex::from_u32(table))
13060                    .is_some()
13061                {
13062                    self.intrinsics.table_get
13063                } else {
13064                    self.intrinsics.imported_table_get
13065                };
13066                let value = self
13067                    .build_call_with_param_attributes(
13068                        table_get,
13069                        &[self.ctx.basic().into(), table_index.into(), elem.into()],
13070                        "",
13071                    )?
13072                    .try_as_basic_value()
13073                    .unwrap_basic();
13074                let value = err!(
13075                    self.builder.build_bit_cast(
13076                        value,
13077                        type_to_llvm(
13078                            self.intrinsics,
13079                            self.wasm_module
13080                                .tables
13081                                .get(TableIndex::from_u32(table))
13082                                .unwrap()
13083                                .ty,
13084                        )?,
13085                        "",
13086                    )
13087                );
13088                self.state.push1(value);
13089            }
13090            Operator::TableSet { table } => {
13091                let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
13092                let (elem, value) = self.state.pop2()?;
13093                let value = err!(
13094                    self.builder
13095                        .build_bit_cast(value, self.intrinsics.ptr_ty, "")
13096                );
13097                let table_set = if self
13098                    .wasm_module
13099                    .local_table_index(TableIndex::from_u32(table))
13100                    .is_some()
13101                {
13102                    self.intrinsics.table_set
13103                } else {
13104                    self.intrinsics.imported_table_set
13105                };
13106                self.build_call_with_param_attributes(
13107                    table_set,
13108                    &[
13109                        self.ctx.basic().into(),
13110                        table_index.into(),
13111                        elem.into(),
13112                        value.into(),
13113                    ],
13114                    "",
13115                )?;
13116            }
13117            Operator::TableCopy {
13118                dst_table,
13119                src_table,
13120            } => {
13121                let (dst, src, len) = self.state.pop3()?;
13122                let dst_table = self.intrinsics.i32_ty.const_int(dst_table as u64, false);
13123                let src_table = self.intrinsics.i32_ty.const_int(src_table as u64, false);
13124                self.build_call_with_param_attributes(
13125                    self.intrinsics.table_copy,
13126                    &[
13127                        self.ctx.basic().into(),
13128                        dst_table.into(),
13129                        src_table.into(),
13130                        dst.into(),
13131                        src.into(),
13132                        len.into(),
13133                    ],
13134                    "",
13135                )?;
13136            }
13137            Operator::TableInit { elem_index, table } => {
13138                let (dst, src, len) = self.state.pop3()?;
13139                let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
13140                let table = self.intrinsics.i32_ty.const_int(table as u64, false);
13141                self.build_call_with_param_attributes(
13142                    self.intrinsics.table_init,
13143                    &[
13144                        self.ctx.basic().into(),
13145                        table.into(),
13146                        segment.into(),
13147                        dst.into(),
13148                        src.into(),
13149                        len.into(),
13150                    ],
13151                    "",
13152                )?;
13153            }
13154            Operator::ElemDrop { elem_index } => {
13155                let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
13156                self.build_call_with_param_attributes(
13157                    self.intrinsics.elem_drop,
13158                    &[self.ctx.basic().into(), segment.into()],
13159                    "",
13160                )?;
13161            }
13162            Operator::TableFill { table } => {
13163                let table = self.intrinsics.i32_ty.const_int(table as u64, false);
13164                let (start, elem, len) = self.state.pop3()?;
13165                let elem = err!(
13166                    self.builder
13167                        .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
13168                );
13169                self.build_call_with_param_attributes(
13170                    self.intrinsics.table_fill,
13171                    &[
13172                        self.ctx.basic().into(),
13173                        table.into(),
13174                        start.into(),
13175                        elem.into(),
13176                        len.into(),
13177                    ],
13178                    "",
13179                )?;
13180            }
13181            Operator::TableGrow { table } => {
13182                let (elem, delta) = self.state.pop2()?;
13183                let elem = err!(
13184                    self.builder
13185                        .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
13186                );
13187                let (table_grow, table_index) = if let Some(local_table_index) = self
13188                    .wasm_module
13189                    .local_table_index(TableIndex::from_u32(table))
13190                {
13191                    (self.intrinsics.table_grow, local_table_index.as_u32())
13192                } else {
13193                    (self.intrinsics.imported_table_grow, table)
13194                };
13195                let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
13196                let size = self
13197                    .build_call_with_param_attributes(
13198                        table_grow,
13199                        &[
13200                            self.ctx.basic().into(),
13201                            elem.into(),
13202                            delta.into(),
13203                            table_index.into(),
13204                        ],
13205                        "",
13206                    )?
13207                    .try_as_basic_value()
13208                    .unwrap_basic();
13209                self.state.push1(size);
13210            }
13211            Operator::TableSize { table } => {
13212                let (table_size, table_index) = if let Some(local_table_index) = self
13213                    .wasm_module
13214                    .local_table_index(TableIndex::from_u32(table))
13215                {
13216                    (self.intrinsics.table_size, local_table_index.as_u32())
13217                } else {
13218                    (self.intrinsics.imported_table_size, table)
13219                };
13220                let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
13221                let size = self
13222                    .build_call_with_param_attributes(
13223                        table_size,
13224                        &[self.ctx.basic().into(), table_index.into()],
13225                        "",
13226                    )?
13227                    .try_as_basic_value()
13228                    .unwrap_basic();
13229                self.state.push1(size);
13230            }
13231            Operator::MemoryAtomicWait32 { memarg } => {
13232                let memory_index = MemoryIndex::from_u32(memarg.memory);
13233                let (dst, val, timeout) = self.state.pop3()?;
13234                let wait32_fn_ptr = self.ctx.memory_wait32(memory_index, self.intrinsics)?;
13235                let ret = err!(
13236                    self.builder.build_indirect_call(
13237                        self.intrinsics.memory_wait32_ty,
13238                        wait32_fn_ptr,
13239                        &[
13240                            vmctx.as_basic_value_enum().into(),
13241                            self.intrinsics
13242                                .i32_ty
13243                                .const_int(memarg.memory as u64, false)
13244                                .into(),
13245                            dst.into(),
13246                            val.into(),
13247                            timeout.into(),
13248                        ],
13249                        "",
13250                    )
13251                );
13252                self.state.push1(ret.try_as_basic_value().unwrap_basic());
13253            }
13254            Operator::MemoryAtomicWait64 { memarg } => {
13255                let memory_index = MemoryIndex::from_u32(memarg.memory);
13256                let (dst, val, timeout) = self.state.pop3()?;
13257                let wait64_fn_ptr = self.ctx.memory_wait64(memory_index, self.intrinsics)?;
13258                let ret = err!(
13259                    self.builder.build_indirect_call(
13260                        self.intrinsics.memory_wait64_ty,
13261                        wait64_fn_ptr,
13262                        &[
13263                            vmctx.as_basic_value_enum().into(),
13264                            self.intrinsics
13265                                .i32_ty
13266                                .const_int(memarg.memory as u64, false)
13267                                .into(),
13268                            dst.into(),
13269                            val.into(),
13270                            timeout.into(),
13271                        ],
13272                        "",
13273                    )
13274                );
13275                self.state.push1(ret.try_as_basic_value().unwrap_basic());
13276            }
13277            Operator::MemoryAtomicNotify { memarg } => {
13278                let memory_index = MemoryIndex::from_u32(memarg.memory);
13279                let (dst, count) = self.state.pop2()?;
13280                let notify_fn_ptr = self.ctx.memory_notify(memory_index, self.intrinsics)?;
13281                let cnt = err!(
13282                    self.builder.build_indirect_call(
13283                        self.intrinsics.memory_notify_ty,
13284                        notify_fn_ptr,
13285                        &[
13286                            vmctx.as_basic_value_enum().into(),
13287                            self.intrinsics
13288                                .i32_ty
13289                                .const_int(memarg.memory as u64, false)
13290                                .into(),
13291                            dst.into(),
13292                            count.into(),
13293                        ],
13294                        "",
13295                    )
13296                );
13297                self.state.push1(cnt.try_as_basic_value().unwrap_basic());
13298            }
13299
13300            Operator::TryTable { try_table } => {
13301                let current_block = self
13302                    .builder
13303                    .get_insert_block()
13304                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
13305
13306                self.builder.position_at_end(current_block);
13307
13308                let end_block = self.context.append_basic_block(self.function, "try_end");
13309
13310                let end_phis = {
13311                    self.builder.position_at_end(end_block);
13312
13313                    let phis = self
13314                        .module_translation
13315                        .blocktype_params_results(&try_table.ty)?
13316                        .1
13317                        .iter()
13318                        .map(|&wp_ty| {
13319                            err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
13320                                type_to_llvm(self.intrinsics, wasm_ty)
13321                                    .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
13322                            })
13323                        })
13324                        .collect::<Result<_, _>>()?;
13325
13326                    self.builder.position_at_end(current_block);
13327                    phis
13328                };
13329
13330                // Collect unique catches. It is not a "hard" error on the wasm side,
13331                // but LLVM will definitely complain about having the same identifier
13332                // match two different branches in the switch below.
13333                let catches: Vec<_> = try_table
13334                    .catches
13335                    .into_iter()
13336                    .unique_by(|v| match v {
13337                        Catch::One { tag, .. } | Catch::OneRef { tag, .. } => *tag as i32,
13338                        Catch::All { .. } | Catch::AllRef { .. } => CATCH_ALL_TAG_VALUE,
13339                    })
13340                    .collect();
13341
13342                // Build the landing pad.
13343                let null = self.intrinsics.ptr_ty.const_zero();
13344
13345                let mut catch_tag_values = vec![];
13346                let mut lpad_clauses: Vec<BasicValueEnum<'ctx>> = catches
13347                    .iter()
13348                    .map(|catch| match catch {
13349                        Catch::All { .. } | Catch::AllRef { .. } => {
13350                            catch_tag_values.push(CATCH_ALL_TAG_VALUE as u32);
13351                            Ok(null.into())
13352                        }
13353                        Catch::One { tag, .. } | Catch::OneRef { tag, .. } => {
13354                            catch_tag_values.push(*tag);
13355                            Ok(self.get_or_insert_tag_type_info_global(*tag as i32))
13356                        }
13357                    })
13358                    .collect::<Result<Vec<BasicValueEnum<'ctx>>, CompileError>>()?;
13359
13360                // Since jumping between landingpads is not possible, we need to collect
13361                // all tags from outer try_tables as well to build a clause for *every*
13362                // possible tag that might be caught.
13363                let mut outer_catch_blocks = vec![];
13364                for outer_landingpad in self.state.landingpads.iter().rev() {
13365                    for catch_info @ TagCatchInfo { tag, .. } in &outer_landingpad.tags {
13366                        if !catch_tag_values.contains(tag) {
13367                            catch_tag_values.push(*tag);
13368                            lpad_clauses.push(if *tag as i32 == CATCH_ALL_TAG_VALUE {
13369                                null.into()
13370                            } else {
13371                                *self.tags_cache.get(&(*tag as i32)).expect(
13372                                    "If a previous try_table encountered a tag, \
13373                                    it should be in the cache",
13374                                )
13375                            });
13376                            outer_catch_blocks.push(*catch_info);
13377                        }
13378                    }
13379                }
13380
13381                // If there are no catch clauses, we have to skip everything, since
13382                // an lpad without catch clauses is invalid (and won't ever be jumped
13383                // to anyway)
13384                let mut maybe_lpad_block = None;
13385                let mut catch_blocks = vec![];
13386                if !lpad_clauses.is_empty() {
13387                    let lpad_block = self.context.append_basic_block(self.function, "catch");
13388                    let catch_all_block =
13389                        self.context.append_basic_block(self.function, "catch_all");
13390                    let catch_specific_block = self
13391                        .context
13392                        .append_basic_block(self.function, "catch_specific");
13393                    let catch_end_block =
13394                        self.context.append_basic_block(self.function, "catch_end");
13395                    let rethrow_block = self.context.append_basic_block(self.function, "rethrow");
13396
13397                    self.builder.position_at_end(lpad_block);
13398
13399                    let res = err!(self.builder.build_landing_pad(
13400                        self.intrinsics.lpad_exception_ty,
13401                        self.intrinsics.personality,
13402                        &lpad_clauses,
13403                        false,
13404                        "exc_struct",
13405                    ));
13406
13407                    let res = res.into_struct_value();
13408
13409                    let uw_exc = err!(self.builder.build_extract_value(res, 0, "exc_ptr"));
13410                    let pre_selector =
13411                        err!(self.builder.build_extract_value(res, 1, "pre_selector"));
13412
13413                    // The pre-selector can be either 0 (for catch-all) or 1 (for a
13414                    // specific, but as-yet-unknown tag).
13415                    let pre_selector_is_zero = err!(self.builder.build_int_compare(
13416                        IntPredicate::EQ,
13417                        pre_selector.into_int_value(),
13418                        self.intrinsics.i32_zero,
13419                        "pre_selector_is_zero"
13420                    ));
13421                    err!(self.builder.build_conditional_branch(
13422                        pre_selector_is_zero,
13423                        catch_all_block,
13424                        catch_specific_block
13425                    ));
13426
13427                    self.builder.position_at_end(catch_all_block);
13428                    err!(self.builder.build_unconditional_branch(catch_end_block));
13429
13430                    self.builder.position_at_end(catch_specific_block);
13431                    let selector_value = self.build_call_with_param_attributes(
13432                        self.intrinsics.personality2,
13433                        &[self.ctx.basic().into(), uw_exc.into()],
13434                        "selector",
13435                    )?;
13436                    err!(self.builder.build_unconditional_branch(catch_end_block));
13437
13438                    self.builder.position_at_end(catch_end_block);
13439                    let selector = err!(self.builder.build_phi(self.intrinsics.i32_ty, "selector"));
13440                    selector.add_incoming(&[
13441                        (
13442                            &self
13443                                .intrinsics
13444                                .i32_ty
13445                                .const_int(CATCH_ALL_TAG_VALUE as u64, false),
13446                            catch_all_block,
13447                        ),
13448                        (
13449                            &selector_value
13450                                .try_as_basic_value()
13451                                .unwrap_basic()
13452                                .into_int_value(),
13453                            catch_specific_block,
13454                        ),
13455                    ]);
13456
13457                    // Now we're done looking at the exception, it's time to deallocate and get
13458                    // the exnref out of it. When an exception is caught, "rethrowing" simply
13459                    // means starting another unwind by calling _Unwind_RaiseException with the
13460                    // same exception bits. Instead of keeping the same exception around, we
13461                    // deallocate the exception once it's caught, and if we need to rethrow, we
13462                    // just re-allocate a new exception.
13463                    //
13464                    // Note that this is different from how it's done in C++ land, where the
13465                    // exception object is kept around for rethrowing; this discrepency exists
13466                    // because in C++, exception handling is lexical (i.e. there's an implicit
13467                    // "current exception" in catch blocks) whereas in WASM, you rethrow with
13468                    // an exnref that may very well have come from somewhere else; consider this
13469                    // (badly implemented and erroneous) pseudo-module:
13470                    //
13471                    // (module
13472                    //   (global $e (mut exnref) (ref.null exn))
13473                    //   ;; Store the given exnref, return the previous one
13474                    //   (func $delay_exnref (param exnref) (result exnref)
13475                    //     (global.get $e)
13476                    //     (local.get 0)
13477                    //     (global.set $e)
13478                    //   )
13479                    //   (func foo
13480                    //     (block $catch (result exnref)
13481                    //       (try_table (catch_all_ref $catch)
13482                    //         ...
13483                    //       )
13484                    //     )
13485                    //     (call $delay_exnref) ;; store the exnref caught above
13486                    //     throw_ref ;; throw the previous exnref
13487                    //   )
13488                    // )
13489                    //
13490                    // Here, it's impossible to reuse the same exception object since the
13491                    // exnref given to throw_ref is a different one than the one we caught
13492                    // with the try_table.
13493                    //
13494                    // Another difference is that C++ exceptions may well carry lots of data
13495                    // around; a WASM exception is just an exnref, backed by a u32, which is
13496                    // just 4 bytes, and is cheap to reallocate. C++ exceptions may also carry
13497                    // things with dtors around; another thing that doesn't exist in WASM.
13498                    //
13499                    // All of this is to say that putting exception deallocation and exnref
13500                    // retrieval in the same function has been a very deliberate choice.
13501                    let uw_exc = uw_exc.into_pointer_value();
13502                    let exnref = self.build_call_with_param_attributes(
13503                        self.intrinsics.exception_into_exnref,
13504                        &[uw_exc.into()],
13505                        "exnref",
13506                    )?;
13507
13508                    let exnref = exnref.try_as_basic_value().unwrap_basic().into_int_value();
13509                    let selector = selector.as_basic_value().into_int_value();
13510
13511                    for catch in catches.iter() {
13512                        match catch {
13513                            Catch::All { label } => {
13514                                let b = self
13515                                    .context
13516                                    .append_basic_block(self.function, "catch_all_clause");
13517                                self.builder.position_at_end(b);
13518                                let frame = self.state.frame_at_depth(*label)?;
13519
13520                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13521
13522                                self.builder.position_at_end(catch_end_block);
13523                                catch_blocks.push((b, None));
13524                            }
13525                            Catch::One { tag, label } => {
13526                                let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
13527                                let signature = &self.wasm_module.signatures[tag_idx];
13528                                let params = signature.params();
13529
13530                                let b = self.context.append_basic_block(
13531                                    self.function,
13532                                    format!("catch_one_clause_{tag}").as_str(),
13533                                );
13534                                self.builder.position_at_end(b);
13535
13536                                let exnref_phi = err!(
13537                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
13538                                );
13539                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
13540
13541                                // Get the payload pointer.
13542                                let exn_payload_ptr = err!(self.builder.build_direct_call(
13543                                    self.intrinsics.read_exnref,
13544                                    &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
13545                                    "exn_ptr",
13546                                ));
13547                                let exn_payload_ptr = exn_payload_ptr
13548                                    .try_as_basic_value()
13549                                    .unwrap_basic()
13550                                    .into_pointer_value();
13551
13552                                // Read each value from the data ptr.
13553                                let values = params
13554                                    .iter()
13555                                    .enumerate()
13556                                    .map(|(i, v)| {
13557                                        let name = format!("value_{i}");
13558                                        let ptr = err!(unsafe {
13559                                            self.builder.build_gep(
13560                                                self.intrinsics.i128_ty,
13561                                                exn_payload_ptr,
13562                                                &[self
13563                                                    .intrinsics
13564                                                    .i32_ty
13565                                                    .const_int(i as u64, false)],
13566                                                format!("{name}_ptr").as_str(),
13567                                            )
13568                                        });
13569                                        err_nt!(self.builder.build_load(
13570                                            type_to_llvm(self.intrinsics, *v)?,
13571                                            ptr,
13572                                            &name,
13573                                        ))
13574                                    })
13575                                    .collect::<Result<Vec<_>, CompileError>>()?;
13576
13577                                let frame = self.state.frame_at_depth(*label)?;
13578
13579                                for (phi, value) in frame.phis().iter().zip(values.iter()) {
13580                                    phi.add_incoming(&[(value, b)])
13581                                }
13582
13583                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13584
13585                                self.builder.position_at_end(catch_end_block);
13586                                catch_blocks.push((b, Some(exnref_phi)));
13587                            }
13588                            Catch::OneRef { label, tag } => {
13589                                let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
13590                                let signature = &self.wasm_module.signatures[tag_idx];
13591                                let params = signature.params();
13592
13593                                let b = self.context.append_basic_block(
13594                                    self.function,
13595                                    format!("catch_one_ref_clause_{tag}").as_str(),
13596                                );
13597                                self.builder.position_at_end(b);
13598
13599                                let exnref_phi = err!(
13600                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
13601                                );
13602                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
13603
13604                                // Get the payload pointer.
13605                                let exn_payload_ptr = err!(self.builder.build_direct_call(
13606                                    self.intrinsics.read_exnref,
13607                                    &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
13608                                    "exn_ptr",
13609                                ));
13610                                let exn_payload_ptr = exn_payload_ptr
13611                                    .try_as_basic_value()
13612                                    .unwrap_basic()
13613                                    .into_pointer_value();
13614
13615                                // Read each value from the data ptr.
13616                                let mut values = params
13617                                    .iter()
13618                                    .enumerate()
13619                                    .map(|(i, v)| {
13620                                        let name = format!("value_{i}");
13621                                        let ptr = err!(unsafe {
13622                                            self.builder.build_gep(
13623                                                self.intrinsics.i128_ty,
13624                                                exn_payload_ptr,
13625                                                &[self
13626                                                    .intrinsics
13627                                                    .i32_ty
13628                                                    .const_int(i as u64, false)],
13629                                                format!("{name}_ptr").as_str(),
13630                                            )
13631                                        });
13632                                        err_nt!(self.builder.build_load(
13633                                            type_to_llvm(self.intrinsics, *v)?,
13634                                            ptr,
13635                                            &name,
13636                                        ))
13637                                    })
13638                                    .collect::<Result<Vec<_>, CompileError>>()?;
13639
13640                                values.push(exnref_phi.as_basic_value());
13641
13642                                let frame = self.state.frame_at_depth(*label)?;
13643
13644                                for (phi, value) in frame.phis().iter().zip(values.iter()) {
13645                                    phi.add_incoming(&[(value, b)])
13646                                }
13647
13648                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13649
13650                                self.builder.position_at_end(catch_end_block);
13651                                catch_blocks.push((b, Some(exnref_phi)));
13652                            }
13653                            Catch::AllRef { label } => {
13654                                let b = self
13655                                    .context
13656                                    .append_basic_block(self.function, "catch_all_ref_clause");
13657                                self.builder.position_at_end(b);
13658
13659                                let exnref_phi = err!(
13660                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
13661                                );
13662                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
13663
13664                                let frame = self.state.frame_at_depth(*label)?;
13665
13666                                let phis = frame.phis();
13667
13668                                assert_eq!(phis.len(), 1);
13669                                phis[0].add_incoming(&[(&exnref_phi.as_basic_value(), b)]);
13670
13671                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13672
13673                                self.builder.position_at_end(catch_end_block);
13674                                catch_blocks.push((b, Some(exnref_phi)));
13675                            }
13676                        }
13677                    }
13678
13679                    for catch_info in &outer_catch_blocks {
13680                        if let Some(phi) = catch_info.exnref_phi {
13681                            phi.add_incoming(&[(&exnref, catch_end_block)]);
13682                        }
13683                    }
13684
13685                    err!(
13686                        self.builder.build_switch(
13687                            selector,
13688                            rethrow_block,
13689                            catch_blocks
13690                                .iter()
13691                                .enumerate()
13692                                .map(|(i, v)| (
13693                                    self.intrinsics
13694                                        .i32_ty
13695                                        .const_int(catch_tag_values[i] as _, false),
13696                                    v.0
13697                                ))
13698                                .chain(outer_catch_blocks.iter().map(|catch_info| (
13699                                    self.intrinsics.i32_ty.const_int(catch_info.tag as _, false),
13700                                    catch_info.catch_block
13701                                )))
13702                                .collect::<Vec<_>>()
13703                                .as_slice()
13704                        )
13705                    );
13706
13707                    // -- end
13708
13709                    // -- The rethrow block
13710                    self.builder.position_at_end(rethrow_block);
13711
13712                    self.build_call_with_param_attributes(
13713                        self.intrinsics.throw,
13714                        &[self.ctx.basic().into(), exnref.into()],
13715                        "rethrow",
13716                    )?;
13717                    // can't reach after an explicit throw!
13718                    err!(self.builder.build_unreachable());
13719
13720                    maybe_lpad_block = Some(lpad_block);
13721                }
13722
13723                // Move back to current block
13724                self.builder.position_at_end(current_block);
13725
13726                // Note: catch_tag_values also containes outer tags, but zipping with
13727                // catch_blocks will let us ignore the extra ones.
13728                let catch_tags_and_blocks = catch_tag_values
13729                    .into_iter()
13730                    .zip(catch_blocks)
13731                    .map(|(tag, (block, exnref_phi))| TagCatchInfo {
13732                        tag,
13733                        catch_block: block,
13734                        exnref_phi,
13735                    })
13736                    .collect::<Vec<_>>();
13737                self.state.push_landingpad(
13738                    maybe_lpad_block,
13739                    end_block,
13740                    end_phis,
13741                    &catch_tags_and_blocks,
13742                    self.module_translation
13743                        .blocktype_params_results(&try_table.ty)?
13744                        .0
13745                        .len(),
13746                );
13747            }
13748            Operator::Throw { tag_index } => {
13749                let current_block = self
13750                    .builder
13751                    .get_insert_block()
13752                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
13753
13754                let sig_index = self.wasm_module.tags[TagIndex::from_u32(tag_index)];
13755                let signature = &self.wasm_module.signatures[sig_index];
13756                let params = signature.params();
13757                let values = self.state.popn_save_extra(params.len())?;
13758
13759                values.iter().enumerate().try_for_each(|(i, (v, _))| {
13760                    let t = type_to_llvm(self.intrinsics, params[i])?;
13761                    if t != v.get_type() {
13762                        return Err(CompileError::Codegen(format!(
13763                            "Incompatible types: {:?} != {:?}",
13764                            t,
13765                            v.get_type()
13766                        )));
13767                    }
13768
13769                    Ok(())
13770                })?;
13771
13772                // Allocate the necessary bytes for the exception.
13773                let exnref = err!(
13774                    self.builder.build_direct_call(
13775                        self.intrinsics.alloc_exception,
13776                        &[
13777                            self.ctx.basic().into(),
13778                            self.intrinsics
13779                                .i32_ty
13780                                .const_int(tag_index as _, false)
13781                                .into()
13782                        ],
13783                        "exnref",
13784                    )
13785                );
13786                let exnref = exnref.try_as_basic_value().unwrap_basic();
13787
13788                let exn_payload_ptr = err!(self.builder.build_direct_call(
13789                    self.intrinsics.read_exnref,
13790                    &[self.ctx.basic().into(), exnref.into()],
13791                    "exn_ptr",
13792                ));
13793                let exn_payload_ptr = exn_payload_ptr
13794                    .try_as_basic_value()
13795                    .unwrap_basic()
13796                    .into_pointer_value();
13797
13798                for (i, value) in values.into_iter().enumerate() {
13799                    let ptr = err!(unsafe {
13800                        self.builder.build_gep(
13801                            self.intrinsics.i128_ty,
13802                            exn_payload_ptr,
13803                            &[self.intrinsics.i32_ty.const_int(i as u64, false)],
13804                            format!("value_{i}_ptr").as_str(),
13805                        )
13806                    });
13807                    err!(self.builder.build_store(ptr, value.0));
13808                }
13809
13810                if let Some(pad) = self.state.get_innermost_landingpad() {
13811                    let unreachable_block = self
13812                        .context
13813                        .append_basic_block(self.function, "_throw_unreachable");
13814
13815                    err!(self.builder.build_invoke(
13816                        self.intrinsics.throw,
13817                        &[self.ctx.basic(), exnref],
13818                        unreachable_block,
13819                        pad,
13820                        "throw",
13821                    ));
13822
13823                    self.builder.position_at_end(unreachable_block);
13824                    // can't reach after an explicit throw!
13825                    err!(self.builder.build_unreachable());
13826
13827                    self.builder.position_at_end(current_block);
13828                } else {
13829                    self.build_call_with_param_attributes(
13830                        self.intrinsics.throw,
13831                        &[self.ctx.basic().into(), exnref.into()],
13832                        "throw",
13833                    )?;
13834                    // can't reach after an explicit throw!
13835                    err!(self.builder.build_unreachable());
13836                }
13837
13838                self.state.reachable = false;
13839            }
13840            Operator::ThrowRef => {
13841                let current_block = self
13842                    .builder
13843                    .get_insert_block()
13844                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
13845
13846                let exnref = self.state.pop1()?;
13847
13848                if let Some(pad) = self.state.get_innermost_landingpad() {
13849                    let unreachable_block = self
13850                        .context
13851                        .append_basic_block(self.function, "_rethrow_unreachable");
13852
13853                    err!(self.builder.build_invoke(
13854                        self.intrinsics.throw,
13855                        &[self.ctx.basic(), exnref],
13856                        unreachable_block,
13857                        pad,
13858                        "throw",
13859                    ));
13860
13861                    self.builder.position_at_end(unreachable_block);
13862                    // can't reach after an explicit throw!
13863                    err!(self.builder.build_unreachable());
13864
13865                    self.builder.position_at_end(current_block);
13866                } else {
13867                    self.build_call_with_param_attributes(
13868                        self.intrinsics.throw,
13869                        &[self.ctx.basic().into(), exnref.into()],
13870                        "throw",
13871                    )?;
13872                    // can't reach after an explicit throw!
13873                    err!(self.builder.build_unreachable());
13874                }
13875
13876                self.state.reachable = false;
13877            }
13878            Operator::I64Add128 | Operator::I64Sub128 => {
13879                let (rhs_hi, rhs_hi_info) = self.state.pop1_extra()?;
13880                let (rhs_lo, rhs_lo_info) = self.state.pop1_extra()?;
13881                let (lhs_hi, lhs_hi_info) = self.state.pop1_extra()?;
13882                let (lhs_lo, lhs_lo_info) = self.state.pop1_extra()?;
13883
13884                let lhs_lo = self
13885                    .apply_pending_canonicalization(lhs_lo, lhs_lo_info)?
13886                    .into_int_value();
13887                let lhs_hi = self
13888                    .apply_pending_canonicalization(lhs_hi, lhs_hi_info)?
13889                    .into_int_value();
13890                let rhs_lo = self
13891                    .apply_pending_canonicalization(rhs_lo, rhs_lo_info)?
13892                    .into_int_value();
13893                let rhs_hi = self
13894                    .apply_pending_canonicalization(rhs_hi, rhs_hi_info)?
13895                    .into_int_value();
13896
13897                let idx0 = self.intrinsics.i32_ty.const_zero();
13898                let idx1 = self.intrinsics.i32_ty.const_int(1, false);
13899
13900                let lhs = self.intrinsics.i64x2_ty.get_undef();
13901                let lhs = err!(self.builder.build_insert_element(lhs, lhs_lo, idx0, ""));
13902                let lhs = err!(self.builder.build_insert_element(lhs, lhs_hi, idx1, ""));
13903                let lhs = err!(
13904                    self.builder
13905                        .build_bit_cast(lhs, self.intrinsics.i128_ty, "a")
13906                )
13907                .into_int_value();
13908
13909                let rhs = self.intrinsics.i64x2_ty.get_undef();
13910                let rhs = err!(self.builder.build_insert_element(rhs, rhs_lo, idx0, ""));
13911                let rhs = err!(self.builder.build_insert_element(rhs, rhs_hi, idx1, ""));
13912                let rhs = err!(
13913                    self.builder
13914                        .build_bit_cast(rhs, self.intrinsics.i128_ty, "b")
13915                )
13916                .into_int_value();
13917
13918                let result = err!(match op {
13919                    Operator::I64Add128 => self.builder.build_int_add(lhs, rhs, ""),
13920                    Operator::I64Sub128 => self.builder.build_int_sub(lhs, rhs, ""),
13921                    _ => unreachable!(),
13922                });
13923                let result = err!(self.builder.build_bit_cast(
13924                    result,
13925                    self.intrinsics.i64x2_ty,
13926                    ""
13927                ))
13928                .into_vector_value();
13929                let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
13930                let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
13931
13932                self.state.push1(result_lo);
13933                self.state.push1(result_hi);
13934            }
13935            Operator::I64MulWideS | Operator::I64MulWideU => {
13936                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
13937                let lhs = self
13938                    .apply_pending_canonicalization(lhs, lhs_info)?
13939                    .into_int_value();
13940                let rhs = self
13941                    .apply_pending_canonicalization(rhs, rhs_info)?
13942                    .into_int_value();
13943
13944                let lhs = err!(match op {
13945                    Operator::I64MulWideS => {
13946                        self.builder
13947                            .build_int_s_extend(lhs, self.intrinsics.i128_ty, "a")
13948                    }
13949                    Operator::I64MulWideU => {
13950                        self.builder
13951                            .build_int_z_extend(lhs, self.intrinsics.i128_ty, "a")
13952                    }
13953                    _ => unreachable!(),
13954                });
13955                let rhs = err!(match op {
13956                    Operator::I64MulWideS => {
13957                        self.builder
13958                            .build_int_s_extend(rhs, self.intrinsics.i128_ty, "b")
13959                    }
13960                    Operator::I64MulWideU => {
13961                        self.builder
13962                            .build_int_z_extend(rhs, self.intrinsics.i128_ty, "b")
13963                    }
13964                    _ => unreachable!(),
13965                });
13966
13967                let result = err!(self.builder.build_int_mul(lhs, rhs, ""));
13968                let result = err!(self.builder.build_bit_cast(
13969                    result,
13970                    self.intrinsics.i64x2_ty,
13971                    ""
13972                ))
13973                .into_vector_value();
13974                let idx0 = self.intrinsics.i32_ty.const_zero();
13975                let idx1 = self.intrinsics.i32_ty.const_int(1, false);
13976                let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
13977                let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
13978
13979                self.state.push1(result_lo);
13980                self.state.push1(result_hi);
13981            }
13982            _ => {
13983                return Err(CompileError::Codegen(format!(
13984                    "Operator {op:?} unimplemented",
13985                )));
13986            }
13987        }
13988
13989        Ok(())
13990    }
13991
13992    fn build_call_with_param_attributes(
13993        &self,
13994        function: FunctionValue<'ctx>,
13995        args: &[BasicMetadataValueEnum<'ctx>],
13996        name: &str,
13997    ) -> Result<CallSiteValue<'ctx>, CompileError> {
13998        let call = self
13999            .builder
14000            .build_call(function, args, name)
14001            .map_err(|e| CompileError::Codegen(e.to_string()))?;
14002
14003        // https://five-embeddev.com/riscv-user-isa-manual/Priv-v1.12/rv64.html
14004        // > The compiler and calling convention maintain an invariant that all 32-bit values are held in a sign-extended format in 64-bit registers.
14005        // > Even 32-bit unsigned integers extend bit 31 into bits 63 through 32. Consequently, conversion between unsigned and signed 32-bit integers
14006        // > is a no-op, as is conversion from a signed 32-bit integer to a signed 64-bit integer.
14007        if matches!(
14008            self.target_triple.architecture,
14009            Architecture::Riscv32(..) | Architecture::Riscv64(..)
14010        ) {
14011            let param_types = function.get_type().get_param_types();
14012            for (i, ty) in param_types.into_iter().enumerate() {
14013                if ty == self.context.i32_type().into() {
14014                    call.add_attribute(
14015                        AttributeLoc::Param(i as u32),
14016                        self.context
14017                            .create_enum_attribute(Attribute::get_named_enum_kind_id("signext"), 0),
14018                    );
14019                    call.add_attribute(
14020                        AttributeLoc::Param(i as u32),
14021                        self.context
14022                            .create_enum_attribute(Attribute::get_named_enum_kind_id("noundef"), 0),
14023                    );
14024                }
14025            }
14026        }
14027
14028        Ok(call)
14029    }
14030}
14031
14032fn is_f32_arithmetic(bits: u32) -> bool {
14033    // Mask off sign bit.
14034    let bits = bits & 0x7FFF_FFFF;
14035    bits < 0x7FC0_0000
14036}
14037
14038fn is_f64_arithmetic(bits: u64) -> bool {
14039    // Mask off sign bit.
14040    let bits = bits & 0x7FFF_FFFF_FFFF_FFFF;
14041    bits < 0x7FF8_0000_0000_0000
14042}