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;
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, PhiValue, PointerValue,
24        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, 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_machine: TargetMachine,
75    target_machine_no_opt: Option<TargetMachine>,
76    abi: Box<dyn Abi>,
77    binary_fmt: BinaryFormat,
78    func_section: String,
79    pointer_width: u8,
80    cpu_features: EnumSet<CpuFeature>,
81    non_volatile_memory_ops: bool,
82}
83
84impl wasmer_compiler::FuncTranslator for FuncTranslator {}
85
86impl FuncTranslator {
87    pub fn new(
88        target_triple: Triple,
89        target_machine: TargetMachine,
90        target_machine_no_opt: Option<TargetMachine>,
91        binary_fmt: BinaryFormat,
92        pointer_width: u8,
93        cpu_features: EnumSet<CpuFeature>,
94        non_volatile_memory_ops: bool,
95    ) -> Result<Self, CompileError> {
96        let abi = get_abi(&target_machine);
97        Ok(Self {
98            ctx: Context::create(),
99            target_triple,
100            target_machine,
101            target_machine_no_opt,
102            abi,
103            func_section: match binary_fmt {
104                BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
105                BinaryFormat::Macho => FUNCTION_SEGMENT_MACHO.to_string(),
106                _ => {
107                    return Err(CompileError::UnsupportedTarget(format!(
108                        "Unsupported binary format: {binary_fmt:?}"
109                    )));
110                }
111            },
112            binary_fmt,
113            pointer_width,
114            cpu_features,
115            non_volatile_memory_ops,
116        })
117    }
118
119    #[allow(clippy::too_many_arguments)]
120    pub fn translate_to_module(
121        &self,
122        wasm_module: &ModuleInfo,
123        module_translation: &ModuleTranslationState,
124        local_func_index: &LocalFunctionIndex,
125        function_body: &FunctionBodyData,
126        config: &LLVM,
127        memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
128        _table_styles: &PrimaryMap<TableIndex, TableStyle>,
129        symbol_registry: &dyn SymbolRegistry,
130        target: &Triple,
131    ) -> Result<Module<'_>, CompileError> {
132        // The function type, used for the callbacks.
133        let func_index = wasm_module.func_index(*local_func_index);
134        let function =
135            CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
136        let function_name =
137            symbol_registry.symbol_to_name(Symbol::LocalFunction(*local_func_index));
138
139        // We can pass and use the heap pointer (memory #0) only and only if the memory static, that means
140        // the allocated heap is never moved to a different location.
141        let m0_is_enabled = memory_styles
142            .get(MemoryIndex::from_u32(0))
143            .is_some_and(|memory| matches!(memory, MemoryStyle::Static { .. }));
144
145        let module_name = match wasm_module.name.as_ref() {
146            None => format!("<anonymous module> function {function_name}"),
147            Some(module_name) => format!("module {module_name} function {function_name}"),
148        };
149        let module = self.ctx.create_module(module_name.as_str());
150
151        let target_machine = &self.target_machine;
152        let target_triple = target_machine.get_triple();
153        let target_data = target_machine.get_target_data();
154        module.set_triple(&target_triple);
155        module.set_data_layout(&target_data.get_data_layout());
156        let wasm_fn_type = wasm_module
157            .signatures
158            .get(wasm_module.functions[func_index])
159            .unwrap();
160
161        let offsets = VMOffsets::new(self.pointer_width, wasm_module);
162        let intrinsics = Intrinsics::declare(
163            &module,
164            &self.ctx,
165            &target_data,
166            &self.target_triple,
167            &self.binary_fmt,
168        );
169        let (func_type, func_attrs) = self.abi.func_type_to_llvm(
170            &self.ctx,
171            &intrinsics,
172            Some(&offsets),
173            wasm_fn_type,
174            m0_is_enabled,
175        )?;
176
177        let func = module.add_function(&function_name, func_type, Some(Linkage::External));
178        for (attr, attr_loc) in &func_attrs {
179            func.add_attribute(*attr_loc, *attr);
180        }
181
182        if !matches!(target.operating_system, OperatingSystem::Windows) {
183            func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe);
184        }
185
186        func.add_attribute(AttributeLoc::Function, intrinsics.uwtable);
187        func.add_attribute(AttributeLoc::Function, intrinsics.frame_pointer);
188
189        let section = match self.binary_fmt {
190            BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
191            BinaryFormat::Macho => {
192                format!("{FUNCTION_SECTION_MACHO},{FUNCTION_SEGMENT_MACHO}")
193            }
194            _ => {
195                return Err(CompileError::UnsupportedTarget(format!(
196                    "Unsupported binary format: {:?}",
197                    self.binary_fmt
198                )));
199            }
200        };
201
202        func.set_personality_function(intrinsics.personality);
203        func.as_global_value().set_section(Some(&section));
204
205        func.set_linkage(Linkage::DLLExport);
206        func.as_global_value()
207            .set_dll_storage_class(DLLStorageClass::Export);
208
209        let entry = self.ctx.append_basic_block(func, "entry");
210        let start_of_code = self.ctx.append_basic_block(func, "start_of_code");
211        let return_ = self.ctx.append_basic_block(func, "return");
212        let alloca_builder = self.ctx.create_builder();
213        let cache_builder = self.ctx.create_builder();
214        let builder = self.ctx.create_builder();
215        cache_builder.position_at_end(entry);
216        let br = err!(cache_builder.build_unconditional_branch(start_of_code));
217        alloca_builder.position_before(&br);
218        cache_builder.position_before(&br);
219        builder.position_at_end(start_of_code);
220
221        let mut state = State::new();
222        builder.position_at_end(return_);
223        let phis: SmallVec<[PhiValue; 1]> = wasm_fn_type
224            .results()
225            .iter()
226            .map(|&wasm_ty| {
227                type_to_llvm(&intrinsics, wasm_ty).map(|ty| builder.build_phi(ty, "").unwrap())
228            })
229            .collect::<Result<_, _>>()?;
230        state.push_block(return_, phis, 0);
231        builder.position_at_end(start_of_code);
232
233        let mut reader = MiddlewareBinaryReader::new_with_offset(
234            function_body.data,
235            function_body.module_offset,
236        );
237        reader.set_middleware_chain(
238            config
239                .middlewares
240                .generate_function_middleware_chain(*local_func_index),
241        );
242
243        let mut params = vec![];
244        let first_param =
245            if func_type.get_return_type().is_none() && wasm_fn_type.results().len() > 1 {
246                if m0_is_enabled { 3 } else { 2 }
247            } else if m0_is_enabled {
248                2
249            } else {
250                1
251            };
252        let mut is_first_alloca = true;
253        let mut insert_alloca = |ty, name: String| -> Result<PointerValue, CompileError> {
254            let alloca = err!(alloca_builder.build_alloca(ty, &name));
255            if is_first_alloca {
256                alloca_builder.position_at(entry, &alloca.as_instruction_value().unwrap());
257                is_first_alloca = false;
258            }
259            Ok(alloca)
260        };
261
262        // Uncomment to print, at the start of the function, the function name.
263        // (poor man's debugger!)
264        //let func_name_str =
265        //    err!(alloca_builder.build_global_string_ptr(&function_name, "function_name"));
266        //
267        //_ = alloca_builder.build_call(
268        //    intrinsics.debug_str,
269        //    &[
270        //        func_name_str.as_pointer_value().into(),
271        //        intrinsics
272        //            .i32_ty
273        //            .const_int(function_name.len() as _, false)
274        //            .into(),
275        //    ],
276        //    "",
277        //);
278
279        for idx in 0..wasm_fn_type.params().len() {
280            let ty = wasm_fn_type.params()[idx];
281            let ty = type_to_llvm(&intrinsics, ty)?;
282            let value = func
283                .get_nth_param((idx as u32).checked_add(first_param).unwrap())
284                .unwrap();
285            let alloca = insert_alloca(ty, format!("param_{idx}"))?;
286            err!(cache_builder.build_store(alloca, value));
287            params.push((ty, alloca));
288        }
289
290        let mut locals = vec![];
291        let num_locals = reader.read_local_count()?;
292        for idx in 0..num_locals {
293            let (count, ty) = reader.read_local_decl()?;
294            let ty = err!(wptype_to_type(ty));
295            let ty = type_to_llvm(&intrinsics, ty)?;
296            for _ in 0..count {
297                let alloca = insert_alloca(ty, format!("local_{idx}"))?;
298                err!(cache_builder.build_store(alloca, ty.const_zero()));
299                locals.push((ty, alloca));
300            }
301        }
302
303        let mut params_locals = params.clone();
304        params_locals.extend(locals.iter().cloned());
305
306        let mut m0_param = None;
307
308        if m0_is_enabled {
309            let m0 = self.abi.get_m0_ptr_param(&func);
310            m0.set_name("m0_base_ptr");
311            m0_param = Some(m0);
312        }
313
314        let mut fcg = LLVMFunctionCodeGenerator {
315            m0_param,
316            context: &self.ctx,
317            builder,
318            alloca_builder,
319            intrinsics: &intrinsics,
320            state,
321            function: func,
322            locals: params_locals,
323            ctx: CtxType::new(
324                wasm_module,
325                &func,
326                &cache_builder,
327                &*self.abi,
328                self.pointer_width,
329                m0_param,
330            ),
331            unreachable_depth: 0,
332            memory_styles,
333            _table_styles,
334            module: &module,
335            module_translation,
336            wasm_module,
337            symbol_registry,
338            abi: &*self.abi,
339            config,
340            target_triple: self.target_triple.clone(),
341            tags_cache: HashMap::new(),
342            binary_fmt: self.binary_fmt,
343            cpu_features: self.cpu_features,
344            non_volatile_memory_ops: self.non_volatile_memory_ops,
345        };
346
347        fcg.ctx.add_func(
348            func_index,
349            func.as_global_value().as_pointer_value(),
350            func_type,
351            fcg.ctx.basic(),
352            &func_attrs,
353        );
354
355        while fcg.state.has_control_frames() {
356            let pos = reader.current_position() as u32;
357            let op = reader.read_operator()?;
358            fcg.translate_operator(op, pos)?;
359        }
360
361        fcg.finalize(wasm_fn_type)?;
362
363        if let Some(ref callbacks) = config.callbacks {
364            callbacks.preopt_ir(&function, &wasm_module.hash_string(), &module);
365        }
366
367        let mut passes = vec![];
368
369        if config.enable_verifier {
370            passes.push("verify");
371        }
372
373        passes.push("sccp");
374        passes.push("early-cse");
375        //passes.push("deadargelim");
376        passes.push("adce");
377        passes.push("sroa");
378        passes.push("aggressive-instcombine");
379        passes.push("jump-threading");
380        //passes.push("ipsccp");
381        passes.push("simplifycfg");
382        passes.push("reassociate");
383        passes.push("loop-rotate");
384        passes.push("indvars");
385        //passes.push("lcssa");
386        //passes.push("licm");
387        //passes.push("instcombine");
388        passes.push("sccp");
389        passes.push("reassociate");
390        passes.push("simplifycfg");
391        passes.push("gvn");
392        passes.push("memcpyopt");
393        passes.push("dse");
394        passes.push("dce");
395        //passes.push("instcombine");
396        passes.push("reassociate");
397        passes.push("simplifycfg");
398        passes.push("mem2reg");
399
400        module
401            .run_passes(
402                passes.join(",").as_str(),
403                target_machine,
404                PassBuilderOptions::create(),
405            )
406            .unwrap();
407
408        if let Some(ref callbacks) = config.callbacks {
409            callbacks.postopt_ir(&function, &wasm_module.hash_string(), &module);
410        }
411
412        Ok(module)
413    }
414
415    #[allow(clippy::too_many_arguments)]
416    pub fn translate(
417        &self,
418        wasm_module: &ModuleInfo,
419        module_translation: &ModuleTranslationState,
420        local_func_index: &LocalFunctionIndex,
421        function_body: &FunctionBodyData,
422        config: &LLVM,
423        memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
424        table_styles: &PrimaryMap<TableIndex, TableStyle>,
425        symbol_registry: &ModuleBasedSymbolRegistry,
426        target: &Triple,
427    ) -> Result<CompiledFunction, CompileError> {
428        let module = self.translate_to_module(
429            wasm_module,
430            module_translation,
431            local_func_index,
432            function_body,
433            config,
434            memory_styles,
435            table_styles,
436            symbol_registry,
437            target,
438        )?;
439        let function = CompiledKind::Local(
440            *local_func_index,
441            wasm_module.get_function_name(wasm_module.func_index(*local_func_index)),
442        );
443
444        let target_machine = if function_body.data.len() as u64 > WASM_LARGE_FUNCTION_THRESHOLD {
445            self.target_machine_no_opt
446                .as_ref()
447                .unwrap_or(&self.target_machine)
448        } else {
449            &self.target_machine
450        };
451        let memory_buffer = target_machine
452            .write_to_memory_buffer(&module, FileType::Object)
453            .unwrap();
454
455        if let Some(ref callbacks) = config.callbacks {
456            let module_hash = wasm_module.hash().map(|m| m.to_string());
457            callbacks.obj_memory_buffer(&function, &module_hash, &memory_buffer);
458            let asm_buffer = target_machine
459                .write_to_memory_buffer(&module, FileType::Assembly)
460                .unwrap();
461            callbacks.asm_memory_buffer(&function, &module_hash, &asm_buffer)
462        }
463
464        let mem_buf_slice = memory_buffer.as_slice();
465
466        load_object_file(
467            mem_buf_slice,
468            &self.func_section,
469            RelocationTarget::LocalFunc(*local_func_index),
470            |name: &str| {
471                Ok({
472                    let name = if matches!(self.binary_fmt, BinaryFormat::Macho) {
473                        if name.starts_with("_") {
474                            name.replacen("_", "", 1)
475                        } else {
476                            name.to_string()
477                        }
478                    } else {
479                        name.to_string()
480                    };
481                    if let Some(Symbol::LocalFunction(local_func_index)) =
482                        symbol_registry.name_to_symbol(&name)
483                    {
484                        Some(RelocationTarget::LocalFunc(local_func_index))
485                    } else {
486                        None
487                    }
488                })
489            },
490            self.binary_fmt,
491        )
492    }
493}
494
495impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
496    // Create a vector where each lane contains the same value.
497    fn splat_vector(
498        &self,
499        value: BasicValueEnum<'ctx>,
500        vec_ty: VectorType<'ctx>,
501    ) -> Result<VectorValue<'ctx>, CompileError> {
502        // Use insert_element to insert the element into an undef vector, then use
503        // shuffle vector to copy that lane to all lanes.
504        err_nt!(
505            self.builder.build_shuffle_vector(
506                err!(self.builder.build_insert_element(
507                    vec_ty.get_undef(),
508                    value,
509                    self.intrinsics.i32_zero,
510                    "",
511                )),
512                vec_ty.get_undef(),
513                self.intrinsics
514                    .i32_ty
515                    .vec_type(vec_ty.get_size())
516                    .const_zero(),
517                "",
518            )
519        )
520    }
521
522    // Convert floating point vector to integer and saturate when out of range.
523    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
524    #[allow(clippy::too_many_arguments)]
525    fn trunc_sat<T: FloatMathType<'ctx>>(
526        &self,
527        fvec_ty: T,
528        ivec_ty: T::MathConvType,
529        lower_bound: u64, // Exclusive (least representable value)
530        upper_bound: u64, // Exclusive (greatest representable value)
531        int_min_value: u64,
532        int_max_value: u64,
533        value: IntValue<'ctx>,
534    ) -> Result<VectorValue<'ctx>, CompileError> {
535        // a) Compare vector with itself to identify NaN lanes.
536        // b) Compare vector with splat of inttofp(upper_bound) to identify
537        //    lanes that need to saturate to max.
538        // c) Compare vector with splat of inttofp(lower_bound) to identify
539        //    lanes that need to saturate to min.
540        // d) Use vector select (not shuffle) to pick from either the
541        //    splat vector or the input vector depending on whether the
542        //    comparison indicates that we have an unrepresentable value. Replace
543        //    unrepresentable values with zero.
544        // e) Now that the value is safe, fpto[su]i it.
545        // f) Use our previous comparison results to replace certain zeros with
546        //    int_min or int_max.
547
548        let fvec_ty = fvec_ty.as_basic_type_enum().into_vector_type();
549        let ivec_ty = ivec_ty.as_basic_type_enum().into_vector_type();
550        let fvec_element_ty = fvec_ty.get_element_type().into_float_type();
551        let ivec_element_ty = ivec_ty.get_element_type().into_int_type();
552
553        let is_signed = int_min_value != 0;
554        let int_min_value = self.splat_vector(
555            ivec_element_ty
556                .const_int(int_min_value, is_signed)
557                .as_basic_value_enum(),
558            ivec_ty,
559        )?;
560        let int_max_value = self.splat_vector(
561            ivec_element_ty
562                .const_int(int_max_value, is_signed)
563                .as_basic_value_enum(),
564            ivec_ty,
565        )?;
566        let lower_bound = if is_signed {
567            err!(self.builder.build_signed_int_to_float(
568                ivec_element_ty.const_int(lower_bound, is_signed),
569                fvec_element_ty,
570                "",
571            ))
572        } else {
573            err!(self.builder.build_unsigned_int_to_float(
574                ivec_element_ty.const_int(lower_bound, is_signed),
575                fvec_element_ty,
576                "",
577            ))
578        };
579        let upper_bound = if is_signed {
580            err!(self.builder.build_signed_int_to_float(
581                ivec_element_ty.const_int(upper_bound, is_signed),
582                fvec_element_ty,
583                "",
584            ))
585        } else {
586            err!(self.builder.build_unsigned_int_to_float(
587                ivec_element_ty.const_int(upper_bound, is_signed),
588                fvec_element_ty,
589                "",
590            ))
591        };
592
593        let value = err!(self.builder.build_bit_cast(value, fvec_ty, "")).into_vector_value();
594        let zero = fvec_ty.const_zero();
595        let lower_bound = self.splat_vector(lower_bound.as_basic_value_enum(), fvec_ty)?;
596        let upper_bound = self.splat_vector(upper_bound.as_basic_value_enum(), fvec_ty)?;
597        let nan_cmp =
598            err!(
599                self.builder
600                    .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
601            );
602        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
603            FloatPredicate::OGT,
604            value,
605            upper_bound,
606            "above_upper_bound",
607        ));
608        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
609            FloatPredicate::OLT,
610            value,
611            lower_bound,
612            "below_lower_bound",
613        ));
614        let not_representable = err!(self.builder.build_or(
615            err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
616            below_lower_bound_cmp,
617            "not_representable_as_int",
618        ));
619        let value =
620            err!(
621                self.builder
622                    .build_select(not_representable, zero, value, "safe_to_convert")
623            )
624            .into_vector_value();
625        let value = if is_signed {
626            self.builder
627                .build_float_to_signed_int(value, ivec_ty, "as_int")
628        } else {
629            self.builder
630                .build_float_to_unsigned_int(value, ivec_ty, "as_int")
631        };
632
633        let value = err!(value);
634        let value =
635            err!(
636                self.builder
637                    .build_select(above_upper_bound_cmp, int_max_value, value, "")
638            )
639            .into_vector_value();
640        err_nt!(
641            self.builder
642                .build_select(below_lower_bound_cmp, int_min_value, value, "")
643                .map(|v| v.into_vector_value())
644        )
645    }
646
647    // Convert floating point vector to integer and saturate when out of range.
648    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
649    #[allow(clippy::too_many_arguments)]
650    fn trunc_sat_into_int<T: FloatMathType<'ctx>>(
651        &self,
652        fvec_ty: T,
653        ivec_ty: T::MathConvType,
654        lower_bound: u64, // Exclusive (least representable value)
655        upper_bound: u64, // Exclusive (greatest representable value)
656        int_min_value: u64,
657        int_max_value: u64,
658        value: IntValue<'ctx>,
659    ) -> Result<IntValue<'ctx>, CompileError> {
660        let res = self.trunc_sat(
661            fvec_ty,
662            ivec_ty,
663            lower_bound,
664            upper_bound,
665            int_min_value,
666            int_max_value,
667            value,
668        )?;
669        err_nt!(
670            self.builder
671                .build_bit_cast(res, self.intrinsics.i128_ty, "")
672                .map(|v| v.into_int_value())
673        )
674    }
675
676    // Convert floating point vector to integer and saturate when out of range.
677    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
678    fn trunc_sat_scalar(
679        &self,
680        int_ty: IntType<'ctx>,
681        lower_bound: u64, // Exclusive (least representable value)
682        upper_bound: u64, // Exclusive (greatest representable value)
683        int_min_value: u64,
684        int_max_value: u64,
685        value: FloatValue<'ctx>,
686    ) -> Result<IntValue<'ctx>, CompileError> {
687        // TODO: this is a scalarized version of the process in trunc_sat. Either
688        // we should merge with trunc_sat, or we should simplify this function.
689
690        // a) Compare value with itself to identify NaN.
691        // b) Compare value inttofp(upper_bound) to identify values that need to
692        //    saturate to max.
693        // c) Compare value with inttofp(lower_bound) to identify values that need
694        //    to saturate to min.
695        // d) Use select to pick from either zero or the input vector depending on
696        //    whether the comparison indicates that we have an unrepresentable
697        //    value.
698        // e) Now that the value is safe, fpto[su]i it.
699        // f) Use our previous comparison results to replace certain zeros with
700        //    int_min or int_max.
701
702        let is_signed = int_min_value != 0;
703        let int_min_value = int_ty.const_int(int_min_value, is_signed);
704        let int_max_value = int_ty.const_int(int_max_value, is_signed);
705
706        let lower_bound = if is_signed {
707            err!(self.builder.build_signed_int_to_float(
708                int_ty.const_int(lower_bound, is_signed),
709                value.get_type(),
710                "",
711            ))
712        } else {
713            err!(self.builder.build_unsigned_int_to_float(
714                int_ty.const_int(lower_bound, is_signed),
715                value.get_type(),
716                "",
717            ))
718        };
719        let upper_bound = if is_signed {
720            err!(self.builder.build_signed_int_to_float(
721                int_ty.const_int(upper_bound, is_signed),
722                value.get_type(),
723                "",
724            ))
725        } else {
726            err!(self.builder.build_unsigned_int_to_float(
727                int_ty.const_int(upper_bound, is_signed),
728                value.get_type(),
729                "",
730            ))
731        };
732
733        let zero = value.get_type().const_zero();
734
735        let nan_cmp =
736            err!(
737                self.builder
738                    .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
739            );
740        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
741            FloatPredicate::OGT,
742            value,
743            upper_bound,
744            "above_upper_bound",
745        ));
746        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
747            FloatPredicate::OLT,
748            value,
749            lower_bound,
750            "below_lower_bound",
751        ));
752        let not_representable = err!(self.builder.build_or(
753            err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
754            below_lower_bound_cmp,
755            "not_representable_as_int",
756        ));
757        let value =
758            err!(
759                self.builder
760                    .build_select(not_representable, zero, value, "safe_to_convert")
761            )
762            .into_float_value();
763        let value = if is_signed {
764            err!(
765                self.builder
766                    .build_float_to_signed_int(value, int_ty, "as_int")
767            )
768        } else {
769            err!(
770                self.builder
771                    .build_float_to_unsigned_int(value, int_ty, "as_int")
772            )
773        };
774        let value =
775            err!(
776                self.builder
777                    .build_select(above_upper_bound_cmp, int_max_value, value, "")
778            )
779            .into_int_value();
780        let value =
781            err!(
782                self.builder
783                    .build_select(below_lower_bound_cmp, int_min_value, value, "")
784            )
785            .into_int_value();
786
787        err_nt!(
788            self.builder
789                .build_bit_cast(value, int_ty, "")
790                .map(|v| v.into_int_value())
791        )
792    }
793
794    fn trap_if_not_representable_as_int(
795        &self,
796        lower_bound: u64, // Inclusive (not a trapping value)
797        upper_bound: u64, // Inclusive (not a trapping value)
798        value: FloatValue<'ctx>,
799    ) -> Result<(), CompileError> {
800        let float_ty = value.get_type();
801        let int_ty = if float_ty == self.intrinsics.f32_ty {
802            self.intrinsics.i32_ty
803        } else {
804            self.intrinsics.i64_ty
805        };
806
807        let lower_bound = err!(self.builder.build_bit_cast(
808            int_ty.const_int(lower_bound, false),
809            float_ty,
810            ""
811        ))
812        .into_float_value();
813        let upper_bound = err!(self.builder.build_bit_cast(
814            int_ty.const_int(upper_bound, false),
815            float_ty,
816            ""
817        ))
818        .into_float_value();
819
820        // The 'U' in the float predicate is short for "unordered" which means that
821        // the comparison will compare true if either operand is a NaN. Thus, NaNs
822        // are out of bounds.
823        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
824            FloatPredicate::UGT,
825            value,
826            upper_bound,
827            "above_upper_bound",
828        ));
829        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
830            FloatPredicate::ULT,
831            value,
832            lower_bound,
833            "below_lower_bound",
834        ));
835        let out_of_bounds = err!(self.builder.build_or(
836            above_upper_bound_cmp,
837            below_lower_bound_cmp,
838            "out_of_bounds",
839        ));
840
841        let failure_block = self
842            .context
843            .append_basic_block(self.function, "conversion_failure_block");
844        let continue_block = self
845            .context
846            .append_basic_block(self.function, "conversion_success_block");
847
848        err!(
849            self.builder
850                .build_conditional_branch(out_of_bounds, failure_block, continue_block)
851        );
852        self.builder.position_at_end(failure_block);
853        let is_nan =
854            err!(
855                self.builder
856                    .build_float_compare(FloatPredicate::UNO, value, value, "is_nan")
857            );
858        let trap_code = err!(self.builder.build_select(
859            is_nan,
860            self.intrinsics.trap_bad_conversion_to_integer,
861            self.intrinsics.trap_illegal_arithmetic,
862            "",
863        ));
864        self.build_call_with_param_attributes(
865            self.intrinsics.throw_trap,
866            &[trap_code.into()],
867            "throw",
868        )?;
869        err!(self.builder.build_unreachable());
870        self.builder.position_at_end(continue_block);
871
872        Ok(())
873    }
874
875    fn trap_if_zero_or_overflow(
876        &self,
877        left: IntValue<'ctx>,
878        right: IntValue<'ctx>,
879    ) -> Result<(), CompileError> {
880        let int_type = left.get_type();
881
882        let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
883            let min_value = int_type.const_int(i32::MIN as u64, false);
884            let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
885            (min_value, neg_one_value)
886        } else if int_type == self.intrinsics.i64_ty {
887            let min_value = int_type.const_int(i64::MIN as u64, false);
888            let neg_one_value = int_type.const_int(-1i64 as u64, false);
889            (min_value, neg_one_value)
890        } else {
891            unreachable!()
892        };
893
894        let divisor_is_zero = err!(self.builder.build_int_compare(
895            IntPredicate::EQ,
896            right,
897            int_type.const_zero(),
898            "divisor_is_zero",
899        ));
900        let should_trap = err!(self.builder.build_or(
901            divisor_is_zero,
902            err!(self.builder.build_and(
903                err!(self.builder.build_int_compare(
904                    IntPredicate::EQ,
905                    left,
906                    min_value,
907                    "left_is_min"
908                )),
909                err!(self.builder.build_int_compare(
910                    IntPredicate::EQ,
911                    right,
912                    neg_one_value,
913                    "right_is_neg_one",
914                )),
915                "div_will_overflow",
916            )),
917            "div_should_trap",
918        ));
919
920        let should_trap = self
921            .build_call_with_param_attributes(
922                self.intrinsics.expect_i1,
923                &[
924                    should_trap.into(),
925                    self.intrinsics.i1_ty.const_zero().into(),
926                ],
927                "should_trap_expect",
928            )?
929            .try_as_basic_value()
930            .unwrap_basic()
931            .into_int_value();
932
933        let shouldnt_trap_block = self
934            .context
935            .append_basic_block(self.function, "shouldnt_trap_block");
936        let should_trap_block = self
937            .context
938            .append_basic_block(self.function, "should_trap_block");
939        err!(self.builder.build_conditional_branch(
940            should_trap,
941            should_trap_block,
942            shouldnt_trap_block
943        ));
944        self.builder.position_at_end(should_trap_block);
945        let trap_code = err!(self.builder.build_select(
946            divisor_is_zero,
947            self.intrinsics.trap_integer_division_by_zero,
948            self.intrinsics.trap_illegal_arithmetic,
949            "",
950        ));
951        err!(
952            self.builder
953                .build_call(self.intrinsics.throw_trap, &[trap_code.into()], "throw")
954        );
955        err!(self.builder.build_unreachable());
956        self.builder.position_at_end(shouldnt_trap_block);
957
958        Ok(())
959    }
960
961    fn trap_if_zero(&self, value: IntValue<'ctx>) -> Result<(), CompileError> {
962        let int_type = value.get_type();
963        let should_trap = err!(self.builder.build_int_compare(
964            IntPredicate::EQ,
965            value,
966            int_type.const_zero(),
967            "divisor_is_zero",
968        ));
969
970        let should_trap = self
971            .build_call_with_param_attributes(
972                self.intrinsics.expect_i1,
973                &[
974                    should_trap.into(),
975                    self.intrinsics.i1_ty.const_zero().into(),
976                ],
977                "should_trap_expect",
978            )?
979            .try_as_basic_value()
980            .unwrap_basic()
981            .into_int_value();
982
983        let shouldnt_trap_block = self
984            .context
985            .append_basic_block(self.function, "shouldnt_trap_block");
986        let should_trap_block = self
987            .context
988            .append_basic_block(self.function, "should_trap_block");
989        err!(self.builder.build_conditional_branch(
990            should_trap,
991            should_trap_block,
992            shouldnt_trap_block
993        ));
994        self.builder.position_at_end(should_trap_block);
995        self.build_call_with_param_attributes(
996            self.intrinsics.throw_trap,
997            &[self.intrinsics.trap_integer_division_by_zero.into()],
998            "throw",
999        )?;
1000        err!(self.builder.build_unreachable());
1001        self.builder.position_at_end(shouldnt_trap_block);
1002
1003        Ok(())
1004    }
1005
1006    fn v128_into_int_vec(
1007        &self,
1008        value: BasicValueEnum<'ctx>,
1009        info: ExtraInfo,
1010        int_vec_ty: VectorType<'ctx>,
1011    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1012        let (value, info) = if self.config.enable_nan_canonicalization {
1013            if info.has_pending_f32_nan() {
1014                let value = err!(
1015                    self.builder
1016                        .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1017                );
1018                (self.canonicalize_nans(value)?, info.strip_pending())
1019            } else if info.has_pending_f64_nan() {
1020                let value = err!(
1021                    self.builder
1022                        .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1023                );
1024                (self.canonicalize_nans(value)?, info.strip_pending())
1025            } else {
1026                (value, info)
1027            }
1028        } else {
1029            (value, info)
1030        };
1031        Ok((
1032            err!(self.builder.build_bit_cast(value, int_vec_ty, "")).into_vector_value(),
1033            info,
1034        ))
1035    }
1036
1037    fn v128_into_i8x16(
1038        &self,
1039        value: BasicValueEnum<'ctx>,
1040        info: ExtraInfo,
1041    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1042        self.v128_into_int_vec(value, info, self.intrinsics.i8x16_ty)
1043    }
1044
1045    fn v128_into_i16x8(
1046        &self,
1047        value: BasicValueEnum<'ctx>,
1048        info: ExtraInfo,
1049    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1050        self.v128_into_int_vec(value, info, self.intrinsics.i16x8_ty)
1051    }
1052
1053    fn v128_into_i32x4(
1054        &self,
1055        value: BasicValueEnum<'ctx>,
1056        info: ExtraInfo,
1057    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1058        self.v128_into_int_vec(value, info, self.intrinsics.i32x4_ty)
1059    }
1060
1061    fn v128_into_i64x2(
1062        &self,
1063        value: BasicValueEnum<'ctx>,
1064        info: ExtraInfo,
1065    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1066        self.v128_into_int_vec(value, info, self.intrinsics.i64x2_ty)
1067    }
1068
1069    // If the value is pending a 64-bit canonicalization, do it now.
1070    // Return a f32x4 vector.
1071    fn v128_into_f32x4(
1072        &self,
1073        value: BasicValueEnum<'ctx>,
1074        info: ExtraInfo,
1075    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1076        let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f64_nan()
1077        {
1078            let value = err!(
1079                self.builder
1080                    .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1081            );
1082            (self.canonicalize_nans(value)?, info.strip_pending())
1083        } else {
1084            (value, info)
1085        };
1086        Ok((
1087            err!(
1088                self.builder
1089                    .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1090            )
1091            .into_vector_value(),
1092            info,
1093        ))
1094    }
1095
1096    // If the value is pending a 32-bit canonicalization, do it now.
1097    // Return a f64x2 vector.
1098    fn v128_into_f64x2(
1099        &self,
1100        value: BasicValueEnum<'ctx>,
1101        info: ExtraInfo,
1102    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1103        let (value, info) = if self.config.enable_nan_canonicalization && info.has_pending_f32_nan()
1104        {
1105            let value = err!(
1106                self.builder
1107                    .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1108            );
1109            (self.canonicalize_nans(value)?, info.strip_pending())
1110        } else {
1111            (value, info)
1112        };
1113        Ok((
1114            err!(
1115                self.builder
1116                    .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1117            )
1118            .into_vector_value(),
1119            info,
1120        ))
1121    }
1122
1123    fn apply_pending_canonicalization(
1124        &self,
1125        value: BasicValueEnum<'ctx>,
1126        info: ExtraInfo,
1127    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1128        if !self.config.enable_nan_canonicalization {
1129            return Ok(value);
1130        }
1131
1132        if info.has_pending_f32_nan() {
1133            if value.get_type().is_vector_type()
1134                || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1135            {
1136                let ty = value.get_type();
1137                let value = err!(
1138                    self.builder
1139                        .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1140                );
1141                let value = self.canonicalize_nans(value)?;
1142                err_nt!(self.builder.build_bit_cast(value, ty, ""))
1143            } else {
1144                self.canonicalize_nans(value)
1145            }
1146        } else if info.has_pending_f64_nan() {
1147            if value.get_type().is_vector_type()
1148                || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1149            {
1150                let ty = value.get_type();
1151                let value = err!(
1152                    self.builder
1153                        .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1154                );
1155                let value = self.canonicalize_nans(value)?;
1156                err_nt!(self.builder.build_bit_cast(value, ty, ""))
1157            } else {
1158                self.canonicalize_nans(value)
1159            }
1160        } else {
1161            Ok(value)
1162        }
1163    }
1164
1165    // Replaces any NaN with the canonical QNaN, otherwise leaves the value alone.
1166    fn canonicalize_nans(
1167        &self,
1168        value: BasicValueEnum<'ctx>,
1169    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1170        if !self.config.enable_nan_canonicalization {
1171            return Ok(value);
1172        }
1173
1174        let f_ty = value.get_type();
1175        if f_ty.is_vector_type() {
1176            let value = value.into_vector_value();
1177            let f_ty = f_ty.into_vector_type();
1178            let zero = f_ty.const_zero();
1179            let nan_cmp =
1180                err!(
1181                    self.builder
1182                        .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1183                );
1184            let canonical_qnan = f_ty
1185                .get_element_type()
1186                .into_float_type()
1187                .const_float(f64::NAN);
1188            let canonical_qnan = self.splat_vector(canonical_qnan.as_basic_value_enum(), f_ty)?;
1189            err_nt!(
1190                self.builder
1191                    .build_select(nan_cmp, canonical_qnan, value, "")
1192                    .map(|v| v.as_basic_value_enum())
1193            )
1194        } else {
1195            let value = value.into_float_value();
1196            let f_ty = f_ty.into_float_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.const_float(f64::NAN);
1204            err_nt!(
1205                self.builder
1206                    .build_select(nan_cmp, canonical_qnan, value, "")
1207                    .map(|v| v.as_basic_value_enum())
1208            )
1209        }
1210    }
1211
1212    // If this memory access must trap when out of bounds (i.e. it is a memory
1213    // access written in the user program as opposed to one used by our VM)
1214    // then mark that it can't be delete.
1215    fn mark_memaccess_nodelete(
1216        &mut self,
1217        memory_index: MemoryIndex,
1218        memaccess: InstructionValue<'ctx>,
1219    ) -> Result<(), CompileError> {
1220        if let MemoryCache::Static { base_ptr: _ } = self.ctx.memory(
1221            memory_index,
1222            self.intrinsics,
1223            self.module,
1224            self.memory_styles,
1225        )? {
1226            // The best we've got is `volatile`.
1227            memaccess.set_volatile(true).map_err(|err| {
1228                CompileError::Codegen(format!("could not set volatile on memory operation: {err}"))
1229            })
1230        } else {
1231            Ok(())
1232        }
1233    }
1234
1235    fn annotate_user_memaccess(
1236        &mut self,
1237        memory_index: MemoryIndex,
1238        _memarg: &MemArg,
1239        alignment: u32,
1240        memaccess: InstructionValue<'ctx>,
1241    ) -> Result<(), CompileError> {
1242        match memaccess.get_opcode() {
1243            InstructionOpcode::Load | InstructionOpcode::Store => {
1244                memaccess.set_alignment(alignment).unwrap();
1245            }
1246            _ => {}
1247        };
1248        if !self.non_volatile_memory_ops {
1249            self.mark_memaccess_nodelete(memory_index, memaccess)?;
1250        }
1251        tbaa_label(
1252            self.module,
1253            self.intrinsics,
1254            format!("memory {}", memory_index.as_u32()),
1255            memaccess,
1256        );
1257        Ok(())
1258    }
1259
1260    fn resolve_memory_ptr(
1261        &mut self,
1262        memory_index: MemoryIndex,
1263        memarg: &MemArg,
1264        ptr_ty: PointerType<'ctx>,
1265        var_offset: IntValue<'ctx>,
1266        value_size: usize,
1267    ) -> Result<PointerValue<'ctx>, CompileError> {
1268        let builder = &self.builder;
1269        let intrinsics = &self.intrinsics;
1270        let context = &self.context;
1271        let function = &self.function;
1272
1273        // Compute the offset into the storage.
1274        let imm_offset = intrinsics.i64_ty.const_int(memarg.offset, false);
1275        let var_offset = err!(builder.build_int_z_extend(var_offset, intrinsics.i64_ty, ""));
1276        let offset = err!(builder.build_int_add(var_offset, imm_offset, ""));
1277
1278        // Look up the memory base (as pointer) and bounds (as unsigned integer).
1279        let base_ptr = if let Some(m0) = self.m0_param {
1280            m0
1281        } else {
1282            match self
1283                .ctx
1284                .memory(memory_index, intrinsics, self.module, self.memory_styles)?
1285            {
1286                MemoryCache::Dynamic {
1287                    ptr_to_base_ptr,
1288                    ptr_to_current_length,
1289                } => {
1290                    // Bounds check it.
1291                    let minimum = self.wasm_module.memories[memory_index].minimum;
1292                    let value_size_v = intrinsics.i64_ty.const_int(value_size as u64, false);
1293                    let ptr_in_bounds = if offset.is_const() {
1294                        // When the offset is constant, if it's below the minimum
1295                        // memory size, we've statically shown that it's safe.
1296                        let load_offset_end =
1297                            offset.const_add(value_size_v).get_zero_extended_constant();
1298                        if load_offset_end.is_some_and(|load_offset_end| {
1299                            load_offset_end <= minimum.bytes().0 as u64
1300                        }) {
1301                            Some(intrinsics.i64_ty.const_int(1, false))
1302                        } else {
1303                            None
1304                        }
1305                    } else {
1306                        None
1307                    };
1308
1309                    let ptr_in_bounds = match ptr_in_bounds {
1310                        Some(ptr) => ptr,
1311                        None => {
1312                            let load_offset_end = err!(builder.build_int_add(
1313                                offset,
1314                                value_size_v,
1315                                "load_offset_end"
1316                            ));
1317
1318                            let current_length = err!(builder.build_load(
1319                                self.intrinsics.i32_ty,
1320                                ptr_to_current_length,
1321                                "current_length"
1322                            ))
1323                            .into_int_value();
1324                            tbaa_label(
1325                                self.module,
1326                                self.intrinsics,
1327                                format!("memory {} length", memory_index.as_u32()),
1328                                current_length.as_instruction_value().unwrap(),
1329                            );
1330                            let current_length = err!(builder.build_int_z_extend(
1331                                current_length,
1332                                intrinsics.i64_ty,
1333                                "current_length_zextd"
1334                            ));
1335
1336                            err!(builder.build_int_compare(
1337                                IntPredicate::ULE,
1338                                load_offset_end,
1339                                current_length,
1340                                "ptr_in_bounds",
1341                            ))
1342                        }
1343                    };
1344
1345                    if !ptr_in_bounds.is_constant_int()
1346                        || ptr_in_bounds.get_zero_extended_constant().unwrap() != 1
1347                    {
1348                        // LLVM may have folded this into 'i1 true' in which case we know
1349                        // the pointer is in bounds. LLVM may also have folded it into a
1350                        // constant expression, not known to be either true or false yet.
1351                        // If it's false, unknown-but-constant, or not-a-constant, emit a
1352                        // runtime bounds check. LLVM may yet succeed at optimizing it away.
1353                        let ptr_in_bounds = err!(self.build_call_with_param_attributes(
1354                            intrinsics.expect_i1,
1355                            &[
1356                                ptr_in_bounds.into(),
1357                                intrinsics.i1_ty.const_int(1, true).into(),
1358                            ],
1359                            "ptr_in_bounds_expect",
1360                        ))
1361                        .try_as_basic_value()
1362                        .unwrap_basic()
1363                        .into_int_value();
1364
1365                        let in_bounds_continue_block =
1366                            context.append_basic_block(*function, "in_bounds_continue_block");
1367                        let not_in_bounds_block =
1368                            context.append_basic_block(*function, "not_in_bounds_block");
1369                        err!(builder.build_conditional_branch(
1370                            ptr_in_bounds,
1371                            in_bounds_continue_block,
1372                            not_in_bounds_block,
1373                        ));
1374                        builder.position_at_end(not_in_bounds_block);
1375                        err!(self.build_call_with_param_attributes(
1376                            intrinsics.throw_trap,
1377                            &[intrinsics.trap_memory_oob.into()],
1378                            "throw",
1379                        ));
1380                        err!(builder.build_unreachable());
1381                        builder.position_at_end(in_bounds_continue_block);
1382                    }
1383                    let ptr_to_base =
1384                        err!(builder.build_load(intrinsics.ptr_ty, ptr_to_base_ptr, "ptr_to_base"))
1385                            .into_pointer_value();
1386                    tbaa_label(
1387                        self.module,
1388                        self.intrinsics,
1389                        format!("memory base_ptr {}", memory_index.as_u32()),
1390                        ptr_to_base.as_instruction_value().unwrap(),
1391                    );
1392                    ptr_to_base
1393                }
1394                MemoryCache::Static { base_ptr } => base_ptr,
1395            }
1396        };
1397        let value_ptr = unsafe {
1398            err!(builder.build_gep(self.intrinsics.i8_ty, base_ptr, &[offset], "mem_value_ptr"))
1399        };
1400        err_nt!(
1401            builder
1402                .build_bit_cast(value_ptr, ptr_ty, "mem_value")
1403                .map(|v| v.into_pointer_value())
1404        )
1405    }
1406
1407    fn trap_if_misaligned(
1408        &self,
1409        _memarg: &MemArg,
1410        ptr: PointerValue<'ctx>,
1411        align: u8,
1412    ) -> Result<(), CompileError> {
1413        if align <= 1 {
1414            return Ok(());
1415        }
1416        let value = err!(self.builder.build_ptr_to_int(
1417            ptr,
1418            self.intrinsics.i64_ty,
1419            "mischeck_value"
1420        ));
1421        let and = err!(self.builder.build_and(
1422            value,
1423            self.intrinsics.i64_ty.const_int((align - 1).into(), false),
1424            "misaligncheck",
1425        ));
1426        let aligned = err!(self.builder.build_int_compare(
1427            IntPredicate::EQ,
1428            and,
1429            self.intrinsics.i64_zero,
1430            "is_aligned"
1431        ));
1432        let aligned = self
1433            .build_call_with_param_attributes(
1434                self.intrinsics.expect_i1,
1435                &[
1436                    aligned.into(),
1437                    self.intrinsics.i1_ty.const_int(1, false).into(),
1438                ],
1439                "is_aligned_expect",
1440            )?
1441            .try_as_basic_value()
1442            .unwrap_basic()
1443            .into_int_value();
1444
1445        let continue_block = self
1446            .context
1447            .append_basic_block(self.function, "aligned_access_continue_block");
1448        let not_aligned_block = self
1449            .context
1450            .append_basic_block(self.function, "misaligned_trap_block");
1451        err!(
1452            self.builder
1453                .build_conditional_branch(aligned, continue_block, not_aligned_block)
1454        );
1455
1456        self.builder.position_at_end(not_aligned_block);
1457        self.build_call_with_param_attributes(
1458            self.intrinsics.throw_trap,
1459            &[self.intrinsics.trap_unaligned_atomic.into()],
1460            "throw",
1461        )?;
1462        err!(self.builder.build_unreachable());
1463
1464        self.builder.position_at_end(continue_block);
1465        Ok(())
1466    }
1467
1468    fn finalize(&mut self, wasm_fn_type: &FunctionType) -> Result<(), CompileError> {
1469        let func_type = self.function.get_type();
1470
1471        let results = self.state.popn_save_extra(wasm_fn_type.results().len())?;
1472        let results = err!(
1473            results
1474                .into_iter()
1475                .map(|(v, i)| self.apply_pending_canonicalization(v, i))
1476                .collect::<Result<Vec<_>, _>>()
1477        );
1478
1479        if wasm_fn_type.results().is_empty() {
1480            err!(self.builder.build_return(None));
1481        } else if self.abi.is_sret(wasm_fn_type)? {
1482            let sret = self
1483                .function
1484                .get_first_param()
1485                .unwrap()
1486                .into_pointer_value();
1487            let llvm_params: Vec<_> = wasm_fn_type
1488                .results()
1489                .iter()
1490                .map(|x| type_to_llvm(self.intrinsics, *x).unwrap())
1491                .collect();
1492            let mut struct_value = self
1493                .context
1494                .struct_type(llvm_params.as_slice(), false)
1495                .get_undef();
1496            for (idx, value) in results.into_iter().enumerate() {
1497                let value = err!(self.builder.build_bit_cast(
1498                    value,
1499                    type_to_llvm(self.intrinsics, wasm_fn_type.results()[idx])?,
1500                    "",
1501                ));
1502                struct_value =
1503                    err!(
1504                        self.builder
1505                            .build_insert_value(struct_value, value, idx as u32, "")
1506                    )
1507                    .into_struct_value();
1508            }
1509            err!(self.builder.build_store(sret, struct_value));
1510            err!(self.builder.build_return(None));
1511        } else {
1512            err!(
1513                self.builder
1514                    .build_return(Some(&self.abi.pack_values_for_register_return(
1515                        self.intrinsics,
1516                        &self.builder,
1517                        &results,
1518                        &func_type,
1519                    )?))
1520            );
1521        }
1522        Ok(())
1523    }
1524
1525    // Generates a global constant with the tag's module-local index, which can be used
1526    // as the "type info" of a catch clause.
1527    fn get_or_insert_tag_type_info_global(&mut self, tag: i32) -> BasicValueEnum<'ctx> {
1528        if let Some(tag) = self.tags_cache.get(&tag) {
1529            return *tag;
1530        }
1531
1532        let tag_ty = self
1533            .context
1534            .struct_type(&[self.intrinsics.i32_ty.into()], false);
1535        let tag_glbl = self.module.add_global(
1536            tag_ty,
1537            Some(AddressSpace::default()),
1538            &format!("__wasmer_eh_type_info_{tag}"),
1539        );
1540        tag_glbl.set_initializer(
1541            &tag_ty
1542                .const_named_struct(&[self.intrinsics.i32_ty.const_int(tag as _, false).into()])
1543                .as_basic_value_enum(),
1544        );
1545
1546        tag_glbl.set_linkage(Linkage::External);
1547        tag_glbl.set_constant(true);
1548        // Why set this to a specific section? On macOS it would land on a specifc read only data
1549        // section. GOT-based relocations will probably be generated with a non-zero addend, making
1550        // some EH-related intricacies not working.
1551        //
1552        // The general idea is that each tag has its own section, so the GOT-based relocation can
1553        // have a zero addend, i.e. the data of the tag is the first (and only) value in a specific
1554        // section we can target in relocations.
1555        if matches!(self.binary_fmt, target_lexicon::BinaryFormat::Macho) {
1556            tag_glbl.set_section(Some(&format!("{FUNCTION_SECTION_MACHO},_eh_ti_{tag}")));
1557        }
1558
1559        let tag_glbl = tag_glbl.as_basic_value_enum();
1560
1561        self.tags_cache.insert(tag, tag_glbl);
1562        tag_glbl
1563    }
1564
1565    fn build_m0_indirect_call(
1566        &mut self,
1567        table_index: u32,
1568        ctx_ptr: PointerValue<'ctx>,
1569        func_type: &FunctionType,
1570        func_ptr: PointerValue<'ctx>,
1571        func_index: IntValue<'ctx>,
1572    ) -> Result<(), CompileError> {
1573        let Some(m0) = self.m0_param else {
1574            return Err(CompileError::Codegen(
1575                "Call to build_m0_indirect_call without m0 parameter!".to_string(),
1576            ));
1577        };
1578
1579        let mut local_func_indices = vec![];
1580        let mut foreign_func_indices = vec![];
1581
1582        for t in &self.wasm_module.table_initializers {
1583            if t.table_index.as_u32() == table_index {
1584                for (func_in_table_idx, func_idx) in t.elements.iter().enumerate() {
1585                    if self.wasm_module.local_func_index(*func_idx).is_some() {
1586                        local_func_indices.push(func_in_table_idx)
1587                    } else {
1588                        foreign_func_indices.push(func_in_table_idx)
1589                    }
1590                }
1591                break;
1592            }
1593        }
1594
1595        let needs_switch = self.m0_param.is_some()
1596            && !local_func_indices.is_empty()
1597            && !foreign_func_indices.is_empty();
1598
1599        if needs_switch {
1600            let foreign_idx_block = self
1601                .context
1602                .append_basic_block(self.function, "foreign_call_block");
1603            let local_idx_block = self
1604                .context
1605                .append_basic_block(self.function, "local_call_block");
1606            let unreachable_indirect_call_branch_block = self
1607                .context
1608                .append_basic_block(self.function, "unreachable_indirect_call_branch");
1609
1610            let cont = self.context.append_basic_block(self.function, "cont");
1611
1612            err!(
1613                self.builder.build_switch(
1614                    func_index,
1615                    unreachable_indirect_call_branch_block,
1616                    &local_func_indices
1617                        .into_iter()
1618                        .map(|v| (
1619                            self.intrinsics.i32_ty.const_int(v as _, false),
1620                            local_idx_block
1621                        ))
1622                        .chain(foreign_func_indices.into_iter().map(|v| (
1623                            self.intrinsics.i32_ty.const_int(v as _, false),
1624                            foreign_idx_block
1625                        )))
1626                        .collect::<Vec<_>>()
1627                )
1628            );
1629
1630            self.builder
1631                .position_at_end(unreachable_indirect_call_branch_block);
1632            err!(self.builder.build_unreachable());
1633
1634            //let current_block = self.builder.get_insert_block().unwrap();
1635            self.builder.position_at_end(local_idx_block);
1636            let local_call_site =
1637                self.build_indirect_call(ctx_ptr, func_type, func_ptr, Some(m0))?;
1638
1639            let local_rets = self.abi.rets_from_call(
1640                &self.builder,
1641                self.intrinsics,
1642                local_call_site,
1643                func_type,
1644            )?;
1645
1646            err!(self.builder.build_unconditional_branch(cont));
1647
1648            self.builder.position_at_end(foreign_idx_block);
1649            let foreign_call_site = self.build_indirect_call(ctx_ptr, func_type, func_ptr, None)?;
1650
1651            let foreign_rets = self.abi.rets_from_call(
1652                &self.builder,
1653                self.intrinsics,
1654                foreign_call_site,
1655                func_type,
1656            )?;
1657
1658            err!(self.builder.build_unconditional_branch(cont));
1659
1660            self.builder.position_at_end(cont);
1661
1662            for i in 0..foreign_rets.len() {
1663                let f_i = foreign_rets[i];
1664                let l_i = local_rets[i];
1665                let ty = f_i.get_type();
1666                let v = err!(self.builder.build_phi(ty, ""));
1667                v.add_incoming(&[(&f_i, foreign_idx_block), (&l_i, local_idx_block)]);
1668                self.state.push1(v.as_basic_value());
1669            }
1670        } else if foreign_func_indices.is_empty() {
1671            let call_site = self.build_indirect_call(ctx_ptr, func_type, func_ptr, Some(m0))?;
1672
1673            self.abi
1674                .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
1675                .iter()
1676                .for_each(|ret| self.state.push1(*ret));
1677        } else {
1678            let call_site = self.build_indirect_call(ctx_ptr, func_type, func_ptr, None)?;
1679            self.abi
1680                .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
1681                .iter()
1682                .for_each(|ret| self.state.push1(*ret));
1683        }
1684
1685        Ok(())
1686    }
1687
1688    fn build_indirect_call(
1689        &mut self,
1690        ctx_ptr: PointerValue<'ctx>,
1691        func_type: &FunctionType,
1692        func_ptr: PointerValue<'ctx>,
1693        m0_param: Option<PointerValue<'ctx>>,
1694    ) -> Result<CallSiteValue<'ctx>, CompileError> {
1695        let (llvm_func_type, llvm_func_attrs) = self.abi.func_type_to_llvm(
1696            self.context,
1697            self.intrinsics,
1698            Some(self.ctx.get_offsets()),
1699            func_type,
1700            m0_param.is_some(),
1701        )?;
1702
1703        let params = self.state.popn_save_extra(func_type.params().len())?;
1704
1705        // Apply pending canonicalizations.
1706        let params = params
1707            .iter()
1708            .zip(func_type.params().iter())
1709            .map(|((v, info), wasm_ty)| match wasm_ty {
1710                Type::F32 => err_nt!(self.builder.build_bit_cast(
1711                    self.apply_pending_canonicalization(*v, *info)?,
1712                    self.intrinsics.f32_ty,
1713                    "",
1714                )),
1715                Type::F64 => err_nt!(self.builder.build_bit_cast(
1716                    self.apply_pending_canonicalization(*v, *info)?,
1717                    self.intrinsics.f64_ty,
1718                    "",
1719                )),
1720                Type::V128 => self.apply_pending_canonicalization(*v, *info),
1721                _ => Ok(*v),
1722            })
1723            .collect::<Result<Vec<_>, _>>()?;
1724
1725        let params = self.abi.args_to_call(
1726            &self.alloca_builder,
1727            func_type,
1728            &llvm_func_type,
1729            ctx_ptr,
1730            params.as_slice(),
1731            self.intrinsics,
1732            m0_param,
1733        )?;
1734
1735        let typed_func_ptr = err!(self.builder.build_pointer_cast(
1736            func_ptr,
1737            self.context.ptr_type(AddressSpace::default()),
1738            "typed_func_ptr",
1739        ));
1740
1741        let call_site_local = self.build_indirect_call_or_invoke(
1742            llvm_func_type,
1743            typed_func_ptr,
1744            params.as_slice(),
1745            "then_block",
1746        )?;
1747        for (attr, attr_loc) in llvm_func_attrs {
1748            call_site_local.add_attribute(attr_loc, attr);
1749        }
1750
1751        Ok(call_site_local)
1752    }
1753
1754    fn build_indirect_call_or_invoke(
1755        &mut self,
1756        llvm_func_type: inkwell::types::FunctionType<'ctx>,
1757        func_ptr: PointerValue<'ctx>,
1758        params: &[BasicValueEnum<'ctx>],
1759        then_block_name: &str,
1760    ) -> Result<CallSiteValue<'ctx>, CompileError> {
1761        if let Some(lpad) = self.state.get_innermost_landingpad() {
1762            let then_block = self
1763                .context
1764                .append_basic_block(self.function, then_block_name);
1765
1766            let ret = err!(self.builder.build_indirect_invoke(
1767                llvm_func_type,
1768                func_ptr,
1769                params,
1770                then_block,
1771                lpad,
1772                "",
1773            ));
1774
1775            self.builder.position_at_end(then_block);
1776            Ok(ret)
1777        } else {
1778            let call_params = params
1779                .iter()
1780                .copied()
1781                .map(Into::into)
1782                .collect::<Vec<BasicMetadataValueEnum>>();
1783            Ok(err!(self.builder.build_indirect_call(
1784                llvm_func_type,
1785                func_ptr,
1786                call_params.as_slice(),
1787                ""
1788            )))
1789        }
1790    }
1791}
1792
1793pub struct LLVMFunctionCodeGenerator<'ctx, 'a> {
1794    m0_param: Option<PointerValue<'ctx>>,
1795    context: &'ctx Context,
1796    builder: Builder<'ctx>,
1797    alloca_builder: Builder<'ctx>,
1798    intrinsics: &'a Intrinsics<'ctx>,
1799    state: State<'ctx>,
1800    function: FunctionValue<'ctx>,
1801    locals: Vec<(BasicTypeEnum<'ctx>, PointerValue<'ctx>)>, // Contains params and locals
1802    ctx: CtxType<'ctx, 'a>,
1803    unreachable_depth: usize,
1804    memory_styles: &'a PrimaryMap<MemoryIndex, MemoryStyle>,
1805    _table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
1806    module: &'a Module<'ctx>,
1807    module_translation: &'a ModuleTranslationState,
1808    wasm_module: &'a ModuleInfo,
1809    symbol_registry: &'a dyn SymbolRegistry,
1810    abi: &'a dyn Abi,
1811    config: &'a LLVM,
1812    target_triple: Triple,
1813    tags_cache: HashMap<i32, BasicValueEnum<'ctx>>,
1814    binary_fmt: target_lexicon::BinaryFormat,
1815    cpu_features: EnumSet<CpuFeature>,
1816    non_volatile_memory_ops: bool,
1817}
1818
1819impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
1820    fn quiet_nan(&self, value: BasicValueEnum<'ctx>) -> Result<BasicValueEnum<'ctx>, CompileError> {
1821        let intrinsic = if value
1822            .get_type()
1823            .eq(&self.intrinsics.f32_ty.as_basic_type_enum())
1824        {
1825            Some(self.intrinsics.add_f32)
1826        } else if value
1827            .get_type()
1828            .eq(&self.intrinsics.f64_ty.as_basic_type_enum())
1829        {
1830            Some(self.intrinsics.add_f64)
1831        } else if value
1832            .get_type()
1833            .eq(&self.intrinsics.f32x4_ty.as_basic_type_enum())
1834        {
1835            Some(self.intrinsics.add_f32x4)
1836        } else if value
1837            .get_type()
1838            .eq(&self.intrinsics.f64x2_ty.as_basic_type_enum())
1839        {
1840            Some(self.intrinsics.add_f64x2)
1841        } else {
1842            None
1843        };
1844
1845        match intrinsic {
1846            Some(intrinsic) => err_nt!(
1847                self.builder
1848                    .build_call(
1849                        intrinsic,
1850                        &[
1851                            value.into(),
1852                            value.get_type().const_zero().into(),
1853                            self.intrinsics.fp_rounding_md,
1854                            self.intrinsics.fp_exception_md,
1855                        ],
1856                        "",
1857                    )
1858                    .map(|v| v.try_as_basic_value().unwrap_basic())
1859            ),
1860            None => Ok(value),
1861        }
1862    }
1863
1864    fn finalize_minmax_result(
1865        &self,
1866        value: BasicValueEnum<'ctx>,
1867    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1868        let ty = value.get_type();
1869        if ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum())
1870            || ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum())
1871        {
1872            let value = value.into_float_value();
1873            let is_nan = err!(self.builder.build_float_compare(
1874                FloatPredicate::UNO,
1875                value,
1876                value,
1877                "res_is_nan"
1878            ));
1879            let quiet = self.quiet_nan(value.as_basic_value_enum())?;
1880            let result =
1881                err!(
1882                    self.builder
1883                        .build_select(is_nan, quiet, value.as_basic_value_enum(), "")
1884                );
1885            Ok(result.as_basic_value_enum())
1886        } else if ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum()) {
1887            let value = value.into_vector_value();
1888            let is_nan = self
1889                .build_call_with_param_attributes(
1890                    self.intrinsics.cmp_f32x4,
1891                    &[
1892                        value.into(),
1893                        value.into(),
1894                        self.intrinsics.fp_uno_md,
1895                        self.intrinsics.fp_exception_md,
1896                    ],
1897                    "",
1898                )?
1899                .try_as_basic_value()
1900                .unwrap_basic()
1901                .into_vector_value();
1902            let quiet = self
1903                .quiet_nan(value.as_basic_value_enum())?
1904                .into_vector_value();
1905            let result = err!(self.builder.build_select(
1906                is_nan,
1907                quiet.as_basic_value_enum(),
1908                value.as_basic_value_enum(),
1909                "",
1910            ));
1911            Ok(result.as_basic_value_enum())
1912        } else if ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum()) {
1913            let value = value.into_vector_value();
1914            let is_nan = self
1915                .build_call_with_param_attributes(
1916                    self.intrinsics.cmp_f64x2,
1917                    &[
1918                        value.into(),
1919                        value.into(),
1920                        self.intrinsics.fp_uno_md,
1921                        self.intrinsics.fp_exception_md,
1922                    ],
1923                    "",
1924                )?
1925                .try_as_basic_value()
1926                .unwrap_basic()
1927                .into_vector_value();
1928            let quiet = self
1929                .quiet_nan(value.as_basic_value_enum())?
1930                .into_vector_value();
1931            let result = err!(self.builder.build_select(
1932                is_nan,
1933                quiet.as_basic_value_enum(),
1934                value.as_basic_value_enum(),
1935                "",
1936            ));
1937            Ok(result.as_basic_value_enum())
1938        } else {
1939            Ok(value)
1940        }
1941    }
1942
1943    fn finalize_rounding_result(
1944        &self,
1945        value: BasicValueEnum<'ctx>,
1946        info: ExtraInfo,
1947    ) -> Result<(BasicValueEnum<'ctx>, ExtraInfo), CompileError> {
1948        let ty = value.get_type();
1949        let is_f32 = ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum());
1950        let is_f64 = ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum());
1951        let is_f32x4 = ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum());
1952        let is_f64x2 = ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum());
1953        debug_assert!(is_f32 || is_f64 || is_f32x4 || is_f64x2);
1954
1955        if matches!(
1956            self.target_triple.architecture,
1957            Architecture::Riscv32(..) | Architecture::Riscv64(..)
1958        ) {
1959            if is_f32 || is_f64 {
1960                let input = value.into_float_value();
1961                let is_nan = err!(self.builder.build_float_compare(
1962                    FloatPredicate::UNO,
1963                    input,
1964                    input,
1965                    "res_is_nan",
1966                ));
1967                let canonical_nan_bits = if is_f32 {
1968                    self.intrinsics
1969                        .i32_ty
1970                        .const_int(CANONICAL_NAN_F32 as _, false)
1971                } else {
1972                    self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false)
1973                };
1974                let canonical_nan = err!(self.builder.build_bit_cast(
1975                    canonical_nan_bits,
1976                    ty,
1977                    "canonical_nan",
1978                ));
1979                let res =
1980                    err!(
1981                        self.builder
1982                            .build_select(is_nan, canonical_nan, value, "canonical_nan",)
1983                    );
1984                Ok((res, info))
1985            } else if is_f32x4 {
1986                let value = value.into_vector_value();
1987                let is_nan = err!(self.builder.build_call(
1988                    self.intrinsics.cmp_f32x4,
1989                    &[
1990                        value.into(),
1991                        value.into(),
1992                        self.intrinsics.fp_uno_md,
1993                        self.intrinsics.fp_exception_md,
1994                    ],
1995                    "",
1996                ))
1997                .try_as_basic_value()
1998                .unwrap_basic()
1999                .into_vector_value();
2000                let canonical_nan_bits = self
2001                    .intrinsics
2002                    .i32_ty
2003                    .const_int(CANONICAL_NAN_F32 as _, false);
2004                let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 4]);
2005                let canonical_nan = err!(self.builder.build_bit_cast(
2006                    canonical_nan_bits,
2007                    self.intrinsics.f32x4_ty,
2008                    "canonical_nan",
2009                ));
2010                let res = err!(self.builder.build_select(
2011                    is_nan,
2012                    canonical_nan.as_basic_value_enum(),
2013                    value.as_basic_value_enum(),
2014                    "canonical_nan",
2015                ));
2016                Ok((res, info))
2017            } else {
2018                let value = value.into_vector_value();
2019                let is_nan = err!(self.builder.build_call(
2020                    self.intrinsics.cmp_f64x2,
2021                    &[
2022                        value.into(),
2023                        value.into(),
2024                        self.intrinsics.fp_uno_md,
2025                        self.intrinsics.fp_exception_md,
2026                    ],
2027                    "",
2028                ))
2029                .try_as_basic_value()
2030                .unwrap_basic()
2031                .into_vector_value();
2032                let canonical_nan_bits = self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false);
2033                let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 2]);
2034                let canonical_nan = err!(self.builder.build_bit_cast(
2035                    canonical_nan_bits,
2036                    self.intrinsics.f64x2_ty,
2037                    "canonical_nan",
2038                ));
2039                let res = err!(self.builder.build_select(
2040                    is_nan,
2041                    canonical_nan.as_basic_value_enum(),
2042                    value.as_basic_value_enum(),
2043                    "canonical_nan",
2044                ));
2045                Ok((res, info))
2046            }
2047        } else {
2048            Ok((
2049                value,
2050                (info
2051                    | if is_f32 || is_f32x4 {
2052                        ExtraInfo::pending_f32_nan()
2053                    } else {
2054                        ExtraInfo::pending_f64_nan()
2055                    })?,
2056            ))
2057        }
2058    }
2059
2060    fn translate_operator(&mut self, op: Operator, _source_loc: u32) -> Result<(), CompileError> {
2061        // TODO: remove this vmctx by moving everything into CtxType. Values
2062        // computed off vmctx usually benefit from caching.
2063        let vmctx = &self.ctx.basic().into_pointer_value();
2064
2065        //let opcode_offset: Option<usize> = None;
2066
2067        if !self.state.reachable {
2068            match op {
2069                Operator::Block { blockty: _ }
2070                | Operator::Loop { blockty: _ }
2071                | Operator::If { blockty: _ }
2072                | Operator::TryTable { .. } => {
2073                    self.unreachable_depth += 1;
2074                    return Ok(());
2075                }
2076                Operator::Else => {
2077                    if self.unreachable_depth != 0 {
2078                        return Ok(());
2079                    }
2080                }
2081                Operator::End => {
2082                    if self.unreachable_depth != 0 {
2083                        self.unreachable_depth -= 1;
2084                        return Ok(());
2085                    }
2086                }
2087                _ => {
2088                    return Ok(());
2089                }
2090            }
2091        }
2092
2093        match op {
2094            /***************************
2095             * Control Flow instructions.
2096             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#control-flow-instructions
2097             ***************************/
2098            Operator::Block { blockty } => {
2099                let current_block = self
2100                    .builder
2101                    .get_insert_block()
2102                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2103
2104                let end_block = self.context.append_basic_block(self.function, "end");
2105                self.builder.position_at_end(end_block);
2106
2107                let phis: SmallVec<[PhiValue<'ctx>; 1]> = self
2108                    .module_translation
2109                    .blocktype_params_results(&blockty)?
2110                    .1
2111                    .iter()
2112                    .map(|&wp_ty| {
2113                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2114                            type_to_llvm(self.intrinsics, wasm_ty)
2115                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2116                        })
2117                    })
2118                    .collect::<Result<_, _>>()?;
2119
2120                self.state.push_block(
2121                    end_block,
2122                    phis,
2123                    self.module_translation
2124                        .blocktype_params_results(&blockty)?
2125                        .0
2126                        .len(),
2127                );
2128                self.builder.position_at_end(current_block);
2129            }
2130            Operator::Loop { blockty } => {
2131                let loop_body = self.context.append_basic_block(self.function, "loop_body");
2132                let loop_next = self.context.append_basic_block(self.function, "loop_outer");
2133                let pre_loop_block = self.builder.get_insert_block().unwrap();
2134
2135                err!(self.builder.build_unconditional_branch(loop_body));
2136
2137                self.builder.position_at_end(loop_next);
2138                let blocktypes = self.module_translation.blocktype_params_results(&blockty)?;
2139                let phis = blocktypes
2140                    .1
2141                    .iter()
2142                    .map(|&wp_ty| {
2143                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2144                            type_to_llvm(self.intrinsics, wasm_ty)
2145                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2146                        })
2147                    })
2148                    .collect::<Result<_, _>>()?;
2149                self.builder.position_at_end(loop_body);
2150                let loop_phis: SmallVec<[PhiValue<'ctx>; 1]> = blocktypes
2151                    .0
2152                    .iter()
2153                    .map(|&wp_ty| {
2154                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2155                            type_to_llvm(self.intrinsics, wasm_ty)
2156                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2157                        })
2158                    })
2159                    .collect::<Result<_, _>>()?;
2160                for phi in loop_phis.iter().rev() {
2161                    let (value, info) = self.state.pop1_extra()?;
2162                    let value = self.apply_pending_canonicalization(value, info)?;
2163                    phi.add_incoming(&[(&value, pre_loop_block)]);
2164                }
2165                for phi in &loop_phis {
2166                    self.state.push1(phi.as_basic_value());
2167                }
2168
2169                let num_inputs = loop_phis.len();
2170                self.state
2171                    .push_loop(loop_body, loop_next, loop_phis, phis, num_inputs);
2172            }
2173            Operator::Br { relative_depth } => {
2174                let frame = self.state.frame_at_depth(relative_depth)?;
2175
2176                let current_block = self
2177                    .builder
2178                    .get_insert_block()
2179                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2180
2181                let phis = if frame.is_loop() {
2182                    frame.loop_body_phis()
2183                } else {
2184                    frame.phis()
2185                };
2186
2187                let len = phis.len();
2188                let values = self.state.peekn_extra(len)?;
2189                let values = values
2190                    .iter()
2191                    .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2192                    .collect::<Result<Vec<_>, _>>()?;
2193
2194                // For each result of the block we're branching to,
2195                // pop a value off the value stack and load it into
2196                // the corresponding phi.
2197                for (phi, value) in phis.iter().zip(values) {
2198                    phi.add_incoming(&[(&value, current_block)]);
2199                }
2200
2201                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2202
2203                self.state.popn(len)?;
2204                self.state.reachable = false;
2205            }
2206            Operator::BrIf { relative_depth } => {
2207                let cond = self.state.pop1()?;
2208                let frame = self.state.frame_at_depth(relative_depth)?;
2209
2210                let current_block = self
2211                    .builder
2212                    .get_insert_block()
2213                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2214
2215                let phis = if frame.is_loop() {
2216                    frame.loop_body_phis()
2217                } else {
2218                    frame.phis()
2219                };
2220
2221                let param_stack = self.state.peekn_extra(phis.len())?;
2222                let param_stack = param_stack
2223                    .iter()
2224                    .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2225                    .collect::<Result<Vec<_>, _>>()?;
2226
2227                for (phi, value) in phis.iter().zip(param_stack) {
2228                    phi.add_incoming(&[(&value, current_block)]);
2229                }
2230
2231                let else_block = self.context.append_basic_block(self.function, "else");
2232
2233                let cond_value = err!(self.builder.build_int_compare(
2234                    IntPredicate::NE,
2235                    cond.into_int_value(),
2236                    self.intrinsics.i32_zero,
2237                    "",
2238                ));
2239                err!(self.builder.build_conditional_branch(
2240                    cond_value,
2241                    *frame.br_dest(),
2242                    else_block
2243                ));
2244                self.builder.position_at_end(else_block);
2245            }
2246            Operator::BrTable { ref targets } => {
2247                let current_block = self
2248                    .builder
2249                    .get_insert_block()
2250                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2251
2252                let index = self.state.pop1()?;
2253
2254                let default_frame = self.state.frame_at_depth(targets.default())?;
2255
2256                let phis = if default_frame.is_loop() {
2257                    default_frame.loop_body_phis()
2258                } else {
2259                    default_frame.phis()
2260                };
2261                let args = self.state.peekn(phis.len())?;
2262
2263                for (phi, value) in phis.iter().zip(args.iter()) {
2264                    phi.add_incoming(&[(value, current_block)]);
2265                }
2266
2267                let cases: Vec<_> = targets
2268                    .targets()
2269                    .enumerate()
2270                    .map(|(case_index, depth)| {
2271                        let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
2272                        let frame_result: Result<&ControlFrame, CompileError> =
2273                            self.state.frame_at_depth(depth);
2274                        let frame = match frame_result {
2275                            Ok(v) => v,
2276                            Err(e) => return Err(e),
2277                        };
2278                        let case_index_literal =
2279                            self.context.i32_type().const_int(case_index as u64, false);
2280                        let phis = if frame.is_loop() {
2281                            frame.loop_body_phis()
2282                        } else {
2283                            frame.phis()
2284                        };
2285                        for (phi, value) in phis.iter().zip(args.iter()) {
2286                            phi.add_incoming(&[(value, current_block)]);
2287                        }
2288
2289                        Ok((case_index_literal, *frame.br_dest()))
2290                    })
2291                    .collect::<Result<_, _>>()?;
2292
2293                err!(self.builder.build_switch(
2294                    index.into_int_value(),
2295                    *default_frame.br_dest(),
2296                    &cases[..],
2297                ));
2298
2299                let args_len = args.len();
2300                self.state.popn(args_len)?;
2301                self.state.reachable = false;
2302            }
2303            Operator::If { blockty } => {
2304                let current_block = self
2305                    .builder
2306                    .get_insert_block()
2307                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2308                let if_then_block = self.context.append_basic_block(self.function, "if_then");
2309                let if_else_block = self.context.append_basic_block(self.function, "if_else");
2310                let end_block = self.context.append_basic_block(self.function, "if_end");
2311
2312                let end_phis = {
2313                    self.builder.position_at_end(end_block);
2314
2315                    let phis = self
2316                        .module_translation
2317                        .blocktype_params_results(&blockty)?
2318                        .1
2319                        .iter()
2320                        .map(|&wp_ty| {
2321                            err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2322                                type_to_llvm(self.intrinsics, wasm_ty)
2323                                    .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2324                            })
2325                        })
2326                        .collect::<Result<_, _>>()?;
2327
2328                    self.builder.position_at_end(current_block);
2329                    phis
2330                };
2331
2332                let cond = self.state.pop1()?;
2333
2334                let cond_value = err!(self.builder.build_int_compare(
2335                    IntPredicate::NE,
2336                    cond.into_int_value(),
2337                    self.intrinsics.i32_zero,
2338                    "",
2339                ));
2340
2341                err!(self.builder.build_conditional_branch(
2342                    cond_value,
2343                    if_then_block,
2344                    if_else_block
2345                ));
2346                self.builder.position_at_end(if_else_block);
2347                let block_param_types = self
2348                    .module_translation
2349                    .blocktype_params_results(&blockty)?
2350                    .0
2351                    .iter()
2352                    .map(|&wp_ty| {
2353                        err_nt!(wptype_to_type(wp_ty))
2354                            .and_then(|wasm_ty| type_to_llvm(self.intrinsics, wasm_ty))
2355                    })
2356                    .collect::<Result<Vec<_>, _>>()?;
2357                let else_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2358                    .iter()
2359                    .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2360                    .collect::<Result<SmallVec<_>, _>>()?;
2361                self.builder.position_at_end(if_then_block);
2362                let then_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
2363                    .iter()
2364                    .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
2365                    .collect::<Result<SmallVec<_>, _>>()?;
2366                for (else_phi, then_phi) in else_phis.iter().rev().zip(then_phis.iter().rev()) {
2367                    let (value, info) = self.state.pop1_extra()?;
2368                    let value = self.apply_pending_canonicalization(value, info)?;
2369                    else_phi.add_incoming(&[(&value, current_block)]);
2370                    then_phi.add_incoming(&[(&value, current_block)]);
2371                }
2372                for phi in then_phis.iter() {
2373                    self.state.push1(phi.as_basic_value());
2374                }
2375
2376                self.state.push_if(
2377                    if_then_block,
2378                    if_else_block,
2379                    end_block,
2380                    then_phis,
2381                    else_phis,
2382                    end_phis,
2383                    block_param_types.len(),
2384                );
2385            }
2386            Operator::Else => {
2387                if self.state.reachable {
2388                    let frame = self.state.frame_at_depth(0)?;
2389                    let current_block = self.builder.get_insert_block().ok_or_else(|| {
2390                        CompileError::Codegen("not currently in a block".to_string())
2391                    })?;
2392
2393                    for phi in frame.phis().to_vec().iter().rev() {
2394                        let (value, info) = self.state.pop1_extra()?;
2395                        let value = self.apply_pending_canonicalization(value, info)?;
2396                        phi.add_incoming(&[(&value, current_block)])
2397                    }
2398
2399                    let frame = self.state.frame_at_depth(0)?;
2400                    err!(self.builder.build_unconditional_branch(*frame.code_after()));
2401                }
2402
2403                let (if_else_block, if_else_state) = if let ControlFrame::IfElse {
2404                    if_else,
2405                    if_else_state,
2406                    ..
2407                } = self.state.frame_at_depth_mut(0)?
2408                {
2409                    (if_else, if_else_state)
2410                } else {
2411                    unreachable!()
2412                };
2413
2414                *if_else_state = IfElseState::Else;
2415
2416                self.builder.position_at_end(*if_else_block);
2417                self.state.reachable = true;
2418
2419                if let ControlFrame::IfElse { else_phis, .. } = self.state.frame_at_depth(0)? {
2420                    // Push our own 'else' phi nodes to the stack.
2421                    for phi in else_phis.clone().iter() {
2422                        self.state.push1(phi.as_basic_value());
2423                    }
2424                };
2425            }
2426
2427            Operator::End => {
2428                let frame = self.state.pop_frame()?;
2429                let current_block = self
2430                    .builder
2431                    .get_insert_block()
2432                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2433
2434                if self.state.reachable {
2435                    for phi in frame.phis().iter().rev() {
2436                        let (value, info) = self.state.pop1_extra()?;
2437                        let value = self.apply_pending_canonicalization(value, info)?;
2438                        phi.add_incoming(&[(&value, current_block)]);
2439                    }
2440
2441                    err!(self.builder.build_unconditional_branch(*frame.code_after()));
2442                }
2443
2444                if let ControlFrame::IfElse {
2445                    if_else,
2446                    next,
2447                    if_else_state: IfElseState::If,
2448                    else_phis,
2449                    ..
2450                } = &frame
2451                {
2452                    for (phi, else_phi) in frame.phis().iter().zip(else_phis.iter()) {
2453                        phi.add_incoming(&[(&else_phi.as_basic_value(), *if_else)]);
2454                    }
2455                    self.builder.position_at_end(*if_else);
2456                    err!(self.builder.build_unconditional_branch(*next));
2457                } else if let ControlFrame::Landingpad { .. } = &frame {
2458                    self.state.pop_landingpad();
2459                };
2460
2461                self.builder.position_at_end(*frame.code_after());
2462                self.state.reset_stack(&frame);
2463
2464                self.state.reachable = true;
2465
2466                // Push each phi value to the value stack.
2467                for phi in frame.phis() {
2468                    if phi.count_incoming() != 0 {
2469                        self.state.push1(phi.as_basic_value());
2470                    } else {
2471                        // TODO if there are no incoming phi values, it means
2472                        // this block has no predecessors, and we can skip it
2473                        // altogether. However, fixing this is non-trivial as
2474                        // some places in the code rely on code getting generated
2475                        // for unreachable end blocks. For now, we let LLVM remove
2476                        // the block during dead code elimination instead.
2477                        let basic_ty = phi.as_basic_value().get_type();
2478                        let placeholder_value = basic_ty.const_zero();
2479                        self.state.push1(placeholder_value);
2480                        phi.as_instruction().erase_from_basic_block();
2481                    }
2482                }
2483            }
2484            Operator::Return => {
2485                let current_block = self
2486                    .builder
2487                    .get_insert_block()
2488                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2489
2490                let frame = self.state.outermost_frame()?;
2491                for phi in frame.phis().to_vec().iter().rev() {
2492                    let (arg, info) = self.state.pop1_extra()?;
2493                    let arg = self.apply_pending_canonicalization(arg, info)?;
2494                    phi.add_incoming(&[(&arg, current_block)]);
2495                }
2496                let frame = self.state.outermost_frame()?;
2497                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2498
2499                self.state.reachable = false;
2500            }
2501
2502            Operator::Unreachable => {
2503                self.build_call_with_param_attributes(
2504                    self.intrinsics.throw_trap,
2505                    &[self.intrinsics.trap_unreachable.into()],
2506                    "throw",
2507                )?;
2508                err!(self.builder.build_unreachable());
2509
2510                self.state.reachable = false;
2511            }
2512
2513            /***************************
2514             * Basic instructions.
2515             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#basic-instructions
2516             ***************************/
2517            Operator::Nop => {
2518                // Do nothing.
2519            }
2520            Operator::Drop => {
2521                self.state.pop1()?;
2522            }
2523
2524            // Generate const values.
2525            Operator::I32Const { value } => {
2526                let i = self.intrinsics.i32_ty.const_int(value as u64, false);
2527                let info = if is_f32_arithmetic(value as u32) {
2528                    ExtraInfo::arithmetic_f32()
2529                } else {
2530                    Default::default()
2531                };
2532                self.state.push1_extra(i, info);
2533            }
2534            Operator::I64Const { value } => {
2535                let i = self.intrinsics.i64_ty.const_int(value as u64, false);
2536                let info = if is_f64_arithmetic(value as u64) {
2537                    ExtraInfo::arithmetic_f64()
2538                } else {
2539                    Default::default()
2540                };
2541                self.state.push1_extra(i, info);
2542            }
2543            Operator::F32Const { value } => {
2544                let bits = self.intrinsics.i32_ty.const_int(value.bits() as u64, false);
2545                let info = if is_f32_arithmetic(value.bits()) {
2546                    ExtraInfo::arithmetic_f32()
2547                } else {
2548                    Default::default()
2549                };
2550                let f = err!(
2551                    self.builder
2552                        .build_bit_cast(bits, self.intrinsics.f32_ty, "f")
2553                );
2554                self.state.push1_extra(f, info);
2555            }
2556            Operator::F64Const { value } => {
2557                let bits = self.intrinsics.i64_ty.const_int(value.bits(), false);
2558                let info = if is_f64_arithmetic(value.bits()) {
2559                    ExtraInfo::arithmetic_f64()
2560                } else {
2561                    Default::default()
2562                };
2563                let f = err!(
2564                    self.builder
2565                        .build_bit_cast(bits, self.intrinsics.f64_ty, "f")
2566                );
2567                self.state.push1_extra(f, info);
2568            }
2569            Operator::V128Const { value } => {
2570                let mut hi: [u8; 8] = Default::default();
2571                let mut lo: [u8; 8] = Default::default();
2572                hi.copy_from_slice(&value.bytes()[0..8]);
2573                lo.copy_from_slice(&value.bytes()[8..16]);
2574                let packed = [u64::from_le_bytes(hi), u64::from_le_bytes(lo)];
2575                let i = self
2576                    .intrinsics
2577                    .i128_ty
2578                    .const_int_arbitrary_precision(&packed);
2579                let mut quad1: [u8; 4] = Default::default();
2580                let mut quad2: [u8; 4] = Default::default();
2581                let mut quad3: [u8; 4] = Default::default();
2582                let mut quad4: [u8; 4] = Default::default();
2583                quad1.copy_from_slice(&value.bytes()[0..4]);
2584                quad2.copy_from_slice(&value.bytes()[4..8]);
2585                quad3.copy_from_slice(&value.bytes()[8..12]);
2586                quad4.copy_from_slice(&value.bytes()[12..16]);
2587                let mut info: ExtraInfo = Default::default();
2588                if is_f32_arithmetic(u32::from_le_bytes(quad1))
2589                    && is_f32_arithmetic(u32::from_le_bytes(quad2))
2590                    && is_f32_arithmetic(u32::from_le_bytes(quad3))
2591                    && is_f32_arithmetic(u32::from_le_bytes(quad4))
2592                {
2593                    info |= ExtraInfo::arithmetic_f32();
2594                }
2595                if is_f64_arithmetic(packed[0]) && is_f64_arithmetic(packed[1]) {
2596                    info |= ExtraInfo::arithmetic_f64();
2597                }
2598                self.state.push1_extra(i, info);
2599            }
2600
2601            Operator::I8x16Splat => {
2602                let (v, i) = self.state.pop1_extra()?;
2603                let v = v.into_int_value();
2604                let v = err!(
2605                    self.builder
2606                        .build_int_truncate(v, self.intrinsics.i8_ty, "")
2607                );
2608                let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
2609                let res = err!(
2610                    self.builder
2611                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
2612                );
2613                self.state.push1_extra(res, i);
2614            }
2615            Operator::I16x8Splat => {
2616                let (v, i) = self.state.pop1_extra()?;
2617                let v = v.into_int_value();
2618                let v = err!(
2619                    self.builder
2620                        .build_int_truncate(v, self.intrinsics.i16_ty, "")
2621                );
2622                let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
2623                let res = err!(
2624                    self.builder
2625                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
2626                );
2627                self.state.push1_extra(res, i);
2628            }
2629            Operator::I32x4Splat => {
2630                let (v, i) = self.state.pop1_extra()?;
2631                let res = self.splat_vector(v, self.intrinsics.i32x4_ty)?;
2632                let res = err!(
2633                    self.builder
2634                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
2635                );
2636                self.state.push1_extra(res, i);
2637            }
2638            Operator::I64x2Splat => {
2639                let (v, i) = self.state.pop1_extra()?;
2640                let res = self.splat_vector(v, self.intrinsics.i64x2_ty)?;
2641                let res = err!(
2642                    self.builder
2643                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
2644                );
2645                self.state.push1_extra(res, i);
2646            }
2647            Operator::F32x4Splat => {
2648                let (v, i) = self.state.pop1_extra()?;
2649                let res = self.splat_vector(v, self.intrinsics.f32x4_ty)?;
2650                let res = err!(
2651                    self.builder
2652                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
2653                );
2654                // The spec is unclear, we interpret splat as preserving NaN
2655                // payload bits.
2656                self.state.push1_extra(res, i);
2657            }
2658            Operator::F64x2Splat => {
2659                let (v, i) = self.state.pop1_extra()?;
2660                let res = self.splat_vector(v, self.intrinsics.f64x2_ty)?;
2661                let res = err!(
2662                    self.builder
2663                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
2664                );
2665                // The spec is unclear, we interpret splat as preserving NaN
2666                // payload bits.
2667                self.state.push1_extra(res, i);
2668            }
2669
2670            // Operate on self.locals.
2671            Operator::LocalGet { local_index } => {
2672                let (type_value, pointer_value) = self.locals[local_index as usize];
2673                let v = err!(self.builder.build_load(
2674                    type_value,
2675                    pointer_value,
2676                    &format!("local_{local_index}_get")
2677                ));
2678                tbaa_label(
2679                    self.module,
2680                    self.intrinsics,
2681                    format!("local {local_index}"),
2682                    v.as_instruction_value().unwrap(),
2683                );
2684                self.state.push1(v);
2685            }
2686            Operator::LocalSet { local_index } => {
2687                let pointer_value = self.locals[local_index as usize].1;
2688                let (v, i) = self.state.pop1_extra()?;
2689                let v = self.apply_pending_canonicalization(v, i)?;
2690                let store = err!(self.builder.build_store(pointer_value, v));
2691                tbaa_label(
2692                    self.module,
2693                    self.intrinsics,
2694                    format!("local {local_index}"),
2695                    store,
2696                );
2697            }
2698            Operator::LocalTee { local_index } => {
2699                let pointer_value = self.locals[local_index as usize].1;
2700                let (v, i) = self.state.peek1_extra()?;
2701                let v = self.apply_pending_canonicalization(v, i)?;
2702                let store = err!(self.builder.build_store(pointer_value, v));
2703                tbaa_label(
2704                    self.module,
2705                    self.intrinsics,
2706                    format!("local {local_index}"),
2707                    store,
2708                );
2709            }
2710
2711            Operator::GlobalGet { global_index } => {
2712                let global_index = GlobalIndex::from_u32(global_index);
2713                match self
2714                    .ctx
2715                    .global(global_index, self.intrinsics, self.module)?
2716                {
2717                    GlobalCache::Const { value } => {
2718                        self.state.push1(*value);
2719                    }
2720                    GlobalCache::Mut {
2721                        ptr_to_value,
2722                        value_type,
2723                    } => {
2724                        let value = err!(self.builder.build_load(*value_type, *ptr_to_value, ""));
2725                        tbaa_label(
2726                            self.module,
2727                            self.intrinsics,
2728                            format!("global {}", global_index.as_u32()),
2729                            value.as_instruction_value().unwrap(),
2730                        );
2731                        self.state.push1(value);
2732                    }
2733                }
2734            }
2735            Operator::GlobalSet { global_index } => {
2736                let global_index = GlobalIndex::from_u32(global_index);
2737                match self
2738                    .ctx
2739                    .global(global_index, self.intrinsics, self.module)?
2740                {
2741                    GlobalCache::Const { value: _ } => {
2742                        return Err(CompileError::Codegen(format!(
2743                            "global.set on immutable global index {}",
2744                            global_index.as_u32()
2745                        )));
2746                    }
2747                    GlobalCache::Mut { ptr_to_value, .. } => {
2748                        let ptr_to_value = *ptr_to_value;
2749                        let (value, info) = self.state.pop1_extra()?;
2750                        let value = self.apply_pending_canonicalization(value, info)?;
2751                        let store = err!(self.builder.build_store(ptr_to_value, value));
2752                        tbaa_label(
2753                            self.module,
2754                            self.intrinsics,
2755                            format!("global {}", global_index.as_u32()),
2756                            store,
2757                        );
2758                    }
2759                }
2760            }
2761
2762            // `TypedSelect` must be used for extern refs so ref counting should
2763            // be done with TypedSelect. But otherwise they're the same.
2764            Operator::TypedSelect { .. } | Operator::Select => {
2765                let ((v1, i1), (v2, i2), (cond, _)) = self.state.pop3_extra()?;
2766                // We don't bother canonicalizing 'cond' here because we only
2767                // compare it to zero, and that's invariant under
2768                // canonicalization.
2769
2770                // If the pending bits of v1 and v2 are the same, we can pass
2771                // them along to the result. Otherwise, apply pending
2772                // canonicalizations now.
2773                let (v1, i1, v2, i2) = if i1.has_pending_f32_nan() != i2.has_pending_f32_nan()
2774                    || i1.has_pending_f64_nan() != i2.has_pending_f64_nan()
2775                {
2776                    (
2777                        self.apply_pending_canonicalization(v1, i1)?,
2778                        i1.strip_pending(),
2779                        self.apply_pending_canonicalization(v2, i2)?,
2780                        i2.strip_pending(),
2781                    )
2782                } else {
2783                    (v1, i1, v2, i2)
2784                };
2785                let cond_value = err!(self.builder.build_int_compare(
2786                    IntPredicate::NE,
2787                    cond.into_int_value(),
2788                    self.intrinsics.i32_zero,
2789                    "",
2790                ));
2791                let res = err!(self.builder.build_select(cond_value, v1, v2, ""));
2792                let info = {
2793                    let mut info = (i1.strip_pending() & i2.strip_pending())?;
2794                    if i1.has_pending_f32_nan() {
2795                        debug_assert!(i2.has_pending_f32_nan());
2796                        info = (info | ExtraInfo::pending_f32_nan())?;
2797                    }
2798                    if i1.has_pending_f64_nan() {
2799                        debug_assert!(i2.has_pending_f64_nan());
2800                        info = (info | ExtraInfo::pending_f64_nan())?;
2801                    }
2802                    info
2803                };
2804                self.state.push1_extra(res, info);
2805            }
2806            Operator::Call { function_index } => {
2807                let func_index = FunctionIndex::from_u32(function_index);
2808                let sigindex = &self.wasm_module.functions[func_index];
2809                let func_type = &self.wasm_module.signatures[*sigindex];
2810
2811                let FunctionCache {
2812                    func,
2813                    llvm_func_type,
2814                    vmctx: callee_vmctx,
2815                    imported_include_m0_param,
2816                    attrs,
2817                } = if let Some(local_func_index) = self.wasm_module.local_func_index(func_index) {
2818                    let function_name = self
2819                        .symbol_registry
2820                        .symbol_to_name(Symbol::LocalFunction(local_func_index));
2821
2822                    self.ctx.local_func(
2823                        local_func_index,
2824                        func_index,
2825                        self.intrinsics,
2826                        self.module,
2827                        self.context,
2828                        func_type,
2829                        &function_name,
2830                    )?
2831                } else {
2832                    self.ctx
2833                        .imported_func(func_index, self.intrinsics, self.context, func_type)?
2834                };
2835                let llvm_func_type = *llvm_func_type;
2836                let func = *func;
2837                let callee_vmctx = *callee_vmctx;
2838                let imported_include_m0_param = *imported_include_m0_param;
2839                let attrs = attrs.clone();
2840
2841                /*
2842                let func_ptr = self.llvm.functions.borrow_mut()[&func_index];
2843
2844                (params, func_ptr.as_global_value().as_pointer_value())
2845                */
2846                let params = self.state.popn_save_extra(func_type.params().len())?;
2847
2848                // Apply pending canonicalizations.
2849                let params = params
2850                    .iter()
2851                    .zip(func_type.params().iter())
2852                    .map(|((v, info), wasm_ty)| match wasm_ty {
2853                        Type::F32 => err_nt!(self.builder.build_bit_cast(
2854                            self.apply_pending_canonicalization(*v, *info)?,
2855                            self.intrinsics.f32_ty,
2856                            "",
2857                        )),
2858                        Type::F64 => err_nt!(self.builder.build_bit_cast(
2859                            self.apply_pending_canonicalization(*v, *info)?,
2860                            self.intrinsics.f64_ty,
2861                            "",
2862                        )),
2863                        Type::V128 => self.apply_pending_canonicalization(*v, *info),
2864                        _ => Ok(*v),
2865                    })
2866                    .collect::<Result<Vec<_>, _>>()?;
2867
2868                if let (Some(m0_param), Some(include_m0_param)) =
2869                    (self.m0_param, imported_include_m0_param)
2870                {
2871                    /* For imported functions, we must be careful about when to include `g0_param`:
2872                    imports from another Wasm module expect it, while host-function imports do not.
2873                    */
2874                    let (llvm_func_type_no_m0, llvm_func_attrs_no_m0) =
2875                        self.abi.func_type_to_llvm(
2876                            self.context,
2877                            self.intrinsics,
2878                            Some(self.ctx.get_offsets()),
2879                            func_type,
2880                            false,
2881                        )?;
2882                    let params_with_m0 = self.abi.args_to_call(
2883                        &self.alloca_builder,
2884                        func_type,
2885                        &llvm_func_type,
2886                        callee_vmctx.into_pointer_value(),
2887                        params.as_slice(),
2888                        self.intrinsics,
2889                        Some(m0_param),
2890                    )?;
2891                    let params_no_m0 = self.abi.args_to_call(
2892                        &self.alloca_builder,
2893                        func_type,
2894                        &llvm_func_type_no_m0,
2895                        callee_vmctx.into_pointer_value(),
2896                        params.as_slice(),
2897                        self.intrinsics,
2898                        None,
2899                    )?;
2900
2901                    let include_m0_call_block = self
2902                        .context
2903                        .append_basic_block(self.function, "call_block_with_m0");
2904                    let skip_m0_call_block =
2905                        self.context.append_basic_block(self.function, "call_block");
2906                    let call_cont = self.context.append_basic_block(self.function, "call_cont");
2907                    err!(self.builder.build_conditional_branch(
2908                        include_m0_param,
2909                        include_m0_call_block,
2910                        skip_m0_call_block,
2911                    ));
2912
2913                    self.builder.position_at_end(include_m0_call_block);
2914                    let call_site_with_m0 = self.build_indirect_call_or_invoke(
2915                        llvm_func_type,
2916                        func,
2917                        params_with_m0.as_slice(),
2918                        "then_block_with_m0",
2919                    )?;
2920                    for (attr, attr_loc) in &attrs {
2921                        call_site_with_m0.add_attribute(*attr_loc, *attr);
2922                    }
2923                    let rets_with_m0 = self.abi.rets_from_call(
2924                        &self.builder,
2925                        self.intrinsics,
2926                        call_site_with_m0,
2927                        func_type,
2928                    )?;
2929                    let with_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
2930                        CompileError::Codegen(
2931                            "missing insertion block after call with m0".to_string(),
2932                        )
2933                    })?;
2934                    err!(self.builder.build_unconditional_branch(call_cont));
2935
2936                    self.builder.position_at_end(skip_m0_call_block);
2937                    let call_site_no_m0 = self.build_indirect_call_or_invoke(
2938                        llvm_func_type_no_m0,
2939                        func,
2940                        params_no_m0.as_slice(),
2941                        "then_block",
2942                    )?;
2943                    for (attr, attr_loc) in &llvm_func_attrs_no_m0 {
2944                        call_site_no_m0.add_attribute(*attr_loc, *attr);
2945                    }
2946                    let rets_no_m0 = self.abi.rets_from_call(
2947                        &self.builder,
2948                        self.intrinsics,
2949                        call_site_no_m0,
2950                        func_type,
2951                    )?;
2952                    let no_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
2953                        CompileError::Codegen(
2954                            "missing insertion block after call without m0".to_string(),
2955                        )
2956                    })?;
2957                    err!(self.builder.build_unconditional_branch(call_cont));
2958
2959                    self.builder.position_at_end(call_cont);
2960                    for i in 0..rets_with_m0.len() {
2961                        let with_m0 = rets_with_m0[i];
2962                        let no_m0 = rets_no_m0[i];
2963                        let phi = err!(self.builder.build_phi(with_m0.get_type(), ""));
2964                        phi.add_incoming(&[(&with_m0, with_m0_pred), (&no_m0, no_m0_pred)]);
2965                        self.state.push1(phi.as_basic_value());
2966                    }
2967                } else {
2968                    let params = self.abi.args_to_call(
2969                        &self.alloca_builder,
2970                        func_type,
2971                        &llvm_func_type,
2972                        callee_vmctx.into_pointer_value(),
2973                        params.as_slice(),
2974                        self.intrinsics,
2975                        self.m0_param,
2976                    )?;
2977
2978                    let call_site = self.build_indirect_call_or_invoke(
2979                        llvm_func_type,
2980                        func,
2981                        params.as_slice(),
2982                        "then_block",
2983                    )?;
2984                    for (attr, attr_loc) in attrs {
2985                        call_site.add_attribute(attr_loc, attr);
2986                    }
2987
2988                    self.abi
2989                        .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2990                        .iter()
2991                        .for_each(|ret| self.state.push1(*ret));
2992                }
2993            }
2994            Operator::CallIndirect {
2995                type_index,
2996                table_index,
2997            } => {
2998                let sigindex = SignatureIndex::from_u32(type_index);
2999                let func_type = &self.wasm_module.signatures[sigindex];
3000                let expected_dynamic_sigindex =
3001                    self.ctx
3002                        .dynamic_sigindex(sigindex, self.intrinsics, self.module)?;
3003                let (table_base, table_bound) = self.ctx.table(
3004                    TableIndex::from_u32(table_index),
3005                    self.intrinsics,
3006                    self.module,
3007                    &self.builder,
3008                )?;
3009                let func_index = self.state.pop1()?.into_int_value();
3010
3011                let truncated_table_bounds = err!(self.builder.build_int_truncate(
3012                    table_bound,
3013                    self.intrinsics.i32_ty,
3014                    "truncated_table_bounds",
3015                ));
3016
3017                // First, check if the index is outside of the table bounds.
3018                let index_in_bounds = err!(self.builder.build_int_compare(
3019                    IntPredicate::ULT,
3020                    func_index,
3021                    truncated_table_bounds,
3022                    "index_in_bounds",
3023                ));
3024
3025                let index_in_bounds = self
3026                    .build_call_with_param_attributes(
3027                        self.intrinsics.expect_i1,
3028                        &[
3029                            index_in_bounds.into(),
3030                            self.intrinsics.i1_ty.const_int(1, false).into(),
3031                        ],
3032                        "index_in_bounds_expect",
3033                    )?
3034                    .try_as_basic_value()
3035                    .unwrap_basic()
3036                    .into_int_value();
3037
3038                let in_bounds_continue_block = self
3039                    .context
3040                    .append_basic_block(self.function, "in_bounds_continue_block");
3041                let not_in_bounds_block = self
3042                    .context
3043                    .append_basic_block(self.function, "not_in_bounds_block");
3044                err!(self.builder.build_conditional_branch(
3045                    index_in_bounds,
3046                    in_bounds_continue_block,
3047                    not_in_bounds_block,
3048                ));
3049                self.builder.position_at_end(not_in_bounds_block);
3050                self.build_call_with_param_attributes(
3051                    self.intrinsics.throw_trap,
3052                    &[self.intrinsics.trap_table_access_oob.into()],
3053                    "throw",
3054                )?;
3055                err!(self.builder.build_unreachable());
3056                self.builder.position_at_end(in_bounds_continue_block);
3057
3058                // We assume the table has the `funcref` (pointer to `anyfunc`)
3059                // element type.
3060                let casted_table_base = err!(self.builder.build_pointer_cast(
3061                    table_base,
3062                    self.context.ptr_type(AddressSpace::default()),
3063                    "casted_table_base",
3064                ));
3065
3066                let funcref_ptr = unsafe {
3067                    err!(self.builder.build_in_bounds_gep(
3068                        self.intrinsics.ptr_ty,
3069                        casted_table_base,
3070                        &[func_index],
3071                        "funcref_ptr",
3072                    ))
3073                };
3074
3075                // a funcref (pointer to `anyfunc`)
3076                let anyfunc_struct_ptr = err!(self.builder.build_load(
3077                    self.intrinsics.ptr_ty,
3078                    funcref_ptr,
3079                    "anyfunc_struct_ptr",
3080                ))
3081                .into_pointer_value();
3082
3083                // trap if we're trying to call a null funcref
3084                {
3085                    let funcref_not_null = err!(
3086                        self.builder
3087                            .build_is_not_null(anyfunc_struct_ptr, "null_funcref_check")
3088                    );
3089
3090                    let funcref_continue_deref_block = self
3091                        .context
3092                        .append_basic_block(self.function, "funcref_continue_deref_block");
3093
3094                    let funcref_is_null_block = self
3095                        .context
3096                        .append_basic_block(self.function, "funcref_is_null_block");
3097                    err!(self.builder.build_conditional_branch(
3098                        funcref_not_null,
3099                        funcref_continue_deref_block,
3100                        funcref_is_null_block,
3101                    ));
3102                    self.builder.position_at_end(funcref_is_null_block);
3103                    self.build_call_with_param_attributes(
3104                        self.intrinsics.throw_trap,
3105                        &[self.intrinsics.trap_call_indirect_null.into()],
3106                        "throw",
3107                    )?;
3108                    err!(self.builder.build_unreachable());
3109                    self.builder.position_at_end(funcref_continue_deref_block);
3110                }
3111
3112                // Load things from the anyfunc data structure.
3113                let func_ptr_ptr = self
3114                    .builder
3115                    .build_struct_gep(
3116                        self.intrinsics.anyfunc_ty,
3117                        anyfunc_struct_ptr,
3118                        0,
3119                        "func_ptr_ptr",
3120                    )
3121                    .unwrap();
3122                let sigindex_ptr = self
3123                    .builder
3124                    .build_struct_gep(
3125                        self.intrinsics.anyfunc_ty,
3126                        anyfunc_struct_ptr,
3127                        1,
3128                        "sigindex_ptr",
3129                    )
3130                    .unwrap();
3131                let ctx_ptr_ptr = self
3132                    .builder
3133                    .build_struct_gep(
3134                        self.intrinsics.anyfunc_ty,
3135                        anyfunc_struct_ptr,
3136                        2,
3137                        "ctx_ptr_ptr",
3138                    )
3139                    .unwrap();
3140                let (func_ptr, found_dynamic_sigindex, ctx_ptr) = (
3141                    err!(
3142                        self.builder
3143                            .build_load(self.intrinsics.ptr_ty, func_ptr_ptr, "func_ptr")
3144                    )
3145                    .into_pointer_value(),
3146                    err!(
3147                        self.builder
3148                            .build_load(self.intrinsics.i32_ty, sigindex_ptr, "sigindex")
3149                    )
3150                    .into_int_value(),
3151                    err!(
3152                        self.builder
3153                            .build_load(self.intrinsics.ptr_ty, ctx_ptr_ptr, "ctx_ptr")
3154                    ),
3155                );
3156
3157                // Next, check if the table element is initialized.
3158
3159                // TODO: we may not need this check anymore
3160                let elem_initialized = err!(self.builder.build_is_not_null(func_ptr, ""));
3161
3162                // Next, check if the signature id is correct.
3163
3164                let sigindices_equal = err!(self.builder.build_int_compare(
3165                    IntPredicate::EQ,
3166                    expected_dynamic_sigindex,
3167                    found_dynamic_sigindex,
3168                    "sigindices_equal",
3169                ));
3170
3171                let initialized_and_sigindices_match = err!(self.builder.build_and(
3172                    elem_initialized,
3173                    sigindices_equal,
3174                    ""
3175                ));
3176
3177                // Tell llvm that `expected_dynamic_sigindex` should equal `found_dynamic_sigindex`.
3178                let initialized_and_sigindices_match = self
3179                    .build_call_with_param_attributes(
3180                        self.intrinsics.expect_i1,
3181                        &[
3182                            initialized_and_sigindices_match.into(),
3183                            self.intrinsics.i1_ty.const_int(1, false).into(),
3184                        ],
3185                        "initialized_and_sigindices_match_expect",
3186                    )?
3187                    .try_as_basic_value()
3188                    .unwrap_basic()
3189                    .into_int_value();
3190
3191                let continue_block = self
3192                    .context
3193                    .append_basic_block(self.function, "continue_block");
3194                let sigindices_notequal_block = self
3195                    .context
3196                    .append_basic_block(self.function, "sigindices_notequal_block");
3197                err!(self.builder.build_conditional_branch(
3198                    initialized_and_sigindices_match,
3199                    continue_block,
3200                    sigindices_notequal_block,
3201                ));
3202
3203                self.builder.position_at_end(sigindices_notequal_block);
3204                let trap_code = err!(self.builder.build_select(
3205                    elem_initialized,
3206                    self.intrinsics.trap_call_indirect_sig,
3207                    self.intrinsics.trap_call_indirect_null,
3208                    "",
3209                ));
3210                self.build_call_with_param_attributes(
3211                    self.intrinsics.throw_trap,
3212                    &[trap_code.into()],
3213                    "throw",
3214                )?;
3215                err!(self.builder.build_unreachable());
3216                self.builder.position_at_end(continue_block);
3217
3218                if self.m0_param.is_some() {
3219                    self.build_m0_indirect_call(
3220                        table_index,
3221                        ctx_ptr.into_pointer_value(),
3222                        func_type,
3223                        func_ptr,
3224                        func_index,
3225                    )?;
3226                } else {
3227                    let call_site = self.build_indirect_call(
3228                        ctx_ptr.into_pointer_value(),
3229                        func_type,
3230                        func_ptr,
3231                        None,
3232                    )?;
3233
3234                    self.abi
3235                        .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3236                        .iter()
3237                        .for_each(|ret| self.state.push1(*ret));
3238                }
3239            }
3240
3241            /***************************
3242             * Integer Arithmetic instructions.
3243             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-arithmetic-instructions
3244             ***************************/
3245            Operator::I32Add | Operator::I64Add => {
3246                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3247                let v1 = self.apply_pending_canonicalization(v1, i1)?;
3248                let v2 = self.apply_pending_canonicalization(v2, i2)?;
3249                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3250                let res = err!(self.builder.build_int_add(v1, v2, ""));
3251                self.state.push1(res);
3252            }
3253            Operator::I8x16Add => {
3254                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3255                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3256                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3257                let res = err!(self.builder.build_int_add(v1, v2, ""));
3258                let res = err!(
3259                    self.builder
3260                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3261                );
3262                self.state.push1(res);
3263            }
3264            Operator::I16x8Add => {
3265                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3266                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3267                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3268                let res = err!(self.builder.build_int_add(v1, v2, ""));
3269                let res = err!(
3270                    self.builder
3271                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3272                );
3273                self.state.push1(res);
3274            }
3275            Operator::I16x8ExtAddPairwiseI8x16S | Operator::I16x8ExtAddPairwiseI8x16U => {
3276                let extend_op = match op {
3277                    Operator::I16x8ExtAddPairwiseI8x16S => {
3278                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, "")
3279                    }
3280                    Operator::I16x8ExtAddPairwiseI8x16U => {
3281                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, "")
3282                    }
3283                    _ => unreachable!("Unhandled internal variant"),
3284                };
3285                let (v, i) = self.state.pop1_extra()?;
3286                let (v, _) = self.v128_into_i8x16(v, i)?;
3287
3288                let left = err!(self.builder.build_shuffle_vector(
3289                    v,
3290                    v.get_type().get_undef(),
3291                    VectorType::const_vector(&[
3292                        self.intrinsics.i32_consts[0],
3293                        self.intrinsics.i32_consts[2],
3294                        self.intrinsics.i32_consts[4],
3295                        self.intrinsics.i32_consts[6],
3296                        self.intrinsics.i32_consts[8],
3297                        self.intrinsics.i32_consts[10],
3298                        self.intrinsics.i32_consts[12],
3299                        self.intrinsics.i32_consts[14],
3300                    ]),
3301                    "",
3302                ));
3303                let left = err!(extend_op(self, left));
3304                let right = err!(self.builder.build_shuffle_vector(
3305                    v,
3306                    v.get_type().get_undef(),
3307                    VectorType::const_vector(&[
3308                        self.intrinsics.i32_consts[1],
3309                        self.intrinsics.i32_consts[3],
3310                        self.intrinsics.i32_consts[5],
3311                        self.intrinsics.i32_consts[7],
3312                        self.intrinsics.i32_consts[9],
3313                        self.intrinsics.i32_consts[11],
3314                        self.intrinsics.i32_consts[13],
3315                        self.intrinsics.i32_consts[15],
3316                    ]),
3317                    "",
3318                ));
3319                let right = err!(extend_op(self, right));
3320
3321                let res = err!(self.builder.build_int_add(left, right, ""));
3322                let res = err!(
3323                    self.builder
3324                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3325                );
3326                self.state.push1(res);
3327            }
3328            Operator::I32x4Add => {
3329                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3330                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3331                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3332                let res = err!(self.builder.build_int_add(v1, v2, ""));
3333                let res = err!(
3334                    self.builder
3335                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3336                );
3337                self.state.push1(res);
3338            }
3339            Operator::I32x4ExtAddPairwiseI16x8S | Operator::I32x4ExtAddPairwiseI16x8U => {
3340                let extend_op = match op {
3341                    Operator::I32x4ExtAddPairwiseI16x8S => {
3342                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
3343                    }
3344                    Operator::I32x4ExtAddPairwiseI16x8U => {
3345                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
3346                    }
3347                    _ => unreachable!("Unhandled internal variant"),
3348                };
3349                let (v, i) = self.state.pop1_extra()?;
3350                let (v, _) = self.v128_into_i16x8(v, i)?;
3351
3352                let left = err!(self.builder.build_shuffle_vector(
3353                    v,
3354                    v.get_type().get_undef(),
3355                    VectorType::const_vector(&[
3356                        self.intrinsics.i32_consts[0],
3357                        self.intrinsics.i32_consts[2],
3358                        self.intrinsics.i32_consts[4],
3359                        self.intrinsics.i32_consts[6],
3360                    ]),
3361                    "",
3362                ));
3363                let left = err!(extend_op(self, left));
3364                let right = err!(self.builder.build_shuffle_vector(
3365                    v,
3366                    v.get_type().get_undef(),
3367                    VectorType::const_vector(&[
3368                        self.intrinsics.i32_consts[1],
3369                        self.intrinsics.i32_consts[3],
3370                        self.intrinsics.i32_consts[5],
3371                        self.intrinsics.i32_consts[7],
3372                    ]),
3373                    "",
3374                ));
3375                let right = err!(extend_op(self, right));
3376
3377                let res = err!(self.builder.build_int_add(left, right, ""));
3378                let res = err!(
3379                    self.builder
3380                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3381                );
3382                self.state.push1(res);
3383            }
3384            Operator::I64x2Add => {
3385                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3386                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3387                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3388                let res = err!(self.builder.build_int_add(v1, v2, ""));
3389                let res = err!(
3390                    self.builder
3391                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3392                );
3393                self.state.push1(res);
3394            }
3395            Operator::I8x16AddSatS => {
3396                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3397                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3398                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3399                let res = self
3400                    .build_call_with_param_attributes(
3401                        self.intrinsics.sadd_sat_i8x16,
3402                        &[v1.into(), v2.into()],
3403                        "",
3404                    )?
3405                    .try_as_basic_value()
3406                    .unwrap_basic();
3407                let res = err!(
3408                    self.builder
3409                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3410                );
3411                self.state.push1(res);
3412            }
3413            Operator::I16x8AddSatS => {
3414                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3415                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3416                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3417                let res = self
3418                    .build_call_with_param_attributes(
3419                        self.intrinsics.sadd_sat_i16x8,
3420                        &[v1.into(), v2.into()],
3421                        "",
3422                    )?
3423                    .try_as_basic_value()
3424                    .unwrap_basic();
3425                let res = err!(
3426                    self.builder
3427                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3428                );
3429                self.state.push1(res);
3430            }
3431            Operator::I8x16AddSatU => {
3432                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3433                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3434                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3435                let res = self
3436                    .build_call_with_param_attributes(
3437                        self.intrinsics.uadd_sat_i8x16,
3438                        &[v1.into(), v2.into()],
3439                        "",
3440                    )?
3441                    .try_as_basic_value()
3442                    .unwrap_basic();
3443                let res = err!(
3444                    self.builder
3445                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3446                );
3447                self.state.push1(res);
3448            }
3449            Operator::I16x8AddSatU => {
3450                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3451                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3452                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3453                let res = self
3454                    .build_call_with_param_attributes(
3455                        self.intrinsics.uadd_sat_i16x8,
3456                        &[v1.into(), v2.into()],
3457                        "",
3458                    )?
3459                    .try_as_basic_value()
3460                    .unwrap_basic();
3461                let res = err!(
3462                    self.builder
3463                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3464                );
3465                self.state.push1(res);
3466            }
3467            Operator::I32Sub | Operator::I64Sub => {
3468                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3469                let v1 = self.apply_pending_canonicalization(v1, i1)?;
3470                let v2 = self.apply_pending_canonicalization(v2, i2)?;
3471                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3472                let res = err!(self.builder.build_int_sub(v1, v2, ""));
3473                self.state.push1(res);
3474            }
3475            Operator::I8x16Sub => {
3476                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3477                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3478                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3479                let res = err!(self.builder.build_int_sub(v1, v2, ""));
3480                let res = err!(
3481                    self.builder
3482                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3483                );
3484                self.state.push1(res);
3485            }
3486            Operator::I16x8Sub => {
3487                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3488                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3489                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3490                let res = err!(self.builder.build_int_sub(v1, v2, ""));
3491                let res = err!(
3492                    self.builder
3493                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3494                );
3495                self.state.push1(res);
3496            }
3497            Operator::I32x4Sub => {
3498                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3499                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3500                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3501                let res = err!(self.builder.build_int_sub(v1, v2, ""));
3502                let res = err!(
3503                    self.builder
3504                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3505                );
3506                self.state.push1(res);
3507            }
3508            Operator::I64x2Sub => {
3509                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3510                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3511                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3512                let res = err!(self.builder.build_int_sub(v1, v2, ""));
3513                let res = err!(
3514                    self.builder
3515                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3516                );
3517                self.state.push1(res);
3518            }
3519            Operator::I8x16SubSatS => {
3520                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3521                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3522                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3523                let res = self
3524                    .build_call_with_param_attributes(
3525                        self.intrinsics.ssub_sat_i8x16,
3526                        &[v1.into(), v2.into()],
3527                        "",
3528                    )?
3529                    .try_as_basic_value()
3530                    .unwrap_basic();
3531                let res = err!(
3532                    self.builder
3533                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3534                );
3535                self.state.push1(res);
3536            }
3537            Operator::I16x8SubSatS => {
3538                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3539                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3540                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3541                let res = self
3542                    .build_call_with_param_attributes(
3543                        self.intrinsics.ssub_sat_i16x8,
3544                        &[v1.into(), v2.into()],
3545                        "",
3546                    )?
3547                    .try_as_basic_value()
3548                    .unwrap_basic();
3549                let res = err!(
3550                    self.builder
3551                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3552                );
3553                self.state.push1(res);
3554            }
3555            Operator::I8x16SubSatU => {
3556                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3557                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3558                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3559                let res = self
3560                    .build_call_with_param_attributes(
3561                        self.intrinsics.usub_sat_i8x16,
3562                        &[v1.into(), v2.into()],
3563                        "",
3564                    )?
3565                    .try_as_basic_value()
3566                    .unwrap_basic();
3567                let res = err!(
3568                    self.builder
3569                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3570                );
3571                self.state.push1(res);
3572            }
3573            Operator::I16x8SubSatU => {
3574                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3575                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3576                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3577                let res = self
3578                    .build_call_with_param_attributes(
3579                        self.intrinsics.usub_sat_i16x8,
3580                        &[v1.into(), v2.into()],
3581                        "",
3582                    )?
3583                    .try_as_basic_value()
3584                    .unwrap_basic();
3585                let res = err!(
3586                    self.builder
3587                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3588                );
3589                self.state.push1(res);
3590            }
3591            Operator::I32Mul | Operator::I64Mul => {
3592                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3593                let v1 = self.apply_pending_canonicalization(v1, i1)?;
3594                let v2 = self.apply_pending_canonicalization(v2, i2)?;
3595                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
3596                let res = err!(self.builder.build_int_mul(v1, v2, ""));
3597                self.state.push1(res);
3598            }
3599            Operator::I16x8Mul => {
3600                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3601                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3602                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3603                let res = err!(self.builder.build_int_mul(v1, v2, ""));
3604                let res = err!(
3605                    self.builder
3606                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3607                );
3608                self.state.push1(res);
3609            }
3610            Operator::I32x4Mul => {
3611                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3612                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3613                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3614                let res = err!(self.builder.build_int_mul(v1, v2, ""));
3615                let res = err!(
3616                    self.builder
3617                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3618                );
3619                self.state.push1(res);
3620            }
3621            Operator::I64x2Mul => {
3622                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3623                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
3624                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
3625                let res = err!(self.builder.build_int_mul(v1, v2, ""));
3626                let res = err!(
3627                    self.builder
3628                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3629                );
3630                self.state.push1(res);
3631            }
3632            Operator::I16x8RelaxedQ15mulrS if self.cpu_features.contains(CpuFeature::SSSE3) => {
3633                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3634                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3635                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3636                let res = self
3637                    .build_call_with_param_attributes(
3638                        self.intrinsics.x86_64.pmulhrsw128,
3639                        &[v1.into(), v2.into()],
3640                        "",
3641                    )?
3642                    .try_as_basic_value()
3643                    .unwrap_basic();
3644                let res = err!(
3645                    self.builder
3646                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3647                );
3648                self.state.push1(res);
3649            }
3650            Operator::I16x8Q15MulrSatS | Operator::I16x8RelaxedQ15mulrS => {
3651                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3652                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3653                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3654
3655                let max_value = self.intrinsics.i16_ty.const_int(i16::MAX as u64, false);
3656                let max_values = VectorType::const_vector(&[max_value; 8]);
3657
3658                let v1 = err!(
3659                    self.builder
3660                        .build_int_s_extend(v1, self.intrinsics.i32x8_ty, "")
3661                );
3662                let v2 = err!(
3663                    self.builder
3664                        .build_int_s_extend(v2, self.intrinsics.i32x8_ty, "")
3665                );
3666                let res = err!(self.builder.build_int_mul(v1, v2, ""));
3667
3668                // magic number specified by the spec
3669                let bit = self.intrinsics.i32_ty.const_int(0x4000, false);
3670                let bits = VectorType::const_vector(&[bit; 8]);
3671
3672                let res = err!(self.builder.build_int_add(res, bits, ""));
3673
3674                let fifteen = self.intrinsics.i32_consts[15];
3675                let fifteens = VectorType::const_vector(&[fifteen; 8]);
3676
3677                let res = err!(self.builder.build_right_shift(res, fifteens, true, ""));
3678                let saturate_up = {
3679                    let max_values = err!(self.builder.build_int_s_extend(
3680                        max_values,
3681                        self.intrinsics.i32x8_ty,
3682                        ""
3683                    ));
3684                    err!(
3685                        self.builder
3686                            .build_int_compare(IntPredicate::SGT, res, max_values, "")
3687                    )
3688                };
3689
3690                let res = err!(
3691                    self.builder
3692                        .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
3693                );
3694
3695                let res = err!(self.builder.build_select(saturate_up, max_values, res, ""))
3696                    .into_vector_value();
3697                let res = err!(
3698                    self.builder
3699                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3700                );
3701                self.state.push1(res);
3702            }
3703            Operator::I16x8ExtMulLowI8x16S
3704            | Operator::I16x8ExtMulLowI8x16U
3705            | Operator::I16x8ExtMulHighI8x16S
3706            | Operator::I16x8ExtMulHighI8x16U => {
3707                let extend_op = match op {
3708                    Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulHighI8x16S => {
3709                        |s: &Self, v| -> Result<VectorValue, CompileError> {
3710                            err_nt!(s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, ""))
3711                        }
3712                    }
3713                    Operator::I16x8ExtMulLowI8x16U | Operator::I16x8ExtMulHighI8x16U => {
3714                        |s: &Self, v| -> Result<VectorValue, CompileError> {
3715                            err_nt!(s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, ""))
3716                        }
3717                    }
3718                    _ => unreachable!("Unhandled internal variant"),
3719                };
3720                let shuffle_array = match op {
3721                    Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulLowI8x16U => [
3722                        self.intrinsics.i32_consts[0],
3723                        self.intrinsics.i32_consts[1],
3724                        self.intrinsics.i32_consts[2],
3725                        self.intrinsics.i32_consts[3],
3726                        self.intrinsics.i32_consts[4],
3727                        self.intrinsics.i32_consts[5],
3728                        self.intrinsics.i32_consts[6],
3729                        self.intrinsics.i32_consts[7],
3730                    ],
3731                    Operator::I16x8ExtMulHighI8x16S | Operator::I16x8ExtMulHighI8x16U => [
3732                        self.intrinsics.i32_consts[8],
3733                        self.intrinsics.i32_consts[9],
3734                        self.intrinsics.i32_consts[10],
3735                        self.intrinsics.i32_consts[11],
3736                        self.intrinsics.i32_consts[12],
3737                        self.intrinsics.i32_consts[13],
3738                        self.intrinsics.i32_consts[14],
3739                        self.intrinsics.i32_consts[15],
3740                    ],
3741                    _ => unreachable!("Unhandled internal variant"),
3742                };
3743                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3744                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3745                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3746                let val1 = err!(self.builder.build_shuffle_vector(
3747                    v1,
3748                    v1.get_type().get_undef(),
3749                    VectorType::const_vector(&shuffle_array),
3750                    "",
3751                ));
3752                let val1 = err!(extend_op(self, val1));
3753                let val2 = err!(self.builder.build_shuffle_vector(
3754                    v2,
3755                    v2.get_type().get_undef(),
3756                    VectorType::const_vector(&shuffle_array),
3757                    "",
3758                ));
3759                let val2 = err!(extend_op(self, val2));
3760                let res = err!(self.builder.build_int_mul(val1, val2, ""));
3761                let res = err!(
3762                    self.builder
3763                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3764                );
3765                self.state.push1(res);
3766            }
3767            Operator::I32x4ExtMulLowI16x8S
3768            | Operator::I32x4ExtMulLowI16x8U
3769            | Operator::I32x4ExtMulHighI16x8S
3770            | Operator::I32x4ExtMulHighI16x8U => {
3771                let extend_op = match op {
3772                    Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulHighI16x8S => {
3773                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
3774                    }
3775                    Operator::I32x4ExtMulLowI16x8U | Operator::I32x4ExtMulHighI16x8U => {
3776                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
3777                    }
3778                    _ => unreachable!("Unhandled internal variant"),
3779                };
3780                let shuffle_array = match op {
3781                    Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulLowI16x8U => [
3782                        self.intrinsics.i32_consts[0],
3783                        self.intrinsics.i32_consts[1],
3784                        self.intrinsics.i32_consts[2],
3785                        self.intrinsics.i32_consts[3],
3786                    ],
3787                    Operator::I32x4ExtMulHighI16x8S | Operator::I32x4ExtMulHighI16x8U => [
3788                        self.intrinsics.i32_consts[4],
3789                        self.intrinsics.i32_consts[5],
3790                        self.intrinsics.i32_consts[6],
3791                        self.intrinsics.i32_consts[7],
3792                    ],
3793                    _ => unreachable!("Unhandled internal variant"),
3794                };
3795                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3796                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3797                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3798                let val1 = err!(self.builder.build_shuffle_vector(
3799                    v1,
3800                    v1.get_type().get_undef(),
3801                    VectorType::const_vector(&shuffle_array),
3802                    "",
3803                ));
3804                let val1 = err!(extend_op(self, val1));
3805                let val2 = err!(self.builder.build_shuffle_vector(
3806                    v2,
3807                    v2.get_type().get_undef(),
3808                    VectorType::const_vector(&shuffle_array),
3809                    "",
3810                ));
3811                let val2 = err!(extend_op(self, val2));
3812                let res = err!(self.builder.build_int_mul(val1, val2, ""));
3813                let res = err!(
3814                    self.builder
3815                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3816                );
3817                self.state.push1(res);
3818            }
3819            Operator::I64x2ExtMulLowI32x4S
3820            | Operator::I64x2ExtMulLowI32x4U
3821            | Operator::I64x2ExtMulHighI32x4S
3822            | Operator::I64x2ExtMulHighI32x4U => {
3823                let extend_op = match op {
3824                    Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulHighI32x4S => {
3825                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
3826                    }
3827                    Operator::I64x2ExtMulLowI32x4U | Operator::I64x2ExtMulHighI32x4U => {
3828                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
3829                    }
3830                    _ => unreachable!("Unhandled internal variant"),
3831                };
3832                let shuffle_array = match op {
3833                    Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulLowI32x4U => {
3834                        [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
3835                    }
3836                    Operator::I64x2ExtMulHighI32x4S | Operator::I64x2ExtMulHighI32x4U => {
3837                        [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
3838                    }
3839                    _ => unreachable!("Unhandled internal variant"),
3840                };
3841                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3842                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
3843                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
3844                let val1 = err!(self.builder.build_shuffle_vector(
3845                    v1,
3846                    v1.get_type().get_undef(),
3847                    VectorType::const_vector(&shuffle_array),
3848                    "",
3849                ));
3850                let val1 = err!(extend_op(self, val1));
3851                let val2 = err!(self.builder.build_shuffle_vector(
3852                    v2,
3853                    v2.get_type().get_undef(),
3854                    VectorType::const_vector(&shuffle_array),
3855                    "",
3856                ));
3857                let val2 = err!(extend_op(self, val2));
3858                let res = err!(self.builder.build_int_mul(val1, val2, ""));
3859                let res = err!(
3860                    self.builder
3861                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3862                );
3863                self.state.push1(res);
3864            }
3865            Operator::I32x4DotI16x8S => {
3866                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3867                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
3868                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
3869                let low_i16 = [
3870                    self.intrinsics.i32_consts[0],
3871                    self.intrinsics.i32_consts[2],
3872                    self.intrinsics.i32_consts[4],
3873                    self.intrinsics.i32_consts[6],
3874                ];
3875                let high_i16 = [
3876                    self.intrinsics.i32_consts[1],
3877                    self.intrinsics.i32_consts[3],
3878                    self.intrinsics.i32_consts[5],
3879                    self.intrinsics.i32_consts[7],
3880                ];
3881                let v1_low = err!(self.builder.build_shuffle_vector(
3882                    v1,
3883                    v1.get_type().get_undef(),
3884                    VectorType::const_vector(&low_i16),
3885                    "",
3886                ));
3887                let v1_low = err!(self.builder.build_int_s_extend(
3888                    v1_low,
3889                    self.intrinsics.i32x4_ty,
3890                    ""
3891                ));
3892                let v1_high = err!(self.builder.build_shuffle_vector(
3893                    v1,
3894                    v1.get_type().get_undef(),
3895                    VectorType::const_vector(&high_i16),
3896                    "",
3897                ));
3898                let v1_high = err!(self.builder.build_int_s_extend(
3899                    v1_high,
3900                    self.intrinsics.i32x4_ty,
3901                    ""
3902                ));
3903                let v2_low = err!(self.builder.build_shuffle_vector(
3904                    v2,
3905                    v2.get_type().get_undef(),
3906                    VectorType::const_vector(&low_i16),
3907                    "",
3908                ));
3909                let v2_low = err!(self.builder.build_int_s_extend(
3910                    v2_low,
3911                    self.intrinsics.i32x4_ty,
3912                    ""
3913                ));
3914                let v2_high = err!(self.builder.build_shuffle_vector(
3915                    v2,
3916                    v2.get_type().get_undef(),
3917                    VectorType::const_vector(&high_i16),
3918                    "",
3919                ));
3920                let v2_high = err!(self.builder.build_int_s_extend(
3921                    v2_high,
3922                    self.intrinsics.i32x4_ty,
3923                    ""
3924                ));
3925                let low_product = err!(self.builder.build_int_mul(v1_low, v2_low, ""));
3926                let high_product = err!(self.builder.build_int_mul(v1_high, v2_high, ""));
3927
3928                let res = err!(self.builder.build_int_add(low_product, high_product, ""));
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::I16x8RelaxedDotI8x16I7x16S
3936                if self.cpu_features.contains(CpuFeature::SSSE3) =>
3937            {
3938                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3939                let (a, _) = self.v128_into_i8x16(v1, i1)?;
3940                let (b, _) = self.v128_into_i8x16(v2, i2)?;
3941
3942                let res = self
3943                    .build_call_with_param_attributes(
3944                        self.intrinsics.x86_64.pmaddubsw128,
3945                        &[b.into(), a.into()],
3946                        "",
3947                    )?
3948                    .try_as_basic_value()
3949                    .unwrap_basic()
3950                    .into_vector_value();
3951                let res = err!(
3952                    self.builder
3953                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3954                );
3955                self.state.push1(res);
3956            }
3957            Operator::I16x8RelaxedDotI8x16I7x16S => {
3958                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
3959                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
3960                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
3961
3962                let left_indices = [
3963                    self.intrinsics.i32_consts[0],
3964                    self.intrinsics.i32_consts[2],
3965                    self.intrinsics.i32_consts[4],
3966                    self.intrinsics.i32_consts[6],
3967                    self.intrinsics.i32_consts[8],
3968                    self.intrinsics.i32_consts[10],
3969                    self.intrinsics.i32_consts[12],
3970                    self.intrinsics.i32_consts[14],
3971                ];
3972                let right_indices = [
3973                    self.intrinsics.i32_consts[1],
3974                    self.intrinsics.i32_consts[3],
3975                    self.intrinsics.i32_consts[5],
3976                    self.intrinsics.i32_consts[7],
3977                    self.intrinsics.i32_consts[9],
3978                    self.intrinsics.i32_consts[11],
3979                    self.intrinsics.i32_consts[13],
3980                    self.intrinsics.i32_consts[15],
3981                ];
3982
3983                let v1_left = err!(self.builder.build_shuffle_vector(
3984                    v1,
3985                    v1.get_type().get_undef(),
3986                    VectorType::const_vector(&left_indices),
3987                    "",
3988                ));
3989                let v1_left = err!(self.builder.build_int_s_extend(
3990                    v1_left,
3991                    self.intrinsics.i16x8_ty,
3992                    ""
3993                ));
3994                let v1_right = err!(self.builder.build_shuffle_vector(
3995                    v1,
3996                    v1.get_type().get_undef(),
3997                    VectorType::const_vector(&right_indices),
3998                    "",
3999                ));
4000                let v1_right = err!(self.builder.build_int_s_extend(
4001                    v1_right,
4002                    self.intrinsics.i16x8_ty,
4003                    ""
4004                ));
4005
4006                let v2_left = err!(self.builder.build_shuffle_vector(
4007                    v2,
4008                    v2.get_type().get_undef(),
4009                    VectorType::const_vector(&left_indices),
4010                    "",
4011                ));
4012                let v2_left = err!(self.builder.build_int_s_extend(
4013                    v2_left,
4014                    self.intrinsics.i16x8_ty,
4015                    ""
4016                ));
4017                let v2_right = err!(self.builder.build_shuffle_vector(
4018                    v2,
4019                    v2.get_type().get_undef(),
4020                    VectorType::const_vector(&right_indices),
4021                    "",
4022                ));
4023                let v2_right = err!(self.builder.build_int_s_extend(
4024                    v2_right,
4025                    self.intrinsics.i16x8_ty,
4026                    ""
4027                ));
4028
4029                let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4030                let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4031                let res = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4032                let res = err!(
4033                    self.builder
4034                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4035                );
4036                self.state.push1(res);
4037            }
4038            Operator::I32x4RelaxedDotI8x16I7x16AddS
4039                if self.cpu_features.contains(CpuFeature::SSSE3) =>
4040            {
4041                let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4042                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4043                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4044                let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4045
4046                // PMADDUBSW computes pairwise u8*i8 with i16 saturation, which
4047                // is one of the valid relaxed dot-product behaviors.
4048                let dot16 = self
4049                    .build_call_with_param_attributes(
4050                        self.intrinsics.x86_64.pmaddubsw128,
4051                        &[v2.into(), v1.into()],
4052                        "",
4053                    )?
4054                    .try_as_basic_value()
4055                    .unwrap_basic()
4056                    .into_vector_value();
4057                let ones =
4058                    VectorType::const_vector(&[self.intrinsics.i16_ty.const_int(1, false); 8]);
4059                let dot32 = self
4060                    .build_call_with_param_attributes(
4061                        self.intrinsics.x86_64.pmaddwd128,
4062                        &[dot16.into(), ones.into()],
4063                        "",
4064                    )?
4065                    .try_as_basic_value()
4066                    .unwrap_basic()
4067                    .into_vector_value();
4068                let res = err!(self.builder.build_int_add(dot32, acc, ""));
4069                let res = err!(
4070                    self.builder
4071                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4072                );
4073                self.state.push1(res);
4074            }
4075            Operator::I32x4RelaxedDotI8x16I7x16AddS => {
4076                let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4077                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4078                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4079                let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4080
4081                let left_indices = [
4082                    self.intrinsics.i32_consts[0],
4083                    self.intrinsics.i32_consts[2],
4084                    self.intrinsics.i32_consts[4],
4085                    self.intrinsics.i32_consts[6],
4086                    self.intrinsics.i32_consts[8],
4087                    self.intrinsics.i32_consts[10],
4088                    self.intrinsics.i32_consts[12],
4089                    self.intrinsics.i32_consts[14],
4090                ];
4091                let right_indices = [
4092                    self.intrinsics.i32_consts[1],
4093                    self.intrinsics.i32_consts[3],
4094                    self.intrinsics.i32_consts[5],
4095                    self.intrinsics.i32_consts[7],
4096                    self.intrinsics.i32_consts[9],
4097                    self.intrinsics.i32_consts[11],
4098                    self.intrinsics.i32_consts[13],
4099                    self.intrinsics.i32_consts[15],
4100                ];
4101
4102                let v1_left = err!(self.builder.build_shuffle_vector(
4103                    v1,
4104                    v1.get_type().get_undef(),
4105                    VectorType::const_vector(&left_indices),
4106                    "",
4107                ));
4108                let v1_left = err!(self.builder.build_int_s_extend(
4109                    v1_left,
4110                    self.intrinsics.i16x8_ty,
4111                    ""
4112                ));
4113                let v1_right = err!(self.builder.build_shuffle_vector(
4114                    v1,
4115                    v1.get_type().get_undef(),
4116                    VectorType::const_vector(&right_indices),
4117                    "",
4118                ));
4119                let v1_right = err!(self.builder.build_int_s_extend(
4120                    v1_right,
4121                    self.intrinsics.i16x8_ty,
4122                    ""
4123                ));
4124
4125                let v2_left = err!(self.builder.build_shuffle_vector(
4126                    v2,
4127                    v2.get_type().get_undef(),
4128                    VectorType::const_vector(&left_indices),
4129                    "",
4130                ));
4131                let v2_left = err!(self.builder.build_int_s_extend(
4132                    v2_left,
4133                    self.intrinsics.i16x8_ty,
4134                    ""
4135                ));
4136                let v2_right = err!(self.builder.build_shuffle_vector(
4137                    v2,
4138                    v2.get_type().get_undef(),
4139                    VectorType::const_vector(&right_indices),
4140                    "",
4141                ));
4142                let v2_right = err!(self.builder.build_int_s_extend(
4143                    v2_right,
4144                    self.intrinsics.i16x8_ty,
4145                    ""
4146                ));
4147
4148                let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4149                let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4150                let dot16 = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4151
4152                let pair_left = err!(self.builder.build_shuffle_vector(
4153                    dot16,
4154                    dot16.get_type().get_undef(),
4155                    VectorType::const_vector(&[
4156                        self.intrinsics.i32_consts[0],
4157                        self.intrinsics.i32_consts[2],
4158                        self.intrinsics.i32_consts[4],
4159                        self.intrinsics.i32_consts[6],
4160                    ]),
4161                    "",
4162                ));
4163                let pair_left = err!(self.builder.build_int_s_extend(
4164                    pair_left,
4165                    self.intrinsics.i32x4_ty,
4166                    ""
4167                ));
4168                let pair_right = err!(self.builder.build_shuffle_vector(
4169                    dot16,
4170                    dot16.get_type().get_undef(),
4171                    VectorType::const_vector(&[
4172                        self.intrinsics.i32_consts[1],
4173                        self.intrinsics.i32_consts[3],
4174                        self.intrinsics.i32_consts[5],
4175                        self.intrinsics.i32_consts[7],
4176                    ]),
4177                    "",
4178                ));
4179                let pair_right = err!(self.builder.build_int_s_extend(
4180                    pair_right,
4181                    self.intrinsics.i32x4_ty,
4182                    ""
4183                ));
4184                let dot32 = err!(self.builder.build_int_add(pair_left, pair_right, ""));
4185                let res = err!(self.builder.build_int_add(dot32, acc, ""));
4186                let res = err!(
4187                    self.builder
4188                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4189                );
4190                self.state.push1(res);
4191            }
4192            Operator::I32DivS | Operator::I64DivS => {
4193                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4194                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4195                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4196                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4197
4198                self.trap_if_zero_or_overflow(v1, v2)?;
4199
4200                let res = err!(self.builder.build_int_signed_div(v1, v2, ""));
4201                self.state.push1(res);
4202            }
4203            Operator::I32DivU | Operator::I64DivU => {
4204                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4205                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4206                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4207                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4208
4209                self.trap_if_zero(v2)?;
4210
4211                let res = err!(self.builder.build_int_unsigned_div(v1, v2, ""));
4212                self.state.push1(res);
4213            }
4214            Operator::I32RemS | Operator::I64RemS => {
4215                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4216                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4217                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4218                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4219                let int_type = v1.get_type();
4220                let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
4221                    let min_value = int_type.const_int(i32::MIN as u64, false);
4222                    let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
4223                    (min_value, neg_one_value)
4224                } else if int_type == self.intrinsics.i64_ty {
4225                    let min_value = int_type.const_int(i64::MIN as u64, false);
4226                    let neg_one_value = int_type.const_int(-1i64 as u64, false);
4227                    (min_value, neg_one_value)
4228                } else {
4229                    unreachable!()
4230                };
4231
4232                self.trap_if_zero(v2)?;
4233
4234                // "Overflow also leads to undefined behavior; this is a rare
4235                // case, but can occur, for example, by taking the remainder of
4236                // a 32-bit division of -2147483648 by -1. (The remainder
4237                // doesn’t actually overflow, but this rule lets srem be
4238                // implemented using instructions that return both the result
4239                // of the division and the remainder.)"
4240                //   -- https://llvm.org/docs/LangRef.html#srem-instruction
4241                //
4242                // In Wasm, the i32.rem_s i32.const -2147483648 i32.const -1 is
4243                // i32.const 0. We implement this by swapping out the left value
4244                // for 0 in this case.
4245                let will_overflow = err!(self.builder.build_and(
4246                    err!(self.builder.build_int_compare(
4247                        IntPredicate::EQ,
4248                        v1,
4249                        min_value,
4250                        "left_is_min"
4251                    )),
4252                    err!(self.builder.build_int_compare(
4253                        IntPredicate::EQ,
4254                        v2,
4255                        neg_one_value,
4256                        "right_is_neg_one",
4257                    )),
4258                    "srem_will_overflow",
4259                ));
4260                let v1 =
4261                    err!(
4262                        self.builder
4263                            .build_select(will_overflow, int_type.const_zero(), v1, "")
4264                    )
4265                    .into_int_value();
4266                let res = err!(self.builder.build_int_signed_rem(v1, v2, ""));
4267                self.state.push1(res);
4268            }
4269            Operator::I32RemU | Operator::I64RemU => {
4270                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4271                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4272                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4273                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4274
4275                self.trap_if_zero(v2)?;
4276
4277                let res = err!(self.builder.build_int_unsigned_rem(v1, v2, ""));
4278                self.state.push1(res);
4279            }
4280            Operator::I32And | Operator::I64And | Operator::V128And => {
4281                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4282                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4283                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4284                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4285                let res = err!(self.builder.build_and(v1, v2, ""));
4286                self.state.push1(res);
4287            }
4288            Operator::I32Or | Operator::I64Or | Operator::V128Or => {
4289                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4290                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4291                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4292                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4293                let res = err!(self.builder.build_or(v1, v2, ""));
4294                self.state.push1(res);
4295            }
4296            Operator::I32Xor | Operator::I64Xor | Operator::V128Xor => {
4297                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4298                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4299                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4300                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4301                let res = err!(self.builder.build_xor(v1, v2, ""));
4302                self.state.push1(res);
4303            }
4304            Operator::V128AndNot => {
4305                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4306                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4307                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4308                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4309                let v2 = err!(self.builder.build_not(v2, ""));
4310                let res = err!(self.builder.build_and(v1, v2, ""));
4311                self.state.push1(res);
4312            }
4313            Operator::I8x16RelaxedLaneselect
4314            | Operator::I16x8RelaxedLaneselect
4315            | Operator::I32x4RelaxedLaneselect
4316            | Operator::I64x2RelaxedLaneselect
4317                if self.cpu_features.contains(CpuFeature::SSE41) =>
4318            {
4319                let ((v1, i1), (v2, i2), (mask, mask_info)) = self.state.pop3_extra()?;
4320                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4321                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4322                let mask = self.apply_pending_canonicalization(mask, mask_info)?;
4323
4324                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4325                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4326                let (mask, _) = self.v128_into_i8x16(mask, mask_info)?;
4327                let res = self
4328                    .build_call_with_param_attributes(
4329                        self.intrinsics.x86_64.pblendvb,
4330                        &[v2.into(), v1.into(), mask.into()],
4331                        "",
4332                    )?
4333                    .try_as_basic_value()
4334                    .unwrap_basic();
4335                let res = err!(
4336                    self.builder
4337                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4338                );
4339                self.state.push1(res);
4340            }
4341            Operator::I8x16RelaxedLaneselect
4342            | Operator::I16x8RelaxedLaneselect
4343            | Operator::I32x4RelaxedLaneselect
4344            | Operator::I64x2RelaxedLaneselect
4345            | Operator::V128Bitselect => {
4346                let ((v1, i1), (v2, i2), (cond, cond_info)) = self.state.pop3_extra()?;
4347                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4348                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4349                let cond = self.apply_pending_canonicalization(cond, cond_info)?;
4350                let v1 = err!(
4351                    self.builder
4352                        .build_bit_cast(v1, self.intrinsics.i1x128_ty, "")
4353                )
4354                .into_vector_value();
4355                let v2 = err!(
4356                    self.builder
4357                        .build_bit_cast(v2, self.intrinsics.i1x128_ty, "")
4358                )
4359                .into_vector_value();
4360                let cond = err!(
4361                    self.builder
4362                        .build_bit_cast(cond, self.intrinsics.i1x128_ty, "")
4363                )
4364                .into_vector_value();
4365                let res = err!(self.builder.build_select(cond, v1, v2, ""));
4366                let res = err!(
4367                    self.builder
4368                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4369                );
4370                self.state.push1(res);
4371            }
4372            Operator::I8x16Bitmask => {
4373                let (v, i) = self.state.pop1_extra()?;
4374                let (v, _) = self.v128_into_i8x16(v, i)?;
4375
4376                let zeros = self.intrinsics.i8x16_ty.const_zero();
4377                let res = err!(
4378                    self.builder
4379                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
4380                );
4381                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i16_ty, ""))
4382                    .into_int_value();
4383                let res = err!(
4384                    self.builder
4385                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4386                );
4387                self.state.push1(res);
4388            }
4389            Operator::I16x8Bitmask => {
4390                let (v, i) = self.state.pop1_extra()?;
4391                let (v, _) = self.v128_into_i16x8(v, i)?;
4392
4393                let zeros = self.intrinsics.i16x8_ty.const_zero();
4394                let res = err!(
4395                    self.builder
4396                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
4397                );
4398                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i8_ty, ""))
4399                    .into_int_value();
4400                let res = err!(
4401                    self.builder
4402                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4403                );
4404                self.state.push1(res);
4405            }
4406            Operator::I32x4Bitmask => {
4407                let (v, i) = self.state.pop1_extra()?;
4408                let (v, _) = self.v128_into_i32x4(v, i)?;
4409
4410                let zeros = self.intrinsics.i32x4_ty.const_zero();
4411                let res = err!(
4412                    self.builder
4413                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
4414                );
4415                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i4_ty, ""))
4416                    .into_int_value();
4417                let res = err!(
4418                    self.builder
4419                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4420                );
4421                self.state.push1(res);
4422            }
4423            Operator::I64x2Bitmask => {
4424                let (v, i) = self.state.pop1_extra()?;
4425                let (v, _) = self.v128_into_i64x2(v, i)?;
4426
4427                let zeros = self.intrinsics.i64x2_ty.const_zero();
4428                let res = err!(
4429                    self.builder
4430                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
4431                );
4432                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i2_ty, ""))
4433                    .into_int_value();
4434                let res = err!(
4435                    self.builder
4436                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
4437                );
4438                self.state.push1(res);
4439            }
4440            Operator::I32Shl => {
4441                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4442                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4443                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4444                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4445                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4446                let v2 = err!(self.builder.build_and(v2, mask, ""));
4447                let res = err!(self.builder.build_left_shift(v1, v2, ""));
4448                self.state.push1(res);
4449            }
4450            Operator::I64Shl => {
4451                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4452                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4453                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4454                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4455                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4456                let v2 = err!(self.builder.build_and(v2, mask, ""));
4457                let res = err!(self.builder.build_left_shift(v1, v2, ""));
4458                self.state.push1(res);
4459            }
4460            Operator::I8x16Shl => {
4461                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4462                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4463                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4464                let v2 = v2.into_int_value();
4465                let v2 = err!(
4466                    self.builder
4467                        .build_and(v2, self.intrinsics.i32_consts[7], "")
4468                );
4469                let v2 = err!(
4470                    self.builder
4471                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
4472                );
4473                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
4474                let res = err!(self.builder.build_left_shift(v1, v2, ""));
4475                let res = err!(
4476                    self.builder
4477                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4478                );
4479                self.state.push1(res);
4480            }
4481            Operator::I16x8Shl => {
4482                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4483                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4484                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4485                let v2 = v2.into_int_value();
4486                let v2 = err!(
4487                    self.builder
4488                        .build_and(v2, self.intrinsics.i32_consts[15], "")
4489                );
4490                let v2 = err!(
4491                    self.builder
4492                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
4493                );
4494                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
4495                let res = err!(self.builder.build_left_shift(v1, v2, ""));
4496                let res = err!(
4497                    self.builder
4498                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4499                );
4500                self.state.push1(res);
4501            }
4502            Operator::I32x4Shl => {
4503                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4504                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4505                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4506                let v2 = v2.into_int_value();
4507                let v2 = err!(self.builder.build_and(
4508                    v2,
4509                    self.intrinsics.i32_ty.const_int(31, false),
4510                    ""
4511                ));
4512                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
4513                let res = err!(self.builder.build_left_shift(v1, v2, ""));
4514                let res = err!(
4515                    self.builder
4516                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4517                );
4518                self.state.push1(res);
4519            }
4520            Operator::I64x2Shl => {
4521                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4522                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4523                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4524                let v2 = v2.into_int_value();
4525                let v2 = err!(self.builder.build_and(
4526                    v2,
4527                    self.intrinsics.i32_ty.const_int(63, false),
4528                    ""
4529                ));
4530                let v2 = err!(
4531                    self.builder
4532                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
4533                );
4534                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
4535                let res = err!(self.builder.build_left_shift(v1, v2, ""));
4536                let res = err!(
4537                    self.builder
4538                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4539                );
4540                self.state.push1(res);
4541            }
4542            Operator::I32ShrS => {
4543                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4544                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4545                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4546                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4547                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4548                let v2 = err!(self.builder.build_and(v2, mask, ""));
4549                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4550                self.state.push1(res);
4551            }
4552            Operator::I64ShrS => {
4553                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4554                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4555                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4556                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4557                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4558                let v2 = err!(self.builder.build_and(v2, mask, ""));
4559                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4560                self.state.push1(res);
4561            }
4562            Operator::I8x16ShrS => {
4563                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4564                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4565                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4566                let v2 = v2.into_int_value();
4567                let v2 = err!(
4568                    self.builder
4569                        .build_and(v2, self.intrinsics.i32_consts[7], "")
4570                );
4571                let v2 = err!(
4572                    self.builder
4573                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
4574                );
4575                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
4576                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4577                let res = err!(
4578                    self.builder
4579                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4580                );
4581                self.state.push1(res);
4582            }
4583            Operator::I16x8ShrS => {
4584                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4585                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4586                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4587                let v2 = v2.into_int_value();
4588                let v2 = err!(
4589                    self.builder
4590                        .build_and(v2, self.intrinsics.i32_consts[15], "")
4591                );
4592                let v2 = err!(
4593                    self.builder
4594                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
4595                );
4596                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
4597                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
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::I32x4ShrS => {
4605                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4606                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4607                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4608                let v2 = v2.into_int_value();
4609                let v2 = err!(self.builder.build_and(
4610                    v2,
4611                    self.intrinsics.i32_ty.const_int(31, false),
4612                    ""
4613                ));
4614                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
4615                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4616                let res = err!(
4617                    self.builder
4618                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4619                );
4620                self.state.push1(res);
4621            }
4622            Operator::I64x2ShrS => {
4623                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4624                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4625                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4626                let v2 = v2.into_int_value();
4627                let v2 = err!(self.builder.build_and(
4628                    v2,
4629                    self.intrinsics.i32_ty.const_int(63, false),
4630                    ""
4631                ));
4632                let v2 = err!(
4633                    self.builder
4634                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
4635                );
4636                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
4637                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
4638                let res = err!(
4639                    self.builder
4640                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4641                );
4642                self.state.push1(res);
4643            }
4644            Operator::I32ShrU => {
4645                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4646                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4647                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4648                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4649                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4650                let v2 = err!(self.builder.build_and(v2, mask, ""));
4651                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4652                self.state.push1(res);
4653            }
4654            Operator::I64ShrU => {
4655                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4656                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4657                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4658                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4659                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4660                let v2 = err!(self.builder.build_and(v2, mask, ""));
4661                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4662                self.state.push1(res);
4663            }
4664            Operator::I8x16ShrU => {
4665                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4666                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4667                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4668                let v2 = v2.into_int_value();
4669                let v2 = err!(
4670                    self.builder
4671                        .build_and(v2, self.intrinsics.i32_consts[7], "")
4672                );
4673                let v2 = err!(
4674                    self.builder
4675                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
4676                );
4677                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
4678                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4679                let res = err!(
4680                    self.builder
4681                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4682                );
4683                self.state.push1(res);
4684            }
4685            Operator::I16x8ShrU => {
4686                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4687                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4688                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4689                let v2 = v2.into_int_value();
4690                let v2 = err!(
4691                    self.builder
4692                        .build_and(v2, self.intrinsics.i32_consts[15], "")
4693                );
4694                let v2 = err!(
4695                    self.builder
4696                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
4697                );
4698                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
4699                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4700                let res = err!(
4701                    self.builder
4702                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4703                );
4704                self.state.push1(res);
4705            }
4706            Operator::I32x4ShrU => {
4707                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4708                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4709                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4710                let v2 = v2.into_int_value();
4711                let v2 = err!(self.builder.build_and(
4712                    v2,
4713                    self.intrinsics.i32_ty.const_int(31, false),
4714                    ""
4715                ));
4716                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
4717                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4718                let res = err!(
4719                    self.builder
4720                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4721                );
4722                self.state.push1(res);
4723            }
4724            Operator::I64x2ShrU => {
4725                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4726                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4727                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4728                let v2 = v2.into_int_value();
4729                let v2 = err!(self.builder.build_and(
4730                    v2,
4731                    self.intrinsics.i32_ty.const_int(63, false),
4732                    ""
4733                ));
4734                let v2 = err!(
4735                    self.builder
4736                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
4737                );
4738                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
4739                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
4740                let res = err!(
4741                    self.builder
4742                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4743                );
4744                self.state.push1(res);
4745            }
4746            Operator::I32Rotl => {
4747                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4748                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4749                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4750                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4751                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4752                let v2 = err!(self.builder.build_and(v2, mask, ""));
4753                let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
4754                let rhs = {
4755                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
4756                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
4757                    err!(self.builder.build_right_shift(v1, rhs, false, ""))
4758                };
4759                let res = err!(self.builder.build_or(lhs, rhs, ""));
4760                self.state.push1(res);
4761            }
4762            Operator::I64Rotl => {
4763                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4764                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4765                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4766                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4767                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4768                let v2 = err!(self.builder.build_and(v2, mask, ""));
4769                let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
4770                let rhs = {
4771                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
4772                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
4773                    err!(self.builder.build_right_shift(v1, rhs, false, ""))
4774                };
4775                let res = err!(self.builder.build_or(lhs, rhs, ""));
4776                self.state.push1(res);
4777            }
4778            Operator::I32Rotr => {
4779                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4780                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4781                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4782                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4783                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
4784                let v2 = err!(self.builder.build_and(v2, mask, ""));
4785                let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
4786                let rhs = {
4787                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
4788                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
4789                    err!(self.builder.build_left_shift(v1, rhs, ""))
4790                };
4791                let res = err!(self.builder.build_or(lhs, rhs, ""));
4792                self.state.push1(res);
4793            }
4794            Operator::I64Rotr => {
4795                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4796                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4797                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4798                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4799                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
4800                let v2 = err!(self.builder.build_and(v2, mask, ""));
4801                let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
4802                let rhs = {
4803                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
4804                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
4805                    err!(self.builder.build_left_shift(v1, rhs, ""))
4806                };
4807                let res = err!(self.builder.build_or(lhs, rhs, ""));
4808                self.state.push1(res);
4809            }
4810            Operator::I32Clz => {
4811                let (input, info) = self.state.pop1_extra()?;
4812                let input = self.apply_pending_canonicalization(input, info)?;
4813                let is_zero_undef = self.intrinsics.i1_zero;
4814                let res = self
4815                    .build_call_with_param_attributes(
4816                        self.intrinsics.ctlz_i32,
4817                        &[input.into(), is_zero_undef.into()],
4818                        "",
4819                    )?
4820                    .try_as_basic_value()
4821                    .unwrap_basic();
4822                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
4823            }
4824            Operator::I64Clz => {
4825                let (input, info) = self.state.pop1_extra()?;
4826                let input = self.apply_pending_canonicalization(input, info)?;
4827                let is_zero_undef = self.intrinsics.i1_zero;
4828                let res = self
4829                    .build_call_with_param_attributes(
4830                        self.intrinsics.ctlz_i64,
4831                        &[input.into(), is_zero_undef.into()],
4832                        "",
4833                    )?
4834                    .try_as_basic_value()
4835                    .unwrap_basic();
4836                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
4837            }
4838            Operator::I32Ctz => {
4839                let (input, info) = self.state.pop1_extra()?;
4840                let input = self.apply_pending_canonicalization(input, info)?;
4841                let is_zero_undef = self.intrinsics.i1_zero;
4842                let res = self
4843                    .build_call_with_param_attributes(
4844                        self.intrinsics.cttz_i32,
4845                        &[input.into(), is_zero_undef.into()],
4846                        "",
4847                    )?
4848                    .try_as_basic_value()
4849                    .unwrap_basic();
4850                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
4851            }
4852            Operator::I64Ctz => {
4853                let (input, info) = self.state.pop1_extra()?;
4854                let input = self.apply_pending_canonicalization(input, info)?;
4855                let is_zero_undef = self.intrinsics.i1_zero;
4856                let res = self
4857                    .build_call_with_param_attributes(
4858                        self.intrinsics.cttz_i64,
4859                        &[input.into(), is_zero_undef.into()],
4860                        "",
4861                    )?
4862                    .try_as_basic_value()
4863                    .unwrap_basic();
4864                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
4865            }
4866            Operator::I8x16Popcnt => {
4867                let (v, i) = self.state.pop1_extra()?;
4868                let (v, _) = self.v128_into_i8x16(v, i)?;
4869                let res = self
4870                    .build_call_with_param_attributes(self.intrinsics.ctpop_i8x16, &[v.into()], "")?
4871                    .try_as_basic_value()
4872                    .unwrap_basic();
4873                let res = err!(
4874                    self.builder
4875                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4876                );
4877                self.state.push1(res);
4878            }
4879            Operator::I32Popcnt => {
4880                let (input, info) = self.state.pop1_extra()?;
4881                let input = self.apply_pending_canonicalization(input, info)?;
4882                let res = self
4883                    .build_call_with_param_attributes(
4884                        self.intrinsics.ctpop_i32,
4885                        &[input.into()],
4886                        "",
4887                    )?
4888                    .try_as_basic_value()
4889                    .unwrap_basic();
4890                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
4891            }
4892            Operator::I64Popcnt => {
4893                let (input, info) = self.state.pop1_extra()?;
4894                let input = self.apply_pending_canonicalization(input, info)?;
4895                let res = self
4896                    .build_call_with_param_attributes(
4897                        self.intrinsics.ctpop_i64,
4898                        &[input.into()],
4899                        "",
4900                    )?
4901                    .try_as_basic_value()
4902                    .unwrap_basic();
4903                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
4904            }
4905            Operator::I32Eqz => {
4906                let input = self.state.pop1()?.into_int_value();
4907                let cond = err!(self.builder.build_int_compare(
4908                    IntPredicate::EQ,
4909                    input,
4910                    self.intrinsics.i32_zero,
4911                    "",
4912                ));
4913                let res = err!(
4914                    self.builder
4915                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
4916                );
4917                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
4918            }
4919            Operator::I64Eqz => {
4920                let input = self.state.pop1()?.into_int_value();
4921                let cond = err!(self.builder.build_int_compare(
4922                    IntPredicate::EQ,
4923                    input,
4924                    self.intrinsics.i64_zero,
4925                    "",
4926                ));
4927                let res = err!(
4928                    self.builder
4929                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
4930                );
4931                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
4932            }
4933            Operator::I8x16Abs => {
4934                let (v, i) = self.state.pop1_extra()?;
4935                let (v, _) = self.v128_into_i8x16(v, i)?;
4936
4937                let seven = self.intrinsics.i8_ty.const_int(7, false);
4938                let seven = VectorType::const_vector(&[seven; 16]);
4939                let all_sign_bits = err!(self.builder.build_right_shift(v, seven, true, ""));
4940                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
4941                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
4942                let res = err!(
4943                    self.builder
4944                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4945                );
4946                self.state.push1(res);
4947            }
4948            Operator::I16x8Abs => {
4949                let (v, i) = self.state.pop1_extra()?;
4950                let (v, _) = self.v128_into_i16x8(v, i)?;
4951
4952                let fifteen = self.intrinsics.i16_ty.const_int(15, false);
4953                let fifteen = VectorType::const_vector(&[fifteen; 8]);
4954                let all_sign_bits = err!(self.builder.build_right_shift(v, fifteen, true, ""));
4955                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
4956                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
4957                let res = err!(
4958                    self.builder
4959                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4960                );
4961                self.state.push1(res);
4962            }
4963            Operator::I32x4Abs => {
4964                let (v, i) = self.state.pop1_extra()?;
4965                let (v, _) = self.v128_into_i32x4(v, i)?;
4966
4967                let thirtyone = self.intrinsics.i32_ty.const_int(31, false);
4968                let thirtyone = VectorType::const_vector(&[thirtyone; 4]);
4969                let all_sign_bits = err!(self.builder.build_right_shift(v, thirtyone, true, ""));
4970                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
4971                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
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::I64x2Abs => {
4979                let (v, i) = self.state.pop1_extra()?;
4980                let (v, _) = self.v128_into_i64x2(v, i)?;
4981
4982                let sixtythree = self.intrinsics.i64_ty.const_int(63, false);
4983                let sixtythree = VectorType::const_vector(&[sixtythree; 2]);
4984                let all_sign_bits = err!(self.builder.build_right_shift(v, sixtythree, true, ""));
4985                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
4986                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
4987                let res = err!(
4988                    self.builder
4989                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4990                );
4991                self.state.push1(res);
4992            }
4993            Operator::I8x16MinS => {
4994                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4995                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4996                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4997                let cmp = err!(
4998                    self.builder
4999                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5000                );
5001                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5002                let res = err!(
5003                    self.builder
5004                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5005                );
5006                self.state.push1(res);
5007            }
5008            Operator::I8x16MinU => {
5009                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5010                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5011                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5012                let cmp = err!(
5013                    self.builder
5014                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5015                );
5016                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5017                let res = err!(
5018                    self.builder
5019                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5020                );
5021                self.state.push1(res);
5022            }
5023            Operator::I8x16MaxS => {
5024                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5025                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5026                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5027                let cmp = err!(
5028                    self.builder
5029                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5030                );
5031                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5032                let res = err!(
5033                    self.builder
5034                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5035                );
5036                self.state.push1(res);
5037            }
5038            Operator::I8x16MaxU => {
5039                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5040                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5041                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5042                let cmp = err!(
5043                    self.builder
5044                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5045                );
5046                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5047                let res = err!(
5048                    self.builder
5049                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5050                );
5051                self.state.push1(res);
5052            }
5053            Operator::I16x8MinS => {
5054                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5055                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5056                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5057                let cmp = err!(
5058                    self.builder
5059                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5060                );
5061                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5062                let res = err!(
5063                    self.builder
5064                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5065                );
5066                self.state.push1(res);
5067            }
5068            Operator::I16x8MinU => {
5069                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5070                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5071                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5072                let cmp = err!(
5073                    self.builder
5074                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5075                );
5076                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5077                let res = err!(
5078                    self.builder
5079                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5080                );
5081                self.state.push1(res);
5082            }
5083            Operator::I16x8MaxS => {
5084                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5085                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5086                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5087                let cmp = err!(
5088                    self.builder
5089                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5090                );
5091                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5092                let res = err!(
5093                    self.builder
5094                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5095                );
5096                self.state.push1(res);
5097            }
5098            Operator::I16x8MaxU => {
5099                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5100                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5101                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5102                let cmp = err!(
5103                    self.builder
5104                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5105                );
5106                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5107                let res = err!(
5108                    self.builder
5109                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5110                );
5111                self.state.push1(res);
5112            }
5113            Operator::I32x4MinS => {
5114                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5115                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5116                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5117                let cmp = err!(
5118                    self.builder
5119                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5120                );
5121                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5122                let res = err!(
5123                    self.builder
5124                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5125                );
5126                self.state.push1(res);
5127            }
5128            Operator::I32x4MinU => {
5129                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5130                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5131                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5132                let cmp = err!(
5133                    self.builder
5134                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5135                );
5136                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5137                let res = err!(
5138                    self.builder
5139                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5140                );
5141                self.state.push1(res);
5142            }
5143            Operator::I32x4MaxS => {
5144                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5145                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5146                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5147                let cmp = err!(
5148                    self.builder
5149                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5150                );
5151                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5152                let res = err!(
5153                    self.builder
5154                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5155                );
5156                self.state.push1(res);
5157            }
5158            Operator::I32x4MaxU => {
5159                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5160                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5161                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5162                let cmp = err!(
5163                    self.builder
5164                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5165                );
5166                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5167                let res = err!(
5168                    self.builder
5169                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5170                );
5171                self.state.push1(res);
5172            }
5173            Operator::I8x16AvgrU => {
5174                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5175                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5176                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5177
5178                // This approach is faster on x86-64 when the PAVG[BW]
5179                // instructions are available. On other platforms, an alternative
5180                // implementation appears likely to outperform, described here:
5181                //   %a = or %v1, %v2
5182                //   %b = and %a, 1
5183                //   %v1 = lshr %v1, 1
5184                //   %v2 = lshr %v2, 1
5185                //   %sum = add %v1, %v2
5186                //   %res = add %sum, %b
5187
5188                let ext_ty = self.intrinsics.i16_ty.vec_type(16);
5189                let one = self.intrinsics.i16_ty.const_int(1, false);
5190                let one = VectorType::const_vector(&[one; 16]);
5191
5192                let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5193                let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5194                let res = err!(self.builder.build_int_add(
5195                    err!(self.builder.build_int_add(one, v1, "")),
5196                    v2,
5197                    ""
5198                ));
5199                let res = err!(self.builder.build_right_shift(res, one, false, ""));
5200                let res = err!(
5201                    self.builder
5202                        .build_int_truncate(res, self.intrinsics.i8x16_ty, "")
5203                );
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::I16x8AvgrU => {
5211                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5212                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5213                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5214
5215                // This approach is faster on x86-64 when the PAVG[BW]
5216                // instructions are available. On other platforms, an alternative
5217                // implementation appears likely to outperform, described here:
5218                //   %a = or %v1, %v2
5219                //   %b = and %a, 1
5220                //   %v1 = lshr %v1, 1
5221                //   %v2 = lshr %v2, 1
5222                //   %sum = add %v1, %v2
5223                //   %res = add %sum, %b
5224
5225                let ext_ty = self.intrinsics.i32_ty.vec_type(8);
5226                let one = self.intrinsics.i32_consts[1];
5227                let one = VectorType::const_vector(&[one; 8]);
5228
5229                let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5230                let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5231                let res = err!(self.builder.build_int_add(
5232                    err!(self.builder.build_int_add(one, v1, "")),
5233                    v2,
5234                    ""
5235                ));
5236                let res = err!(self.builder.build_right_shift(res, one, false, ""));
5237                let res = err!(
5238                    self.builder
5239                        .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
5240                );
5241                let res = err!(
5242                    self.builder
5243                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5244                );
5245                self.state.push1(res);
5246            }
5247
5248            /***************************
5249             * Floating-Point Arithmetic instructions.
5250             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-arithmetic-instructions
5251             ***************************/
5252            Operator::F32Add => {
5253                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5254                let res = self
5255                    .build_call_with_param_attributes(
5256                        self.intrinsics.add_f32,
5257                        &[
5258                            v1.into(),
5259                            v2.into(),
5260                            self.intrinsics.fp_rounding_md,
5261                            self.intrinsics.fp_exception_md,
5262                        ],
5263                        "",
5264                    )?
5265                    .try_as_basic_value()
5266                    .unwrap_basic();
5267                self.state.push1_extra(
5268                    res,
5269                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5270                );
5271            }
5272            Operator::F64Add => {
5273                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5274                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5275                let res = self
5276                    .build_call_with_param_attributes(
5277                        self.intrinsics.add_f64,
5278                        &[
5279                            v1.into(),
5280                            v2.into(),
5281                            self.intrinsics.fp_rounding_md,
5282                            self.intrinsics.fp_exception_md,
5283                        ],
5284                        "",
5285                    )?
5286                    .try_as_basic_value()
5287                    .unwrap_basic();
5288                self.state.push1_extra(
5289                    res,
5290                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5291                );
5292            }
5293            Operator::F32x4Add => {
5294                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5295                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5296                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5297                let res = self
5298                    .build_call_with_param_attributes(
5299                        self.intrinsics.add_f32x4,
5300                        &[
5301                            v1.into(),
5302                            v2.into(),
5303                            self.intrinsics.fp_rounding_md,
5304                            self.intrinsics.fp_exception_md,
5305                        ],
5306                        "",
5307                    )?
5308                    .try_as_basic_value()
5309                    .unwrap_basic();
5310                let res = err!(
5311                    self.builder
5312                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5313                );
5314                self.state.push1_extra(
5315                    res,
5316                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5317                );
5318            }
5319            Operator::F64x2Add => {
5320                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5321                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5322                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5323                let res = self
5324                    .build_call_with_param_attributes(
5325                        self.intrinsics.add_f64x2,
5326                        &[
5327                            v1.into(),
5328                            v2.into(),
5329                            self.intrinsics.fp_rounding_md,
5330                            self.intrinsics.fp_exception_md,
5331                        ],
5332                        "",
5333                    )?
5334                    .try_as_basic_value()
5335                    .unwrap_basic();
5336                let res = err!(
5337                    self.builder
5338                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5339                );
5340                self.state.push1_extra(
5341                    res,
5342                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5343                );
5344            }
5345            Operator::F32Sub => {
5346                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5347                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5348                let res = self
5349                    .build_call_with_param_attributes(
5350                        self.intrinsics.sub_f32,
5351                        &[
5352                            v1.into(),
5353                            v2.into(),
5354                            self.intrinsics.fp_rounding_md,
5355                            self.intrinsics.fp_exception_md,
5356                        ],
5357                        "",
5358                    )?
5359                    .try_as_basic_value()
5360                    .unwrap_basic();
5361                self.state.push1_extra(
5362                    res,
5363                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5364                );
5365            }
5366            Operator::F64Sub => {
5367                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5368                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5369                let res = self
5370                    .build_call_with_param_attributes(
5371                        self.intrinsics.sub_f64,
5372                        &[
5373                            v1.into(),
5374                            v2.into(),
5375                            self.intrinsics.fp_rounding_md,
5376                            self.intrinsics.fp_exception_md,
5377                        ],
5378                        "",
5379                    )?
5380                    .try_as_basic_value()
5381                    .unwrap_basic();
5382                self.state.push1_extra(
5383                    res,
5384                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5385                );
5386            }
5387            Operator::F32x4Sub => {
5388                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5389                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5390                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5391                let res = self
5392                    .build_call_with_param_attributes(
5393                        self.intrinsics.sub_f32x4,
5394                        &[
5395                            v1.into(),
5396                            v2.into(),
5397                            self.intrinsics.fp_rounding_md,
5398                            self.intrinsics.fp_exception_md,
5399                        ],
5400                        "",
5401                    )?
5402                    .try_as_basic_value()
5403                    .unwrap_basic();
5404                let res = err!(
5405                    self.builder
5406                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5407                );
5408                self.state.push1_extra(
5409                    res,
5410                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5411                );
5412            }
5413            Operator::F64x2Sub => {
5414                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5415                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5416                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5417                let res = self
5418                    .build_call_with_param_attributes(
5419                        self.intrinsics.sub_f64x2,
5420                        &[
5421                            v1.into(),
5422                            v2.into(),
5423                            self.intrinsics.fp_rounding_md,
5424                            self.intrinsics.fp_exception_md,
5425                        ],
5426                        "",
5427                    )?
5428                    .try_as_basic_value()
5429                    .unwrap_basic();
5430                let res = err!(
5431                    self.builder
5432                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5433                );
5434                self.state.push1_extra(
5435                    res,
5436                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5437                );
5438            }
5439            Operator::F32Mul => {
5440                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5441                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5442                let res = self
5443                    .build_call_with_param_attributes(
5444                        self.intrinsics.mul_f32,
5445                        &[
5446                            v1.into(),
5447                            v2.into(),
5448                            self.intrinsics.fp_rounding_md,
5449                            self.intrinsics.fp_exception_md,
5450                        ],
5451                        "",
5452                    )?
5453                    .try_as_basic_value()
5454                    .unwrap_basic();
5455                self.state.push1_extra(
5456                    res,
5457                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5458                );
5459            }
5460            Operator::F64Mul => {
5461                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5462                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5463                let res = self
5464                    .build_call_with_param_attributes(
5465                        self.intrinsics.mul_f64,
5466                        &[
5467                            v1.into(),
5468                            v2.into(),
5469                            self.intrinsics.fp_rounding_md,
5470                            self.intrinsics.fp_exception_md,
5471                        ],
5472                        "",
5473                    )?
5474                    .try_as_basic_value()
5475                    .unwrap_basic();
5476                self.state.push1_extra(
5477                    res,
5478                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5479                );
5480            }
5481            Operator::F32x4Mul => {
5482                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5483                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5484                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5485                let res = self
5486                    .build_call_with_param_attributes(
5487                        self.intrinsics.mul_f32x4,
5488                        &[
5489                            v1.into(),
5490                            v2.into(),
5491                            self.intrinsics.fp_rounding_md,
5492                            self.intrinsics.fp_exception_md,
5493                        ],
5494                        "",
5495                    )?
5496                    .try_as_basic_value()
5497                    .unwrap_basic();
5498                let res = err!(
5499                    self.builder
5500                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5501                );
5502                self.state.push1_extra(
5503                    res,
5504                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5505                );
5506            }
5507            Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd
5508                if self.cpu_features.contains(CpuFeature::FMA) =>
5509            {
5510                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5511                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5512                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5513                let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
5514
5515                let v1 = match op {
5516                    Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5517                    _ => v1,
5518                };
5519                let res = self
5520                    .build_call_with_param_attributes(
5521                        self.intrinsics.muladd_f32x4,
5522                        &[
5523                            v1.into(),
5524                            v2.into(),
5525                            v3.into(),
5526                            self.intrinsics.fp_rounding_md,
5527                            self.intrinsics.fp_exception_md,
5528                        ],
5529                        "",
5530                    )?
5531                    .try_as_basic_value()
5532                    .unwrap_basic();
5533                let res = err!(
5534                    self.builder
5535                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5536                );
5537                let info = (i1.strip_pending() & i2.strip_pending())?;
5538                let info = (info & i3.strip_pending())?;
5539                let info = (info | ExtraInfo::pending_f32_nan())?;
5540                self.state.push1_extra(res, info);
5541            }
5542            Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd => {
5543                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5544                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5545                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5546                let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
5547
5548                let v1 = match op {
5549                    Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5550                    _ => v1,
5551                };
5552                let mul = self
5553                    .build_call_with_param_attributes(
5554                        self.intrinsics.mul_f32x4,
5555                        &[
5556                            v1.into(),
5557                            v2.into(),
5558                            self.intrinsics.fp_rounding_md,
5559                            self.intrinsics.fp_exception_md,
5560                        ],
5561                        "",
5562                    )?
5563                    .try_as_basic_value()
5564                    .unwrap_basic();
5565                let mul = mul.into_vector_value();
5566                let res = self
5567                    .build_call_with_param_attributes(
5568                        self.intrinsics.add_f32x4,
5569                        &[
5570                            mul.into(),
5571                            v3.into(),
5572                            self.intrinsics.fp_rounding_md,
5573                            self.intrinsics.fp_exception_md,
5574                        ],
5575                        "",
5576                    )?
5577                    .try_as_basic_value()
5578                    .unwrap_basic();
5579                let res = err!(
5580                    self.builder
5581                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5582                );
5583                let info = (i1.strip_pending() & i2.strip_pending())?;
5584                let info = (info & i3.strip_pending())?;
5585                let info = (info | ExtraInfo::pending_f32_nan())?;
5586                self.state.push1_extra(res, info);
5587            }
5588            Operator::F64x2Mul => {
5589                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5590                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5591                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5592                let res = self
5593                    .build_call_with_param_attributes(
5594                        self.intrinsics.mul_f64x2,
5595                        &[
5596                            v1.into(),
5597                            v2.into(),
5598                            self.intrinsics.fp_rounding_md,
5599                            self.intrinsics.fp_exception_md,
5600                        ],
5601                        "",
5602                    )?
5603                    .try_as_basic_value()
5604                    .unwrap_basic();
5605                let res = err!(
5606                    self.builder
5607                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5608                );
5609                self.state.push1_extra(
5610                    res,
5611                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5612                );
5613            }
5614            Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd
5615                if self.cpu_features.contains(CpuFeature::FMA) =>
5616            {
5617                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5618                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5619                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5620                let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
5621
5622                let v1 = match op {
5623                    Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5624                    _ => v1,
5625                };
5626                let res = self
5627                    .build_call_with_param_attributes(
5628                        self.intrinsics.muladd_f64x2,
5629                        &[
5630                            v1.into(),
5631                            v2.into(),
5632                            v3.into(),
5633                            self.intrinsics.fp_rounding_md,
5634                            self.intrinsics.fp_exception_md,
5635                        ],
5636                        "",
5637                    )?
5638                    .try_as_basic_value()
5639                    .unwrap_basic();
5640                let res = err!(
5641                    self.builder
5642                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5643                );
5644                let info = (i1.strip_pending() & i2.strip_pending())?;
5645                let info = (info & i3.strip_pending())?;
5646                let info = (info | ExtraInfo::pending_f64_nan())?;
5647                self.state.push1_extra(res, info);
5648            }
5649            Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd => {
5650                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
5651                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5652                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5653                let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
5654
5655                let v1 = match op {
5656                    Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
5657                    _ => v1,
5658                };
5659                let mul = self
5660                    .build_call_with_param_attributes(
5661                        self.intrinsics.mul_f64x2,
5662                        &[
5663                            v1.into(),
5664                            v2.into(),
5665                            self.intrinsics.fp_rounding_md,
5666                            self.intrinsics.fp_exception_md,
5667                        ],
5668                        "",
5669                    )?
5670                    .try_as_basic_value()
5671                    .unwrap_basic();
5672                let mul = mul.into_vector_value();
5673                let res = self
5674                    .build_call_with_param_attributes(
5675                        self.intrinsics.add_f64x2,
5676                        &[
5677                            mul.into(),
5678                            v3.into(),
5679                            self.intrinsics.fp_rounding_md,
5680                            self.intrinsics.fp_exception_md,
5681                        ],
5682                        "",
5683                    )?
5684                    .try_as_basic_value()
5685                    .unwrap_basic();
5686                let res = err!(
5687                    self.builder
5688                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5689                );
5690                let info = (i1.strip_pending() & i2.strip_pending())?;
5691                let info = (info & i3.strip_pending())?;
5692                let info = (info | ExtraInfo::pending_f64_nan())?;
5693                self.state.push1_extra(res, info);
5694            }
5695            Operator::F32Div => {
5696                let (v1, v2) = self.state.pop2()?;
5697                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5698                let res = self
5699                    .build_call_with_param_attributes(
5700                        self.intrinsics.div_f32,
5701                        &[
5702                            v1.into(),
5703                            v2.into(),
5704                            self.intrinsics.fp_rounding_md,
5705                            self.intrinsics.fp_exception_md,
5706                        ],
5707                        "",
5708                    )?
5709                    .try_as_basic_value()
5710                    .unwrap_basic();
5711                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
5712            }
5713            Operator::F64Div => {
5714                let (v1, v2) = self.state.pop2()?;
5715                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
5716                let res = self
5717                    .build_call_with_param_attributes(
5718                        self.intrinsics.div_f64,
5719                        &[
5720                            v1.into(),
5721                            v2.into(),
5722                            self.intrinsics.fp_rounding_md,
5723                            self.intrinsics.fp_exception_md,
5724                        ],
5725                        "",
5726                    )?
5727                    .try_as_basic_value()
5728                    .unwrap_basic();
5729                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
5730            }
5731            Operator::F32x4Div => {
5732                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5733                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
5734                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
5735                let res = self
5736                    .build_call_with_param_attributes(
5737                        self.intrinsics.div_f32x4,
5738                        &[
5739                            v1.into(),
5740                            v2.into(),
5741                            self.intrinsics.fp_rounding_md,
5742                            self.intrinsics.fp_exception_md,
5743                        ],
5744                        "",
5745                    )?
5746                    .try_as_basic_value()
5747                    .unwrap_basic();
5748                let res = err!(
5749                    self.builder
5750                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5751                );
5752                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
5753            }
5754            Operator::F64x2Div => {
5755                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5756                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
5757                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
5758                let res = self
5759                    .build_call_with_param_attributes(
5760                        self.intrinsics.div_f64x2,
5761                        &[
5762                            v1.into(),
5763                            v2.into(),
5764                            self.intrinsics.fp_rounding_md,
5765                            self.intrinsics.fp_exception_md,
5766                        ],
5767                        "",
5768                    )?
5769                    .try_as_basic_value()
5770                    .unwrap_basic();
5771                let res = err!(
5772                    self.builder
5773                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5774                );
5775                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
5776            }
5777            Operator::F32Sqrt => {
5778                let input = self.state.pop1()?;
5779                let res = self
5780                    .build_call_with_param_attributes(
5781                        self.intrinsics.sqrt_f32,
5782                        &[input.into()],
5783                        "",
5784                    )?
5785                    .try_as_basic_value()
5786                    .unwrap_basic();
5787                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
5788            }
5789            Operator::F64Sqrt => {
5790                let input = self.state.pop1()?;
5791                let res = self
5792                    .build_call_with_param_attributes(
5793                        self.intrinsics.sqrt_f64,
5794                        &[input.into()],
5795                        "",
5796                    )?
5797                    .try_as_basic_value()
5798                    .unwrap_basic();
5799                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
5800            }
5801            Operator::F32x4Sqrt => {
5802                let (v, i) = self.state.pop1_extra()?;
5803                let (v, _) = self.v128_into_f32x4(v, i)?;
5804                let res = self
5805                    .build_call_with_param_attributes(self.intrinsics.sqrt_f32x4, &[v.into()], "")?
5806                    .try_as_basic_value()
5807                    .unwrap_basic();
5808                let bits = err!(
5809                    self.builder
5810                        .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
5811                );
5812                self.state.push1_extra(bits, ExtraInfo::pending_f32_nan());
5813            }
5814            Operator::F64x2Sqrt => {
5815                let (v, i) = self.state.pop1_extra()?;
5816                let (v, _) = self.v128_into_f64x2(v, i)?;
5817                let res = self
5818                    .build_call_with_param_attributes(self.intrinsics.sqrt_f64x2, &[v.into()], "")?
5819                    .try_as_basic_value()
5820                    .unwrap_basic();
5821                let bits = err!(
5822                    self.builder
5823                        .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
5824                );
5825                self.state.push1(bits);
5826            }
5827            Operator::F32Min => {
5828                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
5829                let lhs = self
5830                    .apply_pending_canonicalization(lhs, lhs_info)?
5831                    .into_float_value();
5832                let rhs = self
5833                    .apply_pending_canonicalization(rhs, rhs_info)?
5834                    .into_float_value();
5835
5836                let res = self
5837                    .build_call_with_param_attributes(
5838                        self.intrinsics.minimum_f32,
5839                        &[lhs.into(), rhs.into()],
5840                        "",
5841                    )?
5842                    .try_as_basic_value()
5843                    .unwrap_basic();
5844
5845                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
5846                let res = res.into_float_value();
5847
5848                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
5849            }
5850            Operator::F64Min => {
5851                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
5852                let lhs = self
5853                    .apply_pending_canonicalization(lhs, lhs_info)?
5854                    .into_float_value();
5855                let rhs = self
5856                    .apply_pending_canonicalization(rhs, rhs_info)?
5857                    .into_float_value();
5858
5859                let res = self
5860                    .build_call_with_param_attributes(
5861                        self.intrinsics.minimum_f64,
5862                        &[lhs.into(), rhs.into()],
5863                        "",
5864                    )?
5865                    .try_as_basic_value()
5866                    .unwrap_basic();
5867
5868                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
5869                let res = res.into_float_value();
5870
5871                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
5872            }
5873            Operator::F32x4RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
5874                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5875                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5876                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5877                let res = self
5878                    .build_call_with_param_attributes(
5879                        self.intrinsics.x86_64.min_ps,
5880                        &[v1.into(), v2.into()],
5881                        "",
5882                    )?
5883                    .try_as_basic_value()
5884                    .unwrap_basic();
5885                let res = err!(
5886                    self.builder
5887                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5888                );
5889                self.state.push1_extra(
5890                    res,
5891                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5892                );
5893            }
5894            Operator::F32x4Min | Operator::F32x4RelaxedMin => {
5895                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5896                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
5897                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
5898                let res = self
5899                    .build_call_with_param_attributes(
5900                        self.intrinsics.minimum_f32x4,
5901                        &[v1.into(), v2.into()],
5902                        "",
5903                    )?
5904                    .try_as_basic_value()
5905                    .unwrap_basic();
5906
5907                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
5908                let res = res.into_vector_value();
5909
5910                let res = err!(
5911                    self.builder
5912                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5913                );
5914                self.state.push1_extra(
5915                    res,
5916                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
5917                );
5918            }
5919            Operator::F32x4PMin => {
5920                // Pseudo-min: b < a ? b : a
5921                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5922                let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
5923                let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
5924                let cmp = err!(
5925                    self.builder
5926                        .build_float_compare(FloatPredicate::OLT, v2, v1, "")
5927                );
5928                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
5929                let res = err!(
5930                    self.builder
5931                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5932                );
5933                self.state.push1(res);
5934            }
5935            Operator::F64x2RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
5936                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5937                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5938                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5939                let res = self
5940                    .build_call_with_param_attributes(
5941                        self.intrinsics.x86_64.min_pd,
5942                        &[v1.into(), v2.into()],
5943                        "",
5944                    )?
5945                    .try_as_basic_value()
5946                    .unwrap_basic();
5947                let res = err!(
5948                    self.builder
5949                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5950                );
5951                self.state.push1_extra(
5952                    res,
5953                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5954                );
5955            }
5956            Operator::F64x2Min | Operator::F64x2RelaxedMin => {
5957                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5958                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
5959                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
5960                let res = self
5961                    .build_call_with_param_attributes(
5962                        self.intrinsics.minimum_f64x2,
5963                        &[v1.into(), v2.into()],
5964                        "",
5965                    )?
5966                    .try_as_basic_value()
5967                    .unwrap_basic();
5968
5969                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
5970                let res = res.into_vector_value();
5971
5972                let res = err!(
5973                    self.builder
5974                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5975                );
5976                self.state.push1_extra(
5977                    res,
5978                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
5979                );
5980            }
5981            Operator::F64x2PMin => {
5982                // Pseudo-min: b < a ? b : a
5983                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5984                let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
5985                let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
5986                let cmp = err!(
5987                    self.builder
5988                        .build_float_compare(FloatPredicate::OLT, v2, v1, "")
5989                );
5990                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
5991                let res = err!(
5992                    self.builder
5993                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5994                );
5995                self.state.push1(res);
5996            }
5997            Operator::F32Max => {
5998                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
5999                let lhs = self
6000                    .apply_pending_canonicalization(lhs, lhs_info)?
6001                    .into_float_value();
6002                let rhs = self
6003                    .apply_pending_canonicalization(rhs, rhs_info)?
6004                    .into_float_value();
6005
6006                let res = self
6007                    .build_call_with_param_attributes(
6008                        self.intrinsics.maximum_f32,
6009                        &[lhs.into(), rhs.into()],
6010                        "",
6011                    )?
6012                    .try_as_basic_value()
6013                    .unwrap_basic();
6014
6015                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6016                let res = res.into_float_value();
6017
6018                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6019            }
6020            Operator::F64Max => {
6021                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6022                let lhs = self
6023                    .apply_pending_canonicalization(lhs, lhs_info)?
6024                    .into_float_value();
6025                let rhs = self
6026                    .apply_pending_canonicalization(rhs, rhs_info)?
6027                    .into_float_value();
6028
6029                let res = self
6030                    .build_call_with_param_attributes(
6031                        self.intrinsics.maximum_f64,
6032                        &[lhs.into(), rhs.into()],
6033                        "",
6034                    )?
6035                    .try_as_basic_value()
6036                    .unwrap_basic();
6037
6038                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6039                let res = res.into_float_value();
6040
6041                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6042            }
6043            Operator::F32x4RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6044                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6045                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6046                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6047                let res = self
6048                    .build_call_with_param_attributes(
6049                        self.intrinsics.x86_64.max_ps,
6050                        &[v1.into(), v2.into()],
6051                        "",
6052                    )?
6053                    .try_as_basic_value()
6054                    .unwrap_basic();
6055                let res = err!(
6056                    self.builder
6057                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6058                );
6059                self.state.push1_extra(
6060                    res,
6061                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6062                );
6063            }
6064            Operator::F32x4Max | Operator::F32x4RelaxedMax => {
6065                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6066                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6067                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6068                let res = self
6069                    .build_call_with_param_attributes(
6070                        self.intrinsics.maximum_f32x4,
6071                        &[v1.into(), v2.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_vector_value();
6079
6080                let res = err!(
6081                    self.builder
6082                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6083                );
6084                self.state.push1_extra(
6085                    res,
6086                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6087                );
6088            }
6089            Operator::F32x4PMax => {
6090                // Pseudo-max: a < b ? b : a
6091                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6092                let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6093                let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6094                let cmp = err!(
6095                    self.builder
6096                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6097                );
6098                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6099
6100                let res = err!(
6101                    self.builder
6102                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6103                );
6104                self.state.push1(res);
6105            }
6106            Operator::F64x2RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6107                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6108                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6109                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6110                let res = self
6111                    .build_call_with_param_attributes(
6112                        self.intrinsics.x86_64.max_pd,
6113                        &[v1.into(), v2.into()],
6114                        "",
6115                    )?
6116                    .try_as_basic_value()
6117                    .unwrap_basic();
6118                let res = err!(
6119                    self.builder
6120                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6121                );
6122                self.state.push1_extra(
6123                    res,
6124                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6125                );
6126            }
6127            Operator::F64x2Max | Operator::F64x2RelaxedMax => {
6128                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6129                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6130                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6131                let res = self
6132                    .build_call_with_param_attributes(
6133                        self.intrinsics.maximum_f64x2,
6134                        &[v1.into(), v2.into()],
6135                        "",
6136                    )?
6137                    .try_as_basic_value()
6138                    .unwrap_basic();
6139
6140                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6141                let res = res.into_vector_value();
6142
6143                let res = err!(
6144                    self.builder
6145                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6146                );
6147                self.state.push1_extra(
6148                    res,
6149                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6150                );
6151            }
6152            Operator::F64x2PMax => {
6153                // Pseudo-max: a < b ? b : a
6154                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6155                let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6156                let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6157                let cmp = err!(
6158                    self.builder
6159                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
6160                );
6161                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6162                let res = err!(
6163                    self.builder
6164                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6165                );
6166                self.state.push1(res);
6167            }
6168            Operator::F32Ceil => {
6169                let (input, info) = self.state.pop1_extra()?;
6170                let res = err!(self.build_call_with_param_attributes(
6171                    self.intrinsics.ceil_f32,
6172                    &[input.into()],
6173                    ""
6174                ))
6175                .try_as_basic_value()
6176                .unwrap_basic();
6177                let (res, info) = self.finalize_rounding_result(res, info)?;
6178                self.state.push1_extra(res, info);
6179            }
6180            Operator::F32x4Ceil => {
6181                let (v, i) = self.state.pop1_extra()?;
6182                let (v, _) = self.v128_into_f32x4(v, i)?;
6183                let res = err!(self.build_call_with_param_attributes(
6184                    self.intrinsics.ceil_f32x4,
6185                    &[v.into()],
6186                    ""
6187                ))
6188                .try_as_basic_value()
6189                .unwrap_basic();
6190                let (res, info) = self.finalize_rounding_result(res, i)?;
6191                let res = err!(
6192                    self.builder
6193                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6194                );
6195                self.state.push1_extra(res, info);
6196            }
6197            Operator::F64Ceil => {
6198                let (input, info) = self.state.pop1_extra()?;
6199                let res = err!(self.build_call_with_param_attributes(
6200                    self.intrinsics.ceil_f64,
6201                    &[input.into()],
6202                    ""
6203                ))
6204                .try_as_basic_value()
6205                .unwrap_basic();
6206                let (res, info) = self.finalize_rounding_result(res, info)?;
6207                self.state.push1_extra(res, info);
6208            }
6209            Operator::F64x2Ceil => {
6210                let (v, i) = self.state.pop1_extra()?;
6211                let (v, _) = self.v128_into_f64x2(v, i)?;
6212                let res = err!(self.build_call_with_param_attributes(
6213                    self.intrinsics.ceil_f64x2,
6214                    &[v.into()],
6215                    ""
6216                ))
6217                .try_as_basic_value()
6218                .unwrap_basic();
6219                let (res, info) = self.finalize_rounding_result(res, i)?;
6220                let res = err!(
6221                    self.builder
6222                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6223                );
6224                self.state.push1_extra(res, info);
6225            }
6226            Operator::F32Floor => {
6227                let (input, info) = self.state.pop1_extra()?;
6228                let res = err!(self.build_call_with_param_attributes(
6229                    self.intrinsics.floor_f32,
6230                    &[input.into()],
6231                    ""
6232                ))
6233                .try_as_basic_value()
6234                .unwrap_basic();
6235                let (res, info) = self.finalize_rounding_result(res, info)?;
6236                self.state.push1_extra(res, info);
6237            }
6238            Operator::F32x4Floor => {
6239                let (v, i) = self.state.pop1_extra()?;
6240                let (v, _) = self.v128_into_f32x4(v, i)?;
6241                let res = err!(self.build_call_with_param_attributes(
6242                    self.intrinsics.floor_f32x4,
6243                    &[v.into()],
6244                    ""
6245                ))
6246                .try_as_basic_value()
6247                .unwrap_basic();
6248                let (res, info) = self.finalize_rounding_result(res, i)?;
6249                let res = err!(
6250                    self.builder
6251                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6252                );
6253                self.state.push1_extra(res, info);
6254            }
6255            Operator::F64Floor => {
6256                let (input, info) = self.state.pop1_extra()?;
6257                let res = err!(self.build_call_with_param_attributes(
6258                    self.intrinsics.floor_f64,
6259                    &[input.into()],
6260                    ""
6261                ))
6262                .try_as_basic_value()
6263                .unwrap_basic();
6264                let (res, info) = self.finalize_rounding_result(res, info)?;
6265                self.state.push1_extra(res, info);
6266            }
6267            Operator::F64x2Floor => {
6268                let (v, i) = self.state.pop1_extra()?;
6269                let (v, _) = self.v128_into_f64x2(v, i)?;
6270                let res = err!(self.build_call_with_param_attributes(
6271                    self.intrinsics.floor_f64x2,
6272                    &[v.into()],
6273                    ""
6274                ))
6275                .try_as_basic_value()
6276                .unwrap_basic();
6277                let (res, info) = self.finalize_rounding_result(res, i)?;
6278                let res = err!(
6279                    self.builder
6280                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6281                );
6282                self.state.push1_extra(res, info);
6283            }
6284            Operator::F32Trunc => {
6285                let (v, info) = self.state.pop1_extra()?;
6286                let res = err!(
6287                    self.builder
6288                        .build_call(self.intrinsics.trunc_f32, &[v.into()], "")
6289                )
6290                .try_as_basic_value()
6291                .unwrap_basic();
6292                let (res, info) = self.finalize_rounding_result(res, info)?;
6293                self.state.push1_extra(res, info);
6294            }
6295            Operator::F32x4Trunc => {
6296                let (v, i) = self.state.pop1_extra()?;
6297                let (v, _) = self.v128_into_f32x4(v, i)?;
6298                let res = err!(self.build_call_with_param_attributes(
6299                    self.intrinsics.trunc_f32x4,
6300                    &[v.into()],
6301                    ""
6302                ))
6303                .try_as_basic_value()
6304                .unwrap_basic();
6305                let (res, info) = self.finalize_rounding_result(res, i)?;
6306                let res = err!(
6307                    self.builder
6308                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6309                );
6310                self.state.push1_extra(res, info);
6311            }
6312            Operator::F64Trunc => {
6313                let (v, info) = self.state.pop1_extra()?;
6314                let res = err!(
6315                    self.builder
6316                        .build_call(self.intrinsics.trunc_f64, &[v.into()], "")
6317                )
6318                .try_as_basic_value()
6319                .unwrap_basic();
6320                let (res, info) = self.finalize_rounding_result(res, info)?;
6321                self.state.push1_extra(res, info);
6322            }
6323            Operator::F64x2Trunc => {
6324                let (v, i) = self.state.pop1_extra()?;
6325                let (v, _) = self.v128_into_f64x2(v, i)?;
6326                let res = err!(self.build_call_with_param_attributes(
6327                    self.intrinsics.trunc_f64x2,
6328                    &[v.into()],
6329                    ""
6330                ))
6331                .try_as_basic_value()
6332                .unwrap_basic();
6333                let (res, info) = self.finalize_rounding_result(res, i)?;
6334                let res = err!(
6335                    self.builder
6336                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6337                );
6338                self.state.push1_extra(res, info);
6339            }
6340            Operator::F32Nearest => {
6341                let (v, info) = self.state.pop1_extra()?;
6342                let res = err!(self.build_call_with_param_attributes(
6343                    self.intrinsics.nearbyint_f32,
6344                    &[v.into()],
6345                    ""
6346                ))
6347                .try_as_basic_value()
6348                .unwrap_basic();
6349                let (res, info) = self.finalize_rounding_result(res, info)?;
6350                self.state.push1_extra(res, info);
6351            }
6352            Operator::F32x4Nearest => {
6353                let (v, i) = self.state.pop1_extra()?;
6354                let (v, _) = self.v128_into_f32x4(v, i)?;
6355                let res = err!(self.build_call_with_param_attributes(
6356                    self.intrinsics.nearbyint_f32x4,
6357                    &[v.into()],
6358                    ""
6359                ))
6360                .try_as_basic_value()
6361                .unwrap_basic();
6362                let (res, info) = self.finalize_rounding_result(res, i)?;
6363                let res = err!(
6364                    self.builder
6365                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6366                );
6367                self.state.push1_extra(res, info);
6368            }
6369            Operator::F64Nearest => {
6370                let (v, info) = self.state.pop1_extra()?;
6371                let res = err!(self.build_call_with_param_attributes(
6372                    self.intrinsics.nearbyint_f64,
6373                    &[v.into()],
6374                    ""
6375                ))
6376                .try_as_basic_value()
6377                .unwrap_basic();
6378                let (res, info) = self.finalize_rounding_result(res, info)?;
6379                self.state.push1_extra(res, info);
6380            }
6381            Operator::F64x2Nearest => {
6382                let (v, i) = self.state.pop1_extra()?;
6383                let (v, _) = self.v128_into_f64x2(v, i)?;
6384                let res = err!(self.build_call_with_param_attributes(
6385                    self.intrinsics.nearbyint_f64x2,
6386                    &[v.into()],
6387                    ""
6388                ))
6389                .try_as_basic_value()
6390                .unwrap_basic();
6391                let (res, info) = self.finalize_rounding_result(res, i)?;
6392                let res = err!(
6393                    self.builder
6394                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6395                );
6396                self.state.push1_extra(res, info);
6397            }
6398            Operator::F32Abs => {
6399                let (v, i) = self.state.pop1_extra()?;
6400                let v = self.apply_pending_canonicalization(v, i)?;
6401                let res = err!(
6402                    self.builder
6403                        .build_call(self.intrinsics.fabs_f32, &[v.into()], "")
6404                )
6405                .try_as_basic_value()
6406                .unwrap_basic();
6407                // The exact NaN returned by F32Abs is fully defined. Do not
6408                // adjust.
6409                self.state.push1_extra(res, i.strip_pending());
6410            }
6411            Operator::F64Abs => {
6412                let (v, i) = self.state.pop1_extra()?;
6413                let v = self.apply_pending_canonicalization(v, i)?;
6414                let res = err!(
6415                    self.builder
6416                        .build_call(self.intrinsics.fabs_f64, &[v.into()], "")
6417                )
6418                .try_as_basic_value()
6419                .unwrap_basic();
6420                // The exact NaN returned by F64Abs is fully defined. Do not
6421                // adjust.
6422                self.state.push1_extra(res, i.strip_pending());
6423            }
6424            Operator::F32x4Abs => {
6425                let (v, i) = self.state.pop1_extra()?;
6426                let v = err!(self.builder.build_bit_cast(
6427                    v.into_int_value(),
6428                    self.intrinsics.f32x4_ty,
6429                    ""
6430                ));
6431                let v = self.apply_pending_canonicalization(v, i)?;
6432                let res = self
6433                    .build_call_with_param_attributes(self.intrinsics.fabs_f32x4, &[v.into()], "")?
6434                    .try_as_basic_value()
6435                    .unwrap_basic();
6436                let res = err!(
6437                    self.builder
6438                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6439                );
6440                // The exact NaN returned by F32x4Abs is fully defined. Do not
6441                // adjust.
6442                self.state.push1_extra(res, i.strip_pending());
6443            }
6444            Operator::F64x2Abs => {
6445                let (v, i) = self.state.pop1_extra()?;
6446                let v = err!(self.builder.build_bit_cast(
6447                    v.into_int_value(),
6448                    self.intrinsics.f64x2_ty,
6449                    ""
6450                ));
6451                let v = self.apply_pending_canonicalization(v, i)?;
6452                let res = self
6453                    .build_call_with_param_attributes(self.intrinsics.fabs_f64x2, &[v.into()], "")?
6454                    .try_as_basic_value()
6455                    .unwrap_basic();
6456                let res = err!(
6457                    self.builder
6458                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6459                );
6460                // The exact NaN returned by F32x4Abs is fully defined. Do not
6461                // adjust.
6462                self.state.push1_extra(res, i.strip_pending());
6463            }
6464            Operator::F32x4Neg => {
6465                let (v, i) = self.state.pop1_extra()?;
6466                let v = err!(self.builder.build_bit_cast(
6467                    v.into_int_value(),
6468                    self.intrinsics.f32x4_ty,
6469                    ""
6470                ));
6471                let v = self
6472                    .apply_pending_canonicalization(v, i)?
6473                    .into_vector_value();
6474                let res = err!(self.builder.build_float_neg(v, ""));
6475                let res = err!(
6476                    self.builder
6477                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6478                );
6479                // The exact NaN returned by F32x4Neg is fully defined. Do not
6480                // adjust.
6481                self.state.push1_extra(res, i.strip_pending());
6482            }
6483            Operator::F64x2Neg => {
6484                let (v, i) = self.state.pop1_extra()?;
6485                let v = err!(self.builder.build_bit_cast(
6486                    v.into_int_value(),
6487                    self.intrinsics.f64x2_ty,
6488                    ""
6489                ));
6490                let v = self
6491                    .apply_pending_canonicalization(v, i)?
6492                    .into_vector_value();
6493                let res = err!(self.builder.build_float_neg(v, ""));
6494                let res = err!(
6495                    self.builder
6496                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6497                );
6498                // The exact NaN returned by F64x2Neg is fully defined. Do not
6499                // adjust.
6500                self.state.push1_extra(res, i.strip_pending());
6501            }
6502            Operator::F32Neg | Operator::F64Neg => {
6503                let (v, i) = self.state.pop1_extra()?;
6504                let v = self
6505                    .apply_pending_canonicalization(v, i)?
6506                    .into_float_value();
6507                let res = err!(self.builder.build_float_neg(v, ""));
6508                // The exact NaN returned by F32Neg and F64Neg are fully defined.
6509                // Do not adjust.
6510                self.state.push1_extra(res, i.strip_pending());
6511            }
6512            Operator::F32Copysign => {
6513                let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
6514                let mag = self.apply_pending_canonicalization(mag, mag_info)?;
6515                let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
6516                let res = self
6517                    .build_call_with_param_attributes(
6518                        self.intrinsics.copysign_f32,
6519                        &[mag.into(), sgn.into()],
6520                        "",
6521                    )?
6522                    .try_as_basic_value()
6523                    .unwrap_basic();
6524                // The exact NaN returned by F32Copysign is fully defined.
6525                // Do not adjust.
6526                self.state.push1_extra(res, mag_info.strip_pending());
6527            }
6528            Operator::F64Copysign => {
6529                let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
6530                let mag = self.apply_pending_canonicalization(mag, mag_info)?;
6531                let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
6532                let res = self
6533                    .build_call_with_param_attributes(
6534                        self.intrinsics.copysign_f64,
6535                        &[mag.into(), sgn.into()],
6536                        "",
6537                    )?
6538                    .try_as_basic_value()
6539                    .unwrap_basic();
6540                // The exact NaN returned by F32Copysign is fully defined.
6541                // Do not adjust.
6542                self.state.push1_extra(res, mag_info.strip_pending());
6543            }
6544
6545            /***************************
6546             * Integer Comparison instructions.
6547             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-comparison-instructions
6548             ***************************/
6549            Operator::I32Eq | Operator::I64Eq => {
6550                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6551                let v1 = self.apply_pending_canonicalization(v1, i1)?;
6552                let v2 = self.apply_pending_canonicalization(v2, i2)?;
6553                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6554                let cond = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6555                let res = err!(
6556                    self.builder
6557                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6558                );
6559                self.state.push1_extra(
6560                    res,
6561                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6562                );
6563            }
6564            Operator::I8x16Eq => {
6565                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6566                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6567                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6568                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6569                let res = err!(
6570                    self.builder
6571                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6572                );
6573                let res = err!(
6574                    self.builder
6575                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6576                );
6577                self.state.push1(res);
6578            }
6579            Operator::I16x8Eq => {
6580                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6581                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6582                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6583                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6584                let res = err!(
6585                    self.builder
6586                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6587                );
6588                let res = err!(
6589                    self.builder
6590                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6591                );
6592                self.state.push1(res);
6593            }
6594            Operator::I32x4Eq => {
6595                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6596                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6597                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6598                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6599                let res = err!(
6600                    self.builder
6601                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6602                );
6603                let res = err!(
6604                    self.builder
6605                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6606                );
6607                self.state.push1(res);
6608            }
6609            Operator::I64x2Eq => {
6610                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6611                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
6612                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
6613                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
6614                let res = err!(
6615                    self.builder
6616                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
6617                );
6618                let res = err!(
6619                    self.builder
6620                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6621                );
6622                self.state.push1(res);
6623            }
6624            Operator::I32Ne | Operator::I64Ne => {
6625                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6626                let v1 = self.apply_pending_canonicalization(v1, i1)?;
6627                let v2 = self.apply_pending_canonicalization(v2, i2)?;
6628                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6629                let cond = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6630                let res = err!(
6631                    self.builder
6632                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6633                );
6634                self.state.push1_extra(
6635                    res,
6636                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6637                );
6638            }
6639            Operator::I8x16Ne => {
6640                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6641                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6642                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6643                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6644                let res = err!(
6645                    self.builder
6646                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6647                );
6648                let res = err!(
6649                    self.builder
6650                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6651                );
6652                self.state.push1(res);
6653            }
6654            Operator::I16x8Ne => {
6655                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6656                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6657                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6658                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6659                let res = err!(
6660                    self.builder
6661                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6662                );
6663                let res = err!(
6664                    self.builder
6665                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6666                );
6667                self.state.push1(res);
6668            }
6669            Operator::I32x4Ne => {
6670                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6671                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6672                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6673                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6674                let res = err!(
6675                    self.builder
6676                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6677                );
6678                let res = err!(
6679                    self.builder
6680                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6681                );
6682                self.state.push1(res);
6683            }
6684            Operator::I64x2Ne => {
6685                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6686                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
6687                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
6688                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
6689                let res = err!(
6690                    self.builder
6691                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
6692                );
6693                let res = err!(
6694                    self.builder
6695                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6696                );
6697                self.state.push1(res);
6698            }
6699            Operator::I32LtS | Operator::I64LtS => {
6700                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6701                let v1 = self.apply_pending_canonicalization(v1, i1)?;
6702                let v2 = self.apply_pending_canonicalization(v2, i2)?;
6703                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6704                let cond = err!(
6705                    self.builder
6706                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
6707                );
6708                let res = err!(
6709                    self.builder
6710                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6711                );
6712                self.state.push1_extra(
6713                    res,
6714                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6715                );
6716            }
6717            Operator::I8x16LtS => {
6718                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6719                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6720                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6721                let res = err!(
6722                    self.builder
6723                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
6724                );
6725                let res = err!(
6726                    self.builder
6727                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6728                );
6729                let res = err!(
6730                    self.builder
6731                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6732                );
6733                self.state.push1(res);
6734            }
6735            Operator::I16x8LtS => {
6736                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6737                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6738                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6739                let res = err!(
6740                    self.builder
6741                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
6742                );
6743                let res = err!(
6744                    self.builder
6745                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6746                );
6747                let res = err!(
6748                    self.builder
6749                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6750                );
6751                self.state.push1(res);
6752            }
6753            Operator::I32x4LtS => {
6754                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6755                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6756                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6757                let res = err!(
6758                    self.builder
6759                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
6760                );
6761                let res = err!(
6762                    self.builder
6763                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6764                );
6765                let res = err!(
6766                    self.builder
6767                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6768                );
6769                self.state.push1(res);
6770            }
6771            Operator::I64x2LtS => {
6772                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6773                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
6774                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
6775                let res = err!(
6776                    self.builder
6777                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
6778                );
6779                let res = err!(
6780                    self.builder
6781                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
6782                );
6783                let res = err!(
6784                    self.builder
6785                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6786                );
6787                self.state.push1(res);
6788            }
6789            Operator::I32LtU | Operator::I64LtU => {
6790                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6791                let v1 = self.apply_pending_canonicalization(v1, i1)?;
6792                let v2 = self.apply_pending_canonicalization(v2, i2)?;
6793                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6794                let cond = err!(
6795                    self.builder
6796                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
6797                );
6798                let res = err!(
6799                    self.builder
6800                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6801                );
6802                self.state.push1(res);
6803            }
6804            Operator::I8x16LtU => {
6805                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6806                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6807                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6808                let res = err!(
6809                    self.builder
6810                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
6811                );
6812                let res = err!(
6813                    self.builder
6814                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6815                );
6816                let res = err!(
6817                    self.builder
6818                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6819                );
6820                self.state.push1(res);
6821            }
6822            Operator::I16x8LtU => {
6823                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6824                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6825                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6826                let res = err!(
6827                    self.builder
6828                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
6829                );
6830                let res = err!(
6831                    self.builder
6832                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6833                );
6834                let res = err!(
6835                    self.builder
6836                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6837                );
6838                self.state.push1(res);
6839            }
6840            Operator::I32x4LtU => {
6841                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6842                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6843                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6844                let res = err!(
6845                    self.builder
6846                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
6847                );
6848                let res = err!(
6849                    self.builder
6850                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6851                );
6852                let res = err!(
6853                    self.builder
6854                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6855                );
6856                self.state.push1(res);
6857            }
6858            Operator::I32LeS | Operator::I64LeS => {
6859                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6860                let v1 = self.apply_pending_canonicalization(v1, i1)?;
6861                let v2 = self.apply_pending_canonicalization(v2, i2)?;
6862                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6863                let cond = err!(
6864                    self.builder
6865                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
6866                );
6867                let res = err!(
6868                    self.builder
6869                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6870                );
6871                self.state.push1_extra(
6872                    res,
6873                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6874                );
6875            }
6876            Operator::I8x16LeS => {
6877                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6878                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6879                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6880                let res = err!(
6881                    self.builder
6882                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
6883                );
6884                let res = err!(
6885                    self.builder
6886                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6887                );
6888                let res = err!(
6889                    self.builder
6890                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6891                );
6892                self.state.push1(res);
6893            }
6894            Operator::I16x8LeS => {
6895                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6896                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6897                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6898                let res = err!(
6899                    self.builder
6900                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
6901                );
6902                let res = err!(
6903                    self.builder
6904                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6905                );
6906                let res = err!(
6907                    self.builder
6908                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6909                );
6910                self.state.push1(res);
6911            }
6912            Operator::I32x4LeS => {
6913                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6914                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
6915                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
6916                let res = err!(
6917                    self.builder
6918                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
6919                );
6920                let res = err!(
6921                    self.builder
6922                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
6923                );
6924                let res = err!(
6925                    self.builder
6926                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6927                );
6928                self.state.push1(res);
6929            }
6930            Operator::I64x2LeS => {
6931                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6932                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
6933                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
6934                let res = err!(
6935                    self.builder
6936                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
6937                );
6938                let res = err!(
6939                    self.builder
6940                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
6941                );
6942                let res = err!(
6943                    self.builder
6944                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6945                );
6946                self.state.push1(res);
6947            }
6948            Operator::I32LeU | Operator::I64LeU => {
6949                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6950                let v1 = self.apply_pending_canonicalization(v1, i1)?;
6951                let v2 = self.apply_pending_canonicalization(v2, i2)?;
6952                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
6953                let cond = err!(
6954                    self.builder
6955                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
6956                );
6957                let res = err!(
6958                    self.builder
6959                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
6960                );
6961                self.state.push1_extra(
6962                    res,
6963                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
6964                );
6965            }
6966            Operator::I8x16LeU => {
6967                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6968                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
6969                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
6970                let res = err!(
6971                    self.builder
6972                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
6973                );
6974                let res = err!(
6975                    self.builder
6976                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
6977                );
6978                let res = err!(
6979                    self.builder
6980                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6981                );
6982                self.state.push1(res);
6983            }
6984            Operator::I16x8LeU => {
6985                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6986                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6987                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6988                let res = err!(
6989                    self.builder
6990                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
6991                );
6992                let res = err!(
6993                    self.builder
6994                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
6995                );
6996                let res = err!(
6997                    self.builder
6998                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6999                );
7000                self.state.push1(res);
7001            }
7002            Operator::I32x4LeU => {
7003                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7004                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7005                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7006                let res = err!(
7007                    self.builder
7008                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7009                );
7010                let res = err!(
7011                    self.builder
7012                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7013                );
7014                let res = err!(
7015                    self.builder
7016                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7017                );
7018                self.state.push1(res);
7019            }
7020            Operator::I32GtS | Operator::I64GtS => {
7021                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7022                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7023                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7024                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7025                let cond = err!(
7026                    self.builder
7027                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7028                );
7029                let res = err!(
7030                    self.builder
7031                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7032                );
7033                self.state.push1_extra(
7034                    res,
7035                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7036                );
7037            }
7038            Operator::I8x16GtS => {
7039                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7040                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7041                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7042                let res = err!(
7043                    self.builder
7044                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7045                );
7046                let res = err!(
7047                    self.builder
7048                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7049                );
7050                let res = err!(
7051                    self.builder
7052                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7053                );
7054                self.state.push1(res);
7055            }
7056            Operator::I16x8GtS => {
7057                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7058                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7059                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7060                let res = err!(
7061                    self.builder
7062                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7063                );
7064                let res = err!(
7065                    self.builder
7066                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7067                );
7068                let res = err!(
7069                    self.builder
7070                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7071                );
7072                self.state.push1(res);
7073            }
7074            Operator::I32x4GtS => {
7075                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7076                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7077                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7078                let res = err!(
7079                    self.builder
7080                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7081                );
7082                let res = err!(
7083                    self.builder
7084                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7085                );
7086                let res = err!(
7087                    self.builder
7088                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7089                );
7090                self.state.push1(res);
7091            }
7092            Operator::I64x2GtS => {
7093                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7094                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7095                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7096                let res = err!(
7097                    self.builder
7098                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7099                );
7100                let res = err!(
7101                    self.builder
7102                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7103                );
7104                let res = err!(
7105                    self.builder
7106                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7107                );
7108                self.state.push1(res);
7109            }
7110            Operator::I32GtU | Operator::I64GtU => {
7111                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7112                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7113                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7114                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7115                let cond = err!(
7116                    self.builder
7117                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
7118                );
7119                let res = err!(
7120                    self.builder
7121                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7122                );
7123                self.state.push1_extra(
7124                    res,
7125                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7126                );
7127            }
7128            Operator::I8x16GtU => {
7129                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7130                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7131                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7132                let res = err!(
7133                    self.builder
7134                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
7135                );
7136                let res = err!(
7137                    self.builder
7138                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7139                );
7140                let res = err!(
7141                    self.builder
7142                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7143                );
7144                self.state.push1(res);
7145            }
7146            Operator::I16x8GtU => {
7147                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7148                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7149                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7150                let res = err!(
7151                    self.builder
7152                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
7153                );
7154                let res = err!(
7155                    self.builder
7156                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7157                );
7158                let res = err!(
7159                    self.builder
7160                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7161                );
7162                self.state.push1(res);
7163            }
7164            Operator::I32x4GtU => {
7165                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7166                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7167                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7168                let res = err!(
7169                    self.builder
7170                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
7171                );
7172                let res = err!(
7173                    self.builder
7174                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7175                );
7176                let res = err!(
7177                    self.builder
7178                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7179                );
7180                self.state.push1(res);
7181            }
7182            Operator::I32GeS | Operator::I64GeS => {
7183                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7184                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7185                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7186                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7187                let cond = err!(
7188                    self.builder
7189                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7190                );
7191                let res = err!(
7192                    self.builder
7193                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7194                );
7195                self.state.push1(res);
7196            }
7197            Operator::I8x16GeS => {
7198                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7199                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7200                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7201                let res = err!(
7202                    self.builder
7203                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7204                );
7205                let res = err!(
7206                    self.builder
7207                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7208                );
7209                let res = err!(
7210                    self.builder
7211                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7212                );
7213                self.state.push1(res);
7214            }
7215            Operator::I16x8GeS => {
7216                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7217                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7218                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7219                let res = err!(
7220                    self.builder
7221                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7222                );
7223                let res = err!(
7224                    self.builder
7225                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7226                );
7227                let res = err!(
7228                    self.builder
7229                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7230                );
7231                self.state.push1(res);
7232            }
7233            Operator::I32x4GeS => {
7234                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7235                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7236                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7237                let res = err!(
7238                    self.builder
7239                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7240                );
7241                let res = err!(
7242                    self.builder
7243                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7244                );
7245                let res = err!(
7246                    self.builder
7247                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7248                );
7249                self.state.push1(res);
7250            }
7251            Operator::I64x2GeS => {
7252                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7253                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7254                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7255                let res = err!(
7256                    self.builder
7257                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
7258                );
7259                let res = err!(
7260                    self.builder
7261                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7262                );
7263                let res = err!(
7264                    self.builder
7265                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7266                );
7267                self.state.push1(res);
7268            }
7269            Operator::I32GeU | Operator::I64GeU => {
7270                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7271                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7272                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7273                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7274                let cond = err!(
7275                    self.builder
7276                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
7277                );
7278                let res = err!(
7279                    self.builder
7280                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7281                );
7282                self.state.push1_extra(
7283                    res,
7284                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7285                );
7286            }
7287            Operator::I8x16GeU => {
7288                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7289                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7290                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7291                let res = err!(
7292                    self.builder
7293                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
7294                );
7295                let res = err!(
7296                    self.builder
7297                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7298                );
7299                let res = err!(
7300                    self.builder
7301                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7302                );
7303                self.state.push1(res);
7304            }
7305            Operator::I16x8GeU => {
7306                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7307                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7308                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7309                let res = err!(
7310                    self.builder
7311                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
7312                );
7313                let res = err!(
7314                    self.builder
7315                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7316                );
7317                let res = err!(
7318                    self.builder
7319                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7320                );
7321                self.state.push1(res);
7322            }
7323            Operator::I32x4GeU => {
7324                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7325                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7326                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7327                let res = err!(
7328                    self.builder
7329                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
7330                );
7331                let res = err!(
7332                    self.builder
7333                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7334                );
7335                let res = err!(
7336                    self.builder
7337                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7338                );
7339                self.state.push1(res);
7340            }
7341
7342            /***************************
7343             * Floating-Point Comparison instructions.
7344             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-comparison-instructions
7345             ***************************/
7346            Operator::F32Eq | Operator::F64Eq => {
7347                let (v1, v2) = self.state.pop2()?;
7348                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7349                let cond = err!(
7350                    self.builder
7351                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
7352                );
7353                let res = err!(
7354                    self.builder
7355                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7356                );
7357                self.state.push1_extra(
7358                    res,
7359                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7360                );
7361            }
7362            Operator::F32x4Eq => {
7363                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7364                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7365                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7366                let res = err!(
7367                    self.builder
7368                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
7369                );
7370                let res = err!(
7371                    self.builder
7372                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7373                );
7374                let res = err!(
7375                    self.builder
7376                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7377                );
7378                self.state.push1(res);
7379            }
7380            Operator::F64x2Eq => {
7381                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7382                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7383                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7384                let res = err!(
7385                    self.builder
7386                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
7387                );
7388                let res = err!(
7389                    self.builder
7390                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7391                );
7392                let res = err!(
7393                    self.builder
7394                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7395                );
7396                self.state.push1(res);
7397            }
7398            Operator::F32Ne | Operator::F64Ne => {
7399                let (v1, v2) = self.state.pop2()?;
7400                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7401                let cond = err!(
7402                    self.builder
7403                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
7404                );
7405                let res = err!(
7406                    self.builder
7407                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7408                );
7409                self.state.push1_extra(
7410                    res,
7411                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7412                );
7413            }
7414            Operator::F32x4Ne => {
7415                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7416                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7417                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7418                let res = err!(
7419                    self.builder
7420                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
7421                );
7422                let res = err!(
7423                    self.builder
7424                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7425                );
7426                let res = err!(
7427                    self.builder
7428                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7429                );
7430                self.state.push1(res);
7431            }
7432            Operator::F64x2Ne => {
7433                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7434                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7435                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7436                let res = err!(
7437                    self.builder
7438                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
7439                );
7440                let res = err!(
7441                    self.builder
7442                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7443                );
7444                let res = err!(
7445                    self.builder
7446                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7447                );
7448                self.state.push1(res);
7449            }
7450            Operator::F32Lt | Operator::F64Lt => {
7451                let (v1, v2) = self.state.pop2()?;
7452                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7453                let cond = err!(
7454                    self.builder
7455                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7456                );
7457                let res = err!(
7458                    self.builder
7459                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7460                );
7461                self.state.push1_extra(
7462                    res,
7463                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7464                );
7465            }
7466            Operator::F32x4Lt => {
7467                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7468                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7469                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7470                let res = err!(
7471                    self.builder
7472                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7473                );
7474                let res = err!(
7475                    self.builder
7476                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7477                );
7478                let res = err!(
7479                    self.builder
7480                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7481                );
7482                self.state.push1(res);
7483            }
7484            Operator::F64x2Lt => {
7485                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7486                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7487                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7488                let res = err!(
7489                    self.builder
7490                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7491                );
7492                let res = err!(
7493                    self.builder
7494                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7495                );
7496                let res = err!(
7497                    self.builder
7498                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7499                );
7500                self.state.push1(res);
7501            }
7502            Operator::F32Le | Operator::F64Le => {
7503                let (v1, v2) = self.state.pop2()?;
7504                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7505                let cond = err!(
7506                    self.builder
7507                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
7508                );
7509                let res = err!(
7510                    self.builder
7511                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7512                );
7513                self.state.push1_extra(
7514                    res,
7515                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7516                );
7517            }
7518            Operator::F32x4Le => {
7519                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7520                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7521                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7522                let res = err!(
7523                    self.builder
7524                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
7525                );
7526                let res = err!(
7527                    self.builder
7528                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7529                );
7530                let res = err!(
7531                    self.builder
7532                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7533                );
7534                self.state.push1(res);
7535            }
7536            Operator::F64x2Le => {
7537                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7538                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7539                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7540                let res = err!(
7541                    self.builder
7542                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
7543                );
7544                let res = err!(
7545                    self.builder
7546                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7547                );
7548                let res = err!(
7549                    self.builder
7550                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7551                );
7552                self.state.push1(res);
7553            }
7554            Operator::F32Gt | Operator::F64Gt => {
7555                let (v1, v2) = self.state.pop2()?;
7556                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7557                let cond = err!(
7558                    self.builder
7559                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
7560                );
7561                let res = err!(
7562                    self.builder
7563                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7564                );
7565                self.state.push1_extra(
7566                    res,
7567                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7568                );
7569            }
7570            Operator::F32x4Gt => {
7571                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7572                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7573                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7574                let res = err!(
7575                    self.builder
7576                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
7577                );
7578                let res = err!(
7579                    self.builder
7580                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7581                );
7582                let res = err!(
7583                    self.builder
7584                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7585                );
7586                self.state.push1(res);
7587            }
7588            Operator::F64x2Gt => {
7589                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7590                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7591                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7592                let res = err!(
7593                    self.builder
7594                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
7595                );
7596                let res = err!(
7597                    self.builder
7598                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7599                );
7600                let res = err!(
7601                    self.builder
7602                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7603                );
7604                self.state.push1(res);
7605            }
7606            Operator::F32Ge | Operator::F64Ge => {
7607                let (v1, v2) = self.state.pop2()?;
7608                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
7609                let cond = err!(
7610                    self.builder
7611                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
7612                );
7613                let res = err!(
7614                    self.builder
7615                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7616                );
7617                self.state.push1_extra(
7618                    res,
7619                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7620                );
7621            }
7622            Operator::F32x4Ge => {
7623                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7624                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
7625                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
7626                let res = err!(
7627                    self.builder
7628                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
7629                );
7630                let res = err!(
7631                    self.builder
7632                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7633                );
7634                let res = err!(
7635                    self.builder
7636                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7637                );
7638                self.state.push1(res);
7639            }
7640            Operator::F64x2Ge => {
7641                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7642                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
7643                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
7644                let res = err!(
7645                    self.builder
7646                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
7647                );
7648                let res = err!(
7649                    self.builder
7650                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7651                );
7652                let res = err!(
7653                    self.builder
7654                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7655                );
7656                self.state.push1(res);
7657            }
7658
7659            /***************************
7660             * Conversion instructions.
7661             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#conversion-instructions
7662             ***************************/
7663            Operator::I32WrapI64 => {
7664                let (v, i) = self.state.pop1_extra()?;
7665                let v = self.apply_pending_canonicalization(v, i)?;
7666                let v = v.into_int_value();
7667                let res = err!(
7668                    self.builder
7669                        .build_int_truncate(v, self.intrinsics.i32_ty, "")
7670                );
7671                self.state.push1(res);
7672            }
7673            Operator::I64ExtendI32S => {
7674                let (v, i) = self.state.pop1_extra()?;
7675                let v = self.apply_pending_canonicalization(v, i)?;
7676                let v = v.into_int_value();
7677                let res = err!(
7678                    self.builder
7679                        .build_int_s_extend(v, self.intrinsics.i64_ty, "")
7680                );
7681                self.state.push1(res);
7682            }
7683            Operator::I64ExtendI32U => {
7684                let (v, i) = self.state.pop1_extra()?;
7685                let v = self.apply_pending_canonicalization(v, i)?;
7686                let v = v.into_int_value();
7687                let res = err!(
7688                    self.builder
7689                        .build_int_z_extend(v, self.intrinsics.i64_ty, "")
7690                );
7691                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
7692            }
7693            Operator::I16x8ExtendLowI8x16S => {
7694                let (v, i) = self.state.pop1_extra()?;
7695                let (v, _) = self.v128_into_i8x16(v, i)?;
7696                let low = err!(self.builder.build_shuffle_vector(
7697                    v,
7698                    v.get_type().get_undef(),
7699                    VectorType::const_vector(&[
7700                        self.intrinsics.i32_consts[0],
7701                        self.intrinsics.i32_consts[1],
7702                        self.intrinsics.i32_consts[2],
7703                        self.intrinsics.i32_consts[3],
7704                        self.intrinsics.i32_consts[4],
7705                        self.intrinsics.i32_consts[5],
7706                        self.intrinsics.i32_consts[6],
7707                        self.intrinsics.i32_consts[7],
7708                    ]),
7709                    "",
7710                ));
7711                let res = err!(
7712                    self.builder
7713                        .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
7714                );
7715                let res = err!(
7716                    self.builder
7717                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7718                );
7719                self.state.push1(res);
7720            }
7721            Operator::I16x8ExtendHighI8x16S => {
7722                let (v, i) = self.state.pop1_extra()?;
7723                let (v, _) = self.v128_into_i8x16(v, i)?;
7724                let low = err!(self.builder.build_shuffle_vector(
7725                    v,
7726                    v.get_type().get_undef(),
7727                    VectorType::const_vector(&[
7728                        self.intrinsics.i32_consts[8],
7729                        self.intrinsics.i32_consts[9],
7730                        self.intrinsics.i32_consts[10],
7731                        self.intrinsics.i32_consts[11],
7732                        self.intrinsics.i32_consts[12],
7733                        self.intrinsics.i32_consts[13],
7734                        self.intrinsics.i32_consts[14],
7735                        self.intrinsics.i32_consts[15],
7736                    ]),
7737                    "",
7738                ));
7739                let res = err!(
7740                    self.builder
7741                        .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
7742                );
7743                let res = err!(
7744                    self.builder
7745                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7746                );
7747                self.state.push1(res);
7748            }
7749            Operator::I16x8ExtendLowI8x16U => {
7750                let (v, i) = self.state.pop1_extra()?;
7751                let (v, _) = self.v128_into_i8x16(v, i)?;
7752                let low = err!(self.builder.build_shuffle_vector(
7753                    v,
7754                    v.get_type().get_undef(),
7755                    VectorType::const_vector(&[
7756                        self.intrinsics.i32_consts[0],
7757                        self.intrinsics.i32_consts[1],
7758                        self.intrinsics.i32_consts[2],
7759                        self.intrinsics.i32_consts[3],
7760                        self.intrinsics.i32_consts[4],
7761                        self.intrinsics.i32_consts[5],
7762                        self.intrinsics.i32_consts[6],
7763                        self.intrinsics.i32_consts[7],
7764                    ]),
7765                    "",
7766                ));
7767                let res = err!(
7768                    self.builder
7769                        .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
7770                );
7771                let res = err!(
7772                    self.builder
7773                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7774                );
7775                self.state.push1(res);
7776            }
7777            Operator::I16x8ExtendHighI8x16U => {
7778                let (v, i) = self.state.pop1_extra()?;
7779                let (v, _) = self.v128_into_i8x16(v, i)?;
7780                let low = err!(self.builder.build_shuffle_vector(
7781                    v,
7782                    v.get_type().get_undef(),
7783                    VectorType::const_vector(&[
7784                        self.intrinsics.i32_consts[8],
7785                        self.intrinsics.i32_consts[9],
7786                        self.intrinsics.i32_consts[10],
7787                        self.intrinsics.i32_consts[11],
7788                        self.intrinsics.i32_consts[12],
7789                        self.intrinsics.i32_consts[13],
7790                        self.intrinsics.i32_consts[14],
7791                        self.intrinsics.i32_consts[15],
7792                    ]),
7793                    "",
7794                ));
7795                let res = err!(
7796                    self.builder
7797                        .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
7798                );
7799                let res = err!(
7800                    self.builder
7801                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7802                );
7803                self.state.push1(res);
7804            }
7805            Operator::I32x4ExtendLowI16x8S => {
7806                let (v, i) = self.state.pop1_extra()?;
7807                let (v, _) = self.v128_into_i16x8(v, i)?;
7808                let low = err!(self.builder.build_shuffle_vector(
7809                    v,
7810                    v.get_type().get_undef(),
7811                    VectorType::const_vector(&[
7812                        self.intrinsics.i32_consts[0],
7813                        self.intrinsics.i32_consts[1],
7814                        self.intrinsics.i32_consts[2],
7815                        self.intrinsics.i32_consts[3],
7816                    ]),
7817                    "",
7818                ));
7819                let res = err!(
7820                    self.builder
7821                        .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
7822                );
7823                let res = err!(
7824                    self.builder
7825                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7826                );
7827                self.state.push1(res);
7828            }
7829            Operator::I32x4ExtendHighI16x8S => {
7830                let (v, i) = self.state.pop1_extra()?;
7831                let (v, _) = self.v128_into_i16x8(v, i)?;
7832                let low = err!(self.builder.build_shuffle_vector(
7833                    v,
7834                    v.get_type().get_undef(),
7835                    VectorType::const_vector(&[
7836                        self.intrinsics.i32_consts[4],
7837                        self.intrinsics.i32_consts[5],
7838                        self.intrinsics.i32_consts[6],
7839                        self.intrinsics.i32_consts[7],
7840                    ]),
7841                    "",
7842                ));
7843                let res = err!(
7844                    self.builder
7845                        .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
7846                );
7847                let res = err!(
7848                    self.builder
7849                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7850                );
7851                self.state.push1(res);
7852            }
7853            Operator::I32x4ExtendLowI16x8U => {
7854                let (v, i) = self.state.pop1_extra()?;
7855                let (v, _) = self.v128_into_i16x8(v, i)?;
7856                let low = err!(self.builder.build_shuffle_vector(
7857                    v,
7858                    v.get_type().get_undef(),
7859                    VectorType::const_vector(&[
7860                        self.intrinsics.i32_consts[0],
7861                        self.intrinsics.i32_consts[1],
7862                        self.intrinsics.i32_consts[2],
7863                        self.intrinsics.i32_consts[3],
7864                    ]),
7865                    "",
7866                ));
7867                let res = err!(
7868                    self.builder
7869                        .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
7870                );
7871                let res = err!(
7872                    self.builder
7873                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7874                );
7875                self.state.push1(res);
7876            }
7877            Operator::I32x4ExtendHighI16x8U => {
7878                let (v, i) = self.state.pop1_extra()?;
7879                let (v, _) = self.v128_into_i16x8(v, i)?;
7880                let low = err!(self.builder.build_shuffle_vector(
7881                    v,
7882                    v.get_type().get_undef(),
7883                    VectorType::const_vector(&[
7884                        self.intrinsics.i32_consts[4],
7885                        self.intrinsics.i32_consts[5],
7886                        self.intrinsics.i32_consts[6],
7887                        self.intrinsics.i32_consts[7],
7888                    ]),
7889                    "",
7890                ));
7891                let res = err!(
7892                    self.builder
7893                        .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
7894                );
7895                let res = err!(
7896                    self.builder
7897                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7898                );
7899                self.state.push1(res);
7900            }
7901            Operator::I64x2ExtendLowI32x4U
7902            | Operator::I64x2ExtendLowI32x4S
7903            | Operator::I64x2ExtendHighI32x4U
7904            | Operator::I64x2ExtendHighI32x4S => {
7905                let extend = match op {
7906                    Operator::I64x2ExtendLowI32x4U | Operator::I64x2ExtendHighI32x4U => {
7907                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
7908                    }
7909                    Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendHighI32x4S => {
7910                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
7911                    }
7912                    _ => unreachable!("Unhandled inner case"),
7913                };
7914                let indices = match op {
7915                    Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendLowI32x4U => {
7916                        [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
7917                    }
7918                    Operator::I64x2ExtendHighI32x4S | Operator::I64x2ExtendHighI32x4U => {
7919                        [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
7920                    }
7921                    _ => unreachable!("Unhandled inner case"),
7922                };
7923                let (v, i) = self.state.pop1_extra()?;
7924                let (v, _) = self.v128_into_i32x4(v, i)?;
7925                let low = err!(self.builder.build_shuffle_vector(
7926                    v,
7927                    v.get_type().get_undef(),
7928                    VectorType::const_vector(&indices),
7929                    "",
7930                ));
7931                let res = err!(extend(self, low));
7932                let res = err!(
7933                    self.builder
7934                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7935                );
7936                self.state.push1(res);
7937            }
7938            Operator::I8x16NarrowI16x8S => {
7939                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7940                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7941                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7942                let min = self.intrinsics.i16_ty.const_int(0xff80, false);
7943                let max = self.intrinsics.i16_ty.const_int(0x007f, false);
7944                let min = VectorType::const_vector(&[min; 8]);
7945                let max = VectorType::const_vector(&[max; 8]);
7946                let apply_min_clamp_v1 =
7947                    err!(
7948                        self.builder
7949                            .build_int_compare(IntPredicate::SLT, v1, min, "")
7950                    );
7951                let apply_max_clamp_v1 =
7952                    err!(
7953                        self.builder
7954                            .build_int_compare(IntPredicate::SGT, v1, max, "")
7955                    );
7956                let apply_min_clamp_v2 =
7957                    err!(
7958                        self.builder
7959                            .build_int_compare(IntPredicate::SLT, v2, min, "")
7960                    );
7961                let apply_max_clamp_v2 =
7962                    err!(
7963                        self.builder
7964                            .build_int_compare(IntPredicate::SGT, v2, max, "")
7965                    );
7966                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
7967                    .into_vector_value();
7968                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
7969                    .into_vector_value();
7970                let v1 = err!(self.builder.build_int_truncate(
7971                    v1,
7972                    self.intrinsics.i8_ty.vec_type(8),
7973                    ""
7974                ));
7975                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
7976                    .into_vector_value();
7977                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
7978                    .into_vector_value();
7979                let v2 = err!(self.builder.build_int_truncate(
7980                    v2,
7981                    self.intrinsics.i8_ty.vec_type(8),
7982                    ""
7983                ));
7984                let res = err!(self.builder.build_shuffle_vector(
7985                    v1,
7986                    v2,
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                        self.intrinsics.i32_consts[8],
7997                        self.intrinsics.i32_consts[9],
7998                        self.intrinsics.i32_consts[10],
7999                        self.intrinsics.i32_consts[11],
8000                        self.intrinsics.i32_consts[12],
8001                        self.intrinsics.i32_consts[13],
8002                        self.intrinsics.i32_consts[14],
8003                        self.intrinsics.i32_consts[15],
8004                    ]),
8005                    "",
8006                ));
8007                let res = err!(
8008                    self.builder
8009                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8010                );
8011                self.state.push1(res);
8012            }
8013            Operator::I8x16NarrowI16x8U => {
8014                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8015                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8016                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8017                let min = self.intrinsics.i16x8_ty.const_zero();
8018                let max = self.intrinsics.i16_ty.const_int(0x00ff, false);
8019                let max = VectorType::const_vector(&[max; 8]);
8020                let apply_min_clamp_v1 =
8021                    err!(
8022                        self.builder
8023                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8024                    );
8025                let apply_max_clamp_v1 =
8026                    err!(
8027                        self.builder
8028                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8029                    );
8030                let apply_min_clamp_v2 =
8031                    err!(
8032                        self.builder
8033                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8034                    );
8035                let apply_max_clamp_v2 =
8036                    err!(
8037                        self.builder
8038                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8039                    );
8040                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8041                    .into_vector_value();
8042                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8043                    .into_vector_value();
8044                let v1 = err!(self.builder.build_int_truncate(
8045                    v1,
8046                    self.intrinsics.i8_ty.vec_type(8),
8047                    ""
8048                ));
8049                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8050                    .into_vector_value();
8051                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8052                    .into_vector_value();
8053                let v2 = err!(self.builder.build_int_truncate(
8054                    v2,
8055                    self.intrinsics.i8_ty.vec_type(8),
8056                    ""
8057                ));
8058                let res = err!(self.builder.build_shuffle_vector(
8059                    v1,
8060                    v2,
8061                    VectorType::const_vector(&[
8062                        self.intrinsics.i32_consts[0],
8063                        self.intrinsics.i32_consts[1],
8064                        self.intrinsics.i32_consts[2],
8065                        self.intrinsics.i32_consts[3],
8066                        self.intrinsics.i32_consts[4],
8067                        self.intrinsics.i32_consts[5],
8068                        self.intrinsics.i32_consts[6],
8069                        self.intrinsics.i32_consts[7],
8070                        self.intrinsics.i32_consts[8],
8071                        self.intrinsics.i32_consts[9],
8072                        self.intrinsics.i32_consts[10],
8073                        self.intrinsics.i32_consts[11],
8074                        self.intrinsics.i32_consts[12],
8075                        self.intrinsics.i32_consts[13],
8076                        self.intrinsics.i32_consts[14],
8077                        self.intrinsics.i32_consts[15],
8078                    ]),
8079                    "",
8080                ));
8081                let res = err!(
8082                    self.builder
8083                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8084                );
8085                self.state.push1(res);
8086            }
8087            Operator::I16x8NarrowI32x4S => {
8088                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8089                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8090                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8091                let min = self.intrinsics.i32_ty.const_int(0xffff8000, false);
8092                let max = self.intrinsics.i32_ty.const_int(0x00007fff, false);
8093                let min = VectorType::const_vector(&[min; 4]);
8094                let max = VectorType::const_vector(&[max; 4]);
8095                let apply_min_clamp_v1 =
8096                    err!(
8097                        self.builder
8098                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8099                    );
8100                let apply_max_clamp_v1 =
8101                    err!(
8102                        self.builder
8103                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8104                    );
8105                let apply_min_clamp_v2 =
8106                    err!(
8107                        self.builder
8108                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8109                    );
8110                let apply_max_clamp_v2 =
8111                    err!(
8112                        self.builder
8113                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8114                    );
8115                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8116                    .into_vector_value();
8117                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8118                    .into_vector_value();
8119                let v1 = err!(self.builder.build_int_truncate(
8120                    v1,
8121                    self.intrinsics.i16_ty.vec_type(4),
8122                    ""
8123                ));
8124                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8125                    .into_vector_value();
8126                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8127                    .into_vector_value();
8128                let v2 = err!(self.builder.build_int_truncate(
8129                    v2,
8130                    self.intrinsics.i16_ty.vec_type(4),
8131                    ""
8132                ));
8133                let res = err!(self.builder.build_shuffle_vector(
8134                    v1,
8135                    v2,
8136                    VectorType::const_vector(&[
8137                        self.intrinsics.i32_consts[0],
8138                        self.intrinsics.i32_consts[1],
8139                        self.intrinsics.i32_consts[2],
8140                        self.intrinsics.i32_consts[3],
8141                        self.intrinsics.i32_consts[4],
8142                        self.intrinsics.i32_consts[5],
8143                        self.intrinsics.i32_consts[6],
8144                        self.intrinsics.i32_consts[7],
8145                    ]),
8146                    "",
8147                ));
8148                let res = err!(
8149                    self.builder
8150                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8151                );
8152                self.state.push1(res);
8153            }
8154            Operator::I16x8NarrowI32x4U => {
8155                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8156                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8157                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8158                let min = self.intrinsics.i32x4_ty.const_zero();
8159                let max = self.intrinsics.i32_ty.const_int(0xffff, false);
8160                let max = VectorType::const_vector(&[max; 4]);
8161                let apply_min_clamp_v1 =
8162                    err!(
8163                        self.builder
8164                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8165                    );
8166                let apply_max_clamp_v1 =
8167                    err!(
8168                        self.builder
8169                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8170                    );
8171                let apply_min_clamp_v2 =
8172                    err!(
8173                        self.builder
8174                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8175                    );
8176                let apply_max_clamp_v2 =
8177                    err!(
8178                        self.builder
8179                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8180                    );
8181                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8182                    .into_vector_value();
8183                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8184                    .into_vector_value();
8185                let v1 = err!(self.builder.build_int_truncate(
8186                    v1,
8187                    self.intrinsics.i16_ty.vec_type(4),
8188                    ""
8189                ));
8190                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8191                    .into_vector_value();
8192                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8193                    .into_vector_value();
8194                let v2 = err!(self.builder.build_int_truncate(
8195                    v2,
8196                    self.intrinsics.i16_ty.vec_type(4),
8197                    ""
8198                ));
8199                let res = err!(self.builder.build_shuffle_vector(
8200                    v1,
8201                    v2,
8202                    VectorType::const_vector(&[
8203                        self.intrinsics.i32_consts[0],
8204                        self.intrinsics.i32_consts[1],
8205                        self.intrinsics.i32_consts[2],
8206                        self.intrinsics.i32_consts[3],
8207                        self.intrinsics.i32_consts[4],
8208                        self.intrinsics.i32_consts[5],
8209                        self.intrinsics.i32_consts[6],
8210                        self.intrinsics.i32_consts[7],
8211                    ]),
8212                    "",
8213                ));
8214                let res = err!(
8215                    self.builder
8216                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8217                );
8218                self.state.push1(res);
8219            }
8220            Operator::I32x4RelaxedTruncF32x4S if self.cpu_features.contains(CpuFeature::SSE2) => {
8221                let (v, i) = self.state.pop1_extra()?;
8222                let (v, _) = self.v128_into_f32x4(v, i)?;
8223                let res = self
8224                    .build_call_with_param_attributes(
8225                        self.intrinsics.x86_64.cvttps2dq,
8226                        &[v.into()],
8227                        "",
8228                    )?
8229                    .try_as_basic_value()
8230                    .unwrap_basic();
8231                let res = err!(
8232                    self.builder
8233                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8234                );
8235                self.state.push1(res);
8236            }
8237            Operator::I32x4TruncSatF32x4S | Operator::I32x4RelaxedTruncF32x4S => {
8238                let (v, i) = self.state.pop1_extra()?;
8239                let v = self.apply_pending_canonicalization(v, i)?;
8240                let v = v.into_int_value();
8241                let res = self.trunc_sat_into_int(
8242                    self.intrinsics.f32x4_ty,
8243                    self.intrinsics.i32x4_ty,
8244                    LEF32_GEQ_I32_MIN,
8245                    GEF32_LEQ_I32_MAX,
8246                    i32::MIN as u64,
8247                    i32::MAX as u64,
8248                    v,
8249                )?;
8250                self.state.push1(res);
8251            }
8252            Operator::I32x4RelaxedTruncF32x4U
8253                if self.cpu_features.contains(CpuFeature::AVX512F)
8254                    && self.cpu_features.contains(CpuFeature::AVX512VL) =>
8255            {
8256                let (v, i) = self.state.pop1_extra()?;
8257                let (v, _) = self.v128_into_f32x4(v, i)?;
8258                let res = self
8259                    .build_call_with_param_attributes(
8260                        self.intrinsics.x86_64.cvtps2udq128,
8261                        &[
8262                            v.into(),
8263                            self.intrinsics.i32x4_ty.const_zero().into(),
8264                            self.intrinsics.i8_ty.const_int(0xff, false).into(),
8265                        ],
8266                        "",
8267                    )?
8268                    .try_as_basic_value()
8269                    .unwrap_basic();
8270                let res = err!(
8271                    self.builder
8272                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8273                );
8274                self.state.push1(res);
8275            }
8276            Operator::I32x4TruncSatF32x4U | Operator::I32x4RelaxedTruncF32x4U => {
8277                let (v, i) = self.state.pop1_extra()?;
8278                let v = self.apply_pending_canonicalization(v, i)?;
8279                let v = v.into_int_value();
8280                let res = self.trunc_sat_into_int(
8281                    self.intrinsics.f32x4_ty,
8282                    self.intrinsics.i32x4_ty,
8283                    LEF32_GEQ_U32_MIN,
8284                    GEF32_LEQ_U32_MAX,
8285                    u32::MIN as u64,
8286                    u32::MAX as u64,
8287                    v,
8288                )?;
8289                self.state.push1(res);
8290            }
8291            Operator::I32x4RelaxedTruncF64x2SZero
8292                if self.cpu_features.contains(CpuFeature::SSE2) =>
8293            {
8294                let (v, i) = self.state.pop1_extra()?;
8295                let (v, _) = self.v128_into_f64x2(v, i)?;
8296                let res = self
8297                    .build_call_with_param_attributes(
8298                        self.intrinsics.x86_64.cvtpd2dq,
8299                        &[v.into()],
8300                        "",
8301                    )?
8302                    .try_as_basic_value()
8303                    .unwrap_basic();
8304                let res = err!(
8305                    self.builder
8306                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8307                );
8308                self.state.push1(res);
8309            }
8310            Operator::I32x4RelaxedTruncF64x2UZero
8311                if self.cpu_features.contains(CpuFeature::AVX512F)
8312                    && self.cpu_features.contains(CpuFeature::AVX512VL) =>
8313            {
8314                let (v, i) = self.state.pop1_extra()?;
8315                let (v, _) = self.v128_into_f64x2(v, i)?;
8316                let res = self
8317                    .build_call_with_param_attributes(
8318                        self.intrinsics.x86_64.cvtpd2udq128,
8319                        &[
8320                            v.into(),
8321                            self.intrinsics.i32x4_ty.const_zero().into(),
8322                            self.intrinsics.i8_ty.const_int(0xff, false).into(),
8323                        ],
8324                        "",
8325                    )?
8326                    .try_as_basic_value()
8327                    .unwrap_basic();
8328                let res = err!(
8329                    self.builder
8330                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8331                );
8332                self.state.push1(res);
8333            }
8334            Operator::I32x4TruncSatF64x2SZero
8335            | Operator::I32x4TruncSatF64x2UZero
8336            | Operator::I32x4RelaxedTruncF64x2SZero
8337            | Operator::I32x4RelaxedTruncF64x2UZero => {
8338                let ((min, max), (cmp_min, cmp_max)) = match op {
8339                    Operator::I32x4TruncSatF64x2SZero => (
8340                        (i32::MIN as u64, i32::MAX as u64),
8341                        (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
8342                    ),
8343                    Operator::I32x4TruncSatF64x2UZero => (
8344                        (u32::MIN as u64, u32::MAX as u64),
8345                        (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
8346                    ),
8347                    Operator::I32x4RelaxedTruncF64x2SZero => (
8348                        (i32::MIN as u64, i32::MAX as u64),
8349                        (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
8350                    ),
8351                    Operator::I32x4RelaxedTruncF64x2UZero => (
8352                        (u32::MIN as u64, u32::MAX as u64),
8353                        (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
8354                    ),
8355                    _ => unreachable!("Unhandled internal variant"),
8356                };
8357                let (v, i) = self.state.pop1_extra()?;
8358                let v = self.apply_pending_canonicalization(v, i)?;
8359                let v = v.into_int_value();
8360                let res = self.trunc_sat(
8361                    self.intrinsics.f64x2_ty,
8362                    self.intrinsics.i32_ty.vec_type(2),
8363                    cmp_min,
8364                    cmp_max,
8365                    min,
8366                    max,
8367                    v,
8368                )?;
8369
8370                let zero = self.intrinsics.i32_consts[0];
8371                let zeros = VectorType::const_vector(&[zero; 2]);
8372                let res = err!(self.builder.build_shuffle_vector(
8373                    res,
8374                    zeros,
8375                    VectorType::const_vector(&[
8376                        self.intrinsics.i32_consts[0],
8377                        self.intrinsics.i32_consts[1],
8378                        self.intrinsics.i32_consts[2],
8379                        self.intrinsics.i32_consts[3],
8380                    ]),
8381                    "",
8382                ));
8383                let res = err!(
8384                    self.builder
8385                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8386                );
8387                self.state.push1(res);
8388            }
8389            // Operator::I64x2TruncSatF64x2S => {
8390            //     let (v, i) = self.state.pop1_extra()?;
8391            //     let v = self.apply_pending_canonicalization(v, i)?;
8392            //     let v = v.into_int_value();
8393            //     let res = self.trunc_sat_into_int(
8394            //         self.intrinsics.f64x2_ty,
8395            //         self.intrinsics.i64x2_ty,
8396            //         i64::MIN as u64,
8397            //         i64::MAX as u64,
8398            //         i64::MIN as u64,
8399            //         i64::MAX as u64,
8400            //         v,
8401            //     )?;
8402            //     self.state.push1(res);
8403            // }
8404            // Operator::I64x2TruncSatF64x2U => {
8405            //     let (v, i) = self.state.pop1_extra()?;
8406            //     let v = self.apply_pending_canonicalization(v, i)?;
8407            //     let v = v.into_int_value();
8408            //     let res = self.trunc_sat_into_int(
8409            //         self.intrinsics.f64x2_ty,
8410            //         self.intrinsics.i64x2_ty,
8411            //         u64::MIN,
8412            //         u64::MAX,
8413            //         u64::MIN,
8414            //         u64::MAX,
8415            //         v,
8416            //     )?;
8417            //     self.state.push1(res);
8418            // }
8419            Operator::I32TruncF32S => {
8420                let v1 = self.state.pop1()?.into_float_value();
8421                self.trap_if_not_representable_as_int(
8422                    0xcf000000, // -2147483600.0
8423                    0x4effffff, // 2147483500.0
8424                    v1,
8425                )?;
8426                let res = err!(self.builder.build_float_to_signed_int(
8427                    v1,
8428                    self.intrinsics.i32_ty,
8429                    ""
8430                ));
8431                self.state.push1(res);
8432            }
8433            Operator::I32TruncF64S => {
8434                let v1 = self.state.pop1()?.into_float_value();
8435                self.trap_if_not_representable_as_int(
8436                    0xc1e00000001fffff, // -2147483648.9999995
8437                    0x41dfffffffffffff, // 2147483647.9999998
8438                    v1,
8439                )?;
8440                let res = err!(self.builder.build_float_to_signed_int(
8441                    v1,
8442                    self.intrinsics.i32_ty,
8443                    ""
8444                ));
8445                self.state.push1(res);
8446            }
8447            Operator::I32TruncSatF32S => {
8448                let (v, i) = self.state.pop1_extra()?;
8449                let v = self.apply_pending_canonicalization(v, i)?;
8450                let v = v.into_float_value();
8451                let res = self.trunc_sat_scalar(
8452                    self.intrinsics.i32_ty,
8453                    LEF32_GEQ_I32_MIN,
8454                    GEF32_LEQ_I32_MAX,
8455                    i32::MIN as u32 as u64,
8456                    i32::MAX as u32 as u64,
8457                    v,
8458                )?;
8459                self.state.push1(res);
8460            }
8461            Operator::I32TruncSatF64S => {
8462                let (v, i) = self.state.pop1_extra()?;
8463                let v = self.apply_pending_canonicalization(v, i)?;
8464                let v = v.into_float_value();
8465                let res = self.trunc_sat_scalar(
8466                    self.intrinsics.i32_ty,
8467                    LEF64_GEQ_I32_MIN,
8468                    GEF64_LEQ_I32_MAX,
8469                    i32::MIN as u64,
8470                    i32::MAX as u64,
8471                    v,
8472                )?;
8473                self.state.push1(res);
8474            }
8475            Operator::I64TruncF32S => {
8476                let v1 = self.state.pop1()?.into_float_value();
8477                self.trap_if_not_representable_as_int(
8478                    0xdf000000, // -9223372000000000000.0
8479                    0x5effffff, // 9223371500000000000.0
8480                    v1,
8481                )?;
8482                let res = err!(self.builder.build_float_to_signed_int(
8483                    v1,
8484                    self.intrinsics.i64_ty,
8485                    ""
8486                ));
8487                self.state.push1(res);
8488            }
8489            Operator::I64TruncF64S => {
8490                let v1 = self.state.pop1()?.into_float_value();
8491                self.trap_if_not_representable_as_int(
8492                    0xc3e0000000000000, // -9223372036854776000.0
8493                    0x43dfffffffffffff, // 9223372036854775000.0
8494                    v1,
8495                )?;
8496                let res = err!(self.builder.build_float_to_signed_int(
8497                    v1,
8498                    self.intrinsics.i64_ty,
8499                    ""
8500                ));
8501                self.state.push1(res);
8502            }
8503            Operator::I64TruncSatF32S => {
8504                let (v, i) = self.state.pop1_extra()?;
8505                let v = self.apply_pending_canonicalization(v, i)?;
8506                let v = v.into_float_value();
8507                let res = self.trunc_sat_scalar(
8508                    self.intrinsics.i64_ty,
8509                    LEF32_GEQ_I64_MIN,
8510                    GEF32_LEQ_I64_MAX,
8511                    i64::MIN as u64,
8512                    i64::MAX as u64,
8513                    v,
8514                )?;
8515                self.state.push1(res);
8516            }
8517            Operator::I64TruncSatF64S => {
8518                let (v, i) = self.state.pop1_extra()?;
8519                let v = self.apply_pending_canonicalization(v, i)?;
8520                let v = v.into_float_value();
8521                let res = self.trunc_sat_scalar(
8522                    self.intrinsics.i64_ty,
8523                    LEF64_GEQ_I64_MIN,
8524                    GEF64_LEQ_I64_MAX,
8525                    i64::MIN as u64,
8526                    i64::MAX as u64,
8527                    v,
8528                )?;
8529                self.state.push1(res);
8530            }
8531            Operator::I32TruncF32U => {
8532                let v1 = self.state.pop1()?.into_float_value();
8533                self.trap_if_not_representable_as_int(
8534                    0xbf7fffff, // -0.99999994
8535                    0x4f7fffff, // 4294967000.0
8536                    v1,
8537                )?;
8538                let res = err!(self.builder.build_float_to_unsigned_int(
8539                    v1,
8540                    self.intrinsics.i32_ty,
8541                    ""
8542                ));
8543                self.state.push1(res);
8544            }
8545            Operator::I32TruncF64U => {
8546                let v1 = self.state.pop1()?.into_float_value();
8547                self.trap_if_not_representable_as_int(
8548                    0xbfefffffffffffff, // -0.9999999999999999
8549                    0x41efffffffffffff, // 4294967295.9999995
8550                    v1,
8551                )?;
8552                let res = err!(self.builder.build_float_to_unsigned_int(
8553                    v1,
8554                    self.intrinsics.i32_ty,
8555                    ""
8556                ));
8557                self.state.push1(res);
8558            }
8559            Operator::I32TruncSatF32U => {
8560                let (v, i) = self.state.pop1_extra()?;
8561                let v = self.apply_pending_canonicalization(v, i)?;
8562                let v = v.into_float_value();
8563                let res = self.trunc_sat_scalar(
8564                    self.intrinsics.i32_ty,
8565                    LEF32_GEQ_U32_MIN,
8566                    GEF32_LEQ_U32_MAX,
8567                    u32::MIN as u64,
8568                    u32::MAX as u64,
8569                    v,
8570                )?;
8571                self.state.push1(res);
8572            }
8573            Operator::I32TruncSatF64U => {
8574                let (v, i) = self.state.pop1_extra()?;
8575                let v = self.apply_pending_canonicalization(v, i)?;
8576                let v = v.into_float_value();
8577                let res = self.trunc_sat_scalar(
8578                    self.intrinsics.i32_ty,
8579                    LEF64_GEQ_U32_MIN,
8580                    GEF64_LEQ_U32_MAX,
8581                    u32::MIN as u64,
8582                    u32::MAX as u64,
8583                    v,
8584                )?;
8585                self.state.push1(res);
8586            }
8587            Operator::I64TruncF32U => {
8588                let v1 = self.state.pop1()?.into_float_value();
8589                self.trap_if_not_representable_as_int(
8590                    0xbf7fffff, // -0.99999994
8591                    0x5f7fffff, // 18446743000000000000.0
8592                    v1,
8593                )?;
8594                let res = err!(self.builder.build_float_to_unsigned_int(
8595                    v1,
8596                    self.intrinsics.i64_ty,
8597                    ""
8598                ));
8599                self.state.push1(res);
8600            }
8601            Operator::I64TruncF64U => {
8602                let v1 = self.state.pop1()?.into_float_value();
8603                self.trap_if_not_representable_as_int(
8604                    0xbfefffffffffffff, // -0.9999999999999999
8605                    0x43efffffffffffff, // 18446744073709550000.0
8606                    v1,
8607                )?;
8608                let res = err!(self.builder.build_float_to_unsigned_int(
8609                    v1,
8610                    self.intrinsics.i64_ty,
8611                    ""
8612                ));
8613                self.state.push1(res);
8614            }
8615            Operator::I64TruncSatF32U => {
8616                let (v, i) = self.state.pop1_extra()?;
8617                let v = self.apply_pending_canonicalization(v, i)?;
8618                let v = v.into_float_value();
8619                let res = self.trunc_sat_scalar(
8620                    self.intrinsics.i64_ty,
8621                    LEF32_GEQ_U64_MIN,
8622                    GEF32_LEQ_U64_MAX,
8623                    u64::MIN,
8624                    u64::MAX,
8625                    v,
8626                )?;
8627                self.state.push1(res);
8628            }
8629            Operator::I64TruncSatF64U => {
8630                let (v, i) = self.state.pop1_extra()?;
8631                let v = self.apply_pending_canonicalization(v, i)?;
8632                let v = v.into_float_value();
8633                let res = self.trunc_sat_scalar(
8634                    self.intrinsics.i64_ty,
8635                    LEF64_GEQ_U64_MIN,
8636                    GEF64_LEQ_U64_MAX,
8637                    u64::MIN,
8638                    u64::MAX,
8639                    v,
8640                )?;
8641                self.state.push1(res);
8642            }
8643            Operator::F32DemoteF64 => {
8644                let v = self.state.pop1()?;
8645                let v = v.into_float_value();
8646                let res = self
8647                    .build_call_with_param_attributes(
8648                        self.intrinsics.fptrunc_f64,
8649                        &[
8650                            v.into(),
8651                            self.intrinsics.fp_rounding_md,
8652                            self.intrinsics.fp_exception_md,
8653                        ],
8654                        "",
8655                    )?
8656                    .try_as_basic_value()
8657                    .unwrap_basic();
8658                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
8659            }
8660            Operator::F64PromoteF32 => {
8661                let v = self.state.pop1()?;
8662                let v = v.into_float_value();
8663                let res = self
8664                    .build_call_with_param_attributes(
8665                        self.intrinsics.fpext_f32,
8666                        &[v.into(), self.intrinsics.fp_exception_md],
8667                        "",
8668                    )?
8669                    .try_as_basic_value()
8670                    .unwrap_basic();
8671                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
8672            }
8673            Operator::F32ConvertI32S | Operator::F32ConvertI64S => {
8674                let (v, i) = self.state.pop1_extra()?;
8675                let v = self.apply_pending_canonicalization(v, i)?;
8676                let v = v.into_int_value();
8677                let res = err!(self.builder.build_signed_int_to_float(
8678                    v,
8679                    self.intrinsics.f32_ty,
8680                    ""
8681                ));
8682                self.state.push1(res);
8683            }
8684            Operator::F64ConvertI32S | Operator::F64ConvertI64S => {
8685                let (v, i) = self.state.pop1_extra()?;
8686                let v = self.apply_pending_canonicalization(v, i)?;
8687                let v = v.into_int_value();
8688                let res = err!(self.builder.build_signed_int_to_float(
8689                    v,
8690                    self.intrinsics.f64_ty,
8691                    ""
8692                ));
8693                self.state.push1(res);
8694            }
8695            Operator::F32ConvertI32U | Operator::F32ConvertI64U => {
8696                let (v, i) = self.state.pop1_extra()?;
8697                let v = self.apply_pending_canonicalization(v, i)?;
8698                let v = v.into_int_value();
8699                let res = err!(self.builder.build_unsigned_int_to_float(
8700                    v,
8701                    self.intrinsics.f32_ty,
8702                    ""
8703                ));
8704                self.state.push1(res);
8705            }
8706            Operator::F64ConvertI32U | Operator::F64ConvertI64U => {
8707                let (v, i) = self.state.pop1_extra()?;
8708                let v = self.apply_pending_canonicalization(v, i)?;
8709                let v = v.into_int_value();
8710                let res = err!(self.builder.build_unsigned_int_to_float(
8711                    v,
8712                    self.intrinsics.f64_ty,
8713                    ""
8714                ));
8715                self.state.push1(res);
8716            }
8717            Operator::F32x4ConvertI32x4S => {
8718                let v = self.state.pop1()?;
8719                let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
8720                    .into_vector_value();
8721                let res = err!(self.builder.build_signed_int_to_float(
8722                    v,
8723                    self.intrinsics.f32x4_ty,
8724                    ""
8725                ));
8726                let res = err!(
8727                    self.builder
8728                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8729                );
8730                self.state.push1(res);
8731            }
8732            Operator::F32x4ConvertI32x4U => {
8733                let v = self.state.pop1()?;
8734                let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
8735                    .into_vector_value();
8736                let res = err!(self.builder.build_unsigned_int_to_float(
8737                    v,
8738                    self.intrinsics.f32x4_ty,
8739                    ""
8740                ));
8741                let res = err!(
8742                    self.builder
8743                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8744                );
8745                self.state.push1(res);
8746            }
8747            Operator::F64x2ConvertLowI32x4S | Operator::F64x2ConvertLowI32x4U => {
8748                let extend = match op {
8749                    Operator::F64x2ConvertLowI32x4U => {
8750                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
8751                    }
8752                    Operator::F64x2ConvertLowI32x4S => {
8753                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
8754                    }
8755                    _ => unreachable!("Unhandled inner case"),
8756                };
8757                let (v, i) = self.state.pop1_extra()?;
8758                let (v, _) = self.v128_into_i32x4(v, i)?;
8759                let low = err!(self.builder.build_shuffle_vector(
8760                    v,
8761                    v.get_type().get_undef(),
8762                    VectorType::const_vector(&[
8763                        self.intrinsics.i32_consts[0],
8764                        self.intrinsics.i32_consts[1],
8765                    ]),
8766                    "",
8767                ));
8768                let res = err!(extend(self, low));
8769                let res = err!(self.builder.build_signed_int_to_float(
8770                    res,
8771                    self.intrinsics.f64x2_ty,
8772                    ""
8773                ));
8774                let res = err!(
8775                    self.builder
8776                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8777                );
8778                self.state.push1(res);
8779            }
8780            Operator::F64x2PromoteLowF32x4 => {
8781                let (v, i) = self.state.pop1_extra()?;
8782                let (v, _) = self.v128_into_f32x4(v, i)?;
8783                let low = err!(self.builder.build_shuffle_vector(
8784                    v,
8785                    v.get_type().get_undef(),
8786                    VectorType::const_vector(&[
8787                        self.intrinsics.i32_consts[0],
8788                        self.intrinsics.i32_consts[1],
8789                    ]),
8790                    "",
8791                ));
8792                let res = err!(
8793                    self.builder
8794                        .build_float_ext(low, self.intrinsics.f64x2_ty, "")
8795                );
8796                let res = err!(
8797                    self.builder
8798                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8799                );
8800                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
8801            }
8802            Operator::F32x4DemoteF64x2Zero => {
8803                let (v, i) = self.state.pop1_extra()?;
8804                let (v, _) = self.v128_into_f64x2(v, i)?;
8805                let f32x2_ty = self.intrinsics.f32_ty.vec_type(2);
8806                let res = err!(self.builder.build_float_trunc(v, f32x2_ty, ""));
8807                let zeros = f32x2_ty.const_zero();
8808                let res = err!(self.builder.build_shuffle_vector(
8809                    res,
8810                    zeros,
8811                    VectorType::const_vector(&[
8812                        self.intrinsics.i32_consts[0],
8813                        self.intrinsics.i32_consts[1],
8814                        self.intrinsics.i32_consts[2],
8815                        self.intrinsics.i32_consts[3],
8816                    ]),
8817                    "",
8818                ));
8819                let res = err!(
8820                    self.builder
8821                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8822                );
8823                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
8824            }
8825            // Operator::F64x2ConvertI64x2S => {
8826            //     let v = self.state.pop1()?;
8827            //     let v = self
8828            //         .builder
8829            //         .build_bit_cast(v, self.intrinsics.i64x2_ty, "")
8830            //         .into_vector_value();
8831            //     let res = self
8832            //         .builder
8833            //         .build_signed_int_to_float(v, self.intrinsics.f64x2_ty, "");
8834            //     let res = chck_err!(self.builder.build_bit_cast(res, self.intrinsics.i128_ty, ""));
8835            //     self.state.push1(res);
8836            // }
8837            // Operator::F64x2ConvertI64x2U => {
8838            //     let v = self.state.pop1()?;
8839            //     let v = self
8840            //         .builder
8841            //         .build_bit_cast(v, self.intrinsics.i64x2_ty, "")
8842            //         .into_vector_value();
8843            //     let res = self
8844            //         .builder
8845            //         .build_unsigned_int_to_float(v, self.intrinsics.f64x2_ty, "");
8846            //     let res = chck_err!(self.builder.build_bit_cast(res, self.intrinsics.i128_ty, ""));
8847            //     self.state.push1(res);
8848            // }
8849            Operator::I32ReinterpretF32 => {
8850                let (v, i) = self.state.pop1_extra()?;
8851                let v = self.apply_pending_canonicalization(v, i)?;
8852                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i32_ty, ""));
8853                self.state.push1_extra(ret, ExtraInfo::arithmetic_f32());
8854            }
8855            Operator::I64ReinterpretF64 => {
8856                let (v, i) = self.state.pop1_extra()?;
8857                let v = self.apply_pending_canonicalization(v, i)?;
8858                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i64_ty, ""));
8859                self.state.push1_extra(ret, ExtraInfo::arithmetic_f64());
8860            }
8861            Operator::F32ReinterpretI32 => {
8862                let (v, i) = self.state.pop1_extra()?;
8863                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f32_ty, ""));
8864                self.state.push1_extra(ret, i);
8865            }
8866            Operator::F64ReinterpretI64 => {
8867                let (v, i) = self.state.pop1_extra()?;
8868                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f64_ty, ""));
8869                self.state.push1_extra(ret, i);
8870            }
8871
8872            /***************************
8873             * Sign-extension operators.
8874             * https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md
8875             ***************************/
8876            Operator::I32Extend8S => {
8877                let value = self.state.pop1()?.into_int_value();
8878                let narrow_value = err!(self.builder.build_int_truncate(
8879                    value,
8880                    self.intrinsics.i8_ty,
8881                    ""
8882                ));
8883                let extended_value = err!(self.builder.build_int_s_extend(
8884                    narrow_value,
8885                    self.intrinsics.i32_ty,
8886                    ""
8887                ));
8888                self.state.push1(extended_value);
8889            }
8890            Operator::I32Extend16S => {
8891                let value = self.state.pop1()?.into_int_value();
8892                let narrow_value = err!(self.builder.build_int_truncate(
8893                    value,
8894                    self.intrinsics.i16_ty,
8895                    ""
8896                ));
8897                let extended_value = err!(self.builder.build_int_s_extend(
8898                    narrow_value,
8899                    self.intrinsics.i32_ty,
8900                    ""
8901                ));
8902                self.state.push1(extended_value);
8903            }
8904            Operator::I64Extend8S => {
8905                let value = self.state.pop1()?.into_int_value();
8906                let narrow_value = err!(self.builder.build_int_truncate(
8907                    value,
8908                    self.intrinsics.i8_ty,
8909                    ""
8910                ));
8911                let extended_value = err!(self.builder.build_int_s_extend(
8912                    narrow_value,
8913                    self.intrinsics.i64_ty,
8914                    ""
8915                ));
8916                self.state.push1(extended_value);
8917            }
8918            Operator::I64Extend16S => {
8919                let value = self.state.pop1()?.into_int_value();
8920                let narrow_value = err!(self.builder.build_int_truncate(
8921                    value,
8922                    self.intrinsics.i16_ty,
8923                    ""
8924                ));
8925                let extended_value = err!(self.builder.build_int_s_extend(
8926                    narrow_value,
8927                    self.intrinsics.i64_ty,
8928                    ""
8929                ));
8930                self.state.push1(extended_value);
8931            }
8932            Operator::I64Extend32S => {
8933                let value = self.state.pop1()?.into_int_value();
8934                let narrow_value = err!(self.builder.build_int_truncate(
8935                    value,
8936                    self.intrinsics.i32_ty,
8937                    ""
8938                ));
8939                let extended_value = err!(self.builder.build_int_s_extend(
8940                    narrow_value,
8941                    self.intrinsics.i64_ty,
8942                    ""
8943                ));
8944                self.state.push1(extended_value);
8945            }
8946
8947            /***************************
8948             * Load and Store instructions.
8949             * https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#load-and-store-instructions
8950             ***************************/
8951            Operator::I32Load { ref memarg } => {
8952                let offset = self.state.pop1()?.into_int_value();
8953                let memory_index = MemoryIndex::from_u32(0);
8954                let effective_address = self.resolve_memory_ptr(
8955                    memory_index,
8956                    memarg,
8957                    self.intrinsics.ptr_ty,
8958                    offset,
8959                    4,
8960                )?;
8961                let result = err!(self.builder.build_load(
8962                    self.intrinsics.i32_ty,
8963                    effective_address,
8964                    ""
8965                ));
8966                self.annotate_user_memaccess(
8967                    memory_index,
8968                    memarg,
8969                    1,
8970                    result.as_instruction_value().unwrap(),
8971                )?;
8972                self.state.push1(result);
8973            }
8974            Operator::I64Load { ref memarg } => {
8975                let offset = self.state.pop1()?.into_int_value();
8976                let memory_index = MemoryIndex::from_u32(0);
8977                let effective_address = self.resolve_memory_ptr(
8978                    memory_index,
8979                    memarg,
8980                    self.intrinsics.ptr_ty,
8981                    offset,
8982                    8,
8983                )?;
8984                let result = err!(self.builder.build_load(
8985                    self.intrinsics.i64_ty,
8986                    effective_address,
8987                    ""
8988                ));
8989                self.annotate_user_memaccess(
8990                    memory_index,
8991                    memarg,
8992                    1,
8993                    result.as_instruction_value().unwrap(),
8994                )?;
8995                self.state.push1(result);
8996            }
8997            Operator::F32Load { ref memarg } => {
8998                let offset = self.state.pop1()?.into_int_value();
8999                let memory_index = MemoryIndex::from_u32(0);
9000                let effective_address = self.resolve_memory_ptr(
9001                    memory_index,
9002                    memarg,
9003                    self.intrinsics.ptr_ty,
9004                    offset,
9005                    4,
9006                )?;
9007                let result = err!(self.builder.build_load(
9008                    self.intrinsics.f32_ty,
9009                    effective_address,
9010                    ""
9011                ));
9012                self.annotate_user_memaccess(
9013                    memory_index,
9014                    memarg,
9015                    1,
9016                    result.as_instruction_value().unwrap(),
9017                )?;
9018                self.state.push1(result);
9019            }
9020            Operator::F64Load { ref memarg } => {
9021                let offset = self.state.pop1()?.into_int_value();
9022                let memory_index = MemoryIndex::from_u32(0);
9023                let effective_address = self.resolve_memory_ptr(
9024                    memory_index,
9025                    memarg,
9026                    self.intrinsics.ptr_ty,
9027                    offset,
9028                    8,
9029                )?;
9030                let result = err!(self.builder.build_load(
9031                    self.intrinsics.f64_ty,
9032                    effective_address,
9033                    ""
9034                ));
9035                self.annotate_user_memaccess(
9036                    memory_index,
9037                    memarg,
9038                    1,
9039                    result.as_instruction_value().unwrap(),
9040                )?;
9041                self.state.push1(result);
9042            }
9043            Operator::V128Load { ref memarg } => {
9044                let offset = self.state.pop1()?.into_int_value();
9045                let memory_index = MemoryIndex::from_u32(0);
9046                let effective_address = self.resolve_memory_ptr(
9047                    memory_index,
9048                    memarg,
9049                    self.intrinsics.ptr_ty,
9050                    offset,
9051                    16,
9052                )?;
9053                let result = err!(self.builder.build_load(
9054                    self.intrinsics.i128_ty,
9055                    effective_address,
9056                    ""
9057                ));
9058                self.annotate_user_memaccess(
9059                    memory_index,
9060                    memarg,
9061                    1,
9062                    result.as_instruction_value().unwrap(),
9063                )?;
9064                self.state.push1(result);
9065            }
9066            Operator::V128Load8Lane { ref memarg, lane } => {
9067                let (v, i) = self.state.pop1_extra()?;
9068                let (v, _i) = self.v128_into_i8x16(v, i)?;
9069                let offset = self.state.pop1()?.into_int_value();
9070                let memory_index = MemoryIndex::from_u32(memarg.memory);
9071                let effective_address = self.resolve_memory_ptr(
9072                    memory_index,
9073                    memarg,
9074                    self.intrinsics.ptr_ty,
9075                    offset,
9076                    1,
9077                )?;
9078                let element = err!(self.builder.build_load(
9079                    self.intrinsics.i8_ty,
9080                    effective_address,
9081                    ""
9082                ));
9083                self.annotate_user_memaccess(
9084                    memory_index,
9085                    memarg,
9086                    1,
9087                    element.as_instruction_value().unwrap(),
9088                )?;
9089                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9090                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9091                let res = err!(
9092                    self.builder
9093                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9094                );
9095                self.state.push1(res);
9096            }
9097            Operator::V128Load16Lane { ref memarg, lane } => {
9098                let (v, i) = self.state.pop1_extra()?;
9099                let (v, i) = self.v128_into_i16x8(v, i)?;
9100                let offset = self.state.pop1()?.into_int_value();
9101                let memory_index = MemoryIndex::from_u32(memarg.memory);
9102                let effective_address = self.resolve_memory_ptr(
9103                    memory_index,
9104                    memarg,
9105                    self.intrinsics.ptr_ty,
9106                    offset,
9107                    2,
9108                )?;
9109                let element = err!(self.builder.build_load(
9110                    self.intrinsics.i16_ty,
9111                    effective_address,
9112                    ""
9113                ));
9114                self.annotate_user_memaccess(
9115                    memory_index,
9116                    memarg,
9117                    1,
9118                    element.as_instruction_value().unwrap(),
9119                )?;
9120                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9121                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9122                let res = err!(
9123                    self.builder
9124                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9125                );
9126                self.state.push1_extra(res, i);
9127            }
9128            Operator::V128Load32Lane { ref memarg, lane } => {
9129                let (v, i) = self.state.pop1_extra()?;
9130                let (v, i) = self.v128_into_i32x4(v, i)?;
9131                let offset = self.state.pop1()?.into_int_value();
9132                let memory_index = MemoryIndex::from_u32(memarg.memory);
9133                let effective_address = self.resolve_memory_ptr(
9134                    memory_index,
9135                    memarg,
9136                    self.intrinsics.ptr_ty,
9137                    offset,
9138                    4,
9139                )?;
9140                let element = err!(self.builder.build_load(
9141                    self.intrinsics.i32_ty,
9142                    effective_address,
9143                    ""
9144                ));
9145                self.annotate_user_memaccess(
9146                    memory_index,
9147                    memarg,
9148                    1,
9149                    element.as_instruction_value().unwrap(),
9150                )?;
9151                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9152                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9153                let res = err!(
9154                    self.builder
9155                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9156                );
9157                self.state.push1_extra(res, i);
9158            }
9159            Operator::V128Load64Lane { ref memarg, lane } => {
9160                let (v, i) = self.state.pop1_extra()?;
9161                let (v, i) = self.v128_into_i64x2(v, i)?;
9162                let offset = self.state.pop1()?.into_int_value();
9163                let memory_index = MemoryIndex::from_u32(memarg.memory);
9164                let effective_address = self.resolve_memory_ptr(
9165                    memory_index,
9166                    memarg,
9167                    self.intrinsics.ptr_ty,
9168                    offset,
9169                    8,
9170                )?;
9171                let element = err!(self.builder.build_load(
9172                    self.intrinsics.i64_ty,
9173                    effective_address,
9174                    ""
9175                ));
9176                self.annotate_user_memaccess(
9177                    memory_index,
9178                    memarg,
9179                    1,
9180                    element.as_instruction_value().unwrap(),
9181                )?;
9182                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9183                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9184                let res = err!(
9185                    self.builder
9186                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9187                );
9188                self.state.push1_extra(res, i);
9189            }
9190
9191            Operator::I32Store { ref memarg } => {
9192                let value = self.state.pop1()?;
9193                let offset = self.state.pop1()?.into_int_value();
9194                let memory_index = MemoryIndex::from_u32(0);
9195                let effective_address = self.resolve_memory_ptr(
9196                    memory_index,
9197                    memarg,
9198                    self.intrinsics.ptr_ty,
9199                    offset,
9200                    4,
9201                )?;
9202                let dead_load = err!(self.builder.build_load(
9203                    self.intrinsics.i32_ty,
9204                    effective_address,
9205                    ""
9206                ));
9207                self.annotate_user_memaccess(
9208                    memory_index,
9209                    memarg,
9210                    1,
9211                    dead_load.as_instruction_value().unwrap(),
9212                )?;
9213                let store = err!(self.builder.build_store(effective_address, value));
9214                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9215            }
9216            Operator::I64Store { ref memarg } => {
9217                let value = self.state.pop1()?;
9218                let offset = self.state.pop1()?.into_int_value();
9219                let memory_index = MemoryIndex::from_u32(0);
9220                let effective_address = self.resolve_memory_ptr(
9221                    memory_index,
9222                    memarg,
9223                    self.intrinsics.ptr_ty,
9224                    offset,
9225                    8,
9226                )?;
9227                let dead_load = err!(self.builder.build_load(
9228                    self.intrinsics.i64_ty,
9229                    effective_address,
9230                    ""
9231                ));
9232                self.annotate_user_memaccess(
9233                    memory_index,
9234                    memarg,
9235                    1,
9236                    dead_load.as_instruction_value().unwrap(),
9237                )?;
9238                let store = err!(self.builder.build_store(effective_address, value));
9239                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9240            }
9241            Operator::F32Store { ref memarg } => {
9242                let (v, i) = self.state.pop1_extra()?;
9243                let v = self.apply_pending_canonicalization(v, i)?;
9244                let offset = self.state.pop1()?.into_int_value();
9245                let memory_index = MemoryIndex::from_u32(0);
9246                let effective_address = self.resolve_memory_ptr(
9247                    memory_index,
9248                    memarg,
9249                    self.intrinsics.ptr_ty,
9250                    offset,
9251                    4,
9252                )?;
9253                let dead_load = err!(self.builder.build_load(
9254                    self.intrinsics.f32_ty,
9255                    effective_address,
9256                    ""
9257                ));
9258                self.annotate_user_memaccess(
9259                    memory_index,
9260                    memarg,
9261                    1,
9262                    dead_load.as_instruction_value().unwrap(),
9263                )?;
9264                let store = err!(self.builder.build_store(effective_address, v));
9265                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9266            }
9267            Operator::F64Store { ref memarg } => {
9268                let (v, i) = self.state.pop1_extra()?;
9269                let v = self.apply_pending_canonicalization(v, i)?;
9270                let offset = self.state.pop1()?.into_int_value();
9271                let memory_index = MemoryIndex::from_u32(0);
9272                let effective_address = self.resolve_memory_ptr(
9273                    memory_index,
9274                    memarg,
9275                    self.intrinsics.ptr_ty,
9276                    offset,
9277                    8,
9278                )?;
9279                let dead_load = err!(self.builder.build_load(
9280                    self.intrinsics.f64_ty,
9281                    effective_address,
9282                    ""
9283                ));
9284                self.annotate_user_memaccess(
9285                    memory_index,
9286                    memarg,
9287                    1,
9288                    dead_load.as_instruction_value().unwrap(),
9289                )?;
9290                let store = err!(self.builder.build_store(effective_address, v));
9291                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9292            }
9293            Operator::V128Store { ref memarg } => {
9294                let (v, i) = self.state.pop1_extra()?;
9295                let v = self.apply_pending_canonicalization(v, i)?;
9296                let offset = self.state.pop1()?.into_int_value();
9297                let memory_index = MemoryIndex::from_u32(0);
9298                let effective_address = self.resolve_memory_ptr(
9299                    memory_index,
9300                    memarg,
9301                    self.intrinsics.ptr_ty,
9302                    offset,
9303                    16,
9304                )?;
9305                let dead_load = err!(self.builder.build_load(
9306                    self.intrinsics.i128_ty,
9307                    effective_address,
9308                    ""
9309                ));
9310                self.annotate_user_memaccess(
9311                    memory_index,
9312                    memarg,
9313                    1,
9314                    dead_load.as_instruction_value().unwrap(),
9315                )?;
9316                let store = err!(self.builder.build_store(effective_address, v));
9317                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9318            }
9319            Operator::V128Store8Lane { ref memarg, lane } => {
9320                let (v, i) = self.state.pop1_extra()?;
9321                let (v, _i) = self.v128_into_i8x16(v, i)?;
9322                let offset = self.state.pop1()?.into_int_value();
9323                let memory_index = MemoryIndex::from_u32(memarg.memory);
9324
9325                let effective_address = self.resolve_memory_ptr(
9326                    memory_index,
9327                    memarg,
9328                    self.intrinsics.ptr_ty,
9329                    offset,
9330                    1,
9331                )?;
9332                let dead_load = err!(self.builder.build_load(
9333                    self.intrinsics.i8_ty,
9334                    effective_address,
9335                    ""
9336                ));
9337                self.annotate_user_memaccess(
9338                    memory_index,
9339                    memarg,
9340                    1,
9341                    dead_load.as_instruction_value().unwrap(),
9342                )?;
9343                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9344                let val = err!(self.builder.build_extract_element(v, idx, ""));
9345                let store = err!(self.builder.build_store(effective_address, val));
9346                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9347            }
9348            Operator::V128Store16Lane { ref memarg, lane } => {
9349                let (v, i) = self.state.pop1_extra()?;
9350                let (v, _i) = self.v128_into_i16x8(v, i)?;
9351                let offset = self.state.pop1()?.into_int_value();
9352                let memory_index = MemoryIndex::from_u32(memarg.memory);
9353
9354                let effective_address = self.resolve_memory_ptr(
9355                    memory_index,
9356                    memarg,
9357                    self.intrinsics.ptr_ty,
9358                    offset,
9359                    2,
9360                )?;
9361                let dead_load = err!(self.builder.build_load(
9362                    self.intrinsics.i16_ty,
9363                    effective_address,
9364                    ""
9365                ));
9366                self.annotate_user_memaccess(
9367                    memory_index,
9368                    memarg,
9369                    1,
9370                    dead_load.as_instruction_value().unwrap(),
9371                )?;
9372                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9373                let val = err!(self.builder.build_extract_element(v, idx, ""));
9374                let store = err!(self.builder.build_store(effective_address, val));
9375                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9376            }
9377            Operator::V128Store32Lane { ref memarg, lane } => {
9378                let (v, i) = self.state.pop1_extra()?;
9379                let (v, _i) = self.v128_into_i32x4(v, i)?;
9380                let offset = self.state.pop1()?.into_int_value();
9381                let memory_index = MemoryIndex::from_u32(memarg.memory);
9382
9383                let effective_address = self.resolve_memory_ptr(
9384                    memory_index,
9385                    memarg,
9386                    self.intrinsics.ptr_ty,
9387                    offset,
9388                    4,
9389                )?;
9390                let dead_load = err!(self.builder.build_load(
9391                    self.intrinsics.i32_ty,
9392                    effective_address,
9393                    ""
9394                ));
9395                self.annotate_user_memaccess(
9396                    memory_index,
9397                    memarg,
9398                    1,
9399                    dead_load.as_instruction_value().unwrap(),
9400                )?;
9401                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9402                let val = err!(self.builder.build_extract_element(v, idx, ""));
9403                let store = err!(self.builder.build_store(effective_address, val));
9404                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9405            }
9406            Operator::V128Store64Lane { ref memarg, lane } => {
9407                let (v, i) = self.state.pop1_extra()?;
9408                let (v, _i) = self.v128_into_i64x2(v, i)?;
9409                let offset = self.state.pop1()?.into_int_value();
9410                let memory_index = MemoryIndex::from_u32(memarg.memory);
9411
9412                let effective_address = self.resolve_memory_ptr(
9413                    memory_index,
9414                    memarg,
9415                    self.intrinsics.ptr_ty,
9416                    offset,
9417                    8,
9418                )?;
9419                let dead_load = err!(self.builder.build_load(
9420                    self.intrinsics.i64_ty,
9421                    effective_address,
9422                    ""
9423                ));
9424                self.annotate_user_memaccess(
9425                    memory_index,
9426                    memarg,
9427                    1,
9428                    dead_load.as_instruction_value().unwrap(),
9429                )?;
9430                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9431                let val = err!(self.builder.build_extract_element(v, idx, ""));
9432                let store = err!(self.builder.build_store(effective_address, val));
9433                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9434            }
9435            Operator::I32Load8S { ref memarg } => {
9436                let offset = self.state.pop1()?.into_int_value();
9437                let memory_index = MemoryIndex::from_u32(0);
9438                let effective_address = self.resolve_memory_ptr(
9439                    memory_index,
9440                    memarg,
9441                    self.intrinsics.ptr_ty,
9442                    offset,
9443                    1,
9444                )?;
9445                let narrow_result = err!(self.builder.build_load(
9446                    self.intrinsics.i8_ty,
9447                    effective_address,
9448                    ""
9449                ));
9450                self.annotate_user_memaccess(
9451                    memory_index,
9452                    memarg,
9453                    1,
9454                    narrow_result.as_instruction_value().unwrap(),
9455                )?;
9456                let result = err!(self.builder.build_int_s_extend(
9457                    narrow_result.into_int_value(),
9458                    self.intrinsics.i32_ty,
9459                    "",
9460                ));
9461                self.state.push1(result);
9462            }
9463            Operator::I32Load16S { ref memarg } => {
9464                let offset = self.state.pop1()?.into_int_value();
9465                let memory_index = MemoryIndex::from_u32(0);
9466                let effective_address = self.resolve_memory_ptr(
9467                    memory_index,
9468                    memarg,
9469                    self.intrinsics.ptr_ty,
9470                    offset,
9471                    2,
9472                )?;
9473                let narrow_result = err!(self.builder.build_load(
9474                    self.intrinsics.i16_ty,
9475                    effective_address,
9476                    ""
9477                ));
9478                self.annotate_user_memaccess(
9479                    memory_index,
9480                    memarg,
9481                    1,
9482                    narrow_result.as_instruction_value().unwrap(),
9483                )?;
9484                let result = err!(self.builder.build_int_s_extend(
9485                    narrow_result.into_int_value(),
9486                    self.intrinsics.i32_ty,
9487                    "",
9488                ));
9489                self.state.push1(result);
9490            }
9491            Operator::I64Load8S { ref memarg } => {
9492                let offset = self.state.pop1()?.into_int_value();
9493                let memory_index = MemoryIndex::from_u32(0);
9494                let effective_address = self.resolve_memory_ptr(
9495                    memory_index,
9496                    memarg,
9497                    self.intrinsics.ptr_ty,
9498                    offset,
9499                    1,
9500                )?;
9501                let narrow_result = err!(self.builder.build_load(
9502                    self.intrinsics.i8_ty,
9503                    effective_address,
9504                    ""
9505                ))
9506                .into_int_value();
9507                self.annotate_user_memaccess(
9508                    memory_index,
9509                    memarg,
9510                    1,
9511                    narrow_result.as_instruction_value().unwrap(),
9512                )?;
9513                let result = err!(self.builder.build_int_s_extend(
9514                    narrow_result,
9515                    self.intrinsics.i64_ty,
9516                    ""
9517                ));
9518                self.state.push1(result);
9519            }
9520            Operator::I64Load16S { ref memarg } => {
9521                let offset = self.state.pop1()?.into_int_value();
9522                let memory_index = MemoryIndex::from_u32(0);
9523                let effective_address = self.resolve_memory_ptr(
9524                    memory_index,
9525                    memarg,
9526                    self.intrinsics.ptr_ty,
9527                    offset,
9528                    2,
9529                )?;
9530                let narrow_result = err!(self.builder.build_load(
9531                    self.intrinsics.i16_ty,
9532                    effective_address,
9533                    ""
9534                ))
9535                .into_int_value();
9536                self.annotate_user_memaccess(
9537                    memory_index,
9538                    memarg,
9539                    1,
9540                    narrow_result.as_instruction_value().unwrap(),
9541                )?;
9542                let result = err!(self.builder.build_int_s_extend(
9543                    narrow_result,
9544                    self.intrinsics.i64_ty,
9545                    ""
9546                ));
9547                self.state.push1(result);
9548            }
9549            Operator::I64Load32S { ref memarg } => {
9550                let offset = self.state.pop1()?.into_int_value();
9551                let memory_index = MemoryIndex::from_u32(0);
9552                let effective_address = self.resolve_memory_ptr(
9553                    memory_index,
9554                    memarg,
9555                    self.intrinsics.ptr_ty,
9556                    offset,
9557                    4,
9558                )?;
9559                let narrow_result = err!(self.builder.build_load(
9560                    self.intrinsics.i32_ty,
9561                    effective_address,
9562                    ""
9563                ));
9564                self.annotate_user_memaccess(
9565                    memory_index,
9566                    memarg,
9567                    1,
9568                    narrow_result.as_instruction_value().unwrap(),
9569                )?;
9570                let result = err!(self.builder.build_int_s_extend(
9571                    narrow_result.into_int_value(),
9572                    self.intrinsics.i64_ty,
9573                    "",
9574                ));
9575                self.state.push1(result);
9576            }
9577
9578            Operator::I32Load8U { ref memarg } => {
9579                let offset = self.state.pop1()?.into_int_value();
9580                let memory_index = MemoryIndex::from_u32(0);
9581                let effective_address = self.resolve_memory_ptr(
9582                    memory_index,
9583                    memarg,
9584                    self.intrinsics.ptr_ty,
9585                    offset,
9586                    1,
9587                )?;
9588                let narrow_result = err!(self.builder.build_load(
9589                    self.intrinsics.i8_ty,
9590                    effective_address,
9591                    ""
9592                ));
9593                self.annotate_user_memaccess(
9594                    memory_index,
9595                    memarg,
9596                    1,
9597                    narrow_result.as_instruction_value().unwrap(),
9598                )?;
9599                let result = err!(self.builder.build_int_z_extend(
9600                    narrow_result.into_int_value(),
9601                    self.intrinsics.i32_ty,
9602                    "",
9603                ));
9604                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9605            }
9606            Operator::I32Load16U { ref memarg } => {
9607                let offset = self.state.pop1()?.into_int_value();
9608                let memory_index = MemoryIndex::from_u32(0);
9609                let effective_address = self.resolve_memory_ptr(
9610                    memory_index,
9611                    memarg,
9612                    self.intrinsics.ptr_ty,
9613                    offset,
9614                    2,
9615                )?;
9616                let narrow_result = err!(self.builder.build_load(
9617                    self.intrinsics.i16_ty,
9618                    effective_address,
9619                    ""
9620                ));
9621                self.annotate_user_memaccess(
9622                    memory_index,
9623                    memarg,
9624                    1,
9625                    narrow_result.as_instruction_value().unwrap(),
9626                )?;
9627                let result = err!(self.builder.build_int_z_extend(
9628                    narrow_result.into_int_value(),
9629                    self.intrinsics.i32_ty,
9630                    "",
9631                ));
9632                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
9633            }
9634            Operator::I64Load8U { ref memarg } => {
9635                let offset = self.state.pop1()?.into_int_value();
9636                let memory_index = MemoryIndex::from_u32(0);
9637                let effective_address = self.resolve_memory_ptr(
9638                    memory_index,
9639                    memarg,
9640                    self.intrinsics.ptr_ty,
9641                    offset,
9642                    1,
9643                )?;
9644                let narrow_result = err!(self.builder.build_load(
9645                    self.intrinsics.i8_ty,
9646                    effective_address,
9647                    ""
9648                ));
9649                self.annotate_user_memaccess(
9650                    memory_index,
9651                    memarg,
9652                    1,
9653                    narrow_result.as_instruction_value().unwrap(),
9654                )?;
9655                let result = err!(self.builder.build_int_z_extend(
9656                    narrow_result.into_int_value(),
9657                    self.intrinsics.i64_ty,
9658                    "",
9659                ));
9660                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9661            }
9662            Operator::I64Load16U { ref memarg } => {
9663                let offset = self.state.pop1()?.into_int_value();
9664                let memory_index = MemoryIndex::from_u32(0);
9665                let effective_address = self.resolve_memory_ptr(
9666                    memory_index,
9667                    memarg,
9668                    self.intrinsics.ptr_ty,
9669                    offset,
9670                    2,
9671                )?;
9672                let narrow_result = err!(self.builder.build_load(
9673                    self.intrinsics.i16_ty,
9674                    effective_address,
9675                    ""
9676                ));
9677                self.annotate_user_memaccess(
9678                    memory_index,
9679                    memarg,
9680                    1,
9681                    narrow_result.as_instruction_value().unwrap(),
9682                )?;
9683                let result = err!(self.builder.build_int_z_extend(
9684                    narrow_result.into_int_value(),
9685                    self.intrinsics.i64_ty,
9686                    "",
9687                ));
9688                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9689            }
9690            Operator::I64Load32U { ref memarg } => {
9691                let offset = self.state.pop1()?.into_int_value();
9692                let memory_index = MemoryIndex::from_u32(0);
9693                let effective_address = self.resolve_memory_ptr(
9694                    memory_index,
9695                    memarg,
9696                    self.intrinsics.ptr_ty,
9697                    offset,
9698                    4,
9699                )?;
9700                let narrow_result = err!(self.builder.build_load(
9701                    self.intrinsics.i32_ty,
9702                    effective_address,
9703                    ""
9704                ));
9705                self.annotate_user_memaccess(
9706                    memory_index,
9707                    memarg,
9708                    1,
9709                    narrow_result.as_instruction_value().unwrap(),
9710                )?;
9711                let result = err!(self.builder.build_int_z_extend(
9712                    narrow_result.into_int_value(),
9713                    self.intrinsics.i64_ty,
9714                    "",
9715                ));
9716                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
9717            }
9718
9719            Operator::I32Store8 { ref memarg } | Operator::I64Store8 { ref memarg } => {
9720                let value = self.state.pop1()?.into_int_value();
9721                let offset = self.state.pop1()?.into_int_value();
9722                let memory_index = MemoryIndex::from_u32(0);
9723                let effective_address = self.resolve_memory_ptr(
9724                    memory_index,
9725                    memarg,
9726                    self.intrinsics.ptr_ty,
9727                    offset,
9728                    1,
9729                )?;
9730                let dead_load = err!(self.builder.build_load(
9731                    self.intrinsics.i8_ty,
9732                    effective_address,
9733                    ""
9734                ));
9735                self.annotate_user_memaccess(
9736                    memory_index,
9737                    memarg,
9738                    1,
9739                    dead_load.as_instruction_value().unwrap(),
9740                )?;
9741                let narrow_value = err!(self.builder.build_int_truncate(
9742                    value,
9743                    self.intrinsics.i8_ty,
9744                    ""
9745                ));
9746                let store = err!(self.builder.build_store(effective_address, narrow_value));
9747                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9748            }
9749            Operator::I32Store16 { ref memarg } | Operator::I64Store16 { ref memarg } => {
9750                let value = self.state.pop1()?.into_int_value();
9751                let offset = self.state.pop1()?.into_int_value();
9752                let memory_index = MemoryIndex::from_u32(0);
9753                let effective_address = self.resolve_memory_ptr(
9754                    memory_index,
9755                    memarg,
9756                    self.intrinsics.ptr_ty,
9757                    offset,
9758                    2,
9759                )?;
9760                let dead_load = err!(self.builder.build_load(
9761                    self.intrinsics.i16_ty,
9762                    effective_address,
9763                    ""
9764                ));
9765                self.annotate_user_memaccess(
9766                    memory_index,
9767                    memarg,
9768                    1,
9769                    dead_load.as_instruction_value().unwrap(),
9770                )?;
9771                let narrow_value = err!(self.builder.build_int_truncate(
9772                    value,
9773                    self.intrinsics.i16_ty,
9774                    ""
9775                ));
9776                let store = err!(self.builder.build_store(effective_address, narrow_value));
9777                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9778            }
9779            Operator::I64Store32 { ref memarg } => {
9780                let value = self.state.pop1()?.into_int_value();
9781                let offset = self.state.pop1()?.into_int_value();
9782                let memory_index = MemoryIndex::from_u32(0);
9783                let effective_address = self.resolve_memory_ptr(
9784                    memory_index,
9785                    memarg,
9786                    self.intrinsics.ptr_ty,
9787                    offset,
9788                    4,
9789                )?;
9790                let dead_load = err!(self.builder.build_load(
9791                    self.intrinsics.i32_ty,
9792                    effective_address,
9793                    ""
9794                ));
9795                self.annotate_user_memaccess(
9796                    memory_index,
9797                    memarg,
9798                    1,
9799                    dead_load.as_instruction_value().unwrap(),
9800                )?;
9801                let narrow_value = err!(self.builder.build_int_truncate(
9802                    value,
9803                    self.intrinsics.i32_ty,
9804                    ""
9805                ));
9806                let store = err!(self.builder.build_store(effective_address, narrow_value));
9807                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
9808            }
9809            Operator::I8x16Neg => {
9810                let (v, i) = self.state.pop1_extra()?;
9811                let (v, _) = self.v128_into_i8x16(v, i)?;
9812                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9813                let res = err!(
9814                    self.builder
9815                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9816                );
9817                self.state.push1(res);
9818            }
9819            Operator::I16x8Neg => {
9820                let (v, i) = self.state.pop1_extra()?;
9821                let (v, _) = self.v128_into_i16x8(v, i)?;
9822                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9823                let res = err!(
9824                    self.builder
9825                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9826                );
9827                self.state.push1(res);
9828            }
9829            Operator::I32x4Neg => {
9830                let (v, i) = self.state.pop1_extra()?;
9831                let (v, _) = self.v128_into_i32x4(v, i)?;
9832                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9833                let res = err!(
9834                    self.builder
9835                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9836                );
9837                self.state.push1(res);
9838            }
9839            Operator::I64x2Neg => {
9840                let (v, i) = self.state.pop1_extra()?;
9841                let (v, _) = self.v128_into_i64x2(v, i)?;
9842                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
9843                let res = err!(
9844                    self.builder
9845                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9846                );
9847                self.state.push1(res);
9848            }
9849            Operator::V128Not => {
9850                let (v, i) = self.state.pop1_extra()?;
9851                let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
9852                let res = err!(self.builder.build_not(v, ""));
9853                self.state.push1(res);
9854            }
9855            Operator::V128AnyTrue => {
9856                // | Operator::I64x2AnyTrue
9857                // Skip canonicalization, it never changes non-zero values to zero or vice versa.
9858                let v = self.state.pop1()?.into_int_value();
9859                let res = err!(self.builder.build_int_compare(
9860                    IntPredicate::NE,
9861                    v,
9862                    v.get_type().const_zero(),
9863                    "",
9864                ));
9865                let res = err!(
9866                    self.builder
9867                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
9868                );
9869                self.state.push1_extra(
9870                    res,
9871                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
9872                );
9873            }
9874            Operator::I8x16AllTrue
9875            | Operator::I16x8AllTrue
9876            | Operator::I32x4AllTrue
9877            | Operator::I64x2AllTrue => {
9878                let vec_ty = match op {
9879                    Operator::I8x16AllTrue => self.intrinsics.i8x16_ty,
9880                    Operator::I16x8AllTrue => self.intrinsics.i16x8_ty,
9881                    Operator::I32x4AllTrue => self.intrinsics.i32x4_ty,
9882                    Operator::I64x2AllTrue => self.intrinsics.i64x2_ty,
9883                    _ => unreachable!(),
9884                };
9885                let (v, i) = self.state.pop1_extra()?;
9886                let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
9887                let lane_int_ty = self.context.custom_width_int_type(vec_ty.get_size());
9888                let vec = err!(self.builder.build_bit_cast(v, vec_ty, "vec")).into_vector_value();
9889                let mask = err!(self.builder.build_int_compare(
9890                    IntPredicate::NE,
9891                    vec,
9892                    vec_ty.const_zero(),
9893                    "mask",
9894                ));
9895                let cmask =
9896                    err!(self.builder.build_bit_cast(mask, lane_int_ty, "cmask")).into_int_value();
9897                let res = err!(self.builder.build_int_compare(
9898                    IntPredicate::EQ,
9899                    cmask,
9900                    lane_int_ty.const_int(u64::MAX, true),
9901                    "",
9902                ));
9903                let res = err!(
9904                    self.builder
9905                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
9906                );
9907                self.state.push1_extra(
9908                    res,
9909                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
9910                );
9911            }
9912            Operator::I8x16ExtractLaneS { lane } => {
9913                let (v, i) = self.state.pop1_extra()?;
9914                let (v, _) = self.v128_into_i8x16(v, i)?;
9915                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9916                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
9917                let res = err!(
9918                    self.builder
9919                        .build_int_s_extend(res, self.intrinsics.i32_ty, "")
9920                );
9921                self.state.push1(res);
9922            }
9923            Operator::I8x16ExtractLaneU { lane } => {
9924                let (v, i) = self.state.pop1_extra()?;
9925                let (v, _) = self.v128_into_i8x16(v, i)?;
9926                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9927                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
9928                let res = err!(
9929                    self.builder
9930                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
9931                );
9932                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
9933            }
9934            Operator::I16x8ExtractLaneS { lane } => {
9935                let (v, i) = self.state.pop1_extra()?;
9936                let (v, _) = self.v128_into_i16x8(v, i)?;
9937                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9938                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
9939                let res = err!(
9940                    self.builder
9941                        .build_int_s_extend(res, self.intrinsics.i32_ty, "")
9942                );
9943                self.state.push1(res);
9944            }
9945            Operator::I16x8ExtractLaneU { lane } => {
9946                let (v, i) = self.state.pop1_extra()?;
9947                let (v, _) = self.v128_into_i16x8(v, i)?;
9948                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9949                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
9950                let res = err!(
9951                    self.builder
9952                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
9953                );
9954                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
9955            }
9956            Operator::I32x4ExtractLane { lane } => {
9957                let (v, i) = self.state.pop1_extra()?;
9958                let (v, i) = self.v128_into_i32x4(v, i)?;
9959                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9960                let res = err!(self.builder.build_extract_element(v, idx, ""));
9961                self.state.push1_extra(res, i);
9962            }
9963            Operator::I64x2ExtractLane { lane } => {
9964                let (v, i) = self.state.pop1_extra()?;
9965                let (v, i) = self.v128_into_i64x2(v, i)?;
9966                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9967                let res = err!(self.builder.build_extract_element(v, idx, ""));
9968                self.state.push1_extra(res, i);
9969            }
9970            Operator::F32x4ExtractLane { lane } => {
9971                let (v, i) = self.state.pop1_extra()?;
9972                let (v, i) = self.v128_into_f32x4(v, i)?;
9973                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9974                let res = err!(self.builder.build_extract_element(v, idx, ""));
9975                self.state.push1_extra(res, i);
9976            }
9977            Operator::F64x2ExtractLane { lane } => {
9978                let (v, i) = self.state.pop1_extra()?;
9979                let (v, i) = self.v128_into_f64x2(v, i)?;
9980                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9981                let res = err!(self.builder.build_extract_element(v, idx, ""));
9982                self.state.push1_extra(res, i);
9983            }
9984            Operator::I8x16ReplaceLane { lane } => {
9985                let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
9986                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
9987                let v2 = v2.into_int_value();
9988                let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i8_ty, ""));
9989                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9990                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
9991                let res = err!(
9992                    self.builder
9993                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9994                );
9995                self.state.push1(res);
9996            }
9997            Operator::I16x8ReplaceLane { lane } => {
9998                let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
9999                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
10000                let v2 = v2.into_int_value();
10001                let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i16_ty, ""));
10002                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10003                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10004                let res = err!(
10005                    self.builder
10006                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10007                );
10008                self.state.push1(res);
10009            }
10010            Operator::I32x4ReplaceLane { lane } => {
10011                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10012                let (v1, i1) = self.v128_into_i32x4(v1, i1)?;
10013                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10014                let v2 = v2.into_int_value();
10015                let i2 = i2.strip_pending();
10016                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10017                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10018                let res = err!(
10019                    self.builder
10020                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10021                );
10022                self.state
10023                    .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f32())?);
10024            }
10025            Operator::I64x2ReplaceLane { lane } => {
10026                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10027                let (v1, i1) = self.v128_into_i64x2(v1, i1)?;
10028                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10029                let v2 = v2.into_int_value();
10030                let i2 = i2.strip_pending();
10031                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10032                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10033                let res = err!(
10034                    self.builder
10035                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10036                );
10037                self.state
10038                    .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f64())?);
10039            }
10040            Operator::F32x4ReplaceLane { lane } => {
10041                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10042                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
10043                let push_pending_f32_nan_to_result =
10044                    i1.has_pending_f32_nan() && i2.has_pending_f32_nan();
10045                let (v1, v2) = if !push_pending_f32_nan_to_result {
10046                    (
10047                        self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10048                            .into_vector_value(),
10049                        self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10050                            .into_float_value(),
10051                    )
10052                } else {
10053                    (v1, v2.into_float_value())
10054                };
10055                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10056                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10057                let res = err!(
10058                    self.builder
10059                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10060                );
10061                let info = if push_pending_f32_nan_to_result {
10062                    ExtraInfo::pending_f32_nan()
10063                } else {
10064                    (i1.strip_pending() & i2.strip_pending())?
10065                };
10066                self.state.push1_extra(res, info);
10067            }
10068            Operator::F64x2ReplaceLane { lane } => {
10069                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10070                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
10071                let push_pending_f64_nan_to_result =
10072                    i1.has_pending_f64_nan() && i2.has_pending_f64_nan();
10073                let (v1, v2) = if !push_pending_f64_nan_to_result {
10074                    (
10075                        self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10076                            .into_vector_value(),
10077                        self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10078                            .into_float_value(),
10079                    )
10080                } else {
10081                    (v1, v2.into_float_value())
10082                };
10083                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10084                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10085                let res = err!(
10086                    self.builder
10087                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10088                );
10089                let info = if push_pending_f64_nan_to_result {
10090                    ExtraInfo::pending_f64_nan()
10091                } else {
10092                    (i1.strip_pending() & i2.strip_pending())?
10093                };
10094                self.state.push1_extra(res, info);
10095            }
10096            Operator::I8x16RelaxedSwizzle if self.cpu_features.contains(CpuFeature::SSSE3) => {
10097                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10098                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10099                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10100
10101                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10102                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
10103                let res = self
10104                    .build_call_with_param_attributes(
10105                        self.intrinsics.x86_64.pshufb128,
10106                        &[v1.into(), v2.into()],
10107                        "",
10108                    )?
10109                    .try_as_basic_value()
10110                    .unwrap_basic();
10111                let res = err!(
10112                    self.builder
10113                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10114                );
10115                self.state.push1(res);
10116            }
10117            Operator::I8x16Swizzle | Operator::I8x16RelaxedSwizzle => {
10118                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10119                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10120                let v1 = err!(
10121                    self.builder
10122                        .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10123                )
10124                .into_vector_value();
10125                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10126                let v2 = err!(
10127                    self.builder
10128                        .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10129                )
10130                .into_vector_value();
10131                let lanes = self.intrinsics.i8_ty.const_int(16, false);
10132                let lanes =
10133                    self.splat_vector(lanes.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
10134                let mut res = self.intrinsics.i8x16_ty.get_undef();
10135                let idx_out_of_range = err!(self.builder.build_int_compare(
10136                    IntPredicate::UGE,
10137                    v2,
10138                    lanes,
10139                    "idx_out_of_range",
10140                ));
10141                let idx_clamped = err!(self.builder.build_select(
10142                    idx_out_of_range,
10143                    self.intrinsics.i8x16_ty.const_zero(),
10144                    v2,
10145                    "idx_clamped",
10146                ))
10147                .into_vector_value();
10148                for i in 0..16 {
10149                    let idx = err!(self.builder.build_extract_element(
10150                        idx_clamped,
10151                        self.intrinsics.i32_ty.const_int(i, false),
10152                        "idx",
10153                    ))
10154                    .into_int_value();
10155                    let replace_with_zero = err!(self.builder.build_extract_element(
10156                        idx_out_of_range,
10157                        self.intrinsics.i32_ty.const_int(i, false),
10158                        "replace_with_zero",
10159                    ))
10160                    .into_int_value();
10161                    let elem =
10162                        err!(self.builder.build_extract_element(v1, idx, "elem")).into_int_value();
10163                    let elem_or_zero = err!(self.builder.build_select(
10164                        replace_with_zero,
10165                        self.intrinsics.i8_zero,
10166                        elem,
10167                        "elem_or_zero",
10168                    ));
10169                    res = err!(self.builder.build_insert_element(
10170                        res,
10171                        elem_or_zero,
10172                        self.intrinsics.i32_ty.const_int(i, false),
10173                        "",
10174                    ));
10175                }
10176                let res = err!(
10177                    self.builder
10178                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10179                );
10180                self.state.push1(res);
10181            }
10182            Operator::I8x16Shuffle { lanes } => {
10183                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10184                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10185                let v1 = err!(
10186                    self.builder
10187                        .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10188                )
10189                .into_vector_value();
10190                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10191                let v2 = err!(
10192                    self.builder
10193                        .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10194                )
10195                .into_vector_value();
10196                let mask = VectorType::const_vector(
10197                    lanes
10198                        .iter()
10199                        .map(|l| self.intrinsics.i32_ty.const_int((*l).into(), false))
10200                        .collect::<Vec<IntValue>>()
10201                        .as_slice(),
10202                );
10203                let res = err!(self.builder.build_shuffle_vector(v1, v2, mask, ""));
10204                let res = err!(
10205                    self.builder
10206                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10207                );
10208                self.state.push1(res);
10209            }
10210            Operator::V128Load8x8S { ref memarg } => {
10211                let offset = self.state.pop1()?.into_int_value();
10212                let memory_index = MemoryIndex::from_u32(0);
10213                let effective_address = self.resolve_memory_ptr(
10214                    memory_index,
10215                    memarg,
10216                    self.intrinsics.ptr_ty,
10217                    offset,
10218                    8,
10219                )?;
10220                let v = err!(self.builder.build_load(
10221                    self.intrinsics.i64_ty,
10222                    effective_address,
10223                    ""
10224                ));
10225                let v = err!(
10226                    self.builder
10227                        .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10228                )
10229                .into_vector_value();
10230                let res = err!(
10231                    self.builder
10232                        .build_int_s_extend(v, self.intrinsics.i16x8_ty, "")
10233                );
10234                let res = err!(
10235                    self.builder
10236                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10237                );
10238                self.state.push1(res);
10239            }
10240            Operator::V128Load8x8U { ref memarg } => {
10241                let offset = self.state.pop1()?.into_int_value();
10242                let memory_index = MemoryIndex::from_u32(0);
10243                let effective_address = self.resolve_memory_ptr(
10244                    memory_index,
10245                    memarg,
10246                    self.intrinsics.ptr_ty,
10247                    offset,
10248                    8,
10249                )?;
10250                let v = err!(self.builder.build_load(
10251                    self.intrinsics.i64_ty,
10252                    effective_address,
10253                    ""
10254                ));
10255                let v = err!(
10256                    self.builder
10257                        .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10258                )
10259                .into_vector_value();
10260                let res = err!(
10261                    self.builder
10262                        .build_int_z_extend(v, self.intrinsics.i16x8_ty, "")
10263                );
10264                let res = err!(
10265                    self.builder
10266                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10267                );
10268                self.state.push1(res);
10269            }
10270            Operator::V128Load16x4S { ref memarg } => {
10271                let offset = self.state.pop1()?.into_int_value();
10272                let memory_index = MemoryIndex::from_u32(0);
10273                let effective_address = self.resolve_memory_ptr(
10274                    memory_index,
10275                    memarg,
10276                    self.intrinsics.ptr_ty,
10277                    offset,
10278                    8,
10279                )?;
10280                let v = err!(self.builder.build_load(
10281                    self.intrinsics.i64_ty,
10282                    effective_address,
10283                    ""
10284                ));
10285                let v = err!(self.builder.build_bit_cast(
10286                    v,
10287                    self.intrinsics.i16_ty.vec_type(4),
10288                    ""
10289                ))
10290                .into_vector_value();
10291                let res = err!(
10292                    self.builder
10293                        .build_int_s_extend(v, self.intrinsics.i32x4_ty, "")
10294                );
10295                let res = err!(
10296                    self.builder
10297                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10298                );
10299                self.state.push1(res);
10300            }
10301            Operator::V128Load16x4U { ref memarg } => {
10302                let offset = self.state.pop1()?.into_int_value();
10303                let memory_index = MemoryIndex::from_u32(0);
10304                let effective_address = self.resolve_memory_ptr(
10305                    memory_index,
10306                    memarg,
10307                    self.intrinsics.ptr_ty,
10308                    offset,
10309                    8,
10310                )?;
10311                let v = err!(self.builder.build_load(
10312                    self.intrinsics.i64_ty,
10313                    effective_address,
10314                    ""
10315                ));
10316                let v = err!(self.builder.build_bit_cast(
10317                    v,
10318                    self.intrinsics.i16_ty.vec_type(4),
10319                    ""
10320                ))
10321                .into_vector_value();
10322                let res = err!(
10323                    self.builder
10324                        .build_int_z_extend(v, self.intrinsics.i32x4_ty, "")
10325                );
10326                let res = err!(
10327                    self.builder
10328                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10329                );
10330                self.state.push1(res);
10331            }
10332            Operator::V128Load32x2S { ref memarg } => {
10333                let offset = self.state.pop1()?.into_int_value();
10334                let memory_index = MemoryIndex::from_u32(0);
10335                let effective_address = self.resolve_memory_ptr(
10336                    memory_index,
10337                    memarg,
10338                    self.intrinsics.ptr_ty,
10339                    offset,
10340                    8,
10341                )?;
10342                let v = err!(self.builder.build_load(
10343                    self.intrinsics.i64_ty,
10344                    effective_address,
10345                    ""
10346                ));
10347                let v = err!(self.builder.build_bit_cast(
10348                    v,
10349                    self.intrinsics.i32_ty.vec_type(2),
10350                    ""
10351                ))
10352                .into_vector_value();
10353                let res = err!(
10354                    self.builder
10355                        .build_int_s_extend(v, self.intrinsics.i64x2_ty, "")
10356                );
10357                let res = err!(
10358                    self.builder
10359                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10360                );
10361                self.state.push1(res);
10362            }
10363            Operator::V128Load32x2U { ref memarg } => {
10364                let offset = self.state.pop1()?.into_int_value();
10365                let memory_index = MemoryIndex::from_u32(0);
10366                let effective_address = self.resolve_memory_ptr(
10367                    memory_index,
10368                    memarg,
10369                    self.intrinsics.ptr_ty,
10370                    offset,
10371                    8,
10372                )?;
10373                let v = err!(self.builder.build_load(
10374                    self.intrinsics.i64_ty,
10375                    effective_address,
10376                    ""
10377                ));
10378                let v = err!(self.builder.build_bit_cast(
10379                    v,
10380                    self.intrinsics.i32_ty.vec_type(2),
10381                    ""
10382                ))
10383                .into_vector_value();
10384                let res = err!(
10385                    self.builder
10386                        .build_int_z_extend(v, self.intrinsics.i64x2_ty, "")
10387                );
10388                let res = err!(
10389                    self.builder
10390                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10391                );
10392                self.state.push1(res);
10393            }
10394            Operator::V128Load32Zero { ref memarg } => {
10395                let offset = self.state.pop1()?.into_int_value();
10396                let memory_index = MemoryIndex::from_u32(0);
10397                let effective_address = self.resolve_memory_ptr(
10398                    memory_index,
10399                    memarg,
10400                    self.intrinsics.ptr_ty,
10401                    offset,
10402                    4,
10403                )?;
10404                let elem = err!(self.builder.build_load(
10405                    self.intrinsics.i32_ty,
10406                    effective_address,
10407                    ""
10408                ));
10409                self.annotate_user_memaccess(
10410                    memory_index,
10411                    memarg,
10412                    1,
10413                    elem.as_instruction_value().unwrap(),
10414                )?;
10415                let res = err!(self.builder.build_int_z_extend(
10416                    elem.into_int_value(),
10417                    self.intrinsics.i128_ty,
10418                    "",
10419                ));
10420                self.state.push1(res);
10421            }
10422            Operator::V128Load64Zero { ref memarg } => {
10423                let offset = self.state.pop1()?.into_int_value();
10424                let memory_index = MemoryIndex::from_u32(0);
10425                let effective_address = self.resolve_memory_ptr(
10426                    memory_index,
10427                    memarg,
10428                    self.intrinsics.ptr_ty,
10429                    offset,
10430                    8,
10431                )?;
10432                let elem = err!(self.builder.build_load(
10433                    self.intrinsics.i64_ty,
10434                    effective_address,
10435                    ""
10436                ));
10437                self.annotate_user_memaccess(
10438                    memory_index,
10439                    memarg,
10440                    1,
10441                    elem.as_instruction_value().unwrap(),
10442                )?;
10443                let res = err!(self.builder.build_int_z_extend(
10444                    elem.into_int_value(),
10445                    self.intrinsics.i128_ty,
10446                    "",
10447                ));
10448                self.state.push1(res);
10449            }
10450            Operator::V128Load8Splat { ref memarg } => {
10451                let offset = self.state.pop1()?.into_int_value();
10452                let memory_index = MemoryIndex::from_u32(0);
10453                let effective_address = self.resolve_memory_ptr(
10454                    memory_index,
10455                    memarg,
10456                    self.intrinsics.ptr_ty,
10457                    offset,
10458                    1,
10459                )?;
10460                let elem = err!(self.builder.build_load(
10461                    self.intrinsics.i8_ty,
10462                    effective_address,
10463                    ""
10464                ));
10465                self.annotate_user_memaccess(
10466                    memory_index,
10467                    memarg,
10468                    1,
10469                    elem.as_instruction_value().unwrap(),
10470                )?;
10471                let res = self.splat_vector(elem, self.intrinsics.i8x16_ty)?;
10472                let res = err!(
10473                    self.builder
10474                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10475                );
10476                self.state.push1(res);
10477            }
10478            Operator::V128Load16Splat { ref memarg } => {
10479                let offset = self.state.pop1()?.into_int_value();
10480                let memory_index = MemoryIndex::from_u32(0);
10481                let effective_address = self.resolve_memory_ptr(
10482                    memory_index,
10483                    memarg,
10484                    self.intrinsics.ptr_ty,
10485                    offset,
10486                    2,
10487                )?;
10488                let elem = err!(self.builder.build_load(
10489                    self.intrinsics.i16_ty,
10490                    effective_address,
10491                    ""
10492                ));
10493                self.annotate_user_memaccess(
10494                    memory_index,
10495                    memarg,
10496                    1,
10497                    elem.as_instruction_value().unwrap(),
10498                )?;
10499                let res = self.splat_vector(elem, self.intrinsics.i16x8_ty)?;
10500                let res = err!(
10501                    self.builder
10502                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10503                );
10504                self.state.push1(res);
10505            }
10506            Operator::V128Load32Splat { ref memarg } => {
10507                let offset = self.state.pop1()?.into_int_value();
10508                let memory_index = MemoryIndex::from_u32(0);
10509                let effective_address = self.resolve_memory_ptr(
10510                    memory_index,
10511                    memarg,
10512                    self.intrinsics.ptr_ty,
10513                    offset,
10514                    4,
10515                )?;
10516                let elem = err!(self.builder.build_load(
10517                    self.intrinsics.i32_ty,
10518                    effective_address,
10519                    ""
10520                ));
10521                self.annotate_user_memaccess(
10522                    memory_index,
10523                    memarg,
10524                    1,
10525                    elem.as_instruction_value().unwrap(),
10526                )?;
10527                let res = self.splat_vector(elem, self.intrinsics.i32x4_ty)?;
10528                let res = err!(
10529                    self.builder
10530                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10531                );
10532                self.state.push1(res);
10533            }
10534            Operator::V128Load64Splat { ref memarg } => {
10535                let offset = self.state.pop1()?.into_int_value();
10536                let memory_index = MemoryIndex::from_u32(0);
10537                let effective_address = self.resolve_memory_ptr(
10538                    memory_index,
10539                    memarg,
10540                    self.intrinsics.ptr_ty,
10541                    offset,
10542                    8,
10543                )?;
10544                let elem = err!(self.builder.build_load(
10545                    self.intrinsics.i64_ty,
10546                    effective_address,
10547                    ""
10548                ));
10549                self.annotate_user_memaccess(
10550                    memory_index,
10551                    memarg,
10552                    1,
10553                    elem.as_instruction_value().unwrap(),
10554                )?;
10555                let res = self.splat_vector(elem, self.intrinsics.i64x2_ty)?;
10556                let res = err!(
10557                    self.builder
10558                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10559                );
10560                self.state.push1(res);
10561            }
10562            Operator::AtomicFence => {
10563                // Fence is a nop.
10564                //
10565                // Fence was added to preserve information about fences from
10566                // source languages. If in the future Wasm extends the memory
10567                // model, and if we hadn't recorded what fences used to be there,
10568                // it would lead to data races that weren't present in the
10569                // original source language.
10570            }
10571            Operator::I32AtomicLoad { ref memarg } => {
10572                let offset = self.state.pop1()?.into_int_value();
10573                let memory_index = MemoryIndex::from_u32(0);
10574                let effective_address = self.resolve_memory_ptr(
10575                    memory_index,
10576                    memarg,
10577                    self.intrinsics.ptr_ty,
10578                    offset,
10579                    4,
10580                )?;
10581                self.trap_if_misaligned(memarg, effective_address, 4)?;
10582                let result = err!(self.builder.build_load(
10583                    self.intrinsics.i32_ty,
10584                    effective_address,
10585                    "atomic_load"
10586                ));
10587                let load = result.as_instruction_value().unwrap();
10588                self.annotate_user_memaccess(memory_index, memarg, 4, load)?;
10589                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10590                    .unwrap();
10591                self.state.push1(result);
10592            }
10593            Operator::I64AtomicLoad { ref memarg } => {
10594                let offset = self.state.pop1()?.into_int_value();
10595                let memory_index = MemoryIndex::from_u32(0);
10596                let effective_address = self.resolve_memory_ptr(
10597                    memory_index,
10598                    memarg,
10599                    self.intrinsics.ptr_ty,
10600                    offset,
10601                    8,
10602                )?;
10603                self.trap_if_misaligned(memarg, effective_address, 8)?;
10604                let result = err!(self.builder.build_load(
10605                    self.intrinsics.i64_ty,
10606                    effective_address,
10607                    ""
10608                ));
10609                let load = result.as_instruction_value().unwrap();
10610                self.annotate_user_memaccess(memory_index, memarg, 8, load)?;
10611                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10612                    .unwrap();
10613                self.state.push1(result);
10614            }
10615            Operator::I32AtomicLoad8U { ref memarg } => {
10616                let offset = self.state.pop1()?.into_int_value();
10617                let memory_index = MemoryIndex::from_u32(0);
10618                let effective_address = self.resolve_memory_ptr(
10619                    memory_index,
10620                    memarg,
10621                    self.intrinsics.ptr_ty,
10622                    offset,
10623                    1,
10624                )?;
10625                self.trap_if_misaligned(memarg, effective_address, 1)?;
10626                let narrow_result = err!(self.builder.build_load(
10627                    self.intrinsics.i8_ty,
10628                    effective_address,
10629                    ""
10630                ))
10631                .into_int_value();
10632                let load = narrow_result.as_instruction_value().unwrap();
10633                self.annotate_user_memaccess(memory_index, memarg, 1, load)?;
10634                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10635                    .unwrap();
10636                let result = err!(self.builder.build_int_z_extend(
10637                    narrow_result,
10638                    self.intrinsics.i32_ty,
10639                    ""
10640                ));
10641                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10642            }
10643            Operator::I32AtomicLoad16U { ref memarg } => {
10644                let offset = self.state.pop1()?.into_int_value();
10645                let memory_index = MemoryIndex::from_u32(0);
10646                let effective_address = self.resolve_memory_ptr(
10647                    memory_index,
10648                    memarg,
10649                    self.intrinsics.ptr_ty,
10650                    offset,
10651                    2,
10652                )?;
10653                self.trap_if_misaligned(memarg, effective_address, 2)?;
10654                let narrow_result = err!(self.builder.build_load(
10655                    self.intrinsics.i16_ty,
10656                    effective_address,
10657                    ""
10658                ))
10659                .into_int_value();
10660                let load = narrow_result.as_instruction_value().unwrap();
10661                self.annotate_user_memaccess(memory_index, memarg, 2, load)?;
10662                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10663                    .unwrap();
10664                let result = err!(self.builder.build_int_z_extend(
10665                    narrow_result,
10666                    self.intrinsics.i32_ty,
10667                    ""
10668                ));
10669                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10670            }
10671            Operator::I64AtomicLoad8U { ref memarg } => {
10672                let offset = self.state.pop1()?.into_int_value();
10673                let memory_index = MemoryIndex::from_u32(0);
10674                let effective_address = self.resolve_memory_ptr(
10675                    memory_index,
10676                    memarg,
10677                    self.intrinsics.ptr_ty,
10678                    offset,
10679                    1,
10680                )?;
10681                self.trap_if_misaligned(memarg, effective_address, 1)?;
10682                let narrow_result = err!(self.builder.build_load(
10683                    self.intrinsics.i8_ty,
10684                    effective_address,
10685                    ""
10686                ))
10687                .into_int_value();
10688                let load = narrow_result.as_instruction_value().unwrap();
10689                self.annotate_user_memaccess(memory_index, memarg, 1, load)?;
10690                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10691                    .unwrap();
10692                let result = err!(self.builder.build_int_z_extend(
10693                    narrow_result,
10694                    self.intrinsics.i64_ty,
10695                    ""
10696                ));
10697                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10698            }
10699            Operator::I64AtomicLoad16U { ref memarg } => {
10700                let offset = self.state.pop1()?.into_int_value();
10701                let memory_index = MemoryIndex::from_u32(0);
10702                let effective_address = self.resolve_memory_ptr(
10703                    memory_index,
10704                    memarg,
10705                    self.intrinsics.ptr_ty,
10706                    offset,
10707                    2,
10708                )?;
10709                self.trap_if_misaligned(memarg, effective_address, 2)?;
10710                let narrow_result = err!(self.builder.build_load(
10711                    self.intrinsics.i16_ty,
10712                    effective_address,
10713                    ""
10714                ))
10715                .into_int_value();
10716                let load = narrow_result.as_instruction_value().unwrap();
10717                self.annotate_user_memaccess(memory_index, memarg, 2, load)?;
10718                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10719                    .unwrap();
10720                let result = err!(self.builder.build_int_z_extend(
10721                    narrow_result,
10722                    self.intrinsics.i64_ty,
10723                    ""
10724                ));
10725                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10726            }
10727            Operator::I64AtomicLoad32U { ref memarg } => {
10728                let offset = self.state.pop1()?.into_int_value();
10729                let memory_index = MemoryIndex::from_u32(0);
10730                let effective_address = self.resolve_memory_ptr(
10731                    memory_index,
10732                    memarg,
10733                    self.intrinsics.ptr_ty,
10734                    offset,
10735                    4,
10736                )?;
10737                self.trap_if_misaligned(memarg, effective_address, 4)?;
10738                let narrow_result = err!(self.builder.build_load(
10739                    self.intrinsics.i32_ty,
10740                    effective_address,
10741                    ""
10742                ))
10743                .into_int_value();
10744                let load = narrow_result.as_instruction_value().unwrap();
10745                self.annotate_user_memaccess(memory_index, memarg, 4, load)?;
10746                load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10747                    .unwrap();
10748                let result = err!(self.builder.build_int_z_extend(
10749                    narrow_result,
10750                    self.intrinsics.i64_ty,
10751                    ""
10752                ));
10753                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10754            }
10755            Operator::I32AtomicStore { ref memarg } => {
10756                let value = self.state.pop1()?;
10757                let offset = self.state.pop1()?.into_int_value();
10758                let memory_index = MemoryIndex::from_u32(0);
10759                let effective_address = self.resolve_memory_ptr(
10760                    memory_index,
10761                    memarg,
10762                    self.intrinsics.ptr_ty,
10763                    offset,
10764                    4,
10765                )?;
10766                self.trap_if_misaligned(memarg, effective_address, 4)?;
10767                let store = err!(self.builder.build_store(effective_address, value));
10768                self.annotate_user_memaccess(memory_index, memarg, 4, store)?;
10769                store
10770                    .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10771                    .unwrap();
10772            }
10773            Operator::I64AtomicStore { ref memarg } => {
10774                let value = self.state.pop1()?;
10775                let offset = self.state.pop1()?.into_int_value();
10776                let memory_index = MemoryIndex::from_u32(0);
10777                let effective_address = self.resolve_memory_ptr(
10778                    memory_index,
10779                    memarg,
10780                    self.intrinsics.ptr_ty,
10781                    offset,
10782                    8,
10783                )?;
10784                self.trap_if_misaligned(memarg, effective_address, 8)?;
10785                let store = err!(self.builder.build_store(effective_address, value));
10786                self.annotate_user_memaccess(memory_index, memarg, 8, store)?;
10787                store
10788                    .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10789                    .unwrap();
10790            }
10791            Operator::I32AtomicStore8 { ref memarg } | Operator::I64AtomicStore8 { ref memarg } => {
10792                let value = self.state.pop1()?.into_int_value();
10793                let offset = self.state.pop1()?.into_int_value();
10794                let memory_index = MemoryIndex::from_u32(0);
10795                let effective_address = self.resolve_memory_ptr(
10796                    memory_index,
10797                    memarg,
10798                    self.intrinsics.ptr_ty,
10799                    offset,
10800                    1,
10801                )?;
10802                self.trap_if_misaligned(memarg, effective_address, 1)?;
10803                let narrow_value = err!(self.builder.build_int_truncate(
10804                    value,
10805                    self.intrinsics.i8_ty,
10806                    ""
10807                ));
10808                let store = err!(self.builder.build_store(effective_address, narrow_value));
10809                self.annotate_user_memaccess(memory_index, memarg, 1, store)?;
10810                store
10811                    .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10812                    .unwrap();
10813            }
10814            Operator::I32AtomicStore16 { ref memarg }
10815            | Operator::I64AtomicStore16 { ref memarg } => {
10816                let value = self.state.pop1()?.into_int_value();
10817                let offset = self.state.pop1()?.into_int_value();
10818                let memory_index = MemoryIndex::from_u32(0);
10819                let effective_address = self.resolve_memory_ptr(
10820                    memory_index,
10821                    memarg,
10822                    self.intrinsics.ptr_ty,
10823                    offset,
10824                    2,
10825                )?;
10826                self.trap_if_misaligned(memarg, effective_address, 2)?;
10827                let narrow_value = err!(self.builder.build_int_truncate(
10828                    value,
10829                    self.intrinsics.i16_ty,
10830                    ""
10831                ));
10832                let store = err!(self.builder.build_store(effective_address, narrow_value));
10833                self.annotate_user_memaccess(memory_index, memarg, 2, store)?;
10834                store
10835                    .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10836                    .unwrap();
10837            }
10838            Operator::I64AtomicStore32 { ref memarg } => {
10839                let value = self.state.pop1()?.into_int_value();
10840                let offset = self.state.pop1()?.into_int_value();
10841                let memory_index = MemoryIndex::from_u32(0);
10842                let effective_address = self.resolve_memory_ptr(
10843                    memory_index,
10844                    memarg,
10845                    self.intrinsics.ptr_ty,
10846                    offset,
10847                    4,
10848                )?;
10849                self.trap_if_misaligned(memarg, effective_address, 4)?;
10850                let narrow_value = err!(self.builder.build_int_truncate(
10851                    value,
10852                    self.intrinsics.i32_ty,
10853                    ""
10854                ));
10855                let store = err!(self.builder.build_store(effective_address, narrow_value));
10856                self.annotate_user_memaccess(memory_index, memarg, 4, store)?;
10857                store
10858                    .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
10859                    .unwrap();
10860            }
10861            Operator::I32AtomicRmw8AddU { ref memarg } => {
10862                let value = self.state.pop1()?.into_int_value();
10863                let offset = self.state.pop1()?.into_int_value();
10864                let memory_index = MemoryIndex::from_u32(0);
10865                let effective_address = self.resolve_memory_ptr(
10866                    memory_index,
10867                    memarg,
10868                    self.intrinsics.ptr_ty,
10869                    offset,
10870                    1,
10871                )?;
10872                self.trap_if_misaligned(memarg, effective_address, 1)?;
10873                let narrow_value = err!(self.builder.build_int_truncate(
10874                    value,
10875                    self.intrinsics.i8_ty,
10876                    ""
10877                ));
10878                let old = self
10879                    .builder
10880                    .build_atomicrmw(
10881                        AtomicRMWBinOp::Add,
10882                        effective_address,
10883                        narrow_value,
10884                        AtomicOrdering::SequentiallyConsistent,
10885                    )
10886                    .unwrap();
10887                tbaa_label(
10888                    self.module,
10889                    self.intrinsics,
10890                    format!("memory {}", memory_index.as_u32()),
10891                    old.as_instruction_value().unwrap(),
10892                );
10893                let old = err!(
10894                    self.builder
10895                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
10896                );
10897                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
10898            }
10899            Operator::I32AtomicRmw16AddU { ref memarg } => {
10900                let value = self.state.pop1()?.into_int_value();
10901                let offset = self.state.pop1()?.into_int_value();
10902                let memory_index = MemoryIndex::from_u32(0);
10903                let effective_address = self.resolve_memory_ptr(
10904                    memory_index,
10905                    memarg,
10906                    self.intrinsics.ptr_ty,
10907                    offset,
10908                    2,
10909                )?;
10910                self.trap_if_misaligned(memarg, effective_address, 2)?;
10911                let narrow_value = err!(self.builder.build_int_truncate(
10912                    value,
10913                    self.intrinsics.i16_ty,
10914                    ""
10915                ));
10916                let old = self
10917                    .builder
10918                    .build_atomicrmw(
10919                        AtomicRMWBinOp::Add,
10920                        effective_address,
10921                        narrow_value,
10922                        AtomicOrdering::SequentiallyConsistent,
10923                    )
10924                    .unwrap();
10925                tbaa_label(
10926                    self.module,
10927                    self.intrinsics,
10928                    format!("memory {}", memory_index.as_u32()),
10929                    old.as_instruction_value().unwrap(),
10930                );
10931                let old = err!(
10932                    self.builder
10933                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
10934                );
10935                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
10936            }
10937            Operator::I32AtomicRmwAdd { ref memarg } => {
10938                let value = self.state.pop1()?.into_int_value();
10939                let offset = self.state.pop1()?.into_int_value();
10940                let memory_index = MemoryIndex::from_u32(0);
10941                let effective_address = self.resolve_memory_ptr(
10942                    memory_index,
10943                    memarg,
10944                    self.intrinsics.ptr_ty,
10945                    offset,
10946                    4,
10947                )?;
10948                self.trap_if_misaligned(memarg, effective_address, 4)?;
10949                let old = self
10950                    .builder
10951                    .build_atomicrmw(
10952                        AtomicRMWBinOp::Add,
10953                        effective_address,
10954                        value,
10955                        AtomicOrdering::SequentiallyConsistent,
10956                    )
10957                    .unwrap();
10958                tbaa_label(
10959                    self.module,
10960                    self.intrinsics,
10961                    format!("memory {}", memory_index.as_u32()),
10962                    old.as_instruction_value().unwrap(),
10963                );
10964                self.state.push1(old);
10965            }
10966            Operator::I64AtomicRmw8AddU { ref memarg } => {
10967                let value = self.state.pop1()?.into_int_value();
10968                let offset = self.state.pop1()?.into_int_value();
10969                let memory_index = MemoryIndex::from_u32(0);
10970                let effective_address = self.resolve_memory_ptr(
10971                    memory_index,
10972                    memarg,
10973                    self.intrinsics.ptr_ty,
10974                    offset,
10975                    1,
10976                )?;
10977                self.trap_if_misaligned(memarg, effective_address, 1)?;
10978                let narrow_value = err!(self.builder.build_int_truncate(
10979                    value,
10980                    self.intrinsics.i8_ty,
10981                    ""
10982                ));
10983                let old = self
10984                    .builder
10985                    .build_atomicrmw(
10986                        AtomicRMWBinOp::Add,
10987                        effective_address,
10988                        narrow_value,
10989                        AtomicOrdering::SequentiallyConsistent,
10990                    )
10991                    .unwrap();
10992                self.annotate_user_memaccess(
10993                    memory_index,
10994                    memarg,
10995                    0,
10996                    old.as_instruction_value().unwrap(),
10997                )?;
10998                let old = err!(
10999                    self.builder
11000                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11001                );
11002                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11003            }
11004            Operator::I64AtomicRmw16AddU { ref memarg } => {
11005                let value = self.state.pop1()?.into_int_value();
11006                let offset = self.state.pop1()?.into_int_value();
11007                let memory_index = MemoryIndex::from_u32(0);
11008                let effective_address = self.resolve_memory_ptr(
11009                    memory_index,
11010                    memarg,
11011                    self.intrinsics.ptr_ty,
11012                    offset,
11013                    2,
11014                )?;
11015                self.trap_if_misaligned(memarg, effective_address, 2)?;
11016                let narrow_value = err!(self.builder.build_int_truncate(
11017                    value,
11018                    self.intrinsics.i16_ty,
11019                    ""
11020                ));
11021                let old = self
11022                    .builder
11023                    .build_atomicrmw(
11024                        AtomicRMWBinOp::Add,
11025                        effective_address,
11026                        narrow_value,
11027                        AtomicOrdering::SequentiallyConsistent,
11028                    )
11029                    .unwrap();
11030                self.annotate_user_memaccess(
11031                    memory_index,
11032                    memarg,
11033                    0,
11034                    old.as_instruction_value().unwrap(),
11035                )?;
11036                let old = err!(
11037                    self.builder
11038                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11039                );
11040                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11041            }
11042            Operator::I64AtomicRmw32AddU { ref memarg } => {
11043                let value = self.state.pop1()?.into_int_value();
11044                let offset = self.state.pop1()?.into_int_value();
11045                let memory_index = MemoryIndex::from_u32(0);
11046                let effective_address = self.resolve_memory_ptr(
11047                    memory_index,
11048                    memarg,
11049                    self.intrinsics.ptr_ty,
11050                    offset,
11051                    4,
11052                )?;
11053                self.trap_if_misaligned(memarg, effective_address, 4)?;
11054                let narrow_value = err!(self.builder.build_int_truncate(
11055                    value,
11056                    self.intrinsics.i32_ty,
11057                    ""
11058                ));
11059                let old = self
11060                    .builder
11061                    .build_atomicrmw(
11062                        AtomicRMWBinOp::Add,
11063                        effective_address,
11064                        narrow_value,
11065                        AtomicOrdering::SequentiallyConsistent,
11066                    )
11067                    .unwrap();
11068                self.annotate_user_memaccess(
11069                    memory_index,
11070                    memarg,
11071                    0,
11072                    old.as_instruction_value().unwrap(),
11073                )?;
11074                let old = err!(
11075                    self.builder
11076                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11077                );
11078                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11079            }
11080            Operator::I64AtomicRmwAdd { ref memarg } => {
11081                let value = self.state.pop1()?.into_int_value();
11082                let offset = self.state.pop1()?.into_int_value();
11083                let memory_index = MemoryIndex::from_u32(0);
11084                let effective_address = self.resolve_memory_ptr(
11085                    memory_index,
11086                    memarg,
11087                    self.intrinsics.ptr_ty,
11088                    offset,
11089                    8,
11090                )?;
11091                self.trap_if_misaligned(memarg, effective_address, 8)?;
11092                let old = self
11093                    .builder
11094                    .build_atomicrmw(
11095                        AtomicRMWBinOp::Add,
11096                        effective_address,
11097                        value,
11098                        AtomicOrdering::SequentiallyConsistent,
11099                    )
11100                    .unwrap();
11101                self.annotate_user_memaccess(
11102                    memory_index,
11103                    memarg,
11104                    0,
11105                    old.as_instruction_value().unwrap(),
11106                )?;
11107                self.state.push1(old);
11108            }
11109            Operator::I32AtomicRmw8SubU { ref memarg } => {
11110                let value = self.state.pop1()?.into_int_value();
11111                let offset = self.state.pop1()?.into_int_value();
11112                let memory_index = MemoryIndex::from_u32(0);
11113                let effective_address = self.resolve_memory_ptr(
11114                    memory_index,
11115                    memarg,
11116                    self.intrinsics.ptr_ty,
11117                    offset,
11118                    1,
11119                )?;
11120                self.trap_if_misaligned(memarg, effective_address, 1)?;
11121                let narrow_value = err!(self.builder.build_int_truncate(
11122                    value,
11123                    self.intrinsics.i8_ty,
11124                    ""
11125                ));
11126                let old = self
11127                    .builder
11128                    .build_atomicrmw(
11129                        AtomicRMWBinOp::Sub,
11130                        effective_address,
11131                        narrow_value,
11132                        AtomicOrdering::SequentiallyConsistent,
11133                    )
11134                    .unwrap();
11135                self.annotate_user_memaccess(
11136                    memory_index,
11137                    memarg,
11138                    0,
11139                    old.as_instruction_value().unwrap(),
11140                )?;
11141                let old = err!(
11142                    self.builder
11143                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11144                );
11145                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11146            }
11147            Operator::I32AtomicRmw16SubU { ref memarg } => {
11148                let value = self.state.pop1()?.into_int_value();
11149                let offset = self.state.pop1()?.into_int_value();
11150                let memory_index = MemoryIndex::from_u32(0);
11151                let effective_address = self.resolve_memory_ptr(
11152                    memory_index,
11153                    memarg,
11154                    self.intrinsics.ptr_ty,
11155                    offset,
11156                    2,
11157                )?;
11158                self.trap_if_misaligned(memarg, effective_address, 2)?;
11159                let narrow_value = err!(self.builder.build_int_truncate(
11160                    value,
11161                    self.intrinsics.i16_ty,
11162                    ""
11163                ));
11164                let old = self
11165                    .builder
11166                    .build_atomicrmw(
11167                        AtomicRMWBinOp::Sub,
11168                        effective_address,
11169                        narrow_value,
11170                        AtomicOrdering::SequentiallyConsistent,
11171                    )
11172                    .unwrap();
11173                self.annotate_user_memaccess(
11174                    memory_index,
11175                    memarg,
11176                    0,
11177                    old.as_instruction_value().unwrap(),
11178                )?;
11179                let old = err!(
11180                    self.builder
11181                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11182                );
11183                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11184            }
11185            Operator::I32AtomicRmwSub { ref memarg } => {
11186                let value = self.state.pop1()?.into_int_value();
11187                let offset = self.state.pop1()?.into_int_value();
11188                let memory_index = MemoryIndex::from_u32(0);
11189                let effective_address = self.resolve_memory_ptr(
11190                    memory_index,
11191                    memarg,
11192                    self.intrinsics.ptr_ty,
11193                    offset,
11194                    4,
11195                )?;
11196                self.trap_if_misaligned(memarg, effective_address, 4)?;
11197                let old = self
11198                    .builder
11199                    .build_atomicrmw(
11200                        AtomicRMWBinOp::Sub,
11201                        effective_address,
11202                        value,
11203                        AtomicOrdering::SequentiallyConsistent,
11204                    )
11205                    .unwrap();
11206                self.annotate_user_memaccess(
11207                    memory_index,
11208                    memarg,
11209                    0,
11210                    old.as_instruction_value().unwrap(),
11211                )?;
11212                self.state.push1(old);
11213            }
11214            Operator::I64AtomicRmw8SubU { ref memarg } => {
11215                let value = self.state.pop1()?.into_int_value();
11216                let offset = self.state.pop1()?.into_int_value();
11217                let memory_index = MemoryIndex::from_u32(0);
11218                let effective_address = self.resolve_memory_ptr(
11219                    memory_index,
11220                    memarg,
11221                    self.intrinsics.ptr_ty,
11222                    offset,
11223                    1,
11224                )?;
11225                self.trap_if_misaligned(memarg, effective_address, 1)?;
11226                let narrow_value = err!(self.builder.build_int_truncate(
11227                    value,
11228                    self.intrinsics.i8_ty,
11229                    ""
11230                ));
11231                let old = self
11232                    .builder
11233                    .build_atomicrmw(
11234                        AtomicRMWBinOp::Sub,
11235                        effective_address,
11236                        narrow_value,
11237                        AtomicOrdering::SequentiallyConsistent,
11238                    )
11239                    .unwrap();
11240                self.annotate_user_memaccess(
11241                    memory_index,
11242                    memarg,
11243                    0,
11244                    old.as_instruction_value().unwrap(),
11245                )?;
11246                let old = err!(
11247                    self.builder
11248                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11249                );
11250                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11251            }
11252            Operator::I64AtomicRmw16SubU { ref memarg } => {
11253                let value = self.state.pop1()?.into_int_value();
11254                let offset = self.state.pop1()?.into_int_value();
11255                let memory_index = MemoryIndex::from_u32(0);
11256                let effective_address = self.resolve_memory_ptr(
11257                    memory_index,
11258                    memarg,
11259                    self.intrinsics.ptr_ty,
11260                    offset,
11261                    2,
11262                )?;
11263                self.trap_if_misaligned(memarg, effective_address, 2)?;
11264                let narrow_value = err!(self.builder.build_int_truncate(
11265                    value,
11266                    self.intrinsics.i16_ty,
11267                    ""
11268                ));
11269                let old = self
11270                    .builder
11271                    .build_atomicrmw(
11272                        AtomicRMWBinOp::Sub,
11273                        effective_address,
11274                        narrow_value,
11275                        AtomicOrdering::SequentiallyConsistent,
11276                    )
11277                    .unwrap();
11278                self.annotate_user_memaccess(
11279                    memory_index,
11280                    memarg,
11281                    0,
11282                    old.as_instruction_value().unwrap(),
11283                )?;
11284                let old = err!(
11285                    self.builder
11286                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11287                );
11288                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11289            }
11290            Operator::I64AtomicRmw32SubU { ref memarg } => {
11291                let value = self.state.pop1()?.into_int_value();
11292                let offset = self.state.pop1()?.into_int_value();
11293                let memory_index = MemoryIndex::from_u32(0);
11294                let effective_address = self.resolve_memory_ptr(
11295                    memory_index,
11296                    memarg,
11297                    self.intrinsics.ptr_ty,
11298                    offset,
11299                    4,
11300                )?;
11301                self.trap_if_misaligned(memarg, effective_address, 4)?;
11302                let narrow_value = err!(self.builder.build_int_truncate(
11303                    value,
11304                    self.intrinsics.i32_ty,
11305                    ""
11306                ));
11307                let old = self
11308                    .builder
11309                    .build_atomicrmw(
11310                        AtomicRMWBinOp::Sub,
11311                        effective_address,
11312                        narrow_value,
11313                        AtomicOrdering::SequentiallyConsistent,
11314                    )
11315                    .unwrap();
11316                self.annotate_user_memaccess(
11317                    memory_index,
11318                    memarg,
11319                    0,
11320                    old.as_instruction_value().unwrap(),
11321                )?;
11322                let old = err!(
11323                    self.builder
11324                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11325                );
11326                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11327            }
11328            Operator::I64AtomicRmwSub { ref memarg } => {
11329                let value = self.state.pop1()?.into_int_value();
11330                let offset = self.state.pop1()?.into_int_value();
11331                let memory_index = MemoryIndex::from_u32(0);
11332                let effective_address = self.resolve_memory_ptr(
11333                    memory_index,
11334                    memarg,
11335                    self.intrinsics.ptr_ty,
11336                    offset,
11337                    8,
11338                )?;
11339                self.trap_if_misaligned(memarg, effective_address, 8)?;
11340                let old = self
11341                    .builder
11342                    .build_atomicrmw(
11343                        AtomicRMWBinOp::Sub,
11344                        effective_address,
11345                        value,
11346                        AtomicOrdering::SequentiallyConsistent,
11347                    )
11348                    .unwrap();
11349                self.annotate_user_memaccess(
11350                    memory_index,
11351                    memarg,
11352                    0,
11353                    old.as_instruction_value().unwrap(),
11354                )?;
11355                self.state.push1(old);
11356            }
11357            Operator::I32AtomicRmw8AndU { ref memarg } => {
11358                let value = self.state.pop1()?.into_int_value();
11359                let offset = self.state.pop1()?.into_int_value();
11360                let memory_index = MemoryIndex::from_u32(0);
11361                let effective_address = self.resolve_memory_ptr(
11362                    memory_index,
11363                    memarg,
11364                    self.intrinsics.ptr_ty,
11365                    offset,
11366                    1,
11367                )?;
11368                self.trap_if_misaligned(memarg, effective_address, 1)?;
11369                let narrow_value = err!(self.builder.build_int_truncate(
11370                    value,
11371                    self.intrinsics.i8_ty,
11372                    ""
11373                ));
11374                let old = self
11375                    .builder
11376                    .build_atomicrmw(
11377                        AtomicRMWBinOp::And,
11378                        effective_address,
11379                        narrow_value,
11380                        AtomicOrdering::SequentiallyConsistent,
11381                    )
11382                    .unwrap();
11383                self.annotate_user_memaccess(
11384                    memory_index,
11385                    memarg,
11386                    0,
11387                    old.as_instruction_value().unwrap(),
11388                )?;
11389                let old = err!(
11390                    self.builder
11391                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11392                );
11393                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11394            }
11395            Operator::I32AtomicRmw16AndU { ref memarg } => {
11396                let value = self.state.pop1()?.into_int_value();
11397                let offset = self.state.pop1()?.into_int_value();
11398                let memory_index = MemoryIndex::from_u32(0);
11399                let effective_address = self.resolve_memory_ptr(
11400                    memory_index,
11401                    memarg,
11402                    self.intrinsics.ptr_ty,
11403                    offset,
11404                    2,
11405                )?;
11406                self.trap_if_misaligned(memarg, effective_address, 2)?;
11407                let narrow_value = err!(self.builder.build_int_truncate(
11408                    value,
11409                    self.intrinsics.i16_ty,
11410                    ""
11411                ));
11412                let old = self
11413                    .builder
11414                    .build_atomicrmw(
11415                        AtomicRMWBinOp::And,
11416                        effective_address,
11417                        narrow_value,
11418                        AtomicOrdering::SequentiallyConsistent,
11419                    )
11420                    .unwrap();
11421                self.annotate_user_memaccess(
11422                    memory_index,
11423                    memarg,
11424                    0,
11425                    old.as_instruction_value().unwrap(),
11426                )?;
11427                let old = err!(
11428                    self.builder
11429                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11430                );
11431                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11432            }
11433            Operator::I32AtomicRmwAnd { ref memarg } => {
11434                let value = self.state.pop1()?.into_int_value();
11435                let offset = self.state.pop1()?.into_int_value();
11436                let memory_index = MemoryIndex::from_u32(0);
11437                let effective_address = self.resolve_memory_ptr(
11438                    memory_index,
11439                    memarg,
11440                    self.intrinsics.ptr_ty,
11441                    offset,
11442                    4,
11443                )?;
11444                self.trap_if_misaligned(memarg, effective_address, 4)?;
11445                let old = self
11446                    .builder
11447                    .build_atomicrmw(
11448                        AtomicRMWBinOp::And,
11449                        effective_address,
11450                        value,
11451                        AtomicOrdering::SequentiallyConsistent,
11452                    )
11453                    .unwrap();
11454                self.annotate_user_memaccess(
11455                    memory_index,
11456                    memarg,
11457                    0,
11458                    old.as_instruction_value().unwrap(),
11459                )?;
11460                self.state.push1(old);
11461            }
11462            Operator::I64AtomicRmw8AndU { ref memarg } => {
11463                let value = self.state.pop1()?.into_int_value();
11464                let offset = self.state.pop1()?.into_int_value();
11465                let memory_index = MemoryIndex::from_u32(0);
11466                let effective_address = self.resolve_memory_ptr(
11467                    memory_index,
11468                    memarg,
11469                    self.intrinsics.ptr_ty,
11470                    offset,
11471                    1,
11472                )?;
11473                self.trap_if_misaligned(memarg, effective_address, 1)?;
11474                let narrow_value = err!(self.builder.build_int_truncate(
11475                    value,
11476                    self.intrinsics.i8_ty,
11477                    ""
11478                ));
11479                let old = self
11480                    .builder
11481                    .build_atomicrmw(
11482                        AtomicRMWBinOp::And,
11483                        effective_address,
11484                        narrow_value,
11485                        AtomicOrdering::SequentiallyConsistent,
11486                    )
11487                    .unwrap();
11488                self.annotate_user_memaccess(
11489                    memory_index,
11490                    memarg,
11491                    0,
11492                    old.as_instruction_value().unwrap(),
11493                )?;
11494                let old = err!(
11495                    self.builder
11496                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11497                );
11498                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11499            }
11500            Operator::I64AtomicRmw16AndU { ref memarg } => {
11501                let value = self.state.pop1()?.into_int_value();
11502                let offset = self.state.pop1()?.into_int_value();
11503                let memory_index = MemoryIndex::from_u32(0);
11504                let effective_address = self.resolve_memory_ptr(
11505                    memory_index,
11506                    memarg,
11507                    self.intrinsics.ptr_ty,
11508                    offset,
11509                    2,
11510                )?;
11511                self.trap_if_misaligned(memarg, effective_address, 2)?;
11512                let narrow_value = err!(self.builder.build_int_truncate(
11513                    value,
11514                    self.intrinsics.i16_ty,
11515                    ""
11516                ));
11517                let old = self
11518                    .builder
11519                    .build_atomicrmw(
11520                        AtomicRMWBinOp::And,
11521                        effective_address,
11522                        narrow_value,
11523                        AtomicOrdering::SequentiallyConsistent,
11524                    )
11525                    .unwrap();
11526                self.annotate_user_memaccess(
11527                    memory_index,
11528                    memarg,
11529                    0,
11530                    old.as_instruction_value().unwrap(),
11531                )?;
11532                let old = err!(
11533                    self.builder
11534                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11535                );
11536                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11537            }
11538            Operator::I64AtomicRmw32AndU { ref memarg } => {
11539                let value = self.state.pop1()?.into_int_value();
11540                let offset = self.state.pop1()?.into_int_value();
11541                let memory_index = MemoryIndex::from_u32(0);
11542                let effective_address = self.resolve_memory_ptr(
11543                    memory_index,
11544                    memarg,
11545                    self.intrinsics.ptr_ty,
11546                    offset,
11547                    4,
11548                )?;
11549                self.trap_if_misaligned(memarg, effective_address, 4)?;
11550                let narrow_value = err!(self.builder.build_int_truncate(
11551                    value,
11552                    self.intrinsics.i32_ty,
11553                    ""
11554                ));
11555                let old = self
11556                    .builder
11557                    .build_atomicrmw(
11558                        AtomicRMWBinOp::And,
11559                        effective_address,
11560                        narrow_value,
11561                        AtomicOrdering::SequentiallyConsistent,
11562                    )
11563                    .unwrap();
11564                self.annotate_user_memaccess(
11565                    memory_index,
11566                    memarg,
11567                    0,
11568                    old.as_instruction_value().unwrap(),
11569                )?;
11570                let old = err!(
11571                    self.builder
11572                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11573                );
11574                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11575            }
11576            Operator::I64AtomicRmwAnd { ref memarg } => {
11577                let value = self.state.pop1()?.into_int_value();
11578                let offset = self.state.pop1()?.into_int_value();
11579                let memory_index = MemoryIndex::from_u32(0);
11580                let effective_address = self.resolve_memory_ptr(
11581                    memory_index,
11582                    memarg,
11583                    self.intrinsics.ptr_ty,
11584                    offset,
11585                    8,
11586                )?;
11587                self.trap_if_misaligned(memarg, effective_address, 8)?;
11588                let old = self
11589                    .builder
11590                    .build_atomicrmw(
11591                        AtomicRMWBinOp::And,
11592                        effective_address,
11593                        value,
11594                        AtomicOrdering::SequentiallyConsistent,
11595                    )
11596                    .unwrap();
11597                self.annotate_user_memaccess(
11598                    memory_index,
11599                    memarg,
11600                    0,
11601                    old.as_instruction_value().unwrap(),
11602                )?;
11603                self.state.push1(old);
11604            }
11605            Operator::I32AtomicRmw8OrU { ref memarg } => {
11606                let value = self.state.pop1()?.into_int_value();
11607                let offset = self.state.pop1()?.into_int_value();
11608                let memory_index = MemoryIndex::from_u32(0);
11609                let effective_address = self.resolve_memory_ptr(
11610                    memory_index,
11611                    memarg,
11612                    self.intrinsics.ptr_ty,
11613                    offset,
11614                    1,
11615                )?;
11616                self.trap_if_misaligned(memarg, effective_address, 1)?;
11617                let narrow_value = err!(self.builder.build_int_truncate(
11618                    value,
11619                    self.intrinsics.i8_ty,
11620                    ""
11621                ));
11622                let old = self
11623                    .builder
11624                    .build_atomicrmw(
11625                        AtomicRMWBinOp::Or,
11626                        effective_address,
11627                        narrow_value,
11628                        AtomicOrdering::SequentiallyConsistent,
11629                    )
11630                    .unwrap();
11631                self.annotate_user_memaccess(
11632                    memory_index,
11633                    memarg,
11634                    0,
11635                    old.as_instruction_value().unwrap(),
11636                )?;
11637                let old = err!(
11638                    self.builder
11639                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11640                );
11641                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11642            }
11643            Operator::I32AtomicRmw16OrU { ref memarg } => {
11644                let value = self.state.pop1()?.into_int_value();
11645                let offset = self.state.pop1()?.into_int_value();
11646                let memory_index = MemoryIndex::from_u32(0);
11647                let effective_address = self.resolve_memory_ptr(
11648                    memory_index,
11649                    memarg,
11650                    self.intrinsics.ptr_ty,
11651                    offset,
11652                    2,
11653                )?;
11654                self.trap_if_misaligned(memarg, effective_address, 2)?;
11655                let narrow_value = err!(self.builder.build_int_truncate(
11656                    value,
11657                    self.intrinsics.i16_ty,
11658                    ""
11659                ));
11660                let old = self
11661                    .builder
11662                    .build_atomicrmw(
11663                        AtomicRMWBinOp::Or,
11664                        effective_address,
11665                        narrow_value,
11666                        AtomicOrdering::SequentiallyConsistent,
11667                    )
11668                    .unwrap();
11669                self.annotate_user_memaccess(
11670                    memory_index,
11671                    memarg,
11672                    0,
11673                    old.as_instruction_value().unwrap(),
11674                )?;
11675                let old = err!(
11676                    self.builder
11677                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11678                );
11679                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11680            }
11681            Operator::I32AtomicRmwOr { ref memarg } => {
11682                let value = self.state.pop1()?.into_int_value();
11683                let offset = self.state.pop1()?.into_int_value();
11684                let memory_index = MemoryIndex::from_u32(0);
11685                let effective_address = self.resolve_memory_ptr(
11686                    memory_index,
11687                    memarg,
11688                    self.intrinsics.ptr_ty,
11689                    offset,
11690                    4,
11691                )?;
11692                self.trap_if_misaligned(memarg, effective_address, 4)?;
11693                let old = self
11694                    .builder
11695                    .build_atomicrmw(
11696                        AtomicRMWBinOp::Or,
11697                        effective_address,
11698                        value,
11699                        AtomicOrdering::SequentiallyConsistent,
11700                    )
11701                    .unwrap();
11702                self.annotate_user_memaccess(
11703                    memory_index,
11704                    memarg,
11705                    0,
11706                    old.as_instruction_value().unwrap(),
11707                )?;
11708                let old = err!(
11709                    self.builder
11710                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11711                );
11712                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11713            }
11714            Operator::I64AtomicRmw8OrU { ref memarg } => {
11715                let value = self.state.pop1()?.into_int_value();
11716                let offset = self.state.pop1()?.into_int_value();
11717                let memory_index = MemoryIndex::from_u32(0);
11718                let effective_address = self.resolve_memory_ptr(
11719                    memory_index,
11720                    memarg,
11721                    self.intrinsics.ptr_ty,
11722                    offset,
11723                    1,
11724                )?;
11725                self.trap_if_misaligned(memarg, effective_address, 1)?;
11726                let narrow_value = err!(self.builder.build_int_truncate(
11727                    value,
11728                    self.intrinsics.i8_ty,
11729                    ""
11730                ));
11731                let old = self
11732                    .builder
11733                    .build_atomicrmw(
11734                        AtomicRMWBinOp::Or,
11735                        effective_address,
11736                        narrow_value,
11737                        AtomicOrdering::SequentiallyConsistent,
11738                    )
11739                    .unwrap();
11740                self.annotate_user_memaccess(
11741                    memory_index,
11742                    memarg,
11743                    0,
11744                    old.as_instruction_value().unwrap(),
11745                )?;
11746                let old = err!(
11747                    self.builder
11748                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11749                );
11750                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11751            }
11752            Operator::I64AtomicRmw16OrU { ref memarg } => {
11753                let value = self.state.pop1()?.into_int_value();
11754                let offset = self.state.pop1()?.into_int_value();
11755                let memory_index = MemoryIndex::from_u32(0);
11756                let effective_address = self.resolve_memory_ptr(
11757                    memory_index,
11758                    memarg,
11759                    self.intrinsics.ptr_ty,
11760                    offset,
11761                    2,
11762                )?;
11763                self.trap_if_misaligned(memarg, effective_address, 2)?;
11764                let narrow_value = err!(self.builder.build_int_truncate(
11765                    value,
11766                    self.intrinsics.i16_ty,
11767                    ""
11768                ));
11769                let old = self
11770                    .builder
11771                    .build_atomicrmw(
11772                        AtomicRMWBinOp::Or,
11773                        effective_address,
11774                        narrow_value,
11775                        AtomicOrdering::SequentiallyConsistent,
11776                    )
11777                    .unwrap();
11778                self.annotate_user_memaccess(
11779                    memory_index,
11780                    memarg,
11781                    0,
11782                    old.as_instruction_value().unwrap(),
11783                )?;
11784                let old = err!(
11785                    self.builder
11786                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11787                );
11788                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11789            }
11790            Operator::I64AtomicRmw32OrU { ref memarg } => {
11791                let value = self.state.pop1()?.into_int_value();
11792                let offset = self.state.pop1()?.into_int_value();
11793                let memory_index = MemoryIndex::from_u32(0);
11794                let effective_address = self.resolve_memory_ptr(
11795                    memory_index,
11796                    memarg,
11797                    self.intrinsics.ptr_ty,
11798                    offset,
11799                    4,
11800                )?;
11801                self.trap_if_misaligned(memarg, effective_address, 4)?;
11802                let narrow_value = err!(self.builder.build_int_truncate(
11803                    value,
11804                    self.intrinsics.i32_ty,
11805                    ""
11806                ));
11807                let old = self
11808                    .builder
11809                    .build_atomicrmw(
11810                        AtomicRMWBinOp::Or,
11811                        effective_address,
11812                        narrow_value,
11813                        AtomicOrdering::SequentiallyConsistent,
11814                    )
11815                    .unwrap();
11816                self.annotate_user_memaccess(
11817                    memory_index,
11818                    memarg,
11819                    0,
11820                    old.as_instruction_value().unwrap(),
11821                )?;
11822                let old = err!(
11823                    self.builder
11824                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11825                );
11826                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11827            }
11828            Operator::I64AtomicRmwOr { ref memarg } => {
11829                let value = self.state.pop1()?.into_int_value();
11830                let offset = self.state.pop1()?.into_int_value();
11831                let memory_index = MemoryIndex::from_u32(0);
11832                let effective_address = self.resolve_memory_ptr(
11833                    memory_index,
11834                    memarg,
11835                    self.intrinsics.ptr_ty,
11836                    offset,
11837                    8,
11838                )?;
11839                self.trap_if_misaligned(memarg, effective_address, 8)?;
11840                let old = self
11841                    .builder
11842                    .build_atomicrmw(
11843                        AtomicRMWBinOp::Or,
11844                        effective_address,
11845                        value,
11846                        AtomicOrdering::SequentiallyConsistent,
11847                    )
11848                    .unwrap();
11849                self.annotate_user_memaccess(
11850                    memory_index,
11851                    memarg,
11852                    0,
11853                    old.as_instruction_value().unwrap(),
11854                )?;
11855                self.state.push1(old);
11856            }
11857            Operator::I32AtomicRmw8XorU { ref memarg } => {
11858                let value = self.state.pop1()?.into_int_value();
11859                let offset = self.state.pop1()?.into_int_value();
11860                let memory_index = MemoryIndex::from_u32(0);
11861                let effective_address = self.resolve_memory_ptr(
11862                    memory_index,
11863                    memarg,
11864                    self.intrinsics.ptr_ty,
11865                    offset,
11866                    1,
11867                )?;
11868                self.trap_if_misaligned(memarg, effective_address, 2)?;
11869                let narrow_value = err!(self.builder.build_int_truncate(
11870                    value,
11871                    self.intrinsics.i8_ty,
11872                    ""
11873                ));
11874                let old = self
11875                    .builder
11876                    .build_atomicrmw(
11877                        AtomicRMWBinOp::Xor,
11878                        effective_address,
11879                        narrow_value,
11880                        AtomicOrdering::SequentiallyConsistent,
11881                    )
11882                    .unwrap();
11883                self.annotate_user_memaccess(
11884                    memory_index,
11885                    memarg,
11886                    0,
11887                    old.as_instruction_value().unwrap(),
11888                )?;
11889                let old = err!(
11890                    self.builder
11891                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11892                );
11893                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11894            }
11895            Operator::I32AtomicRmw16XorU { ref memarg } => {
11896                let value = self.state.pop1()?.into_int_value();
11897                let offset = self.state.pop1()?.into_int_value();
11898                let memory_index = MemoryIndex::from_u32(0);
11899                let effective_address = self.resolve_memory_ptr(
11900                    memory_index,
11901                    memarg,
11902                    self.intrinsics.ptr_ty,
11903                    offset,
11904                    2,
11905                )?;
11906                self.trap_if_misaligned(memarg, effective_address, 2)?;
11907                let narrow_value = err!(self.builder.build_int_truncate(
11908                    value,
11909                    self.intrinsics.i16_ty,
11910                    ""
11911                ));
11912                let old = self
11913                    .builder
11914                    .build_atomicrmw(
11915                        AtomicRMWBinOp::Xor,
11916                        effective_address,
11917                        narrow_value,
11918                        AtomicOrdering::SequentiallyConsistent,
11919                    )
11920                    .unwrap();
11921                self.annotate_user_memaccess(
11922                    memory_index,
11923                    memarg,
11924                    0,
11925                    old.as_instruction_value().unwrap(),
11926                )?;
11927                let old = err!(
11928                    self.builder
11929                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
11930                );
11931                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
11932            }
11933            Operator::I32AtomicRmwXor { ref memarg } => {
11934                let value = self.state.pop1()?.into_int_value();
11935                let offset = self.state.pop1()?.into_int_value();
11936                let memory_index = MemoryIndex::from_u32(0);
11937                let effective_address = self.resolve_memory_ptr(
11938                    memory_index,
11939                    memarg,
11940                    self.intrinsics.ptr_ty,
11941                    offset,
11942                    4,
11943                )?;
11944                self.trap_if_misaligned(memarg, effective_address, 4)?;
11945                let old = self
11946                    .builder
11947                    .build_atomicrmw(
11948                        AtomicRMWBinOp::Xor,
11949                        effective_address,
11950                        value,
11951                        AtomicOrdering::SequentiallyConsistent,
11952                    )
11953                    .unwrap();
11954                self.annotate_user_memaccess(
11955                    memory_index,
11956                    memarg,
11957                    0,
11958                    old.as_instruction_value().unwrap(),
11959                )?;
11960                self.state.push1(old);
11961            }
11962            Operator::I64AtomicRmw8XorU { ref memarg } => {
11963                let value = self.state.pop1()?.into_int_value();
11964                let offset = self.state.pop1()?.into_int_value();
11965                let memory_index = MemoryIndex::from_u32(0);
11966                let effective_address = self.resolve_memory_ptr(
11967                    memory_index,
11968                    memarg,
11969                    self.intrinsics.ptr_ty,
11970                    offset,
11971                    1,
11972                )?;
11973                self.trap_if_misaligned(memarg, effective_address, 1)?;
11974                let narrow_value = err!(self.builder.build_int_truncate(
11975                    value,
11976                    self.intrinsics.i8_ty,
11977                    ""
11978                ));
11979                let old = self
11980                    .builder
11981                    .build_atomicrmw(
11982                        AtomicRMWBinOp::Xor,
11983                        effective_address,
11984                        narrow_value,
11985                        AtomicOrdering::SequentiallyConsistent,
11986                    )
11987                    .unwrap();
11988                self.annotate_user_memaccess(
11989                    memory_index,
11990                    memarg,
11991                    0,
11992                    old.as_instruction_value().unwrap(),
11993                )?;
11994                let old = err!(
11995                    self.builder
11996                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
11997                );
11998                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
11999            }
12000            Operator::I64AtomicRmw16XorU { ref memarg } => {
12001                let value = self.state.pop1()?.into_int_value();
12002                let offset = self.state.pop1()?.into_int_value();
12003                let memory_index = MemoryIndex::from_u32(0);
12004                let effective_address = self.resolve_memory_ptr(
12005                    memory_index,
12006                    memarg,
12007                    self.intrinsics.ptr_ty,
12008                    offset,
12009                    2,
12010                )?;
12011                self.trap_if_misaligned(memarg, effective_address, 2)?;
12012                let narrow_value = err!(self.builder.build_int_truncate(
12013                    value,
12014                    self.intrinsics.i16_ty,
12015                    ""
12016                ));
12017                let old = self
12018                    .builder
12019                    .build_atomicrmw(
12020                        AtomicRMWBinOp::Xor,
12021                        effective_address,
12022                        narrow_value,
12023                        AtomicOrdering::SequentiallyConsistent,
12024                    )
12025                    .unwrap();
12026                self.annotate_user_memaccess(
12027                    memory_index,
12028                    memarg,
12029                    0,
12030                    old.as_instruction_value().unwrap(),
12031                )?;
12032                let old = err!(
12033                    self.builder
12034                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12035                );
12036                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12037            }
12038            Operator::I64AtomicRmw32XorU { ref memarg } => {
12039                let value = self.state.pop1()?.into_int_value();
12040                let offset = self.state.pop1()?.into_int_value();
12041                let memory_index = MemoryIndex::from_u32(0);
12042                let effective_address = self.resolve_memory_ptr(
12043                    memory_index,
12044                    memarg,
12045                    self.intrinsics.ptr_ty,
12046                    offset,
12047                    4,
12048                )?;
12049                self.trap_if_misaligned(memarg, effective_address, 4)?;
12050                let narrow_value = err!(self.builder.build_int_truncate(
12051                    value,
12052                    self.intrinsics.i32_ty,
12053                    ""
12054                ));
12055                let old = self
12056                    .builder
12057                    .build_atomicrmw(
12058                        AtomicRMWBinOp::Xor,
12059                        effective_address,
12060                        narrow_value,
12061                        AtomicOrdering::SequentiallyConsistent,
12062                    )
12063                    .unwrap();
12064                self.annotate_user_memaccess(
12065                    memory_index,
12066                    memarg,
12067                    0,
12068                    old.as_instruction_value().unwrap(),
12069                )?;
12070                let old = err!(
12071                    self.builder
12072                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12073                );
12074                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12075            }
12076            Operator::I64AtomicRmwXor { ref memarg } => {
12077                let value = self.state.pop1()?.into_int_value();
12078                let offset = self.state.pop1()?.into_int_value();
12079                let memory_index = MemoryIndex::from_u32(0);
12080                let effective_address = self.resolve_memory_ptr(
12081                    memory_index,
12082                    memarg,
12083                    self.intrinsics.ptr_ty,
12084                    offset,
12085                    8,
12086                )?;
12087                self.trap_if_misaligned(memarg, effective_address, 8)?;
12088                let old = self
12089                    .builder
12090                    .build_atomicrmw(
12091                        AtomicRMWBinOp::Xor,
12092                        effective_address,
12093                        value,
12094                        AtomicOrdering::SequentiallyConsistent,
12095                    )
12096                    .unwrap();
12097                self.annotate_user_memaccess(
12098                    memory_index,
12099                    memarg,
12100                    0,
12101                    old.as_instruction_value().unwrap(),
12102                )?;
12103                self.state.push1(old);
12104            }
12105            Operator::I32AtomicRmw8XchgU { ref memarg } => {
12106                let value = self.state.pop1()?.into_int_value();
12107                let offset = self.state.pop1()?.into_int_value();
12108                let memory_index = MemoryIndex::from_u32(0);
12109                let effective_address = self.resolve_memory_ptr(
12110                    memory_index,
12111                    memarg,
12112                    self.intrinsics.ptr_ty,
12113                    offset,
12114                    1,
12115                )?;
12116                self.trap_if_misaligned(memarg, effective_address, 1)?;
12117                let narrow_value = err!(self.builder.build_int_truncate(
12118                    value,
12119                    self.intrinsics.i8_ty,
12120                    ""
12121                ));
12122                let old = self
12123                    .builder
12124                    .build_atomicrmw(
12125                        AtomicRMWBinOp::Xchg,
12126                        effective_address,
12127                        narrow_value,
12128                        AtomicOrdering::SequentiallyConsistent,
12129                    )
12130                    .unwrap();
12131                self.annotate_user_memaccess(
12132                    memory_index,
12133                    memarg,
12134                    0,
12135                    old.as_instruction_value().unwrap(),
12136                )?;
12137                let old = err!(
12138                    self.builder
12139                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12140                );
12141                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12142            }
12143            Operator::I32AtomicRmw16XchgU { ref memarg } => {
12144                let value = self.state.pop1()?.into_int_value();
12145                let offset = self.state.pop1()?.into_int_value();
12146                let memory_index = MemoryIndex::from_u32(0);
12147                let effective_address = self.resolve_memory_ptr(
12148                    memory_index,
12149                    memarg,
12150                    self.intrinsics.ptr_ty,
12151                    offset,
12152                    2,
12153                )?;
12154                self.trap_if_misaligned(memarg, effective_address, 2)?;
12155                let narrow_value = err!(self.builder.build_int_truncate(
12156                    value,
12157                    self.intrinsics.i16_ty,
12158                    ""
12159                ));
12160                let old = self
12161                    .builder
12162                    .build_atomicrmw(
12163                        AtomicRMWBinOp::Xchg,
12164                        effective_address,
12165                        narrow_value,
12166                        AtomicOrdering::SequentiallyConsistent,
12167                    )
12168                    .unwrap();
12169                self.annotate_user_memaccess(
12170                    memory_index,
12171                    memarg,
12172                    0,
12173                    old.as_instruction_value().unwrap(),
12174                )?;
12175                let old = err!(
12176                    self.builder
12177                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12178                );
12179                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12180            }
12181            Operator::I32AtomicRmwXchg { ref memarg } => {
12182                let value = self.state.pop1()?.into_int_value();
12183                let offset = self.state.pop1()?.into_int_value();
12184                let memory_index = MemoryIndex::from_u32(0);
12185                let effective_address = self.resolve_memory_ptr(
12186                    memory_index,
12187                    memarg,
12188                    self.intrinsics.ptr_ty,
12189                    offset,
12190                    4,
12191                )?;
12192                self.trap_if_misaligned(memarg, effective_address, 4)?;
12193                let old = self
12194                    .builder
12195                    .build_atomicrmw(
12196                        AtomicRMWBinOp::Xchg,
12197                        effective_address,
12198                        value,
12199                        AtomicOrdering::SequentiallyConsistent,
12200                    )
12201                    .unwrap();
12202                self.annotate_user_memaccess(
12203                    memory_index,
12204                    memarg,
12205                    0,
12206                    old.as_instruction_value().unwrap(),
12207                )?;
12208                self.state.push1(old);
12209            }
12210            Operator::I64AtomicRmw8XchgU { ref memarg } => {
12211                let value = self.state.pop1()?.into_int_value();
12212                let offset = self.state.pop1()?.into_int_value();
12213                let memory_index = MemoryIndex::from_u32(0);
12214                let effective_address = self.resolve_memory_ptr(
12215                    memory_index,
12216                    memarg,
12217                    self.intrinsics.ptr_ty,
12218                    offset,
12219                    1,
12220                )?;
12221                self.trap_if_misaligned(memarg, effective_address, 1)?;
12222                let narrow_value = err!(self.builder.build_int_truncate(
12223                    value,
12224                    self.intrinsics.i8_ty,
12225                    ""
12226                ));
12227                let old = self
12228                    .builder
12229                    .build_atomicrmw(
12230                        AtomicRMWBinOp::Xchg,
12231                        effective_address,
12232                        narrow_value,
12233                        AtomicOrdering::SequentiallyConsistent,
12234                    )
12235                    .unwrap();
12236                self.annotate_user_memaccess(
12237                    memory_index,
12238                    memarg,
12239                    0,
12240                    old.as_instruction_value().unwrap(),
12241                )?;
12242                let old = err!(
12243                    self.builder
12244                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12245                );
12246                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12247            }
12248            Operator::I64AtomicRmw16XchgU { ref memarg } => {
12249                let value = self.state.pop1()?.into_int_value();
12250                let offset = self.state.pop1()?.into_int_value();
12251                let memory_index = MemoryIndex::from_u32(0);
12252                let effective_address = self.resolve_memory_ptr(
12253                    memory_index,
12254                    memarg,
12255                    self.intrinsics.ptr_ty,
12256                    offset,
12257                    2,
12258                )?;
12259                self.trap_if_misaligned(memarg, effective_address, 2)?;
12260                let narrow_value = err!(self.builder.build_int_truncate(
12261                    value,
12262                    self.intrinsics.i16_ty,
12263                    ""
12264                ));
12265                let old = self
12266                    .builder
12267                    .build_atomicrmw(
12268                        AtomicRMWBinOp::Xchg,
12269                        effective_address,
12270                        narrow_value,
12271                        AtomicOrdering::SequentiallyConsistent,
12272                    )
12273                    .unwrap();
12274                self.annotate_user_memaccess(
12275                    memory_index,
12276                    memarg,
12277                    0,
12278                    old.as_instruction_value().unwrap(),
12279                )?;
12280                let old = err!(
12281                    self.builder
12282                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12283                );
12284                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12285            }
12286            Operator::I64AtomicRmw32XchgU { ref memarg } => {
12287                let value = self.state.pop1()?.into_int_value();
12288                let offset = self.state.pop1()?.into_int_value();
12289                let memory_index = MemoryIndex::from_u32(0);
12290                let effective_address = self.resolve_memory_ptr(
12291                    memory_index,
12292                    memarg,
12293                    self.intrinsics.ptr_ty,
12294                    offset,
12295                    4,
12296                )?;
12297                self.trap_if_misaligned(memarg, effective_address, 4)?;
12298                let narrow_value = err!(self.builder.build_int_truncate(
12299                    value,
12300                    self.intrinsics.i32_ty,
12301                    ""
12302                ));
12303                let old = self
12304                    .builder
12305                    .build_atomicrmw(
12306                        AtomicRMWBinOp::Xchg,
12307                        effective_address,
12308                        narrow_value,
12309                        AtomicOrdering::SequentiallyConsistent,
12310                    )
12311                    .unwrap();
12312                self.annotate_user_memaccess(
12313                    memory_index,
12314                    memarg,
12315                    0,
12316                    old.as_instruction_value().unwrap(),
12317                )?;
12318                let old = err!(
12319                    self.builder
12320                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12321                );
12322                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12323            }
12324            Operator::I64AtomicRmwXchg { ref memarg } => {
12325                let value = self.state.pop1()?.into_int_value();
12326                let offset = self.state.pop1()?.into_int_value();
12327                let memory_index = MemoryIndex::from_u32(0);
12328                let effective_address = self.resolve_memory_ptr(
12329                    memory_index,
12330                    memarg,
12331                    self.intrinsics.ptr_ty,
12332                    offset,
12333                    8,
12334                )?;
12335                self.trap_if_misaligned(memarg, effective_address, 8)?;
12336                let old = self
12337                    .builder
12338                    .build_atomicrmw(
12339                        AtomicRMWBinOp::Xchg,
12340                        effective_address,
12341                        value,
12342                        AtomicOrdering::SequentiallyConsistent,
12343                    )
12344                    .unwrap();
12345                self.annotate_user_memaccess(
12346                    memory_index,
12347                    memarg,
12348                    0,
12349                    old.as_instruction_value().unwrap(),
12350                )?;
12351                self.state.push1(old);
12352            }
12353            Operator::I32AtomicRmw8CmpxchgU { ref memarg } => {
12354                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12355                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12356                let new = self.apply_pending_canonicalization(new, new_info)?;
12357                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12358                let offset = self.state.pop1()?.into_int_value();
12359                let memory_index = MemoryIndex::from_u32(0);
12360                let effective_address = self.resolve_memory_ptr(
12361                    memory_index,
12362                    memarg,
12363                    self.intrinsics.ptr_ty,
12364                    offset,
12365                    1,
12366                )?;
12367                self.trap_if_misaligned(memarg, effective_address, 1)?;
12368                let narrow_cmp = err!(self.builder.build_int_truncate(
12369                    cmp,
12370                    self.intrinsics.i8_ty,
12371                    ""
12372                ));
12373                let narrow_new = err!(self.builder.build_int_truncate(
12374                    new,
12375                    self.intrinsics.i8_ty,
12376                    ""
12377                ));
12378                let old = self
12379                    .builder
12380                    .build_cmpxchg(
12381                        effective_address,
12382                        narrow_cmp,
12383                        narrow_new,
12384                        AtomicOrdering::SequentiallyConsistent,
12385                        AtomicOrdering::SequentiallyConsistent,
12386                    )
12387                    .unwrap();
12388                self.annotate_user_memaccess(
12389                    memory_index,
12390                    memarg,
12391                    0,
12392                    old.as_instruction_value().unwrap(),
12393                )?;
12394                let old = self
12395                    .builder
12396                    .build_extract_value(old, 0, "")
12397                    .unwrap()
12398                    .into_int_value();
12399                let old = err!(
12400                    self.builder
12401                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12402                );
12403                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12404            }
12405            Operator::I32AtomicRmw16CmpxchgU { ref memarg } => {
12406                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12407                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12408                let new = self.apply_pending_canonicalization(new, new_info)?;
12409                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12410                let offset = self.state.pop1()?.into_int_value();
12411                let memory_index = MemoryIndex::from_u32(0);
12412                let effective_address = self.resolve_memory_ptr(
12413                    memory_index,
12414                    memarg,
12415                    self.intrinsics.ptr_ty,
12416                    offset,
12417                    2,
12418                )?;
12419                self.trap_if_misaligned(memarg, effective_address, 2)?;
12420                let narrow_cmp = err!(self.builder.build_int_truncate(
12421                    cmp,
12422                    self.intrinsics.i16_ty,
12423                    ""
12424                ));
12425                let narrow_new = err!(self.builder.build_int_truncate(
12426                    new,
12427                    self.intrinsics.i16_ty,
12428                    ""
12429                ));
12430                let old = self
12431                    .builder
12432                    .build_cmpxchg(
12433                        effective_address,
12434                        narrow_cmp,
12435                        narrow_new,
12436                        AtomicOrdering::SequentiallyConsistent,
12437                        AtomicOrdering::SequentiallyConsistent,
12438                    )
12439                    .unwrap();
12440                self.annotate_user_memaccess(
12441                    memory_index,
12442                    memarg,
12443                    0,
12444                    old.as_instruction_value().unwrap(),
12445                )?;
12446                let old = self
12447                    .builder
12448                    .build_extract_value(old, 0, "")
12449                    .unwrap()
12450                    .into_int_value();
12451                let old = err!(
12452                    self.builder
12453                        .build_int_z_extend(old, self.intrinsics.i32_ty, "")
12454                );
12455                self.state.push1_extra(old, ExtraInfo::arithmetic_f32());
12456            }
12457            Operator::I32AtomicRmwCmpxchg { ref memarg } => {
12458                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12459                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12460                let new = self.apply_pending_canonicalization(new, new_info)?;
12461                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12462                let offset = self.state.pop1()?.into_int_value();
12463                let memory_index = MemoryIndex::from_u32(0);
12464                let effective_address = self.resolve_memory_ptr(
12465                    memory_index,
12466                    memarg,
12467                    self.intrinsics.ptr_ty,
12468                    offset,
12469                    4,
12470                )?;
12471                self.trap_if_misaligned(memarg, effective_address, 4)?;
12472                let old = self
12473                    .builder
12474                    .build_cmpxchg(
12475                        effective_address,
12476                        cmp,
12477                        new,
12478                        AtomicOrdering::SequentiallyConsistent,
12479                        AtomicOrdering::SequentiallyConsistent,
12480                    )
12481                    .unwrap();
12482                self.annotate_user_memaccess(
12483                    memory_index,
12484                    memarg,
12485                    0,
12486                    old.as_instruction_value().unwrap(),
12487                )?;
12488                let old = err!(self.builder.build_extract_value(old, 0, ""));
12489                self.state.push1(old);
12490            }
12491            Operator::I64AtomicRmw8CmpxchgU { ref memarg } => {
12492                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12493                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12494                let new = self.apply_pending_canonicalization(new, new_info)?;
12495                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12496                let offset = self.state.pop1()?.into_int_value();
12497                let memory_index = MemoryIndex::from_u32(0);
12498                let effective_address = self.resolve_memory_ptr(
12499                    memory_index,
12500                    memarg,
12501                    self.intrinsics.ptr_ty,
12502                    offset,
12503                    1,
12504                )?;
12505                self.trap_if_misaligned(memarg, effective_address, 1)?;
12506                let narrow_cmp = err!(self.builder.build_int_truncate(
12507                    cmp,
12508                    self.intrinsics.i8_ty,
12509                    ""
12510                ));
12511                let narrow_new = err!(self.builder.build_int_truncate(
12512                    new,
12513                    self.intrinsics.i8_ty,
12514                    ""
12515                ));
12516                let old = self
12517                    .builder
12518                    .build_cmpxchg(
12519                        effective_address,
12520                        narrow_cmp,
12521                        narrow_new,
12522                        AtomicOrdering::SequentiallyConsistent,
12523                        AtomicOrdering::SequentiallyConsistent,
12524                    )
12525                    .unwrap();
12526                self.annotate_user_memaccess(
12527                    memory_index,
12528                    memarg,
12529                    0,
12530                    old.as_instruction_value().unwrap(),
12531                )?;
12532                let old = self
12533                    .builder
12534                    .build_extract_value(old, 0, "")
12535                    .unwrap()
12536                    .into_int_value();
12537                let old = err!(
12538                    self.builder
12539                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12540                );
12541                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12542            }
12543            Operator::I64AtomicRmw16CmpxchgU { ref memarg } => {
12544                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12545                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12546                let new = self.apply_pending_canonicalization(new, new_info)?;
12547                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12548                let offset = self.state.pop1()?.into_int_value();
12549                let memory_index = MemoryIndex::from_u32(0);
12550                let effective_address = self.resolve_memory_ptr(
12551                    memory_index,
12552                    memarg,
12553                    self.intrinsics.ptr_ty,
12554                    offset,
12555                    2,
12556                )?;
12557                self.trap_if_misaligned(memarg, effective_address, 2)?;
12558                let narrow_cmp = err!(self.builder.build_int_truncate(
12559                    cmp,
12560                    self.intrinsics.i16_ty,
12561                    ""
12562                ));
12563                let narrow_new = err!(self.builder.build_int_truncate(
12564                    new,
12565                    self.intrinsics.i16_ty,
12566                    ""
12567                ));
12568                let old = self
12569                    .builder
12570                    .build_cmpxchg(
12571                        effective_address,
12572                        narrow_cmp,
12573                        narrow_new,
12574                        AtomicOrdering::SequentiallyConsistent,
12575                        AtomicOrdering::SequentiallyConsistent,
12576                    )
12577                    .unwrap();
12578                self.annotate_user_memaccess(
12579                    memory_index,
12580                    memarg,
12581                    0,
12582                    old.as_instruction_value().unwrap(),
12583                )?;
12584                let old = self
12585                    .builder
12586                    .build_extract_value(old, 0, "")
12587                    .unwrap()
12588                    .into_int_value();
12589                let old = err!(
12590                    self.builder
12591                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12592                );
12593                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12594            }
12595            Operator::I64AtomicRmw32CmpxchgU { ref memarg } => {
12596                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12597                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12598                let new = self.apply_pending_canonicalization(new, new_info)?;
12599                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12600                let offset = self.state.pop1()?.into_int_value();
12601                let memory_index = MemoryIndex::from_u32(0);
12602                let effective_address = self.resolve_memory_ptr(
12603                    memory_index,
12604                    memarg,
12605                    self.intrinsics.ptr_ty,
12606                    offset,
12607                    4,
12608                )?;
12609                self.trap_if_misaligned(memarg, effective_address, 4)?;
12610                let narrow_cmp = err!(self.builder.build_int_truncate(
12611                    cmp,
12612                    self.intrinsics.i32_ty,
12613                    ""
12614                ));
12615                let narrow_new = err!(self.builder.build_int_truncate(
12616                    new,
12617                    self.intrinsics.i32_ty,
12618                    ""
12619                ));
12620                let old = self
12621                    .builder
12622                    .build_cmpxchg(
12623                        effective_address,
12624                        narrow_cmp,
12625                        narrow_new,
12626                        AtomicOrdering::SequentiallyConsistent,
12627                        AtomicOrdering::SequentiallyConsistent,
12628                    )
12629                    .unwrap();
12630                self.annotate_user_memaccess(
12631                    memory_index,
12632                    memarg,
12633                    0,
12634                    old.as_instruction_value().unwrap(),
12635                )?;
12636                let old = self
12637                    .builder
12638                    .build_extract_value(old, 0, "")
12639                    .unwrap()
12640                    .into_int_value();
12641                let old = err!(
12642                    self.builder
12643                        .build_int_z_extend(old, self.intrinsics.i64_ty, "")
12644                );
12645                self.state.push1_extra(old, ExtraInfo::arithmetic_f64());
12646            }
12647            Operator::I64AtomicRmwCmpxchg { ref memarg } => {
12648                let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
12649                let cmp = self.apply_pending_canonicalization(cmp, cmp_info)?;
12650                let new = self.apply_pending_canonicalization(new, new_info)?;
12651                let (cmp, new) = (cmp.into_int_value(), new.into_int_value());
12652                let offset = self.state.pop1()?.into_int_value();
12653                let memory_index = MemoryIndex::from_u32(0);
12654                let effective_address = self.resolve_memory_ptr(
12655                    memory_index,
12656                    memarg,
12657                    self.intrinsics.ptr_ty,
12658                    offset,
12659                    8,
12660                )?;
12661                self.trap_if_misaligned(memarg, effective_address, 8)?;
12662                let old = self
12663                    .builder
12664                    .build_cmpxchg(
12665                        effective_address,
12666                        cmp,
12667                        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 = err!(self.builder.build_extract_value(old, 0, ""));
12679                self.state.push1(old);
12680            }
12681
12682            Operator::MemoryGrow { mem } => {
12683                let memory_index = MemoryIndex::from_u32(mem);
12684                let delta = self.state.pop1()?;
12685                let grow_fn_ptr = self.ctx.memory_grow(memory_index, self.intrinsics)?;
12686                let grow = err!(self.builder.build_indirect_call(
12687                    self.intrinsics.memory_grow_ty,
12688                    grow_fn_ptr,
12689                    &[
12690                        vmctx.as_basic_value_enum().into(),
12691                        delta.into(),
12692                        self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
12693                    ],
12694                    "",
12695                ));
12696                self.state.push1(grow.try_as_basic_value().unwrap_basic());
12697            }
12698            Operator::MemorySize { mem } => {
12699                let memory_index = MemoryIndex::from_u32(mem);
12700                let size_fn_ptr = self.ctx.memory_size(memory_index, self.intrinsics)?;
12701                let size = err!(self.builder.build_indirect_call(
12702                    self.intrinsics.memory_size_ty,
12703                    size_fn_ptr,
12704                    &[
12705                        vmctx.as_basic_value_enum().into(),
12706                        self.intrinsics.i32_ty.const_int(mem.into(), false).into(),
12707                    ],
12708                    "",
12709                ));
12710                //size.add_attribute(AttributeLoc::Function, self.intrinsics.readonly);
12711                self.state.push1(size.try_as_basic_value().unwrap_basic());
12712            }
12713            Operator::MemoryInit { data_index, mem } => {
12714                let (dest, src, len) = self.state.pop3()?;
12715                let mem = self.intrinsics.i32_ty.const_int(mem.into(), false);
12716                let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
12717                self.build_call_with_param_attributes(
12718                    self.intrinsics.memory_init,
12719                    &[
12720                        vmctx.as_basic_value_enum().into(),
12721                        mem.into(),
12722                        segment.into(),
12723                        dest.into(),
12724                        src.into(),
12725                        len.into(),
12726                    ],
12727                    "",
12728                )?;
12729            }
12730            Operator::DataDrop { data_index } => {
12731                let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
12732                self.build_call_with_param_attributes(
12733                    self.intrinsics.data_drop,
12734                    &[vmctx.as_basic_value_enum().into(), segment.into()],
12735                    "",
12736                )?;
12737            }
12738            Operator::MemoryCopy { dst_mem, src_mem } => {
12739                // ignored until we support multiple memories
12740                let _dst = dst_mem;
12741                let (memory_copy, src) = if let Some(local_memory_index) = self
12742                    .wasm_module
12743                    .local_memory_index(MemoryIndex::from_u32(src_mem))
12744                {
12745                    (self.intrinsics.memory_copy, local_memory_index.as_u32())
12746                } else {
12747                    (self.intrinsics.imported_memory_copy, src_mem)
12748                };
12749
12750                let (dest_pos, src_pos, len) = self.state.pop3()?;
12751                let src_index = self.intrinsics.i32_ty.const_int(src.into(), false);
12752                self.build_call_with_param_attributes(
12753                    memory_copy,
12754                    &[
12755                        vmctx.as_basic_value_enum().into(),
12756                        src_index.into(),
12757                        dest_pos.into(),
12758                        src_pos.into(),
12759                        len.into(),
12760                    ],
12761                    "",
12762                )?;
12763            }
12764            Operator::MemoryFill { mem } => {
12765                let (memory_fill, mem) = if let Some(local_memory_index) = self
12766                    .wasm_module
12767                    .local_memory_index(MemoryIndex::from_u32(mem))
12768                {
12769                    (self.intrinsics.memory_fill, local_memory_index.as_u32())
12770                } else {
12771                    (self.intrinsics.imported_memory_fill, mem)
12772                };
12773
12774                let (dst, val, len) = self.state.pop3()?;
12775                let mem_index = self.intrinsics.i32_ty.const_int(mem.into(), false);
12776                self.build_call_with_param_attributes(
12777                    memory_fill,
12778                    &[
12779                        vmctx.as_basic_value_enum().into(),
12780                        mem_index.into(),
12781                        dst.into(),
12782                        val.into(),
12783                        len.into(),
12784                    ],
12785                    "",
12786                )?;
12787            }
12788            /***************************
12789             * Reference types.
12790             * https://github.com/WebAssembly/reference-types/blob/master/proposals/reference-types/Overview.md
12791             ***************************/
12792            Operator::RefNull { hty } => {
12793                let ty = err!(wpheaptype_to_type(hty));
12794                let ty = type_to_llvm(self.intrinsics, ty)?;
12795                self.state.push1(ty.const_zero());
12796            }
12797            Operator::RefIsNull => {
12798                let value = self.state.pop1()?.into_pointer_value();
12799                let is_null = err!(self.builder.build_is_null(value, ""));
12800                let is_null = err!(self.builder.build_int_z_extend(
12801                    is_null,
12802                    self.intrinsics.i32_ty,
12803                    ""
12804                ));
12805                self.state.push1(is_null);
12806            }
12807            Operator::RefFunc { function_index } => {
12808                let index = self
12809                    .intrinsics
12810                    .i32_ty
12811                    .const_int(function_index.into(), false);
12812                let value = self
12813                    .build_call_with_param_attributes(
12814                        self.intrinsics.func_ref,
12815                        &[self.ctx.basic().into(), index.into()],
12816                        "",
12817                    )?
12818                    .try_as_basic_value()
12819                    .unwrap_basic();
12820                self.state.push1(value);
12821            }
12822            Operator::TableGet { table } => {
12823                let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
12824                let elem = self.state.pop1()?;
12825                let table_get = if self
12826                    .wasm_module
12827                    .local_table_index(TableIndex::from_u32(table))
12828                    .is_some()
12829                {
12830                    self.intrinsics.table_get
12831                } else {
12832                    self.intrinsics.imported_table_get
12833                };
12834                let value = self
12835                    .build_call_with_param_attributes(
12836                        table_get,
12837                        &[self.ctx.basic().into(), table_index.into(), elem.into()],
12838                        "",
12839                    )?
12840                    .try_as_basic_value()
12841                    .unwrap_basic();
12842                let value = err!(
12843                    self.builder.build_bit_cast(
12844                        value,
12845                        type_to_llvm(
12846                            self.intrinsics,
12847                            self.wasm_module
12848                                .tables
12849                                .get(TableIndex::from_u32(table))
12850                                .unwrap()
12851                                .ty,
12852                        )?,
12853                        "",
12854                    )
12855                );
12856                self.state.push1(value);
12857            }
12858            Operator::TableSet { table } => {
12859                let table_index = self.intrinsics.i32_ty.const_int(table.into(), false);
12860                let (elem, value) = self.state.pop2()?;
12861                let value = err!(
12862                    self.builder
12863                        .build_bit_cast(value, self.intrinsics.ptr_ty, "")
12864                );
12865                let table_set = if self
12866                    .wasm_module
12867                    .local_table_index(TableIndex::from_u32(table))
12868                    .is_some()
12869                {
12870                    self.intrinsics.table_set
12871                } else {
12872                    self.intrinsics.imported_table_set
12873                };
12874                self.build_call_with_param_attributes(
12875                    table_set,
12876                    &[
12877                        self.ctx.basic().into(),
12878                        table_index.into(),
12879                        elem.into(),
12880                        value.into(),
12881                    ],
12882                    "",
12883                )?;
12884            }
12885            Operator::TableCopy {
12886                dst_table,
12887                src_table,
12888            } => {
12889                let (dst, src, len) = self.state.pop3()?;
12890                let dst_table = self.intrinsics.i32_ty.const_int(dst_table as u64, false);
12891                let src_table = self.intrinsics.i32_ty.const_int(src_table as u64, false);
12892                self.build_call_with_param_attributes(
12893                    self.intrinsics.table_copy,
12894                    &[
12895                        self.ctx.basic().into(),
12896                        dst_table.into(),
12897                        src_table.into(),
12898                        dst.into(),
12899                        src.into(),
12900                        len.into(),
12901                    ],
12902                    "",
12903                )?;
12904            }
12905            Operator::TableInit { elem_index, table } => {
12906                let (dst, src, len) = self.state.pop3()?;
12907                let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
12908                let table = self.intrinsics.i32_ty.const_int(table as u64, false);
12909                self.build_call_with_param_attributes(
12910                    self.intrinsics.table_init,
12911                    &[
12912                        self.ctx.basic().into(),
12913                        table.into(),
12914                        segment.into(),
12915                        dst.into(),
12916                        src.into(),
12917                        len.into(),
12918                    ],
12919                    "",
12920                )?;
12921            }
12922            Operator::ElemDrop { elem_index } => {
12923                let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
12924                self.build_call_with_param_attributes(
12925                    self.intrinsics.elem_drop,
12926                    &[self.ctx.basic().into(), segment.into()],
12927                    "",
12928                )?;
12929            }
12930            Operator::TableFill { table } => {
12931                let table = self.intrinsics.i32_ty.const_int(table as u64, false);
12932                let (start, elem, len) = self.state.pop3()?;
12933                let elem = err!(
12934                    self.builder
12935                        .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
12936                );
12937                self.build_call_with_param_attributes(
12938                    self.intrinsics.table_fill,
12939                    &[
12940                        self.ctx.basic().into(),
12941                        table.into(),
12942                        start.into(),
12943                        elem.into(),
12944                        len.into(),
12945                    ],
12946                    "",
12947                )?;
12948            }
12949            Operator::TableGrow { table } => {
12950                let (elem, delta) = self.state.pop2()?;
12951                let elem = err!(
12952                    self.builder
12953                        .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
12954                );
12955                let (table_grow, table_index) = if let Some(local_table_index) = self
12956                    .wasm_module
12957                    .local_table_index(TableIndex::from_u32(table))
12958                {
12959                    (self.intrinsics.table_grow, local_table_index.as_u32())
12960                } else {
12961                    (self.intrinsics.imported_table_grow, table)
12962                };
12963                let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
12964                let size = self
12965                    .build_call_with_param_attributes(
12966                        table_grow,
12967                        &[
12968                            self.ctx.basic().into(),
12969                            elem.into(),
12970                            delta.into(),
12971                            table_index.into(),
12972                        ],
12973                        "",
12974                    )?
12975                    .try_as_basic_value()
12976                    .unwrap_basic();
12977                self.state.push1(size);
12978            }
12979            Operator::TableSize { table } => {
12980                let (table_size, table_index) = if let Some(local_table_index) = self
12981                    .wasm_module
12982                    .local_table_index(TableIndex::from_u32(table))
12983                {
12984                    (self.intrinsics.table_size, local_table_index.as_u32())
12985                } else {
12986                    (self.intrinsics.imported_table_size, table)
12987                };
12988                let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
12989                let size = self
12990                    .build_call_with_param_attributes(
12991                        table_size,
12992                        &[self.ctx.basic().into(), table_index.into()],
12993                        "",
12994                    )?
12995                    .try_as_basic_value()
12996                    .unwrap_basic();
12997                self.state.push1(size);
12998            }
12999            Operator::MemoryAtomicWait32 { memarg } => {
13000                let memory_index = MemoryIndex::from_u32(memarg.memory);
13001                let (dst, val, timeout) = self.state.pop3()?;
13002                let wait32_fn_ptr = self.ctx.memory_wait32(memory_index, self.intrinsics)?;
13003                let ret = err!(
13004                    self.builder.build_indirect_call(
13005                        self.intrinsics.memory_wait32_ty,
13006                        wait32_fn_ptr,
13007                        &[
13008                            vmctx.as_basic_value_enum().into(),
13009                            self.intrinsics
13010                                .i32_ty
13011                                .const_int(memarg.memory as u64, false)
13012                                .into(),
13013                            dst.into(),
13014                            val.into(),
13015                            timeout.into(),
13016                        ],
13017                        "",
13018                    )
13019                );
13020                self.state.push1(ret.try_as_basic_value().unwrap_basic());
13021            }
13022            Operator::MemoryAtomicWait64 { memarg } => {
13023                let memory_index = MemoryIndex::from_u32(memarg.memory);
13024                let (dst, val, timeout) = self.state.pop3()?;
13025                let wait64_fn_ptr = self.ctx.memory_wait64(memory_index, self.intrinsics)?;
13026                let ret = err!(
13027                    self.builder.build_indirect_call(
13028                        self.intrinsics.memory_wait64_ty,
13029                        wait64_fn_ptr,
13030                        &[
13031                            vmctx.as_basic_value_enum().into(),
13032                            self.intrinsics
13033                                .i32_ty
13034                                .const_int(memarg.memory as u64, false)
13035                                .into(),
13036                            dst.into(),
13037                            val.into(),
13038                            timeout.into(),
13039                        ],
13040                        "",
13041                    )
13042                );
13043                self.state.push1(ret.try_as_basic_value().unwrap_basic());
13044            }
13045            Operator::MemoryAtomicNotify { memarg } => {
13046                let memory_index = MemoryIndex::from_u32(memarg.memory);
13047                let (dst, count) = self.state.pop2()?;
13048                let notify_fn_ptr = self.ctx.memory_notify(memory_index, self.intrinsics)?;
13049                let cnt = err!(
13050                    self.builder.build_indirect_call(
13051                        self.intrinsics.memory_notify_ty,
13052                        notify_fn_ptr,
13053                        &[
13054                            vmctx.as_basic_value_enum().into(),
13055                            self.intrinsics
13056                                .i32_ty
13057                                .const_int(memarg.memory as u64, false)
13058                                .into(),
13059                            dst.into(),
13060                            count.into(),
13061                        ],
13062                        "",
13063                    )
13064                );
13065                self.state.push1(cnt.try_as_basic_value().unwrap_basic());
13066            }
13067
13068            Operator::TryTable { try_table } => {
13069                let current_block = self
13070                    .builder
13071                    .get_insert_block()
13072                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
13073
13074                self.builder.position_at_end(current_block);
13075
13076                let end_block = self.context.append_basic_block(self.function, "try_end");
13077
13078                let end_phis = {
13079                    self.builder.position_at_end(end_block);
13080
13081                    let phis = self
13082                        .module_translation
13083                        .blocktype_params_results(&try_table.ty)?
13084                        .1
13085                        .iter()
13086                        .map(|&wp_ty| {
13087                            err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
13088                                type_to_llvm(self.intrinsics, wasm_ty)
13089                                    .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
13090                            })
13091                        })
13092                        .collect::<Result<_, _>>()?;
13093
13094                    self.builder.position_at_end(current_block);
13095                    phis
13096                };
13097
13098                // Collect unique catches. It is not a "hard" error on the wasm side,
13099                // but LLVM will definitely complain about having the same identifier
13100                // match two different branches in the switch below.
13101                let catches: Vec<_> = try_table
13102                    .catches
13103                    .into_iter()
13104                    .unique_by(|v| match v {
13105                        Catch::One { tag, .. } | Catch::OneRef { tag, .. } => *tag as i32,
13106                        Catch::All { .. } | Catch::AllRef { .. } => CATCH_ALL_TAG_VALUE,
13107                    })
13108                    .collect();
13109
13110                // Build the landing pad.
13111                let null = self.intrinsics.ptr_ty.const_zero();
13112
13113                let mut catch_tag_values = vec![];
13114                let mut lpad_clauses: Vec<BasicValueEnum<'ctx>> = catches
13115                    .iter()
13116                    .map(|catch| match catch {
13117                        Catch::All { .. } | Catch::AllRef { .. } => {
13118                            catch_tag_values.push(CATCH_ALL_TAG_VALUE as u32);
13119                            Ok(null.into())
13120                        }
13121                        Catch::One { tag, .. } | Catch::OneRef { tag, .. } => {
13122                            catch_tag_values.push(*tag);
13123                            Ok(self.get_or_insert_tag_type_info_global(*tag as i32))
13124                        }
13125                    })
13126                    .collect::<Result<Vec<BasicValueEnum<'ctx>>, CompileError>>()?;
13127
13128                // Since jumping between landingpads is not possible, we need to collect
13129                // all tags from outer try_tables as well to build a clause for *every*
13130                // possible tag that might be caught.
13131                let mut outer_catch_blocks = vec![];
13132                for outer_landingpad in self.state.landingpads.iter().rev() {
13133                    for catch_info @ TagCatchInfo { tag, .. } in &outer_landingpad.tags {
13134                        if !catch_tag_values.contains(tag) {
13135                            catch_tag_values.push(*tag);
13136                            lpad_clauses.push(if *tag as i32 == CATCH_ALL_TAG_VALUE {
13137                                null.into()
13138                            } else {
13139                                *self.tags_cache.get(&(*tag as i32)).expect(
13140                                    "If a previous try_table encountered a tag, \
13141                                    it should be in the cache",
13142                                )
13143                            });
13144                            outer_catch_blocks.push(*catch_info);
13145                        }
13146                    }
13147                }
13148
13149                // If there are no catch clauses, we have to skip everything, since
13150                // an lpad without catch clauses is invalid (and won't ever be jumped
13151                // to anyway)
13152                let mut maybe_lpad_block = None;
13153                let mut catch_blocks = vec![];
13154                if !lpad_clauses.is_empty() {
13155                    let lpad_block = self.context.append_basic_block(self.function, "catch");
13156                    let catch_all_block =
13157                        self.context.append_basic_block(self.function, "catch_all");
13158                    let catch_specific_block = self
13159                        .context
13160                        .append_basic_block(self.function, "catch_specific");
13161                    let catch_end_block =
13162                        self.context.append_basic_block(self.function, "catch_end");
13163                    let rethrow_block = self.context.append_basic_block(self.function, "rethrow");
13164
13165                    self.builder.position_at_end(lpad_block);
13166
13167                    let res = err!(self.builder.build_landing_pad(
13168                        self.intrinsics.lpad_exception_ty,
13169                        self.intrinsics.personality,
13170                        &lpad_clauses,
13171                        false,
13172                        "exc_struct",
13173                    ));
13174
13175                    let res = res.into_struct_value();
13176
13177                    let uw_exc = err!(self.builder.build_extract_value(res, 0, "exc_ptr"));
13178                    let pre_selector =
13179                        err!(self.builder.build_extract_value(res, 1, "pre_selector"));
13180
13181                    // The pre-selector can be either 0 (for catch-all) or 1 (for a
13182                    // specific, but as-yet-unknown tag).
13183                    let pre_selector_is_zero = err!(self.builder.build_int_compare(
13184                        IntPredicate::EQ,
13185                        pre_selector.into_int_value(),
13186                        self.intrinsics.i32_zero,
13187                        "pre_selector_is_zero"
13188                    ));
13189                    err!(self.builder.build_conditional_branch(
13190                        pre_selector_is_zero,
13191                        catch_all_block,
13192                        catch_specific_block
13193                    ));
13194
13195                    self.builder.position_at_end(catch_all_block);
13196                    err!(self.builder.build_unconditional_branch(catch_end_block));
13197
13198                    self.builder.position_at_end(catch_specific_block);
13199                    let selector_value = self.build_call_with_param_attributes(
13200                        self.intrinsics.personality2,
13201                        &[self.ctx.basic().into(), uw_exc.into()],
13202                        "selector",
13203                    )?;
13204                    err!(self.builder.build_unconditional_branch(catch_end_block));
13205
13206                    self.builder.position_at_end(catch_end_block);
13207                    let selector = err!(self.builder.build_phi(self.intrinsics.i32_ty, "selector"));
13208                    selector.add_incoming(&[
13209                        (
13210                            &self
13211                                .intrinsics
13212                                .i32_ty
13213                                .const_int(CATCH_ALL_TAG_VALUE as u64, false),
13214                            catch_all_block,
13215                        ),
13216                        (
13217                            &selector_value
13218                                .try_as_basic_value()
13219                                .unwrap_basic()
13220                                .into_int_value(),
13221                            catch_specific_block,
13222                        ),
13223                    ]);
13224
13225                    // Now we're done looking at the exception, it's time to deallocate and get
13226                    // the exnref out of it. When an exception is caught, "rethrowing" simply
13227                    // means starting another unwind by calling _Unwind_RaiseException with the
13228                    // same exception bits. Instead of keeping the same exception around, we
13229                    // deallocate the exception once it's caught, and if we need to rethrow, we
13230                    // just re-allocate a new exception.
13231                    //
13232                    // Note that this is different from how it's done in C++ land, where the
13233                    // exception object is kept around for rethrowing; this discrepency exists
13234                    // because in C++, exception handling is lexical (i.e. there's an implicit
13235                    // "current exception" in catch blocks) whereas in WASM, you rethrow with
13236                    // an exnref that may very well have come from somewhere else; consider this
13237                    // (badly implemented and erroneous) pseudo-module:
13238                    //
13239                    // (module
13240                    //   (global $e (mut exnref) (ref.null exn))
13241                    //   ;; Store the given exnref, return the previous one
13242                    //   (func $delay_exnref (param exnref) (result exnref)
13243                    //     (global.get $e)
13244                    //     (local.get 0)
13245                    //     (global.set $e)
13246                    //   )
13247                    //   (func foo
13248                    //     (block $catch (result exnref)
13249                    //       (try_table (catch_all_ref $catch)
13250                    //         ...
13251                    //       )
13252                    //     )
13253                    //     (call $delay_exnref) ;; store the exnref caught above
13254                    //     throw_ref ;; throw the previous exnref
13255                    //   )
13256                    // )
13257                    //
13258                    // Here, it's impossible to reuse the same exception object since the
13259                    // exnref given to throw_ref is a different one than the one we caught
13260                    // with the try_table.
13261                    //
13262                    // Another difference is that C++ exceptions may well carry lots of data
13263                    // around; a WASM exception is just an exnref, backed by a u32, which is
13264                    // just 4 bytes, and is cheap to reallocate. C++ exceptions may also carry
13265                    // things with dtors around; another thing that doesn't exist in WASM.
13266                    //
13267                    // All of this is to say that putting exception deallocation and exnref
13268                    // retrieval in the same function has been a very deliberate choice.
13269                    let uw_exc = uw_exc.into_pointer_value();
13270                    let exnref = self.build_call_with_param_attributes(
13271                        self.intrinsics.exception_into_exnref,
13272                        &[uw_exc.into()],
13273                        "exnref",
13274                    )?;
13275
13276                    let exnref = exnref.try_as_basic_value().unwrap_basic().into_int_value();
13277                    let selector = selector.as_basic_value().into_int_value();
13278
13279                    for catch in catches.iter() {
13280                        match catch {
13281                            Catch::All { label } => {
13282                                let b = self
13283                                    .context
13284                                    .append_basic_block(self.function, "catch_all_clause");
13285                                self.builder.position_at_end(b);
13286                                let frame = self.state.frame_at_depth(*label)?;
13287
13288                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13289
13290                                self.builder.position_at_end(catch_end_block);
13291                                catch_blocks.push((b, None));
13292                            }
13293                            Catch::One { tag, label } => {
13294                                let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
13295                                let signature = &self.wasm_module.signatures[tag_idx];
13296                                let params = signature.params();
13297
13298                                let b = self.context.append_basic_block(
13299                                    self.function,
13300                                    format!("catch_one_clause_{tag}").as_str(),
13301                                );
13302                                self.builder.position_at_end(b);
13303
13304                                let exnref_phi = err!(
13305                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
13306                                );
13307                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
13308
13309                                // Get the payload pointer.
13310                                let exn_payload_ptr = err!(self.builder.build_direct_call(
13311                                    self.intrinsics.read_exnref,
13312                                    &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
13313                                    "exn_ptr",
13314                                ));
13315                                let exn_payload_ptr = exn_payload_ptr
13316                                    .try_as_basic_value()
13317                                    .unwrap_basic()
13318                                    .into_pointer_value();
13319
13320                                // Read each value from the data ptr.
13321                                let values = params
13322                                    .iter()
13323                                    .enumerate()
13324                                    .map(|(i, v)| {
13325                                        let name = format!("value_{i}");
13326                                        let ptr = err!(unsafe {
13327                                            self.builder.build_gep(
13328                                                self.intrinsics.i128_ty,
13329                                                exn_payload_ptr,
13330                                                &[self
13331                                                    .intrinsics
13332                                                    .i32_ty
13333                                                    .const_int(i as u64, false)],
13334                                                format!("{name}_ptr").as_str(),
13335                                            )
13336                                        });
13337                                        err_nt!(self.builder.build_load(
13338                                            type_to_llvm(self.intrinsics, *v)?,
13339                                            ptr,
13340                                            &name,
13341                                        ))
13342                                    })
13343                                    .collect::<Result<Vec<_>, CompileError>>()?;
13344
13345                                let frame = self.state.frame_at_depth(*label)?;
13346
13347                                for (phi, value) in frame.phis().iter().zip(values.iter()) {
13348                                    phi.add_incoming(&[(value, b)])
13349                                }
13350
13351                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13352
13353                                self.builder.position_at_end(catch_end_block);
13354                                catch_blocks.push((b, Some(exnref_phi)));
13355                            }
13356                            Catch::OneRef { label, tag } => {
13357                                let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
13358                                let signature = &self.wasm_module.signatures[tag_idx];
13359                                let params = signature.params();
13360
13361                                let b = self.context.append_basic_block(
13362                                    self.function,
13363                                    format!("catch_one_ref_clause_{tag}").as_str(),
13364                                );
13365                                self.builder.position_at_end(b);
13366
13367                                let exnref_phi = err!(
13368                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
13369                                );
13370                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
13371
13372                                // Get the payload pointer.
13373                                let exn_payload_ptr = err!(self.builder.build_direct_call(
13374                                    self.intrinsics.read_exnref,
13375                                    &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
13376                                    "exn_ptr",
13377                                ));
13378                                let exn_payload_ptr = exn_payload_ptr
13379                                    .try_as_basic_value()
13380                                    .unwrap_basic()
13381                                    .into_pointer_value();
13382
13383                                // Read each value from the data ptr.
13384                                let mut values = params
13385                                    .iter()
13386                                    .enumerate()
13387                                    .map(|(i, v)| {
13388                                        let name = format!("value_{i}");
13389                                        let ptr = err!(unsafe {
13390                                            self.builder.build_gep(
13391                                                self.intrinsics.i128_ty,
13392                                                exn_payload_ptr,
13393                                                &[self
13394                                                    .intrinsics
13395                                                    .i32_ty
13396                                                    .const_int(i as u64, false)],
13397                                                format!("{name}_ptr").as_str(),
13398                                            )
13399                                        });
13400                                        err_nt!(self.builder.build_load(
13401                                            type_to_llvm(self.intrinsics, *v)?,
13402                                            ptr,
13403                                            &name,
13404                                        ))
13405                                    })
13406                                    .collect::<Result<Vec<_>, CompileError>>()?;
13407
13408                                values.push(exnref_phi.as_basic_value());
13409
13410                                let frame = self.state.frame_at_depth(*label)?;
13411
13412                                for (phi, value) in frame.phis().iter().zip(values.iter()) {
13413                                    phi.add_incoming(&[(value, b)])
13414                                }
13415
13416                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13417
13418                                self.builder.position_at_end(catch_end_block);
13419                                catch_blocks.push((b, Some(exnref_phi)));
13420                            }
13421                            Catch::AllRef { label } => {
13422                                let b = self
13423                                    .context
13424                                    .append_basic_block(self.function, "catch_all_ref_clause");
13425                                self.builder.position_at_end(b);
13426
13427                                let exnref_phi = err!(
13428                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
13429                                );
13430                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
13431
13432                                let frame = self.state.frame_at_depth(*label)?;
13433
13434                                let phis = frame.phis();
13435
13436                                assert_eq!(phis.len(), 1);
13437                                phis[0].add_incoming(&[(&exnref_phi.as_basic_value(), b)]);
13438
13439                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
13440
13441                                self.builder.position_at_end(catch_end_block);
13442                                catch_blocks.push((b, Some(exnref_phi)));
13443                            }
13444                        }
13445                    }
13446
13447                    for catch_info in &outer_catch_blocks {
13448                        if let Some(phi) = catch_info.exnref_phi {
13449                            phi.add_incoming(&[(&exnref, catch_end_block)]);
13450                        }
13451                    }
13452
13453                    err!(
13454                        self.builder.build_switch(
13455                            selector,
13456                            rethrow_block,
13457                            catch_blocks
13458                                .iter()
13459                                .enumerate()
13460                                .map(|(i, v)| (
13461                                    self.intrinsics
13462                                        .i32_ty
13463                                        .const_int(catch_tag_values[i] as _, false),
13464                                    v.0
13465                                ))
13466                                .chain(outer_catch_blocks.iter().map(|catch_info| (
13467                                    self.intrinsics.i32_ty.const_int(catch_info.tag as _, false),
13468                                    catch_info.catch_block
13469                                )))
13470                                .collect::<Vec<_>>()
13471                                .as_slice()
13472                        )
13473                    );
13474
13475                    // -- end
13476
13477                    // -- The rethrow block
13478                    self.builder.position_at_end(rethrow_block);
13479
13480                    self.build_call_with_param_attributes(
13481                        self.intrinsics.throw,
13482                        &[self.ctx.basic().into(), exnref.into()],
13483                        "rethrow",
13484                    )?;
13485                    // can't reach after an explicit throw!
13486                    err!(self.builder.build_unreachable());
13487
13488                    maybe_lpad_block = Some(lpad_block);
13489                }
13490
13491                // Move back to current block
13492                self.builder.position_at_end(current_block);
13493
13494                // Note: catch_tag_values also containes outer tags, but zipping with
13495                // catch_blocks will let us ignore the extra ones.
13496                let catch_tags_and_blocks = catch_tag_values
13497                    .into_iter()
13498                    .zip(catch_blocks)
13499                    .map(|(tag, (block, exnref_phi))| TagCatchInfo {
13500                        tag,
13501                        catch_block: block,
13502                        exnref_phi,
13503                    })
13504                    .collect::<Vec<_>>();
13505                self.state.push_landingpad(
13506                    maybe_lpad_block,
13507                    end_block,
13508                    end_phis,
13509                    &catch_tags_and_blocks,
13510                    self.module_translation
13511                        .blocktype_params_results(&try_table.ty)?
13512                        .0
13513                        .len(),
13514                );
13515            }
13516            Operator::Throw { tag_index } => {
13517                let current_block = self
13518                    .builder
13519                    .get_insert_block()
13520                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
13521
13522                let sig_index = self.wasm_module.tags[TagIndex::from_u32(tag_index)];
13523                let signature = &self.wasm_module.signatures[sig_index];
13524                let params = signature.params();
13525                let values = self.state.popn_save_extra(params.len())?;
13526
13527                values.iter().enumerate().try_for_each(|(i, (v, _))| {
13528                    let t = type_to_llvm(self.intrinsics, params[i])?;
13529                    if t != v.get_type() {
13530                        return Err(CompileError::Codegen(format!(
13531                            "Incompatible types: {:?} != {:?}",
13532                            t,
13533                            v.get_type()
13534                        )));
13535                    }
13536
13537                    Ok(())
13538                })?;
13539
13540                // Allocate the necessary bytes for the exception.
13541                let exnref = err!(
13542                    self.builder.build_direct_call(
13543                        self.intrinsics.alloc_exception,
13544                        &[
13545                            self.ctx.basic().into(),
13546                            self.intrinsics
13547                                .i32_ty
13548                                .const_int(tag_index as _, false)
13549                                .into()
13550                        ],
13551                        "exnref",
13552                    )
13553                );
13554                let exnref = exnref.try_as_basic_value().unwrap_basic();
13555
13556                let exn_payload_ptr = err!(self.builder.build_direct_call(
13557                    self.intrinsics.read_exnref,
13558                    &[self.ctx.basic().into(), exnref.into()],
13559                    "exn_ptr",
13560                ));
13561                let exn_payload_ptr = exn_payload_ptr
13562                    .try_as_basic_value()
13563                    .unwrap_basic()
13564                    .into_pointer_value();
13565
13566                for (i, value) in values.into_iter().enumerate() {
13567                    let ptr = err!(unsafe {
13568                        self.builder.build_gep(
13569                            self.intrinsics.i128_ty,
13570                            exn_payload_ptr,
13571                            &[self.intrinsics.i32_ty.const_int(i as u64, false)],
13572                            format!("value_{i}_ptr").as_str(),
13573                        )
13574                    });
13575                    err!(self.builder.build_store(ptr, value.0));
13576                }
13577
13578                if let Some(pad) = self.state.get_innermost_landingpad() {
13579                    let unreachable_block = self
13580                        .context
13581                        .append_basic_block(self.function, "_throw_unreachable");
13582
13583                    err!(self.builder.build_invoke(
13584                        self.intrinsics.throw,
13585                        &[self.ctx.basic(), exnref],
13586                        unreachable_block,
13587                        pad,
13588                        "throw",
13589                    ));
13590
13591                    self.builder.position_at_end(unreachable_block);
13592                    // can't reach after an explicit throw!
13593                    err!(self.builder.build_unreachable());
13594
13595                    self.builder.position_at_end(current_block);
13596                } else {
13597                    self.build_call_with_param_attributes(
13598                        self.intrinsics.throw,
13599                        &[self.ctx.basic().into(), exnref.into()],
13600                        "throw",
13601                    )?;
13602                    // can't reach after an explicit throw!
13603                    err!(self.builder.build_unreachable());
13604                }
13605
13606                self.state.reachable = false;
13607            }
13608            Operator::ThrowRef => {
13609                let current_block = self
13610                    .builder
13611                    .get_insert_block()
13612                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
13613
13614                let exnref = self.state.pop1()?;
13615
13616                if let Some(pad) = self.state.get_innermost_landingpad() {
13617                    let unreachable_block = self
13618                        .context
13619                        .append_basic_block(self.function, "_rethrow_unreachable");
13620
13621                    err!(self.builder.build_invoke(
13622                        self.intrinsics.throw,
13623                        &[self.ctx.basic(), exnref],
13624                        unreachable_block,
13625                        pad,
13626                        "throw",
13627                    ));
13628
13629                    self.builder.position_at_end(unreachable_block);
13630                    // can't reach after an explicit throw!
13631                    err!(self.builder.build_unreachable());
13632
13633                    self.builder.position_at_end(current_block);
13634                } else {
13635                    self.build_call_with_param_attributes(
13636                        self.intrinsics.throw,
13637                        &[self.ctx.basic().into(), exnref.into()],
13638                        "throw",
13639                    )?;
13640                    // can't reach after an explicit throw!
13641                    err!(self.builder.build_unreachable());
13642                }
13643
13644                self.state.reachable = false;
13645            }
13646            Operator::I64Add128 | Operator::I64Sub128 => {
13647                let (rhs_hi, rhs_hi_info) = self.state.pop1_extra()?;
13648                let (rhs_lo, rhs_lo_info) = self.state.pop1_extra()?;
13649                let (lhs_hi, lhs_hi_info) = self.state.pop1_extra()?;
13650                let (lhs_lo, lhs_lo_info) = self.state.pop1_extra()?;
13651
13652                let lhs_lo = self
13653                    .apply_pending_canonicalization(lhs_lo, lhs_lo_info)?
13654                    .into_int_value();
13655                let lhs_hi = self
13656                    .apply_pending_canonicalization(lhs_hi, lhs_hi_info)?
13657                    .into_int_value();
13658                let rhs_lo = self
13659                    .apply_pending_canonicalization(rhs_lo, rhs_lo_info)?
13660                    .into_int_value();
13661                let rhs_hi = self
13662                    .apply_pending_canonicalization(rhs_hi, rhs_hi_info)?
13663                    .into_int_value();
13664
13665                let idx0 = self.intrinsics.i32_ty.const_zero();
13666                let idx1 = self.intrinsics.i32_ty.const_int(1, false);
13667
13668                let lhs = self.intrinsics.i64x2_ty.get_undef();
13669                let lhs = err!(self.builder.build_insert_element(lhs, lhs_lo, idx0, ""));
13670                let lhs = err!(self.builder.build_insert_element(lhs, lhs_hi, idx1, ""));
13671                let lhs = err!(
13672                    self.builder
13673                        .build_bit_cast(lhs, self.intrinsics.i128_ty, "a")
13674                )
13675                .into_int_value();
13676
13677                let rhs = self.intrinsics.i64x2_ty.get_undef();
13678                let rhs = err!(self.builder.build_insert_element(rhs, rhs_lo, idx0, ""));
13679                let rhs = err!(self.builder.build_insert_element(rhs, rhs_hi, idx1, ""));
13680                let rhs = err!(
13681                    self.builder
13682                        .build_bit_cast(rhs, self.intrinsics.i128_ty, "b")
13683                )
13684                .into_int_value();
13685
13686                let result = err!(match op {
13687                    Operator::I64Add128 => self.builder.build_int_add(lhs, rhs, ""),
13688                    Operator::I64Sub128 => self.builder.build_int_sub(lhs, rhs, ""),
13689                    _ => unreachable!(),
13690                });
13691                let result = err!(self.builder.build_bit_cast(
13692                    result,
13693                    self.intrinsics.i64x2_ty,
13694                    ""
13695                ))
13696                .into_vector_value();
13697                let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
13698                let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
13699
13700                self.state.push1(result_lo);
13701                self.state.push1(result_hi);
13702            }
13703            Operator::I64MulWideS | Operator::I64MulWideU => {
13704                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
13705                let lhs = self
13706                    .apply_pending_canonicalization(lhs, lhs_info)?
13707                    .into_int_value();
13708                let rhs = self
13709                    .apply_pending_canonicalization(rhs, rhs_info)?
13710                    .into_int_value();
13711
13712                let lhs = err!(match op {
13713                    Operator::I64MulWideS => {
13714                        self.builder
13715                            .build_int_s_extend(lhs, self.intrinsics.i128_ty, "a")
13716                    }
13717                    Operator::I64MulWideU => {
13718                        self.builder
13719                            .build_int_z_extend(lhs, self.intrinsics.i128_ty, "a")
13720                    }
13721                    _ => unreachable!(),
13722                });
13723                let rhs = err!(match op {
13724                    Operator::I64MulWideS => {
13725                        self.builder
13726                            .build_int_s_extend(rhs, self.intrinsics.i128_ty, "b")
13727                    }
13728                    Operator::I64MulWideU => {
13729                        self.builder
13730                            .build_int_z_extend(rhs, self.intrinsics.i128_ty, "b")
13731                    }
13732                    _ => unreachable!(),
13733                });
13734
13735                let result = err!(self.builder.build_int_mul(lhs, rhs, ""));
13736                let result = err!(self.builder.build_bit_cast(
13737                    result,
13738                    self.intrinsics.i64x2_ty,
13739                    ""
13740                ))
13741                .into_vector_value();
13742                let idx0 = self.intrinsics.i32_ty.const_zero();
13743                let idx1 = self.intrinsics.i32_ty.const_int(1, false);
13744                let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
13745                let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
13746
13747                self.state.push1(result_lo);
13748                self.state.push1(result_hi);
13749            }
13750            _ => {
13751                return Err(CompileError::Codegen(format!(
13752                    "Operator {op:?} unimplemented",
13753                )));
13754            }
13755        }
13756
13757        Ok(())
13758    }
13759
13760    fn build_call_with_param_attributes(
13761        &self,
13762        function: FunctionValue<'ctx>,
13763        args: &[BasicMetadataValueEnum<'ctx>],
13764        name: &str,
13765    ) -> Result<CallSiteValue<'ctx>, CompileError> {
13766        let call = self
13767            .builder
13768            .build_call(function, args, name)
13769            .map_err(|e| CompileError::Codegen(e.to_string()))?;
13770
13771        // https://five-embeddev.com/riscv-user-isa-manual/Priv-v1.12/rv64.html
13772        // > The compiler and calling convention maintain an invariant that all 32-bit values are held in a sign-extended format in 64-bit registers.
13773        // > Even 32-bit unsigned integers extend bit 31 into bits 63 through 32. Consequently, conversion between unsigned and signed 32-bit integers
13774        // > is a no-op, as is conversion from a signed 32-bit integer to a signed 64-bit integer.
13775        if matches!(
13776            self.target_triple.architecture,
13777            Architecture::Riscv32(..) | Architecture::Riscv64(..)
13778        ) {
13779            let param_types = function.get_type().get_param_types();
13780            for (i, ty) in param_types.into_iter().enumerate() {
13781                if ty == self.context.i32_type().into() {
13782                    call.add_attribute(
13783                        AttributeLoc::Param(i as u32),
13784                        self.context
13785                            .create_enum_attribute(Attribute::get_named_enum_kind_id("signext"), 0),
13786                    );
13787                    call.add_attribute(
13788                        AttributeLoc::Param(i as u32),
13789                        self.context
13790                            .create_enum_attribute(Attribute::get_named_enum_kind_id("noundef"), 0),
13791                    );
13792                }
13793            }
13794        }
13795
13796        Ok(call)
13797    }
13798}
13799
13800fn is_f32_arithmetic(bits: u32) -> bool {
13801    // Mask off sign bit.
13802    let bits = bits & 0x7FFF_FFFF;
13803    bits < 0x7FC0_0000
13804}
13805
13806fn is_f64_arithmetic(bits: u64) -> bool {
13807    // Mask off sign bit.
13808    let bits = bits & 0x7FFF_FFFF_FFFF_FFFF;
13809    bits < 0x7FF8_0000_0000_0000
13810}