Skip to main content

wasmer_compiler_llvm/translator/
code.rs

1use std::borrow::Cow;
2use std::num::NonZero;
3use std::{
4    collections::HashMap,
5    sync::{Arc, OnceLock},
6};
7
8use super::{
9    intrinsics::{
10        CtxType, FunctionCache, GlobalCache, Intrinsics, MemoryCache, tbaa_label, type_to_llvm,
11    },
12    // stackmap::{StackmapEntry, StackmapEntryKind, StackmapRegistry, ValueSemantic},
13    state::{ControlFrame, ExtraInfo, IfElseState, State, TagCatchInfo},
14};
15use crate::{
16    compiler::ModuleBasedSymbolRegistry, config::OptimizationStyle, object_file::CompiledFunction,
17};
18use enumset::EnumSet;
19use inkwell::support::get_llvm_version;
20use inkwell::{
21    AddressSpace, AtomicOrdering, AtomicRMWBinOp, DLLStorageClass, FloatPredicate, IntPredicate,
22    attributes::{Attribute, AttributeLoc},
23    builder::Builder,
24    context::Context,
25    debug_info::{AsDIScope, DIFlags, DIFlagsConstants, DWARFEmissionKind, DWARFSourceLanguage},
26    module::{FlagBehavior, Linkage, Module},
27    passes::PassBuilderOptions,
28    targets::{FileType, TargetData, TargetMachine},
29    types::{BasicType, BasicTypeEnum, FloatMathType, IntType, PointerType, VectorType},
30    values::{
31        BasicMetadataValueEnum, BasicValue, BasicValueEnum, CallSiteValue, FloatValue,
32        FunctionValue, InstructionOpcode, InstructionValue, IntValue, LLVMTailCallKind, PhiValue,
33        PointerValue, VectorValue,
34    },
35};
36use itertools::Itertools;
37use smallvec::SmallVec;
38use target_lexicon::{Architecture, BinaryFormat, OperatingSystem, Triple};
39use wasmer_compiler::WASM_LARGE_FUNCTION_THRESHOLD;
40
41use crate::{
42    abi::{LLVMAbi, get_abi},
43    config::LLVM,
44    error::{err, err_nt},
45    object_file::load_object_file,
46};
47use wasmer_compiler::{
48    CANONICAL_NAN_F32, CANONICAL_NAN_F64, FunctionBinaryReader, FunctionBodyData,
49    GEF32_LEQ_I32_MAX, GEF32_LEQ_I64_MAX, GEF32_LEQ_U32_MAX, GEF32_LEQ_U64_MAX, GEF64_LEQ_I32_MAX,
50    GEF64_LEQ_I64_MAX, GEF64_LEQ_U32_MAX, GEF64_LEQ_U64_MAX, LEF32_GEQ_I32_MIN, LEF32_GEQ_I64_MIN,
51    LEF32_GEQ_U32_MIN, LEF32_GEQ_U64_MIN, LEF64_GEQ_I32_MIN, LEF64_GEQ_I64_MIN, LEF64_GEQ_U32_MIN,
52    LEF64_GEQ_U64_MIN, MiddlewareBinaryReader, ModuleMiddlewareChain, ModuleTranslationState,
53    WasmSourceMap, from_binaryreadererror_wasmerror,
54    misc::{CompiledFunctionExt, CompiledKind},
55    types::{
56        relocation::RelocationTarget,
57        symbols::{Symbol, SymbolRegistry},
58    },
59    wasmparser::{Catch, MemArg, Operator},
60    wpheaptype_to_type, wptype_to_type,
61};
62use wasmer_types::{
63    CompileError, FunctionIndex, FunctionType, GlobalIndex, LocalFunctionIndex, MemoryIndex,
64    ModuleInfo, SignatureHash, SignatureIndex, TableIndex, Type, target::CpuFeature,
65};
66use wasmer_types::{TagIndex, entity::PrimaryMap};
67use wasmer_vm::{MemoryStyle, TableStyle, VMOffsets};
68
69const FUNCTION_SECTION_ELF: &str = "__TEXT,wasmer_function";
70const FUNCTION_SECTION_MACHO: &str = "__TEXT";
71const FUNCTION_SEGMENT_MACHO: &str = "wasmer_function";
72
73// Since we want to use module-local tag numbers for landing pads,
74// the catch-all tag can't be zero; we instead use i32::MAX, which
75// is hopefully large enough to not conflict with any real tag.
76// If you have 2 billion tags in a single module, you deserve what you get.
77// ( Arshia: that comment above is AI-generated... AI is savage XD )
78const CATCH_ALL_TAG_VALUE: i32 = i32::MAX;
79
80// The following constants are generated by
81// `echo '' | opt -passes='default<O0>' -print-pipeline-passes 2>/dev/null` and
82// must be updated whenever a new LLVM version is released. The following
83// optimization passes are disabled because of known limitations:
84// - `memcpyopt` emits `memset` and `memcpy` library calls.
85// - `tailcallelim` allows self-recursive functions to be inlined despite
86//   differences in the forward-progress guarantees of WebAssembly and C++.
87//   In WebAssembly, this manifests as a stack overflow.
88// - `instcombine` removes one of the NaN canonicalization checks for `sqrt`.
89
90const LLVM_OPT_O0_PASSES: &str = "function(ee-instrument<>),always-inline,coro-cond(coro-early,cgscc(coro-split),coro-cleanup,globaldce),alloc-token,function(annotation-remarks),verify";
91const LLVM_OPT_O1_PASSES: &str = "memprof-remove-attributes,annotation2metadata,forceattrs,inferattrs,coro-early,function<eager-inv>(ee-instrument<>,lower-expect,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-arithmetic;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,sroa<modify-cfg>,early-cse<>),openmp-opt,ipsccp,called-value-propagation,globalopt,function<eager-inv>(mem2reg,instcombine<max-iterations=1;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-arithmetic;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>),always-inline,require<globals-aa>,function(invalidate<aa>),require<profile-summary>,cgscc(devirt<4>(inline,function-attrs<skip-non-recursive-function-attrs>,function<eager-inv;no-rerun>(sroa<modify-cfg>,early-cse<memssa>,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-arithmetic;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,libcalls-shrinkwrap,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-arithmetic;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,reassociate,loop-mssa(loop-instsimplify,loop-simplifycfg,licm<no-allowspeculation>,loop-rotate<header-duplication;no-prepare-for-lto>,licm<allowspeculation>,simple-loop-unswitch<no-nontrivial;trivial>),simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-arithmetic;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>,loop(loop-idiom,indvars,loop-deletion,loop-unroll-full),sroa<modify-cfg>,memcpyopt,sccp,bdce,instcombine<max-iterations=1;no-verify-fixpoint>,coro-elide,adce,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-arithmetic;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,instcombine<max-iterations=1;no-verify-fixpoint>),function-attrs,function(require<should-not-run-function-passes>),coro-split,coro-annotation-elide)),deadargelim,coro-cleanup,globalopt,globaldce,elim-avail-extern,rpo-function-attrs,recompute-globalsaa,function<eager-inv>(drop-unnecessary-assumes,float2int,lower-constant-intrinsics,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;vectorize-forced-only;>,drop-unnecessary-assumes,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-arithmetic;switch-to-lookup;no-keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,vector-combine,instcombine<max-iterations=1;no-verify-fixpoint>,loop-unroll<O1>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;switch-to-arithmetic;no-switch-to-lookup;keep-loops;no-hoist-common-insts;hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>),alloc-token,globaldce,constmerge,cg-profile,rel-lookup-table-converter,function(annotation-remarks),verify";
92const IGNORED_PASSES: &[&str] = &[
93    "memcpyopt",
94    "tailcallelim",
95    "instcombine<max-iterations=1;no-verify-fixpoint>",
96];
97
98static LLVM_OPT_PASSES: OnceLock<[String; 2]> = OnceLock::new();
99
100fn llvm_opt_passes() -> &'static [String; 2] {
101    LLVM_OPT_PASSES.get_or_init(|| {
102        // Update the LLVM_OPT_Ox_PASSES constants based on the release!
103        debug_assert_eq!(get_llvm_version().0, 22);
104
105        [LLVM_OPT_O0_PASSES, LLVM_OPT_O1_PASSES].map(|passes| {
106            let mut passes = passes.to_string();
107            for ignored_pass in IGNORED_PASSES {
108                passes = passes.replace(&format!(",{ignored_pass},"), ",");
109                // The pass might be a last one in group.
110                passes = passes.replace(&format!(",{ignored_pass})"), ")");
111                assert!(!passes.contains(ignored_pass));
112            }
113            passes
114        })
115    })
116}
117
118pub struct FuncTranslator {
119    ctx: Context,
120    target_triple: Triple,
121    target_machines: HashMap<OptimizationStyle, TargetMachine>,
122    abi: LLVMAbi,
123    binary_fmt: BinaryFormat,
124    func_section: String,
125    pointer_width: u8,
126    cpu_features: EnumSet<CpuFeature>,
127    non_volatile_memory_ops: bool,
128    source_map: Arc<WasmSourceMap>,
129    wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
130}
131
132impl wasmer_compiler::FuncTranslator for FuncTranslator {}
133
134pub(crate) fn enable_m0_optimization(
135    config: &LLVM,
136    memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
137) -> bool {
138    config.enable_m0
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        && memory_styles
142            .get(MemoryIndex::from_u32(0))
143            .is_some_and(|memory| matches!(memory, MemoryStyle::Static))
144}
145
146impl FuncTranslator {
147    #[allow(clippy::too_many_arguments)]
148    pub fn new(
149        target_triple: Triple,
150        target_machines: HashMap<OptimizationStyle, TargetMachine>,
151        binary_fmt: BinaryFormat,
152        pointer_width: u8,
153        cpu_features: EnumSet<CpuFeature>,
154        non_volatile_memory_ops: bool,
155        source_map: Arc<WasmSourceMap>,
156        wasm_apply_data_relocs_fn_index: Option<FunctionIndex>,
157    ) -> Result<Self, CompileError> {
158        let abi_source_tm = target_machines
159            .get(&OptimizationStyle::ForSpeed)
160            .expect("target_machines must contain OptimizationStyle::ForSpeed");
161        let abi = get_abi(abi_source_tm)?;
162        Ok(Self {
163            ctx: Context::create(),
164            target_triple,
165            target_machines,
166            abi,
167            func_section: match binary_fmt {
168                BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
169                BinaryFormat::Macho => FUNCTION_SEGMENT_MACHO.to_string(),
170                _ => {
171                    return Err(CompileError::UnsupportedTarget(format!(
172                        "Unsupported binary format: {binary_fmt:?}"
173                    )));
174                }
175            },
176            binary_fmt,
177            pointer_width,
178            cpu_features,
179            non_volatile_memory_ops,
180            source_map,
181            wasm_apply_data_relocs_fn_index,
182        })
183    }
184
185    #[allow(clippy::too_many_arguments)]
186    pub fn translate_to_module(
187        &self,
188        wasm_module: &ModuleInfo,
189        module_translation: &ModuleTranslationState,
190        signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
191        local_func_index: &LocalFunctionIndex,
192        function_body: &FunctionBodyData,
193        config: &LLVM,
194        memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
195        _table_styles: &PrimaryMap<TableIndex, TableStyle>,
196        symbol_registry: &dyn SymbolRegistry,
197        target: &Triple,
198        opt_style: OptimizationStyle,
199    ) -> Result<Module<'_>, CompileError> {
200        // The function type, used for the callbacks.
201        let func_index = wasm_module.func_index(*local_func_index);
202        let function =
203            CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
204
205        let m0_is_enabled = enable_m0_optimization(config, memory_styles);
206
207        let (function_name, module_name) = if config.experimental_artifact {
208            (function.linkage_name(), String::new())
209        } else {
210            let function_name =
211                symbol_registry.symbol_to_name(Symbol::LocalFunction(*local_func_index));
212            let module_name = match wasm_module.name.as_ref() {
213                None => format!("<anonymous module> function {function_name}"),
214                Some(module_name) => format!("module {module_name} function {function_name}"),
215            };
216            (function_name, module_name)
217        };
218
219        let module = self.ctx.create_module(module_name.as_str());
220
221        let target_machine = &self.target_machines.values().next().unwrap();
222        let target_triple = target_machine.get_triple();
223        let target_data = target_machine.get_target_data();
224        module.set_triple(&target_triple);
225        module.set_data_layout(&target_data.get_data_layout());
226        let wasm_fn_type = wasm_module
227            .signatures
228            .get(wasm_module.functions[func_index])
229            .unwrap();
230
231        let offsets =
232            VMOffsets::try_new(self.pointer_width, wasm_module).map_err(CompileError::Resource)?;
233        let intrinsics = Intrinsics::declare(
234            &module,
235            &self.ctx,
236            &target_data,
237            &self.target_triple,
238            &self.binary_fmt,
239        );
240        let (func_type, func_attrs) = self.abi.func_type_to_llvm(
241            &self.ctx,
242            &intrinsics,
243            Some(&offsets),
244            wasm_fn_type,
245            m0_is_enabled,
246        )?;
247
248        let func = module.add_function(&function_name, func_type, Some(Linkage::External));
249        let debug_info = if config.experimental_artifact {
250            let source_location = self.source_map.first_in_function(function_body);
251            let debug_metadata_version = self
252                .ctx
253                .i32_type()
254                .const_int(inkwell::debug_info::debug_metadata_version().into(), false);
255            module.add_basic_value_flag(
256                "Debug Info Version",
257                FlagBehavior::Warning,
258                debug_metadata_version,
259            );
260            module.add_basic_value_flag(
261                "Dwarf Version",
262                FlagBehavior::Warning,
263                self.ctx.i32_type().const_int(4, false),
264            );
265
266            let fallback_source_file = wasm_module.name();
267            let (source_file, source_directory) = source_location
268                .map(|location| (location.file.as_str(), location.directory.as_str()))
269                .unwrap_or((&fallback_source_file, "."));
270            let (dibuilder, compile_unit) = module.create_debug_info_builder(
271                true,
272                DWARFSourceLanguage::C,
273                source_file,
274                source_directory,
275                "wasmer",
276                true,
277                "",
278                0,
279                "",
280                DWARFEmissionKind::Full,
281                0,
282                false,
283                false,
284                "",
285                "",
286            );
287            let subroutine_type = dibuilder.create_subroutine_type(
288                compile_unit.get_file(),
289                None,
290                &[],
291                DIFlags::PUBLIC,
292            );
293            let function_name = wasm_module.get_function_name(func_index);
294            let start_line = source_location
295                .map(|location| location.line)
296                .unwrap_or_else(|| (function_body.module_offset as u32).saturating_add(1));
297            let subprogram = dibuilder.create_function(
298                compile_unit.as_debug_info_scope(),
299                &function_name,
300                None,
301                compile_unit.get_file(),
302                start_line,
303                subroutine_type,
304                false,
305                true,
306                start_line,
307                DIFlags::PUBLIC,
308                true,
309            );
310            func.set_subprogram(subprogram);
311            Some((dibuilder, subprogram))
312        } else {
313            None
314        };
315        for (attr, attr_loc) in &func_attrs {
316            func.add_attribute(*attr_loc, *attr);
317        }
318
319        if !matches!(target.operating_system, OperatingSystem::Windows) {
320            func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe);
321        }
322
323        func.add_attribute(AttributeLoc::Function, intrinsics.uwtable);
324        func.add_attribute(AttributeLoc::Function, intrinsics.frame_pointer);
325
326        let section = match self.binary_fmt {
327            BinaryFormat::Elf => FUNCTION_SECTION_ELF.to_string(),
328            BinaryFormat::Macho => {
329                format!("{FUNCTION_SECTION_MACHO},{FUNCTION_SEGMENT_MACHO}")
330            }
331            _ => {
332                return Err(CompileError::UnsupportedTarget(format!(
333                    "Unsupported binary format: {:?}",
334                    self.binary_fmt
335                )));
336            }
337        };
338
339        func.set_personality_function(intrinsics.personality);
340        if !config.experimental_artifact {
341            func.as_global_value().set_section(Some(&section));
342        }
343
344        func.set_linkage(Linkage::DLLExport);
345        func.as_global_value()
346            .set_dll_storage_class(DLLStorageClass::Export);
347
348        let entry = self.ctx.append_basic_block(func, "entry");
349        let start_of_code = self.ctx.append_basic_block(func, "start_of_code");
350        let return_ = self.ctx.append_basic_block(func, "return");
351        let alloca_builder = self.ctx.create_builder();
352        let cache_builder = self.ctx.create_builder();
353        let builder = self.ctx.create_builder();
354        cache_builder.position_at_end(entry);
355        let br = err!(cache_builder.build_unconditional_branch(start_of_code));
356        alloca_builder.position_before(&br);
357        cache_builder.position_before(&br);
358        builder.position_at_end(start_of_code);
359
360        let mut state = State::new();
361        builder.position_at_end(return_);
362        let phis: SmallVec<[PhiValue; 1]> = wasm_fn_type
363            .results()
364            .iter()
365            .map(|&wasm_ty| {
366                type_to_llvm(&intrinsics, wasm_ty).map(|ty| builder.build_phi(ty, "").unwrap())
367            })
368            .collect::<Result<_, _>>()?;
369        state.push_block(return_, phis, 0);
370        builder.position_at_end(start_of_code);
371
372        let mut reader = MiddlewareBinaryReader::new_with_offset(
373            function_body.data,
374            function_body.module_offset,
375        );
376        reader.set_middleware_chain(
377            config
378                .middlewares
379                .generate_function_middleware_chain(*local_func_index),
380        );
381
382        let mut params = vec![];
383        let first_param =
384            if func_type.get_return_type().is_none() && wasm_fn_type.results().len() > 1 {
385                if m0_is_enabled { 3 } else { 2 }
386            } else if m0_is_enabled {
387                2
388            } else {
389                1
390            };
391        let mut is_first_alloca = true;
392        let mut insert_alloca = |ty, name: String| -> Result<PointerValue, CompileError> {
393            let alloca = err!(alloca_builder.build_alloca(ty, &name));
394            if is_first_alloca {
395                alloca_builder.position_at(entry, &alloca.as_instruction_value().unwrap());
396                is_first_alloca = false;
397            }
398            Ok(alloca)
399        };
400
401        // Uncomment to print, at the start of the function, the function name.
402        // (poor man's debugger!)
403        //let func_name_str =
404        //    err!(alloca_builder.build_global_string_ptr(&function_name, "function_name"));
405        //
406        //_ = alloca_builder.build_call(
407        //    intrinsics.debug_str,
408        //    &[
409        //        func_name_str.as_pointer_value().into(),
410        //        intrinsics
411        //            .i32_ty
412        //            .const_int(function_name.len() as _, false)
413        //            .into(),
414        //    ],
415        //    "",
416        //);
417
418        for idx in 0..wasm_fn_type.params().len() {
419            let ty = wasm_fn_type.params()[idx];
420            let ty = type_to_llvm(&intrinsics, ty)?;
421            let value = func
422                .get_nth_param((idx as u32).checked_add(first_param).unwrap())
423                .unwrap();
424            let alloca = insert_alloca(ty, format!("param_{idx}"))?;
425            err!(cache_builder.build_store(alloca, value));
426            params.push((ty, alloca));
427        }
428
429        let mut locals = vec![];
430        let num_locals = reader.read_local_count()?;
431        for idx in 0..num_locals {
432            let (count, ty) = reader.read_local_decl()?;
433            let ty = err!(wptype_to_type(ty));
434            let ty = type_to_llvm(&intrinsics, ty)?;
435            for _ in 0..count {
436                let alloca = insert_alloca(ty, format!("local_{idx}"))?;
437                err!(cache_builder.build_store(alloca, ty.const_zero()));
438                locals.push((ty, alloca));
439            }
440        }
441
442        let mut params_locals = params.clone();
443        params_locals.extend(locals.iter().cloned());
444
445        let mut m0_param = None;
446
447        if m0_is_enabled {
448            let m0 = self.abi.get_m0_ptr_param(&func);
449            m0.set_name("m0_base_ptr");
450            m0_param = Some(m0);
451        }
452
453        let mut fcg = LLVMFunctionCodeGenerator {
454            m0_param,
455            context: &self.ctx,
456            builder,
457            alloca_builder,
458            intrinsics: &intrinsics,
459            target_data: &target_data,
460            state,
461            function: func,
462            locals: params_locals,
463            ctx: CtxType::new(
464                wasm_module,
465                &func,
466                &cache_builder,
467                &self.abi,
468                self.pointer_width,
469                m0_param,
470            )?,
471            unreachable_depth: 0,
472            memory_styles,
473            _table_styles,
474            module: &module,
475            module_translation,
476            signature_hashes,
477            wasm_module,
478            symbol_registry,
479            abi: &self.abi,
480            config,
481            target_triple: self.target_triple.clone(),
482            tags_cache: HashMap::new(),
483            binary_fmt: self.binary_fmt,
484            cpu_features: self.cpu_features,
485            non_volatile_memory_ops: self.non_volatile_memory_ops,
486        };
487
488        fcg.ctx.add_func(
489            func_index,
490            func.as_global_value().as_pointer_value(),
491            func_type,
492            fcg.ctx.basic(),
493            &func_attrs,
494        );
495
496        while fcg.state.has_control_frames() {
497            let pos = reader.current_position() as u32;
498            let original_pos = reader.original_position() as u32;
499            let op = reader.read_operator()?;
500            if let Some((dibuilder, subprogram)) = debug_info.as_ref() {
501                let (line, column, scope) =
502                    if let Some(location) = self.source_map.get(u64::from(original_pos)) {
503                        let file = dibuilder.create_file(&location.file, &location.directory);
504                        // TODO: try caching the lexical scopes (might be a space saver)
505                        let block = dibuilder.create_lexical_block(
506                            subprogram.as_debug_info_scope(),
507                            file,
508                            location.line,
509                            location.column,
510                        );
511                        (location.line, location.column, block.as_debug_info_scope())
512                    } else {
513                        (
514                            original_pos.saturating_add(1),
515                            1,
516                            subprogram.as_debug_info_scope(),
517                        )
518                    };
519                let loc = dibuilder.create_debug_location(&self.ctx, line, column, scope, None);
520                fcg.builder.set_current_debug_location(loc);
521            }
522            fcg.translate_operator(op, pos)?;
523        }
524
525        fcg.finalize(wasm_fn_type)?;
526        if let Some((dibuilder, _)) = debug_info {
527            dibuilder.finalize();
528        }
529
530        if let Some(ref callbacks) = config.callbacks {
531            callbacks.preopt_ir(&function, &wasm_module.hash_string(), &module);
532        }
533
534        let llvm_opt_passes = llvm_opt_passes();
535        let mut passes = Vec::new();
536
537        let passes = match opt_style {
538            OptimizationStyle::Disabled => Cow::Borrowed(llvm_opt_passes[0].as_str()),
539            OptimizationStyle::ForSize => {
540                // Apparently, the default<Os> could be much slower compared to -O1.
541                Cow::Borrowed(llvm_opt_passes[1].as_str())
542            }
543            OptimizationStyle::ForSpeed => {
544                passes.push("sccp");
545                passes.push("early-cse");
546                //passes.push("deadargelim");
547                passes.push("adce");
548                passes.push("sroa");
549                passes.push("aggressive-instcombine");
550                passes.push("jump-threading");
551                //passes.push("ipsccp");
552                passes.push("simplifycfg");
553                passes.push("reassociate");
554                passes.push("loop-rotate");
555                passes.push("indvars");
556                //passes.push("lcssa");
557                //passes.push("licm");
558                //passes.push("instcombine");
559                passes.push("sccp");
560                passes.push("reassociate");
561                passes.push("simplifycfg");
562                passes.push("gvn");
563                passes.push("memcpyopt");
564                passes.push("dse");
565                passes.push("dce");
566                //passes.push("instcombine");
567                passes.push("reassociate");
568                passes.push("simplifycfg");
569                passes.push("mem2reg");
570                Cow::Owned(passes.join(","))
571            }
572        };
573
574        // Always verify the LLVM IR; otherwise, invalid IR could cause a nasty
575        // miscompilation instead of a compilation error. Measurements show that
576        // verification adds approximately 2% to compilation time.
577        err!(module.verify());
578
579        err!(module.run_passes(&passes, target_machine, PassBuilderOptions::create(),));
580
581        if let Some(ref callbacks) = config.callbacks {
582            callbacks.postopt_ir(&function, &wasm_module.hash_string(), &module);
583        }
584
585        Ok(module)
586    }
587
588    #[allow(clippy::too_many_arguments)]
589    pub fn translate(
590        &self,
591        wasm_module: &ModuleInfo,
592        module_translation: &ModuleTranslationState,
593        signature_hashes: &PrimaryMap<SignatureIndex, SignatureHash>,
594        local_func_index: &LocalFunctionIndex,
595        function_body: &FunctionBodyData,
596        config: &LLVM,
597        memory_styles: &PrimaryMap<MemoryIndex, MemoryStyle>,
598        table_styles: &PrimaryMap<TableIndex, TableStyle>,
599        symbol_registry: &ModuleBasedSymbolRegistry,
600        target: &Triple,
601    ) -> Result<CompiledFunction, CompileError> {
602        let func_index = wasm_module.func_index(*local_func_index);
603        let opt_style = if Some(func_index) == self.wasm_apply_data_relocs_fn_index {
604            // `__wasm_apply_data_relocs` can become a very large function made up
605            // mostly of loads and stores, and even `-O1` can spend significant
606            // time optimizing it.
607            OptimizationStyle::Disabled
608        } else if function_body.data.len() as u64 > WASM_LARGE_FUNCTION_THRESHOLD {
609            OptimizationStyle::ForSize
610        } else {
611            OptimizationStyle::ForSpeed
612        };
613        let module = self.translate_to_module(
614            wasm_module,
615            module_translation,
616            signature_hashes,
617            local_func_index,
618            function_body,
619            config,
620            memory_styles,
621            table_styles,
622            symbol_registry,
623            target,
624            opt_style,
625        )?;
626        let function =
627            CompiledKind::Local(*local_func_index, wasm_module.get_function_name(func_index));
628
629        let target_machine = self.target_machines.get(&opt_style).unwrap();
630        let memory_buffer = target_machine
631            .write_to_memory_buffer(&module, FileType::Object)
632            .unwrap();
633
634        if let Some(ref callbacks) = config.callbacks {
635            let module_hash = wasm_module.hash().map(|m| m.to_string());
636            callbacks.obj_memory_buffer(&function, &module_hash, &memory_buffer);
637            let asm_buffer = target_machine
638                .write_to_memory_buffer(&module, FileType::Assembly)
639                .unwrap();
640            callbacks.asm_memory_buffer(&function, &module_hash, &asm_buffer)
641        }
642
643        if config.experimental_artifact {
644            Ok(CompiledFunction::Elf(memory_buffer.as_slice().to_vec()))
645        } else {
646            Ok(CompiledFunction::Rkyv(Box::new(load_object_file(
647                memory_buffer.as_slice(),
648                &self.func_section,
649                RelocationTarget::LocalFunc(*local_func_index),
650                |name: &str| {
651                    Ok({
652                        let name = if matches!(self.binary_fmt, BinaryFormat::Macho) {
653                            name.strip_prefix("_").unwrap_or(name)
654                        } else {
655                            name
656                        }
657                        .to_string();
658                        if let Some(Symbol::LocalFunction(local_func_index)) =
659                            symbol_registry.name_to_symbol(&name)
660                        {
661                            Some(RelocationTarget::LocalFunc(local_func_index))
662                        } else {
663                            None
664                        }
665                    })
666                },
667                self.binary_fmt,
668                &self.target_triple,
669            )?)))
670        }
671    }
672}
673
674impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
675    // Create a vector where each lane contains the same value.
676    fn splat_vector(
677        &self,
678        value: BasicValueEnum<'ctx>,
679        vec_ty: VectorType<'ctx>,
680    ) -> Result<VectorValue<'ctx>, CompileError> {
681        // Use insert_element to insert the element into an undef vector, then use
682        // shuffle vector to copy that lane to all lanes.
683        err_nt!(
684            self.builder.build_shuffle_vector(
685                err!(self.builder.build_insert_element(
686                    vec_ty.get_undef(),
687                    value,
688                    self.intrinsics.i32_zero,
689                    "",
690                )),
691                vec_ty.get_undef(),
692                self.intrinsics
693                    .i32_ty
694                    .vec_type(vec_ty.get_size())
695                    .const_zero(),
696                "",
697            )
698        )
699    }
700
701    // Convert floating point vector to integer and saturate when out of range.
702    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
703    #[allow(clippy::too_many_arguments)]
704    fn trunc_sat<T: FloatMathType<'ctx>>(
705        &self,
706        fvec_ty: T,
707        ivec_ty: T::MathConvType,
708        lower_bound: u64, // Exclusive (least representable value)
709        upper_bound: u64, // Exclusive (greatest representable value)
710        int_min_value: u64,
711        int_max_value: u64,
712        value: IntValue<'ctx>,
713    ) -> Result<VectorValue<'ctx>, CompileError> {
714        // a) Compare vector with itself to identify NaN lanes.
715        // b) Compare vector with splat of inttofp(upper_bound) to identify
716        //    lanes that need to saturate to max.
717        // c) Compare vector with splat of inttofp(lower_bound) to identify
718        //    lanes that need to saturate to min.
719        // d) Use vector select (not shuffle) to pick from either the
720        //    splat vector or the input vector depending on whether the
721        //    comparison indicates that we have an unrepresentable value. Replace
722        //    unrepresentable values with zero.
723        // e) Now that the value is safe, fpto[su]i it.
724        // f) Use our previous comparison results to replace certain zeros with
725        //    int_min or int_max.
726
727        let fvec_ty = fvec_ty.as_basic_type_enum().into_vector_type();
728        let ivec_ty = ivec_ty.as_basic_type_enum().into_vector_type();
729        let fvec_element_ty = fvec_ty.get_element_type().into_float_type();
730        let ivec_element_ty = ivec_ty.get_element_type().into_int_type();
731
732        let is_signed = int_min_value != 0;
733        let int_min_value = self.splat_vector(
734            ivec_element_ty
735                .const_int(int_min_value, is_signed)
736                .as_basic_value_enum(),
737            ivec_ty,
738        )?;
739        let int_max_value = self.splat_vector(
740            ivec_element_ty
741                .const_int(int_max_value, is_signed)
742                .as_basic_value_enum(),
743            ivec_ty,
744        )?;
745        let lower_bound = if is_signed {
746            err!(self.builder.build_signed_int_to_float(
747                ivec_element_ty.const_int(lower_bound, is_signed),
748                fvec_element_ty,
749                "",
750            ))
751        } else {
752            err!(self.builder.build_unsigned_int_to_float(
753                ivec_element_ty.const_int(lower_bound, is_signed),
754                fvec_element_ty,
755                "",
756            ))
757        };
758        let upper_bound = if is_signed {
759            err!(self.builder.build_signed_int_to_float(
760                ivec_element_ty.const_int(upper_bound, is_signed),
761                fvec_element_ty,
762                "",
763            ))
764        } else {
765            err!(self.builder.build_unsigned_int_to_float(
766                ivec_element_ty.const_int(upper_bound, is_signed),
767                fvec_element_ty,
768                "",
769            ))
770        };
771
772        let value = err!(self.builder.build_bit_cast(value, fvec_ty, "")).into_vector_value();
773        let zero = fvec_ty.const_zero();
774        let lower_bound = self.splat_vector(lower_bound.as_basic_value_enum(), fvec_ty)?;
775        let upper_bound = self.splat_vector(upper_bound.as_basic_value_enum(), fvec_ty)?;
776        let nan_cmp =
777            err!(
778                self.builder
779                    .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
780            );
781        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
782            FloatPredicate::OGT,
783            value,
784            upper_bound,
785            "above_upper_bound",
786        ));
787        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
788            FloatPredicate::OLT,
789            value,
790            lower_bound,
791            "below_lower_bound",
792        ));
793        let not_representable = err!(self.builder.build_or(
794            err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
795            below_lower_bound_cmp,
796            "not_representable_as_int",
797        ));
798        let value =
799            err!(
800                self.builder
801                    .build_select(not_representable, zero, value, "safe_to_convert")
802            )
803            .into_vector_value();
804        let value = if is_signed {
805            self.builder
806                .build_float_to_signed_int(value, ivec_ty, "as_int")
807        } else {
808            self.builder
809                .build_float_to_unsigned_int(value, ivec_ty, "as_int")
810        };
811
812        let value = err!(value);
813        let value =
814            err!(
815                self.builder
816                    .build_select(above_upper_bound_cmp, int_max_value, value, "")
817            )
818            .into_vector_value();
819        err_nt!(
820            self.builder
821                .build_select(below_lower_bound_cmp, int_min_value, value, "")
822                .map(|v| v.into_vector_value())
823        )
824    }
825
826    // Convert floating point vector to integer and saturate when out of range.
827    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
828    #[allow(clippy::too_many_arguments)]
829    fn trunc_sat_into_int<T: FloatMathType<'ctx>>(
830        &self,
831        fvec_ty: T,
832        ivec_ty: T::MathConvType,
833        lower_bound: u64, // Exclusive (least representable value)
834        upper_bound: u64, // Exclusive (greatest representable value)
835        int_min_value: u64,
836        int_max_value: u64,
837        value: IntValue<'ctx>,
838    ) -> Result<IntValue<'ctx>, CompileError> {
839        let res = self.trunc_sat(
840            fvec_ty,
841            ivec_ty,
842            lower_bound,
843            upper_bound,
844            int_min_value,
845            int_max_value,
846            value,
847        )?;
848        err_nt!(
849            self.builder
850                .build_bit_cast(res, self.intrinsics.i128_ty, "")
851                .map(|v| v.into_int_value())
852        )
853    }
854
855    // Convert floating point vector to integer and saturate when out of range.
856    // https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md
857    fn trunc_sat_scalar(
858        &self,
859        int_ty: IntType<'ctx>,
860        lower_bound: u64, // Exclusive (least representable value)
861        upper_bound: u64, // Exclusive (greatest representable value)
862        int_min_value: u64,
863        int_max_value: u64,
864        value: FloatValue<'ctx>,
865    ) -> Result<IntValue<'ctx>, CompileError> {
866        // TODO: this is a scalarized version of the process in trunc_sat. Either
867        // we should merge with trunc_sat, or we should simplify this function.
868
869        // a) Compare value with itself to identify NaN.
870        // b) Compare value inttofp(upper_bound) to identify values that need to
871        //    saturate to max.
872        // c) Compare value with inttofp(lower_bound) to identify values that need
873        //    to saturate to min.
874        // d) Use select to pick from either zero or the input vector depending on
875        //    whether the comparison indicates that we have an unrepresentable
876        //    value.
877        // e) Now that the value is safe, fpto[su]i it.
878        // f) Use our previous comparison results to replace certain zeros with
879        //    int_min or int_max.
880
881        let is_signed = int_min_value != 0;
882        let int_min_value = int_ty.const_int(int_min_value, is_signed);
883        let int_max_value = int_ty.const_int(int_max_value, is_signed);
884
885        let lower_bound = if is_signed {
886            err!(self.builder.build_signed_int_to_float(
887                int_ty.const_int(lower_bound, is_signed),
888                value.get_type(),
889                "",
890            ))
891        } else {
892            err!(self.builder.build_unsigned_int_to_float(
893                int_ty.const_int(lower_bound, is_signed),
894                value.get_type(),
895                "",
896            ))
897        };
898        let upper_bound = if is_signed {
899            err!(self.builder.build_signed_int_to_float(
900                int_ty.const_int(upper_bound, is_signed),
901                value.get_type(),
902                "",
903            ))
904        } else {
905            err!(self.builder.build_unsigned_int_to_float(
906                int_ty.const_int(upper_bound, is_signed),
907                value.get_type(),
908                "",
909            ))
910        };
911
912        let zero = value.get_type().const_zero();
913
914        let nan_cmp =
915            err!(
916                self.builder
917                    .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
918            );
919        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
920            FloatPredicate::OGT,
921            value,
922            upper_bound,
923            "above_upper_bound",
924        ));
925        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
926            FloatPredicate::OLT,
927            value,
928            lower_bound,
929            "below_lower_bound",
930        ));
931        let not_representable = err!(self.builder.build_or(
932            err!(self.builder.build_or(nan_cmp, above_upper_bound_cmp, "")),
933            below_lower_bound_cmp,
934            "not_representable_as_int",
935        ));
936        let value =
937            err!(
938                self.builder
939                    .build_select(not_representable, zero, value, "safe_to_convert")
940            )
941            .into_float_value();
942        let value = if is_signed {
943            err!(
944                self.builder
945                    .build_float_to_signed_int(value, int_ty, "as_int")
946            )
947        } else {
948            err!(
949                self.builder
950                    .build_float_to_unsigned_int(value, int_ty, "as_int")
951            )
952        };
953        let value =
954            err!(
955                self.builder
956                    .build_select(above_upper_bound_cmp, int_max_value, value, "")
957            )
958            .into_int_value();
959        let value =
960            err!(
961                self.builder
962                    .build_select(below_lower_bound_cmp, int_min_value, value, "")
963            )
964            .into_int_value();
965
966        err_nt!(
967            self.builder
968                .build_bit_cast(value, int_ty, "")
969                .map(|v| v.into_int_value())
970        )
971    }
972
973    fn trap_if_not_representable_as_int(
974        &self,
975        lower_bound: u64, // Inclusive (not a trapping value)
976        upper_bound: u64, // Inclusive (not a trapping value)
977        value: FloatValue<'ctx>,
978    ) -> Result<(), CompileError> {
979        let float_ty = value.get_type();
980        let int_ty = if float_ty == self.intrinsics.f32_ty {
981            self.intrinsics.i32_ty
982        } else {
983            self.intrinsics.i64_ty
984        };
985
986        let lower_bound = err!(self.builder.build_bit_cast(
987            int_ty.const_int(lower_bound, false),
988            float_ty,
989            ""
990        ))
991        .into_float_value();
992        let upper_bound = err!(self.builder.build_bit_cast(
993            int_ty.const_int(upper_bound, false),
994            float_ty,
995            ""
996        ))
997        .into_float_value();
998
999        // The 'U' in the float predicate is short for "unordered" which means that
1000        // the comparison will compare true if either operand is a NaN. Thus, NaNs
1001        // are out of bounds.
1002        let above_upper_bound_cmp = err!(self.builder.build_float_compare(
1003            FloatPredicate::UGT,
1004            value,
1005            upper_bound,
1006            "above_upper_bound",
1007        ));
1008        let below_lower_bound_cmp = err!(self.builder.build_float_compare(
1009            FloatPredicate::ULT,
1010            value,
1011            lower_bound,
1012            "below_lower_bound",
1013        ));
1014        let out_of_bounds = err!(self.builder.build_or(
1015            above_upper_bound_cmp,
1016            below_lower_bound_cmp,
1017            "out_of_bounds",
1018        ));
1019
1020        let failure_block = self
1021            .context
1022            .append_basic_block(self.function, "conversion_failure_block");
1023        let continue_block = self
1024            .context
1025            .append_basic_block(self.function, "conversion_success_block");
1026
1027        err!(
1028            self.builder
1029                .build_conditional_branch(out_of_bounds, failure_block, continue_block)
1030        );
1031        self.builder.position_at_end(failure_block);
1032        let is_nan =
1033            err!(
1034                self.builder
1035                    .build_float_compare(FloatPredicate::UNO, value, value, "is_nan")
1036            );
1037        let trap_code = err!(self.builder.build_select(
1038            is_nan,
1039            self.intrinsics.trap_bad_conversion_to_integer,
1040            self.intrinsics.trap_illegal_arithmetic,
1041            "",
1042        ));
1043        self.build_call_with_param_attributes(
1044            self.intrinsics.throw_trap,
1045            &[trap_code.into()],
1046            "throw",
1047        )?;
1048        err!(self.builder.build_unreachable());
1049        self.builder.position_at_end(continue_block);
1050
1051        Ok(())
1052    }
1053
1054    fn trap_if_zero_or_overflow(
1055        &self,
1056        left: IntValue<'ctx>,
1057        right: IntValue<'ctx>,
1058    ) -> Result<(), CompileError> {
1059        let int_type = left.get_type();
1060
1061        let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
1062            let min_value = int_type.const_int(i32::MIN as u64, false);
1063            let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
1064            (min_value, neg_one_value)
1065        } else if int_type == self.intrinsics.i64_ty {
1066            let min_value = int_type.const_int(i64::MIN as u64, false);
1067            let neg_one_value = int_type.const_int(-1i64 as u64, false);
1068            (min_value, neg_one_value)
1069        } else {
1070            unreachable!()
1071        };
1072
1073        let divisor_is_zero = err!(self.builder.build_int_compare(
1074            IntPredicate::EQ,
1075            right,
1076            int_type.const_zero(),
1077            "divisor_is_zero",
1078        ));
1079        let should_trap = err!(self.builder.build_or(
1080            divisor_is_zero,
1081            err!(self.builder.build_and(
1082                err!(self.builder.build_int_compare(
1083                    IntPredicate::EQ,
1084                    left,
1085                    min_value,
1086                    "left_is_min"
1087                )),
1088                err!(self.builder.build_int_compare(
1089                    IntPredicate::EQ,
1090                    right,
1091                    neg_one_value,
1092                    "right_is_neg_one",
1093                )),
1094                "div_will_overflow",
1095            )),
1096            "div_should_trap",
1097        ));
1098
1099        let should_trap = self
1100            .build_call_with_param_attributes(
1101                self.intrinsics.expect_i1,
1102                &[
1103                    should_trap.into(),
1104                    self.intrinsics.i1_ty.const_zero().into(),
1105                ],
1106                "should_trap_expect",
1107            )?
1108            .try_as_basic_value()
1109            .unwrap_basic()
1110            .into_int_value();
1111
1112        let shouldnt_trap_block = self
1113            .context
1114            .append_basic_block(self.function, "shouldnt_trap_block");
1115        let should_trap_block = self
1116            .context
1117            .append_basic_block(self.function, "should_trap_block");
1118        err!(self.builder.build_conditional_branch(
1119            should_trap,
1120            should_trap_block,
1121            shouldnt_trap_block
1122        ));
1123        self.builder.position_at_end(should_trap_block);
1124        let trap_code = err!(self.builder.build_select(
1125            divisor_is_zero,
1126            self.intrinsics.trap_integer_division_by_zero,
1127            self.intrinsics.trap_illegal_arithmetic,
1128            "",
1129        ));
1130        err!(
1131            self.builder
1132                .build_call(self.intrinsics.throw_trap, &[trap_code.into()], "throw")
1133        );
1134        err!(self.builder.build_unreachable());
1135        self.builder.position_at_end(shouldnt_trap_block);
1136
1137        Ok(())
1138    }
1139
1140    fn trap_if_zero(&self, value: IntValue<'ctx>) -> Result<(), CompileError> {
1141        let int_type = value.get_type();
1142        let should_trap = err!(self.builder.build_int_compare(
1143            IntPredicate::EQ,
1144            value,
1145            int_type.const_zero(),
1146            "divisor_is_zero",
1147        ));
1148
1149        let should_trap = self
1150            .build_call_with_param_attributes(
1151                self.intrinsics.expect_i1,
1152                &[
1153                    should_trap.into(),
1154                    self.intrinsics.i1_ty.const_zero().into(),
1155                ],
1156                "should_trap_expect",
1157            )?
1158            .try_as_basic_value()
1159            .unwrap_basic()
1160            .into_int_value();
1161
1162        let shouldnt_trap_block = self
1163            .context
1164            .append_basic_block(self.function, "shouldnt_trap_block");
1165        let should_trap_block = self
1166            .context
1167            .append_basic_block(self.function, "should_trap_block");
1168        err!(self.builder.build_conditional_branch(
1169            should_trap,
1170            should_trap_block,
1171            shouldnt_trap_block
1172        ));
1173        self.builder.position_at_end(should_trap_block);
1174        self.build_call_with_param_attributes(
1175            self.intrinsics.throw_trap,
1176            &[self.intrinsics.trap_integer_division_by_zero.into()],
1177            "throw",
1178        )?;
1179        err!(self.builder.build_unreachable());
1180        self.builder.position_at_end(shouldnt_trap_block);
1181
1182        Ok(())
1183    }
1184
1185    fn v128_into_int_vec(
1186        &self,
1187        value: BasicValueEnum<'ctx>,
1188        info: ExtraInfo,
1189        int_vec_ty: VectorType<'ctx>,
1190    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1191        let (value, info) = if info.has_pending_f32_nan() {
1192            let value = if self.config.enable_nan_canonicalization {
1193                let value = err!(
1194                    self.builder
1195                        .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1196                );
1197                self.canonicalize_nans(value)?
1198            } else {
1199                value
1200            };
1201            (value, info.strip_pending())
1202        } else if info.has_pending_f64_nan() {
1203            let value = if self.config.enable_nan_canonicalization {
1204                let value = err!(
1205                    self.builder
1206                        .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1207                );
1208                self.canonicalize_nans(value)?
1209            } else {
1210                value
1211            };
1212            (value, info.strip_pending())
1213        } else {
1214            (value, info)
1215        };
1216        Ok((
1217            err!(self.builder.build_bit_cast(value, int_vec_ty, "")).into_vector_value(),
1218            info,
1219        ))
1220    }
1221
1222    fn v128_into_i8x16(
1223        &self,
1224        value: BasicValueEnum<'ctx>,
1225        info: ExtraInfo,
1226    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1227        self.v128_into_int_vec(value, info, self.intrinsics.i8x16_ty)
1228    }
1229
1230    fn v128_into_i16x8(
1231        &self,
1232        value: BasicValueEnum<'ctx>,
1233        info: ExtraInfo,
1234    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1235        self.v128_into_int_vec(value, info, self.intrinsics.i16x8_ty)
1236    }
1237
1238    fn v128_into_i32x4(
1239        &self,
1240        value: BasicValueEnum<'ctx>,
1241        info: ExtraInfo,
1242    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1243        self.v128_into_int_vec(value, info, self.intrinsics.i32x4_ty)
1244    }
1245
1246    fn v128_into_i64x2(
1247        &self,
1248        value: BasicValueEnum<'ctx>,
1249        info: ExtraInfo,
1250    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1251        self.v128_into_int_vec(value, info, self.intrinsics.i64x2_ty)
1252    }
1253
1254    // If the value is pending a 64-bit canonicalization, do it now.
1255    // Return a f32x4 vector.
1256    fn v128_into_f32x4(
1257        &self,
1258        value: BasicValueEnum<'ctx>,
1259        info: ExtraInfo,
1260    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1261        let (value, info) = if info.has_pending_f64_nan() {
1262            let value = if self.config.enable_nan_canonicalization {
1263                let value = err!(
1264                    self.builder
1265                        .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1266                );
1267                self.canonicalize_nans(value)?
1268            } else {
1269                value
1270            };
1271            (value, info.strip_pending())
1272        } else {
1273            (value, info)
1274        };
1275        Ok((
1276            err!(
1277                self.builder
1278                    .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1279            )
1280            .into_vector_value(),
1281            info,
1282        ))
1283    }
1284
1285    // If the value is pending a 32-bit canonicalization, do it now.
1286    // Return a f64x2 vector.
1287    fn v128_into_f64x2(
1288        &self,
1289        value: BasicValueEnum<'ctx>,
1290        info: ExtraInfo,
1291    ) -> Result<(VectorValue<'ctx>, ExtraInfo), CompileError> {
1292        let (value, info) = if info.has_pending_f32_nan() {
1293            let value = if self.config.enable_nan_canonicalization {
1294                let value = err!(
1295                    self.builder
1296                        .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1297                );
1298                self.canonicalize_nans(value)?
1299            } else {
1300                value
1301            };
1302            (value, info.strip_pending())
1303        } else {
1304            (value, info)
1305        };
1306        Ok((
1307            err!(
1308                self.builder
1309                    .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1310            )
1311            .into_vector_value(),
1312            info,
1313        ))
1314    }
1315
1316    fn apply_pending_canonicalization(
1317        &self,
1318        value: BasicValueEnum<'ctx>,
1319        info: ExtraInfo,
1320    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1321        if !self.config.enable_nan_canonicalization {
1322            return Ok(value);
1323        }
1324
1325        if info.has_pending_f32_nan() {
1326            if value.get_type().is_vector_type()
1327                || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1328            {
1329                let ty = value.get_type();
1330                let value = err!(
1331                    self.builder
1332                        .build_bit_cast(value, self.intrinsics.f32x4_ty, "")
1333                );
1334                let value = self.canonicalize_nans(value)?;
1335                err_nt!(self.builder.build_bit_cast(value, ty, ""))
1336            } else {
1337                self.canonicalize_nans(value)
1338            }
1339        } else if info.has_pending_f64_nan() {
1340            if value.get_type().is_vector_type()
1341                || value.get_type() == self.intrinsics.i128_ty.as_basic_type_enum()
1342            {
1343                let ty = value.get_type();
1344                let value = err!(
1345                    self.builder
1346                        .build_bit_cast(value, self.intrinsics.f64x2_ty, "")
1347                );
1348                let value = self.canonicalize_nans(value)?;
1349                err_nt!(self.builder.build_bit_cast(value, ty, ""))
1350            } else {
1351                self.canonicalize_nans(value)
1352            }
1353        } else {
1354            Ok(value)
1355        }
1356    }
1357
1358    // Replaces any NaN with the canonical QNaN, otherwise leaves the value alone.
1359    fn canonicalize_nans(
1360        &self,
1361        value: BasicValueEnum<'ctx>,
1362    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1363        if !self.config.enable_nan_canonicalization {
1364            return Ok(value);
1365        }
1366
1367        let f_ty = value.get_type();
1368        if f_ty.is_vector_type() {
1369            let value = value.into_vector_value();
1370            let f_ty = f_ty.into_vector_type();
1371            let zero = f_ty.const_zero();
1372            let nan_cmp =
1373                err!(
1374                    self.builder
1375                        .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1376                );
1377            let canonical_qnan = f_ty
1378                .get_element_type()
1379                .into_float_type()
1380                .const_float(f64::NAN);
1381            let canonical_qnan = self.splat_vector(canonical_qnan.as_basic_value_enum(), f_ty)?;
1382            err_nt!(
1383                self.builder
1384                    .build_select(nan_cmp, canonical_qnan, value, "")
1385                    .map(|v| v.as_basic_value_enum())
1386            )
1387        } else {
1388            let value = value.into_float_value();
1389            let f_ty = f_ty.into_float_type();
1390            let zero = f_ty.const_zero();
1391            let nan_cmp =
1392                err!(
1393                    self.builder
1394                        .build_float_compare(FloatPredicate::UNO, value, zero, "nan")
1395                );
1396            let canonical_qnan = f_ty.const_float(f64::NAN);
1397            err_nt!(
1398                self.builder
1399                    .build_select(nan_cmp, canonical_qnan, value, "")
1400                    .map(|v| v.as_basic_value_enum())
1401            )
1402        }
1403    }
1404
1405    fn annotate_user_memaccess(
1406        &mut self,
1407        memory_index: MemoryIndex,
1408        _memarg: &MemArg,
1409        alignment: u32,
1410        memaccess: InstructionValue<'ctx>,
1411    ) -> Result<(), CompileError> {
1412        match memaccess.get_opcode() {
1413            InstructionOpcode::Load | InstructionOpcode::Store => {
1414                memaccess.set_alignment(alignment).unwrap();
1415            }
1416            _ => {}
1417        };
1418        if !self.non_volatile_memory_ops {
1419            // If this memory access must trap when out of bounds (i.e. it is a memory
1420            // access written in the user program as opposed to one used by our VM)
1421            // then mark that it can't be deleted.
1422            if let MemoryCache::Static { base_ptr: _ } = self.ctx.memory(
1423                memory_index,
1424                self.intrinsics,
1425                self.module,
1426                self.memory_styles,
1427            )? {
1428                // The best we've got is `volatile`.
1429                memaccess.set_volatile(true).map_err(|err| {
1430                    CompileError::Codegen(format!(
1431                        "could not set volatile on memory operation: {err}"
1432                    ))
1433                })?;
1434            }
1435        }
1436        tbaa_label(
1437            self.module,
1438            self.intrinsics,
1439            format!("memory {}", memory_index.as_u32()),
1440            memaccess,
1441        );
1442        Ok(())
1443    }
1444
1445    fn build_annotated_load<T: BasicType<'ctx>>(
1446        &mut self,
1447        pointee_ty: T,
1448        offset: IntValue<'ctx>,
1449        memarg: &MemArg,
1450        alignment: u32,
1451    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1452        let memory_index = MemoryIndex::from_u32(memarg.memory);
1453        let pointee_size = usize::try_from(self.target_data.get_store_size(&pointee_ty))
1454            .map_err(|_| CompileError::Codegen("pointee type size does not fit in usize".into()))?;
1455        let effective_address = self.resolve_memory_ptr(
1456            memory_index,
1457            memarg,
1458            self.intrinsics.ptr_ty,
1459            offset,
1460            pointee_size,
1461        )?;
1462        let result = err!(self.builder.build_load(pointee_ty, effective_address, ""));
1463        self.annotate_user_memaccess(
1464            MemoryIndex::from_u32(memarg.memory),
1465            memarg,
1466            alignment,
1467            result.as_instruction_value().unwrap(),
1468        )?;
1469        Ok(result)
1470    }
1471
1472    fn build_annotated_atomic_load(
1473        &mut self,
1474        outer_ty: IntType<'ctx>,
1475        inner_ty: IntType<'ctx>,
1476        offset: IntValue<'ctx>,
1477        memarg: &MemArg,
1478    ) -> Result<IntValue<'ctx>, CompileError> {
1479        let alignment = 2u32.pow(memarg.align as u32);
1480        let memory_index = MemoryIndex::from_u32(memarg.memory);
1481        let inner_size =
1482            usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1483                CompileError::Codegen("atomic inner type size does not fit in usize".into())
1484            })?;
1485        let outer_size =
1486            usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1487                CompileError::Codegen("atomic outer type size does not fit in usize".into())
1488            })?;
1489
1490        let effective_address = self.resolve_memory_ptr(
1491            memory_index,
1492            memarg,
1493            self.intrinsics.ptr_ty,
1494            offset,
1495            inner_size,
1496        )?;
1497        self.trap_if_misaligned(
1498            memarg,
1499            effective_address,
1500            u8::try_from(inner_size).map_err(|_| {
1501                CompileError::Codegen("atomic inner type size does not fit in u8".into())
1502            })?,
1503        )?;
1504
1505        let result = err!(
1506            self.builder
1507                .build_load(inner_ty, effective_address, "atomic_load")
1508        );
1509        let load = result.into_int_value();
1510        let load_inst = load.as_instruction_value().unwrap();
1511        self.annotate_user_memaccess(memory_index, memarg, alignment, load_inst)?;
1512        load_inst
1513            .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
1514            .unwrap();
1515
1516        if inner_size < outer_size {
1517            Ok(err_nt!(
1518                self.builder.build_int_z_extend(load, outer_ty, "")
1519            )?)
1520        } else {
1521            Ok(load)
1522        }
1523    }
1524
1525    fn build_annotated_store<T: BasicType<'ctx>>(
1526        &mut self,
1527        pointee_ty: T,
1528        offset: IntValue<'ctx>,
1529        value: BasicValueEnum<'ctx>,
1530        memarg: &MemArg,
1531        alignment: u32,
1532    ) -> Result<(), CompileError> {
1533        let memory_index = MemoryIndex::from_u32(memarg.memory);
1534        let pointee_size = usize::try_from(self.target_data.get_store_size(&pointee_ty))
1535            .map_err(|_| CompileError::Codegen("pointee type size does not fit in usize".into()))?;
1536        let effective_address = self.resolve_memory_ptr(
1537            memory_index,
1538            memarg,
1539            self.intrinsics.ptr_ty,
1540            offset,
1541            pointee_size,
1542        )?;
1543
1544        // Build a dead load (if non-volatile memory operations are disabled) to preserve
1545        // artifacts from partial store operations.
1546        if !self.non_volatile_memory_ops {
1547            self.build_annotated_load(pointee_ty, offset, memarg, alignment)?;
1548        }
1549
1550        let store = err!(self.builder.build_store(effective_address, value));
1551        self.annotate_user_memaccess(memory_index, memarg, alignment, store)
1552    }
1553
1554    fn build_annotated_atomic_store(
1555        &mut self,
1556        outer_ty: IntType<'ctx>,
1557        inner_ty: IntType<'ctx>,
1558        offset: IntValue<'ctx>,
1559        value: IntValue<'ctx>,
1560        memarg: &MemArg,
1561    ) -> Result<(), CompileError> {
1562        let alignment = 2u32.pow(memarg.align as u32);
1563        let memory_index = MemoryIndex::from_u32(memarg.memory);
1564        let inner_size =
1565            usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1566                CompileError::Codegen("atomic inner type size does not fit in usize".into())
1567            })?;
1568        let outer_size =
1569            usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1570                CompileError::Codegen("atomic outer type size does not fit in usize".into())
1571            })?;
1572
1573        let effective_address = self.resolve_memory_ptr(
1574            memory_index,
1575            memarg,
1576            self.intrinsics.ptr_ty,
1577            offset,
1578            inner_size,
1579        )?;
1580        self.trap_if_misaligned(
1581            memarg,
1582            effective_address,
1583            u8::try_from(inner_size).map_err(|_| {
1584                CompileError::Codegen("atomic inner type size does not fit in u8".into())
1585            })?,
1586        )?;
1587
1588        let value = if inner_size < outer_size {
1589            err!(self.builder.build_int_truncate(value, inner_ty, ""))
1590        } else {
1591            value
1592        };
1593        let store = err!(self.builder.build_store(effective_address, value));
1594        self.annotate_user_memaccess(memory_index, memarg, alignment, store)?;
1595        store
1596            .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
1597            .unwrap();
1598        Ok(())
1599    }
1600
1601    fn build_annotated_atomic_rmw(
1602        &mut self,
1603        outer_ty: IntType<'ctx>,
1604        inner_ty: IntType<'ctx>,
1605        offset: IntValue<'ctx>,
1606        value: IntValue<'ctx>,
1607        memarg: &MemArg,
1608        op: AtomicRMWBinOp,
1609    ) -> Result<IntValue<'ctx>, CompileError> {
1610        let alignment = 2u32.pow(memarg.align as u32);
1611        let memory_index = MemoryIndex::from_u32(memarg.memory);
1612        let inner_size =
1613            usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1614                CompileError::Codegen("atomic inner type size does not fit in usize".into())
1615            })?;
1616        let outer_size =
1617            usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1618                CompileError::Codegen("atomic outer type size does not fit in usize".into())
1619            })?;
1620
1621        let effective_address = self.resolve_memory_ptr(
1622            memory_index,
1623            memarg,
1624            self.intrinsics.ptr_ty,
1625            offset,
1626            inner_size,
1627        )?;
1628        self.trap_if_misaligned(
1629            memarg,
1630            effective_address,
1631            u8::try_from(inner_size).map_err(|_| {
1632                CompileError::Codegen("atomic inner type size does not fit in u8".into())
1633            })?,
1634        )?;
1635        let value = if inner_size < outer_size {
1636            err!(self.builder.build_int_truncate(value, inner_ty, ""))
1637        } else {
1638            value
1639        };
1640        let old = self
1641            .builder
1642            .build_atomicrmw(
1643                op,
1644                effective_address,
1645                value,
1646                AtomicOrdering::SequentiallyConsistent,
1647            )
1648            .unwrap();
1649        self.annotate_user_memaccess(
1650            memory_index,
1651            memarg,
1652            alignment,
1653            old.as_instruction_value().unwrap(),
1654        )?;
1655
1656        let value = if inner_size < outer_size {
1657            err!(self.builder.build_int_z_extend(old, outer_ty, ""))
1658        } else {
1659            old
1660        };
1661        Ok(value)
1662    }
1663
1664    fn build_annotated_atomic_rmw_cmpxchg(
1665        &mut self,
1666        outer_ty: IntType<'ctx>,
1667        inner_ty: IntType<'ctx>,
1668        offset: IntValue<'ctx>,
1669        cmp: IntValue<'ctx>,
1670        new: IntValue<'ctx>,
1671        memarg: &MemArg,
1672    ) -> Result<IntValue<'ctx>, CompileError> {
1673        let alignment = 2u32.pow(memarg.align as u32);
1674        let memory_index = MemoryIndex::from_u32(memarg.memory);
1675        let inner_size =
1676            usize::try_from(self.target_data.get_store_size(&inner_ty)).map_err(|_| {
1677                CompileError::Codegen("atomic inner type size does not fit in usize".into())
1678            })?;
1679        let outer_size =
1680            usize::try_from(self.target_data.get_store_size(&outer_ty)).map_err(|_| {
1681                CompileError::Codegen("atomic outer type size does not fit in usize".into())
1682            })?;
1683
1684        let effective_address = self.resolve_memory_ptr(
1685            memory_index,
1686            memarg,
1687            self.intrinsics.ptr_ty,
1688            offset,
1689            inner_size,
1690        )?;
1691        self.trap_if_misaligned(
1692            memarg,
1693            effective_address,
1694            u8::try_from(inner_size).map_err(|_| {
1695                CompileError::Codegen("atomic inner type size does not fit in u8".into())
1696            })?,
1697        )?;
1698        let (cmp, new) = if inner_size < outer_size {
1699            (
1700                err!(self.builder.build_int_truncate(cmp, inner_ty, "")),
1701                err!(self.builder.build_int_truncate(new, inner_ty, "")),
1702            )
1703        } else {
1704            (cmp, new)
1705        };
1706        let old = self
1707            .builder
1708            .build_cmpxchg(
1709                effective_address,
1710                cmp,
1711                new,
1712                AtomicOrdering::SequentiallyConsistent,
1713                AtomicOrdering::SequentiallyConsistent,
1714            )
1715            .unwrap();
1716        self.annotate_user_memaccess(
1717            memory_index,
1718            memarg,
1719            alignment,
1720            old.as_instruction_value().unwrap(),
1721        )?;
1722        let old = self
1723            .builder
1724            .build_extract_value(old, 0, "")
1725            .unwrap()
1726            .into_int_value();
1727
1728        let value = if inner_size < outer_size {
1729            err!(self.builder.build_int_z_extend(old, outer_ty, ""))
1730        } else {
1731            old
1732        };
1733        Ok(value)
1734    }
1735
1736    fn translate_atomic_rmw(
1737        &mut self,
1738        outer_ty: IntType<'ctx>,
1739        inner_ty: IntType<'ctx>,
1740        memarg: &MemArg,
1741        op: AtomicRMWBinOp,
1742        extra_info: Option<ExtraInfo>,
1743    ) -> Result<(), CompileError> {
1744        let value = self.state.pop1()?.into_int_value();
1745        let offset = self.state.pop1()?.into_int_value();
1746        let old = self.build_annotated_atomic_rmw(outer_ty, inner_ty, offset, value, memarg, op)?;
1747        if let Some(extra_info) = extra_info {
1748            self.state.push1_extra(old, extra_info);
1749        } else {
1750            self.state.push1(old);
1751        }
1752        Ok(())
1753    }
1754
1755    fn translate_atomic_rmw_cmpxchg(
1756        &mut self,
1757        outer_ty: IntType<'ctx>,
1758        inner_ty: IntType<'ctx>,
1759        memarg: &MemArg,
1760        extra_info: Option<ExtraInfo>,
1761    ) -> Result<(), CompileError> {
1762        let ((cmp, cmp_info), (new, new_info)) = self.state.pop2_extra()?;
1763        let cmp = self
1764            .apply_pending_canonicalization(cmp, cmp_info)?
1765            .into_int_value();
1766        let new = self
1767            .apply_pending_canonicalization(new, new_info)?
1768            .into_int_value();
1769        let offset = self.state.pop1()?.into_int_value();
1770        let old =
1771            self.build_annotated_atomic_rmw_cmpxchg(outer_ty, inner_ty, offset, cmp, new, memarg)?;
1772        if let Some(extra_info) = extra_info {
1773            self.state.push1_extra(old, extra_info);
1774        } else {
1775            self.state.push1(old);
1776        }
1777        Ok(())
1778    }
1779
1780    fn fold_atomic_mem_addr(
1781        &self,
1782        addr: BasicValueEnum<'ctx>,
1783        memarg: &MemArg,
1784    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
1785        let addr = addr.into_int_value();
1786        let addr = if memarg.offset > 0 {
1787            let extended_addr = err!(self.builder.build_int_z_extend(
1788                addr,
1789                self.intrinsics.i64_ty,
1790                "atomic_addr_extended"
1791            ));
1792            let effective_addr = err!(self.builder.build_int_add(
1793                extended_addr,
1794                self.intrinsics.i64_ty.const_int(memarg.offset, false),
1795                "atomic_effective_addr"
1796            ));
1797            let out_of_bounds = err!(self.builder.build_int_compare(
1798                IntPredicate::UGE,
1799                effective_addr,
1800                self.intrinsics.i64_ty.const_int(0x1_0000_0000, false),
1801                "atomic_addr_out_of_bounds"
1802            ));
1803            let continue_block = self
1804                .context
1805                .append_basic_block(self.function, "atomic_addr_in_bounds_block");
1806            let trap_block = self
1807                .context
1808                .append_basic_block(self.function, "atomic_addr_out_of_bounds_block");
1809            err!(
1810                self.builder
1811                    .build_conditional_branch(out_of_bounds, trap_block, continue_block)
1812            );
1813
1814            self.builder.position_at_end(trap_block);
1815            self.build_call_with_param_attributes(
1816                self.intrinsics.throw_trap,
1817                &[self.intrinsics.trap_memory_oob.into()],
1818                "throw",
1819            )?;
1820            err!(self.builder.build_unreachable());
1821
1822            self.builder.position_at_end(continue_block);
1823            err!(self.builder.build_int_truncate(
1824                effective_addr,
1825                self.intrinsics.i32_ty,
1826                "atomic_effective_addr_i32"
1827            ))
1828        } else {
1829            addr
1830        };
1831
1832        // Note the alignment is checked at the libcall side.
1833        Ok(addr.as_basic_value_enum())
1834    }
1835
1836    fn resolve_memory_ptr(
1837        &mut self,
1838        memory_index: MemoryIndex,
1839        memarg: &MemArg,
1840        ptr_ty: PointerType<'ctx>,
1841        var_offset: IntValue<'ctx>,
1842        value_size: usize,
1843    ) -> Result<PointerValue<'ctx>, CompileError> {
1844        let builder = &self.builder;
1845        let intrinsics = &self.intrinsics;
1846        let context = &self.context;
1847        let function = &self.function;
1848
1849        // Compute the offset into the storage.
1850        let imm_offset = intrinsics.i64_ty.const_int(memarg.offset, false);
1851        let var_offset = err!(builder.build_int_z_extend(var_offset, intrinsics.i64_ty, ""));
1852        let offset = err!(builder.build_int_add(var_offset, imm_offset, ""));
1853
1854        // Look up the memory base (as pointer) and bounds (as unsigned integer).
1855        let base_ptr = if let (0, Some(m0)) = (memory_index.as_u32(), self.m0_param) {
1856            m0
1857        } else {
1858            match self
1859                .ctx
1860                .memory(memory_index, intrinsics, self.module, self.memory_styles)?
1861            {
1862                MemoryCache::Dynamic {
1863                    ptr_to_base_ptr,
1864                    ptr_to_current_length,
1865                } => {
1866                    // Bounds check it.
1867                    let minimum = self.wasm_module.memories[memory_index].minimum;
1868                    let value_size_v = intrinsics.i64_ty.const_int(value_size as u64, false);
1869                    let ptr_in_bounds = if offset.is_const() {
1870                        // When the offset is constant, if it's below the minimum
1871                        // memory size, we've statically shown that it's safe.
1872                        let load_offset_end =
1873                            offset.const_add(value_size_v).get_zero_extended_constant();
1874                        if load_offset_end.is_some_and(|load_offset_end| {
1875                            load_offset_end <= minimum.bytes().0 as u64
1876                        }) {
1877                            Some(intrinsics.i64_ty.const_int(1, false))
1878                        } else {
1879                            None
1880                        }
1881                    } else {
1882                        None
1883                    };
1884
1885                    let ptr_in_bounds = match ptr_in_bounds {
1886                        Some(ptr) => ptr,
1887                        None => {
1888                            let load_offset_end = err!(builder.build_int_add(
1889                                offset,
1890                                value_size_v,
1891                                "load_offset_end"
1892                            ));
1893
1894                            let current_length = err!(builder.build_load(
1895                                self.intrinsics.i32_ty,
1896                                ptr_to_current_length,
1897                                "current_length"
1898                            ))
1899                            .into_int_value();
1900                            tbaa_label(
1901                                self.module,
1902                                self.intrinsics,
1903                                format!("memory {} length", memory_index.as_u32()),
1904                                current_length.as_instruction_value().unwrap(),
1905                            );
1906                            let current_length = err!(builder.build_int_z_extend(
1907                                current_length,
1908                                intrinsics.i64_ty,
1909                                "current_length_zextd"
1910                            ));
1911
1912                            err!(builder.build_int_compare(
1913                                IntPredicate::ULE,
1914                                load_offset_end,
1915                                current_length,
1916                                "ptr_in_bounds",
1917                            ))
1918                        }
1919                    };
1920
1921                    if !ptr_in_bounds.is_constant_int()
1922                        || ptr_in_bounds.get_zero_extended_constant().unwrap() != 1
1923                    {
1924                        // LLVM may have folded this into 'i1 true' in which case we know
1925                        // the pointer is in bounds. LLVM may also have folded it into a
1926                        // constant expression, not known to be either true or false yet.
1927                        // If it's false, unknown-but-constant, or not-a-constant, emit a
1928                        // runtime bounds check. LLVM may yet succeed at optimizing it away.
1929                        let ptr_in_bounds = err!(self.build_call_with_param_attributes(
1930                            intrinsics.expect_i1,
1931                            &[
1932                                ptr_in_bounds.into(),
1933                                intrinsics.i1_ty.const_int(1, true).into(),
1934                            ],
1935                            "ptr_in_bounds_expect",
1936                        ))
1937                        .try_as_basic_value()
1938                        .unwrap_basic()
1939                        .into_int_value();
1940
1941                        let in_bounds_continue_block =
1942                            context.append_basic_block(*function, "in_bounds_continue_block");
1943                        let not_in_bounds_block =
1944                            context.append_basic_block(*function, "not_in_bounds_block");
1945                        err!(builder.build_conditional_branch(
1946                            ptr_in_bounds,
1947                            in_bounds_continue_block,
1948                            not_in_bounds_block,
1949                        ));
1950                        builder.position_at_end(not_in_bounds_block);
1951                        err!(self.build_call_with_param_attributes(
1952                            intrinsics.throw_trap,
1953                            &[intrinsics.trap_memory_oob.into()],
1954                            "throw",
1955                        ));
1956                        err!(builder.build_unreachable());
1957                        builder.position_at_end(in_bounds_continue_block);
1958                    }
1959                    let ptr_to_base =
1960                        err!(builder.build_load(intrinsics.ptr_ty, ptr_to_base_ptr, "ptr_to_base"))
1961                            .into_pointer_value();
1962                    tbaa_label(
1963                        self.module,
1964                        self.intrinsics,
1965                        format!("memory base_ptr {}", memory_index.as_u32()),
1966                        ptr_to_base.as_instruction_value().unwrap(),
1967                    );
1968                    ptr_to_base
1969                }
1970                MemoryCache::Static { base_ptr } => base_ptr,
1971            }
1972        };
1973        let value_ptr = unsafe {
1974            err!(builder.build_gep(self.intrinsics.i8_ty, base_ptr, &[offset], "mem_value_ptr"))
1975        };
1976        err_nt!(
1977            builder
1978                .build_bit_cast(value_ptr, ptr_ty, "mem_value")
1979                .map(|v| v.into_pointer_value())
1980        )
1981    }
1982
1983    fn trap_if_misaligned(
1984        &self,
1985        _memarg: &MemArg,
1986        ptr: PointerValue<'ctx>,
1987        align: u8,
1988    ) -> Result<(), CompileError> {
1989        if align <= 1 {
1990            return Ok(());
1991        }
1992        let value = err!(self.builder.build_ptr_to_int(
1993            ptr,
1994            self.intrinsics.i64_ty,
1995            "mischeck_value"
1996        ));
1997        let and = err!(self.builder.build_and(
1998            value,
1999            self.intrinsics.i64_ty.const_int((align - 1).into(), false),
2000            "misaligncheck",
2001        ));
2002        let aligned = err!(self.builder.build_int_compare(
2003            IntPredicate::EQ,
2004            and,
2005            self.intrinsics.i64_zero,
2006            "is_aligned"
2007        ));
2008        let aligned = self
2009            .build_call_with_param_attributes(
2010                self.intrinsics.expect_i1,
2011                &[
2012                    aligned.into(),
2013                    self.intrinsics.i1_ty.const_int(1, false).into(),
2014                ],
2015                "is_aligned_expect",
2016            )?
2017            .try_as_basic_value()
2018            .unwrap_basic()
2019            .into_int_value();
2020
2021        let continue_block = self
2022            .context
2023            .append_basic_block(self.function, "aligned_access_continue_block");
2024        let not_aligned_block = self
2025            .context
2026            .append_basic_block(self.function, "misaligned_trap_block");
2027        err!(
2028            self.builder
2029                .build_conditional_branch(aligned, continue_block, not_aligned_block)
2030        );
2031
2032        self.builder.position_at_end(not_aligned_block);
2033        self.build_call_with_param_attributes(
2034            self.intrinsics.throw_trap,
2035            &[self.intrinsics.trap_unaligned_atomic.into()],
2036            "throw",
2037        )?;
2038        err!(self.builder.build_unreachable());
2039
2040        self.builder.position_at_end(continue_block);
2041        Ok(())
2042    }
2043
2044    fn finalize(&mut self, wasm_fn_type: &FunctionType) -> Result<(), CompileError> {
2045        let func_type = self.function.get_type();
2046
2047        let results = self.state.popn_save_extra(wasm_fn_type.results().len())?;
2048        let results = err!(
2049            results
2050                .into_iter()
2051                .map(|(v, i)| self.apply_pending_canonicalization(v, i))
2052                .collect::<Result<Vec<_>, _>>()
2053        );
2054
2055        if wasm_fn_type.results().is_empty() {
2056            err!(self.builder.build_return(None));
2057        } else if self.abi.is_sret(wasm_fn_type)? {
2058            let sret = self
2059                .function
2060                .get_first_param()
2061                .unwrap()
2062                .into_pointer_value();
2063            let llvm_params: Vec<_> = wasm_fn_type
2064                .results()
2065                .iter()
2066                .map(|x| type_to_llvm(self.intrinsics, *x).unwrap())
2067                .collect();
2068            let mut struct_value = self
2069                .context
2070                .struct_type(llvm_params.as_slice(), false)
2071                .get_undef();
2072            for (idx, value) in results.into_iter().enumerate() {
2073                let value = err!(self.builder.build_bit_cast(
2074                    value,
2075                    type_to_llvm(self.intrinsics, wasm_fn_type.results()[idx])?,
2076                    "",
2077                ));
2078                struct_value =
2079                    err!(
2080                        self.builder
2081                            .build_insert_value(struct_value, value, idx as u32, "")
2082                    )
2083                    .into_struct_value();
2084            }
2085            err!(self.builder.build_store(sret, struct_value));
2086            err!(self.builder.build_return(None));
2087        } else {
2088            err!(
2089                self.builder
2090                    .build_return(Some(&self.abi.pack_values_for_register_return(
2091                        self.intrinsics,
2092                        &self.builder,
2093                        &results,
2094                        wasm_fn_type,
2095                        &func_type,
2096                    )?))
2097            );
2098        }
2099        Ok(())
2100    }
2101
2102    // Generates a global constant with the tag's module-local index, which can be used
2103    // as the "type info" of a catch clause.
2104    fn get_or_insert_tag_type_info_global(&mut self, tag: i32) -> BasicValueEnum<'ctx> {
2105        if let Some(tag) = self.tags_cache.get(&tag) {
2106            return *tag;
2107        }
2108
2109        let tag_ty = self
2110            .context
2111            .struct_type(&[self.intrinsics.i32_ty.into()], false);
2112        let tag_glbl = self.module.add_global(
2113            tag_ty,
2114            Some(AddressSpace::default()),
2115            &format!("__wasmer_eh_type_info_{tag}"),
2116        );
2117        tag_glbl.set_initializer(
2118            &tag_ty
2119                .const_named_struct(&[self.intrinsics.i32_ty.const_int(tag as _, false).into()])
2120                .as_basic_value_enum(),
2121        );
2122
2123        tag_glbl.set_linkage(Linkage::LinkOnceODR);
2124        tag_glbl.set_constant(true);
2125        // Why set this to a specific section? On macOS it would land on a specific read only data
2126        // section. GOT-based relocations will probably be generated with a non-zero addend, making
2127        // some EH-related intricacies not working.
2128        //
2129        // The general idea is that each tag has its own section, so the GOT-based relocation can
2130        // have a zero addend, i.e. the data of the tag is the first (and only) value in a specific
2131        // section we can target in relocations.
2132        if matches!(self.binary_fmt, target_lexicon::BinaryFormat::Macho) {
2133            tag_glbl.set_section(Some(&format!("{FUNCTION_SECTION_MACHO},_eh_ti_{tag}")));
2134        }
2135
2136        let tag_glbl = tag_glbl.as_basic_value_enum();
2137
2138        self.tags_cache.insert(tag, tag_glbl);
2139        tag_glbl
2140    }
2141
2142    fn emit_return_call(
2143        &mut self,
2144        call_site: CallSiteValue<'ctx>,
2145        callee_llvm_func_type: inkwell::types::FunctionType<'ctx>,
2146    ) -> Result<(), CompileError> {
2147        // This is an unintuitive spec corner case: a tail call must bypass all enclosing
2148        // try_table blocks in the function. See https://github.com/WebAssembly/exception-handling/issues/249.
2149        //
2150        // The LLVM MustTail is more restrictive than the one defined in the WebAssembly spec.
2151        // WebAssembly types alone are not enough here: the lowered ABI can add hidden arguments
2152        // like `m0` and `sret`, so we must compare the actual LLVM function types instead.
2153        let tail_call_kind = if self.function.get_type() == callee_llvm_func_type {
2154            LLVMTailCallKind::LLVMTailCallKindMustTail
2155        } else {
2156            LLVMTailCallKind::LLVMTailCallKindTail
2157        };
2158        call_site.set_tail_call_kind(tail_call_kind);
2159
2160        if self.function.get_type().get_return_type().is_none() {
2161            err!(self.builder.build_return(None));
2162        } else {
2163            let ret = call_site.try_as_basic_value();
2164            if ret.is_instruction() {
2165                return Err(CompileError::Codegen(
2166                    "return_call expected a non-void call result".to_string(),
2167                ));
2168            }
2169            err!(self.builder.build_return(Some(&ret.unwrap_basic())));
2170        }
2171        Ok(())
2172    }
2173
2174    // Return sret pointer if the functions needs the hidden argument for multiple return values.
2175    fn current_sret_ptr(&self, func_type: &FunctionType) -> Option<PointerValue<'ctx>> {
2176        self.abi.is_sret(func_type).ok().map(|_| {
2177            self.function
2178                .get_first_param()
2179                .unwrap()
2180                .into_pointer_value()
2181        })
2182    }
2183
2184    fn build_m0_indirect_call(
2185        &mut self,
2186        table_index: u32,
2187        ctx_ptr: PointerValue<'ctx>,
2188        func_type: &FunctionType,
2189        func_ptr: PointerValue<'ctx>,
2190        func_index: IntValue<'ctx>,
2191        is_return_call: bool,
2192    ) -> Result<(), CompileError> {
2193        let Some(m0) = self.m0_param else {
2194            return Err(CompileError::Codegen(
2195                "Call to build_m0_indirect_call without m0 parameter!".to_string(),
2196            ));
2197        };
2198
2199        let params = self.state.popn_save_extra(func_type.params().len())?;
2200
2201        let mut local_func_indices = vec![];
2202        let mut foreign_func_indices = vec![];
2203
2204        for t in &self.wasm_module.table_initializers {
2205            if t.table_index.as_u32() == table_index {
2206                for (func_in_table_idx, func_idx) in t.elements.iter().enumerate() {
2207                    if self.wasm_module.local_func_index(*func_idx).is_some() {
2208                        local_func_indices.push(func_in_table_idx)
2209                    } else {
2210                        foreign_func_indices.push(func_in_table_idx)
2211                    }
2212                }
2213                break;
2214            }
2215        }
2216
2217        let needs_switch = !local_func_indices.is_empty() && !foreign_func_indices.is_empty();
2218
2219        if needs_switch {
2220            let foreign_idx_block = self
2221                .context
2222                .append_basic_block(self.function, "foreign_call_block");
2223            let local_idx_block = self
2224                .context
2225                .append_basic_block(self.function, "local_call_block");
2226            let unreachable_indirect_call_branch_block = self
2227                .context
2228                .append_basic_block(self.function, "unreachable_indirect_call_branch");
2229
2230            let cont =
2231                (!is_return_call).then(|| self.context.append_basic_block(self.function, "cont"));
2232
2233            err!(
2234                self.builder.build_switch(
2235                    func_index,
2236                    unreachable_indirect_call_branch_block,
2237                    &local_func_indices
2238                        .into_iter()
2239                        .map(|v| (
2240                            self.intrinsics.i32_ty.const_int(v as _, false),
2241                            local_idx_block
2242                        ))
2243                        .chain(foreign_func_indices.into_iter().map(|v| (
2244                            self.intrinsics.i32_ty.const_int(v as _, false),
2245                            foreign_idx_block
2246                        )))
2247                        .collect_vec()
2248                )
2249            );
2250
2251            self.builder
2252                .position_at_end(unreachable_indirect_call_branch_block);
2253            err!(self.builder.build_unreachable());
2254
2255            //let current_block = self.builder.get_insert_block().unwrap();
2256            self.builder.position_at_end(local_idx_block);
2257            let (local_call_site, local_llvm_func_type) = self.build_indirect_call_with_params(
2258                ctx_ptr,
2259                func_type,
2260                func_ptr,
2261                Some(m0),
2262                is_return_call,
2263                &params,
2264            )?;
2265
2266            let local_rets = if is_return_call {
2267                self.emit_return_call(local_call_site, local_llvm_func_type)?;
2268                Vec::new()
2269            } else {
2270                let rets = self.abi.rets_from_call(
2271                    &self.builder,
2272                    self.intrinsics,
2273                    local_call_site,
2274                    func_type,
2275                )?;
2276                err!(
2277                    self.builder
2278                        .build_unconditional_branch(cont.expect("non-return call requires cont"))
2279                );
2280                rets
2281            };
2282            let local_call_block = self
2283                .builder
2284                .get_insert_block()
2285                .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2286
2287            self.builder.position_at_end(foreign_idx_block);
2288            let (foreign_call_site, foreign_llvm_func_type) = self
2289                .build_indirect_call_with_params(
2290                    ctx_ptr,
2291                    func_type,
2292                    func_ptr,
2293                    None,
2294                    is_return_call,
2295                    &params,
2296                )?;
2297
2298            let foreign_rets = if is_return_call {
2299                self.emit_return_call(foreign_call_site, foreign_llvm_func_type)?;
2300                Vec::new()
2301            } else {
2302                let rets = self.abi.rets_from_call(
2303                    &self.builder,
2304                    self.intrinsics,
2305                    foreign_call_site,
2306                    func_type,
2307                )?;
2308                err!(
2309                    self.builder
2310                        .build_unconditional_branch(cont.expect("non-return call requires cont"))
2311                );
2312                rets
2313            };
2314            let foreign_call_block = self
2315                .builder
2316                .get_insert_block()
2317                .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2318
2319            if is_return_call {
2320                return Ok(());
2321            }
2322
2323            self.builder
2324                .position_at_end(cont.expect("non-return call requires cont"));
2325
2326            if foreign_rets.len() != local_rets.len() {
2327                return Err(CompileError::Codegen(format!(
2328                    "mismatched return counts in indirect call branches: foreign={}, local={}.",
2329                    foreign_rets.len(),
2330                    local_rets.len()
2331                )));
2332            }
2333
2334            for (foreign_ret, local_ret) in foreign_rets.iter().zip(local_rets.iter()) {
2335                let v = err!(self.builder.build_phi(foreign_ret.get_type(), ""));
2336                v.add_incoming(&[
2337                    (foreign_ret, foreign_call_block),
2338                    (local_ret, local_call_block),
2339                ]);
2340                self.state.push1(v.as_basic_value());
2341            }
2342        } else if foreign_func_indices.is_empty() {
2343            let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
2344                ctx_ptr,
2345                func_type,
2346                func_ptr,
2347                Some(m0),
2348                is_return_call,
2349                &params,
2350            )?;
2351
2352            if is_return_call {
2353                self.emit_return_call(call_site, llvm_func_type)?;
2354            } else {
2355                self.abi
2356                    .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2357                    .iter()
2358                    .for_each(|ret| self.state.push1(*ret));
2359            }
2360        } else {
2361            let (call_site, llvm_func_type) = self.build_indirect_call_with_params(
2362                ctx_ptr,
2363                func_type,
2364                func_ptr,
2365                None,
2366                is_return_call,
2367                &params,
2368            )?;
2369            if is_return_call {
2370                self.emit_return_call(call_site, llvm_func_type)?;
2371            } else {
2372                self.abi
2373                    .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
2374                    .iter()
2375                    .for_each(|ret| self.state.push1(*ret));
2376            }
2377        }
2378
2379        Ok(())
2380    }
2381
2382    fn build_indirect_call(
2383        &mut self,
2384        ctx_ptr: PointerValue<'ctx>,
2385        func_type: &FunctionType,
2386        func_ptr: PointerValue<'ctx>,
2387        m0_param: Option<PointerValue<'ctx>>,
2388        is_return_call: bool,
2389    ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
2390        let params = self.state.popn_save_extra(func_type.params().len())?;
2391        self.build_indirect_call_with_params(
2392            ctx_ptr,
2393            func_type,
2394            func_ptr,
2395            m0_param,
2396            is_return_call,
2397            &params,
2398        )
2399    }
2400
2401    fn build_indirect_call_with_params(
2402        &mut self,
2403        ctx_ptr: PointerValue<'ctx>,
2404        func_type: &FunctionType,
2405        func_ptr: PointerValue<'ctx>,
2406        m0_param: Option<PointerValue<'ctx>>,
2407        is_return_call: bool,
2408        params: &[(BasicValueEnum<'ctx>, ExtraInfo)],
2409    ) -> Result<(CallSiteValue<'ctx>, inkwell::types::FunctionType<'ctx>), CompileError> {
2410        let (llvm_func_type, llvm_func_attrs) = self.abi.func_type_to_llvm(
2411            self.context,
2412            self.intrinsics,
2413            Some(self.ctx.get_offsets()),
2414            func_type,
2415            m0_param.is_some(),
2416        )?;
2417
2418        // Apply pending canonicalization.
2419        let params = params
2420            .iter()
2421            .zip(func_type.params().iter())
2422            .map(|((v, info), wasm_ty)| match wasm_ty {
2423                Type::F32 => err_nt!(self.builder.build_bit_cast(
2424                    self.apply_pending_canonicalization(*v, *info)?,
2425                    self.intrinsics.f32_ty,
2426                    "",
2427                )),
2428                Type::F64 => err_nt!(self.builder.build_bit_cast(
2429                    self.apply_pending_canonicalization(*v, *info)?,
2430                    self.intrinsics.f64_ty,
2431                    "",
2432                )),
2433                Type::V128 => self.apply_pending_canonicalization(*v, *info),
2434                _ => Ok(*v),
2435            })
2436            .collect::<Result<Vec<_>, _>>()?;
2437
2438        let params = self.abi.args_to_call(
2439            &self.alloca_builder,
2440            func_type,
2441            &llvm_func_type,
2442            ctx_ptr,
2443            params.as_slice(),
2444            self.intrinsics,
2445            m0_param,
2446            is_return_call
2447                .then(|| self.current_sret_ptr(func_type))
2448                .flatten(),
2449        )?;
2450
2451        let typed_func_ptr = err!(self.builder.build_pointer_cast(
2452            func_ptr,
2453            self.context.ptr_type(AddressSpace::default()),
2454            "typed_func_ptr",
2455        ));
2456
2457        let call_site_local = self.build_indirect_call_or_invoke(
2458            llvm_func_type,
2459            typed_func_ptr,
2460            params.as_slice(),
2461            "then_block",
2462            is_return_call,
2463        )?;
2464        for (attr, attr_loc) in llvm_func_attrs {
2465            call_site_local.add_attribute(attr_loc, attr);
2466        }
2467
2468        Ok((call_site_local, llvm_func_type))
2469    }
2470
2471    fn build_indirect_call_or_invoke(
2472        &mut self,
2473        llvm_func_type: inkwell::types::FunctionType<'ctx>,
2474        func_ptr: PointerValue<'ctx>,
2475        params: &[BasicValueEnum<'ctx>],
2476        then_block_name: &str,
2477        is_return_call: bool,
2478    ) -> Result<CallSiteValue<'ctx>, CompileError> {
2479        // This is an unintuitive spec corner case: a tail call must bypass all enclosing
2480        // try_table blocks in the function. See https://github.com/WebAssembly/exception-handling/issues/249.
2481        if let Some(lpad) = self.state.get_innermost_landingpad()
2482            && !is_return_call
2483        {
2484            let then_block = self
2485                .context
2486                .append_basic_block(self.function, then_block_name);
2487
2488            let ret = err!(self.builder.build_indirect_invoke(
2489                llvm_func_type,
2490                func_ptr,
2491                params,
2492                then_block,
2493                lpad,
2494                "",
2495            ));
2496
2497            self.builder.position_at_end(then_block);
2498            Ok(ret)
2499        } else {
2500            let call_params = params
2501                .iter()
2502                .copied()
2503                .map(Into::into)
2504                .collect::<Vec<BasicMetadataValueEnum>>();
2505            Ok(err!(self.builder.build_indirect_call(
2506                llvm_func_type,
2507                func_ptr,
2508                call_params.as_slice(),
2509                ""
2510            )))
2511        }
2512    }
2513}
2514
2515pub struct LLVMFunctionCodeGenerator<'ctx, 'a> {
2516    m0_param: Option<PointerValue<'ctx>>,
2517    context: &'ctx Context,
2518    builder: Builder<'ctx>,
2519    alloca_builder: Builder<'ctx>,
2520    intrinsics: &'a Intrinsics<'ctx>,
2521    target_data: &'a TargetData,
2522    state: State<'ctx>,
2523    function: FunctionValue<'ctx>,
2524    locals: Vec<(BasicTypeEnum<'ctx>, PointerValue<'ctx>)>, // Contains params and locals
2525    ctx: CtxType<'ctx, 'a>,
2526    unreachable_depth: usize,
2527    memory_styles: &'a PrimaryMap<MemoryIndex, MemoryStyle>,
2528    _table_styles: &'a PrimaryMap<TableIndex, TableStyle>,
2529    module: &'a Module<'ctx>,
2530    module_translation: &'a ModuleTranslationState,
2531    signature_hashes: &'a PrimaryMap<SignatureIndex, SignatureHash>,
2532    wasm_module: &'a ModuleInfo,
2533    #[allow(dead_code)]
2534    symbol_registry: &'a dyn SymbolRegistry,
2535    abi: &'a LLVMAbi,
2536    config: &'a LLVM,
2537    target_triple: Triple,
2538    tags_cache: HashMap<i32, BasicValueEnum<'ctx>>,
2539    binary_fmt: target_lexicon::BinaryFormat,
2540    cpu_features: EnumSet<CpuFeature>,
2541    non_volatile_memory_ops: bool,
2542}
2543
2544impl<'ctx> LLVMFunctionCodeGenerator<'ctx, '_> {
2545    fn quiet_nan(&self, value: BasicValueEnum<'ctx>) -> Result<BasicValueEnum<'ctx>, CompileError> {
2546        let intrinsic = if value
2547            .get_type()
2548            .eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2549        {
2550            Some(self.intrinsics.add_f32)
2551        } else if value
2552            .get_type()
2553            .eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2554        {
2555            Some(self.intrinsics.add_f64)
2556        } else if value
2557            .get_type()
2558            .eq(&self.intrinsics.f32x4_ty.as_basic_type_enum())
2559        {
2560            Some(self.intrinsics.add_f32x4)
2561        } else if value
2562            .get_type()
2563            .eq(&self.intrinsics.f64x2_ty.as_basic_type_enum())
2564        {
2565            Some(self.intrinsics.add_f64x2)
2566        } else {
2567            None
2568        };
2569
2570        match intrinsic {
2571            Some(intrinsic) => err_nt!(
2572                self.builder
2573                    .build_call(
2574                        intrinsic,
2575                        &[
2576                            value.into(),
2577                            value.get_type().const_zero().into(),
2578                            self.intrinsics.fp_rounding_md,
2579                            self.intrinsics.fp_exception_md,
2580                        ],
2581                        "",
2582                    )
2583                    .map(|v| v.try_as_basic_value().unwrap_basic())
2584            ),
2585            None => Ok(value),
2586        }
2587    }
2588
2589    fn finalize_minmax_result(
2590        &self,
2591        value: BasicValueEnum<'ctx>,
2592    ) -> Result<BasicValueEnum<'ctx>, CompileError> {
2593        let ty = value.get_type();
2594        if ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum())
2595            || ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum())
2596        {
2597            let value = value.into_float_value();
2598            let is_nan = err!(self.builder.build_float_compare(
2599                FloatPredicate::UNO,
2600                value,
2601                value,
2602                "res_is_nan"
2603            ));
2604            let quiet = self.quiet_nan(value.as_basic_value_enum())?;
2605            let result =
2606                err!(
2607                    self.builder
2608                        .build_select(is_nan, quiet, value.as_basic_value_enum(), "")
2609                );
2610            Ok(result.as_basic_value_enum())
2611        } else if ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum()) {
2612            let value = value.into_vector_value();
2613            let is_nan = self
2614                .build_call_with_param_attributes(
2615                    self.intrinsics.cmp_f32x4,
2616                    &[
2617                        value.into(),
2618                        value.into(),
2619                        self.intrinsics.fp_uno_md,
2620                        self.intrinsics.fp_exception_md,
2621                    ],
2622                    "",
2623                )?
2624                .try_as_basic_value()
2625                .unwrap_basic()
2626                .into_vector_value();
2627            let quiet = self
2628                .quiet_nan(value.as_basic_value_enum())?
2629                .into_vector_value();
2630            let result = err!(self.builder.build_select(
2631                is_nan,
2632                quiet.as_basic_value_enum(),
2633                value.as_basic_value_enum(),
2634                "",
2635            ));
2636            Ok(result.as_basic_value_enum())
2637        } else if ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum()) {
2638            let value = value.into_vector_value();
2639            let is_nan = self
2640                .build_call_with_param_attributes(
2641                    self.intrinsics.cmp_f64x2,
2642                    &[
2643                        value.into(),
2644                        value.into(),
2645                        self.intrinsics.fp_uno_md,
2646                        self.intrinsics.fp_exception_md,
2647                    ],
2648                    "",
2649                )?
2650                .try_as_basic_value()
2651                .unwrap_basic()
2652                .into_vector_value();
2653            let quiet = self
2654                .quiet_nan(value.as_basic_value_enum())?
2655                .into_vector_value();
2656            let result = err!(self.builder.build_select(
2657                is_nan,
2658                quiet.as_basic_value_enum(),
2659                value.as_basic_value_enum(),
2660                "",
2661            ));
2662            Ok(result.as_basic_value_enum())
2663        } else {
2664            Ok(value)
2665        }
2666    }
2667
2668    fn finalize_rounding_result(
2669        &self,
2670        value: BasicValueEnum<'ctx>,
2671        info: ExtraInfo,
2672    ) -> Result<(BasicValueEnum<'ctx>, ExtraInfo), CompileError> {
2673        let ty = value.get_type();
2674        let is_f32 = ty.eq(&self.intrinsics.f32_ty.as_basic_type_enum());
2675        let is_f64 = ty.eq(&self.intrinsics.f64_ty.as_basic_type_enum());
2676        let is_f32x4 = ty.eq(&self.intrinsics.f32x4_ty.as_basic_type_enum());
2677        let is_f64x2 = ty.eq(&self.intrinsics.f64x2_ty.as_basic_type_enum());
2678        debug_assert!(is_f32 || is_f64 || is_f32x4 || is_f64x2);
2679
2680        if matches!(self.target_triple.architecture, Architecture::Riscv64(..)) {
2681            if is_f32 || is_f64 {
2682                let input = value.into_float_value();
2683                let is_nan = err!(self.builder.build_float_compare(
2684                    FloatPredicate::UNO,
2685                    input,
2686                    input,
2687                    "res_is_nan",
2688                ));
2689                let canonical_nan_bits = if is_f32 {
2690                    self.intrinsics
2691                        .i32_ty
2692                        .const_int(CANONICAL_NAN_F32 as _, false)
2693                } else {
2694                    self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false)
2695                };
2696                let canonical_nan = err!(self.builder.build_bit_cast(
2697                    canonical_nan_bits,
2698                    ty,
2699                    "canonical_nan",
2700                ));
2701                let res =
2702                    err!(
2703                        self.builder
2704                            .build_select(is_nan, canonical_nan, value, "canonical_nan",)
2705                    );
2706                Ok((res, info))
2707            } else if is_f32x4 {
2708                let value = value.into_vector_value();
2709                let is_nan = err!(self.builder.build_call(
2710                    self.intrinsics.cmp_f32x4,
2711                    &[
2712                        value.into(),
2713                        value.into(),
2714                        self.intrinsics.fp_uno_md,
2715                        self.intrinsics.fp_exception_md,
2716                    ],
2717                    "",
2718                ))
2719                .try_as_basic_value()
2720                .unwrap_basic()
2721                .into_vector_value();
2722                let canonical_nan_bits = self
2723                    .intrinsics
2724                    .i32_ty
2725                    .const_int(CANONICAL_NAN_F32 as _, false);
2726                let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 4]);
2727                let canonical_nan = err!(self.builder.build_bit_cast(
2728                    canonical_nan_bits,
2729                    self.intrinsics.f32x4_ty,
2730                    "canonical_nan",
2731                ));
2732                let res = err!(self.builder.build_select(
2733                    is_nan,
2734                    canonical_nan.as_basic_value_enum(),
2735                    value.as_basic_value_enum(),
2736                    "canonical_nan",
2737                ));
2738                Ok((res, info))
2739            } else {
2740                let value = value.into_vector_value();
2741                let is_nan = err!(self.builder.build_call(
2742                    self.intrinsics.cmp_f64x2,
2743                    &[
2744                        value.into(),
2745                        value.into(),
2746                        self.intrinsics.fp_uno_md,
2747                        self.intrinsics.fp_exception_md,
2748                    ],
2749                    "",
2750                ))
2751                .try_as_basic_value()
2752                .unwrap_basic()
2753                .into_vector_value();
2754                let canonical_nan_bits = self.intrinsics.i64_ty.const_int(CANONICAL_NAN_F64, false);
2755                let canonical_nan_bits = VectorType::const_vector(&[canonical_nan_bits; 2]);
2756                let canonical_nan = err!(self.builder.build_bit_cast(
2757                    canonical_nan_bits,
2758                    self.intrinsics.f64x2_ty,
2759                    "canonical_nan",
2760                ));
2761                let res = err!(self.builder.build_select(
2762                    is_nan,
2763                    canonical_nan.as_basic_value_enum(),
2764                    value.as_basic_value_enum(),
2765                    "canonical_nan",
2766                ));
2767                Ok((res, info))
2768            }
2769        } else {
2770            Ok((
2771                value,
2772                (info
2773                    | if is_f32 || is_f32x4 {
2774                        ExtraInfo::pending_f32_nan()
2775                    } else {
2776                        ExtraInfo::pending_f64_nan()
2777                    })?,
2778            ))
2779        }
2780    }
2781
2782    // Control Flow instructions.
2783    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#control-flow-instructions
2784    fn translate_control_flow_operator(&mut self, op: Operator) -> Result<(), CompileError> {
2785        match op {
2786            Operator::Block { blockty } => {
2787                let current_block = self
2788                    .builder
2789                    .get_insert_block()
2790                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2791
2792                let end_block = self.context.append_basic_block(self.function, "end");
2793                self.builder.position_at_end(end_block);
2794
2795                let phis: SmallVec<[PhiValue<'ctx>; 1]> = self
2796                    .module_translation
2797                    .blocktype_params_results(&blockty)?
2798                    .1
2799                    .iter()
2800                    .map(|&wp_ty| {
2801                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2802                            type_to_llvm(self.intrinsics, wasm_ty)
2803                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2804                        })
2805                    })
2806                    .collect::<Result<_, _>>()?;
2807
2808                self.state.push_block(
2809                    end_block,
2810                    phis,
2811                    self.module_translation
2812                        .blocktype_params_results(&blockty)?
2813                        .0
2814                        .len(),
2815                );
2816                self.builder.position_at_end(current_block);
2817            }
2818            Operator::Loop { blockty } => {
2819                let loop_body = self.context.append_basic_block(self.function, "loop_body");
2820                let loop_next = self.context.append_basic_block(self.function, "loop_outer");
2821                let pre_loop_block = self.builder.get_insert_block().unwrap();
2822
2823                let blocktypes = self.module_translation.blocktype_params_results(&blockty)?;
2824
2825                self.builder.position_at_end(loop_next);
2826                let phis = blocktypes
2827                    .1
2828                    .iter()
2829                    .map(|&wp_ty| {
2830                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2831                            type_to_llvm(self.intrinsics, wasm_ty)
2832                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2833                        })
2834                    })
2835                    .collect::<Result<_, _>>()?;
2836                self.builder.position_at_end(loop_body);
2837                let loop_phis: SmallVec<[PhiValue<'ctx>; 1]> = blocktypes
2838                    .0
2839                    .iter()
2840                    .map(|&wp_ty| {
2841                        err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
2842                            type_to_llvm(self.intrinsics, wasm_ty)
2843                                .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
2844                        })
2845                    })
2846                    .collect::<Result<_, _>>()?;
2847
2848                // Pop the loop parameters and canonicalize them in
2849                // pre_loop_block (before the terminator is emitted) so that the
2850                // select instruction dominates the phi uses.
2851                self.builder.position_at_end(pre_loop_block);
2852                for phi in loop_phis.iter().rev() {
2853                    let (value, info) = self.state.pop1_extra()?;
2854                    let value = self.apply_pending_canonicalization(value, info)?;
2855                    phi.add_incoming(&[(&value, pre_loop_block)]);
2856                }
2857
2858                err!(self.builder.build_unconditional_branch(loop_body));
2859
2860                self.builder.position_at_end(loop_body);
2861                for phi in &loop_phis {
2862                    self.state.push1(phi.as_basic_value());
2863                }
2864
2865                let num_inputs = loop_phis.len();
2866                self.state
2867                    .push_loop(loop_body, loop_next, loop_phis, phis, num_inputs);
2868            }
2869            Operator::Br { relative_depth } => {
2870                let frame = self.state.frame_at_depth(relative_depth)?;
2871
2872                let current_block = self
2873                    .builder
2874                    .get_insert_block()
2875                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2876
2877                let phis = if frame.is_loop() {
2878                    frame.loop_body_phis()
2879                } else {
2880                    frame.phis()
2881                };
2882
2883                let len = phis.len();
2884                let values = self.state.peekn_extra(len)?;
2885                let values = values
2886                    .iter()
2887                    .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2888                    .collect::<Result<Vec<_>, _>>()?;
2889
2890                // For each result of the block we're branching to,
2891                // pop a value off the value stack and load it into
2892                // the corresponding phi.
2893                for (phi, value) in phis.iter().zip(values) {
2894                    phi.add_incoming(&[(&value, current_block)]);
2895                }
2896
2897                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
2898
2899                self.state.popn(len)?;
2900                self.state.reachable = false;
2901            }
2902            Operator::BrIf { relative_depth } => {
2903                let cond = self.state.pop1()?;
2904                let frame = self.state.frame_at_depth(relative_depth)?;
2905
2906                let current_block = self
2907                    .builder
2908                    .get_insert_block()
2909                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2910
2911                let phis = if frame.is_loop() {
2912                    frame.loop_body_phis()
2913                } else {
2914                    frame.phis()
2915                };
2916
2917                let param_stack = self.state.peekn_extra(phis.len())?;
2918                let param_stack = param_stack
2919                    .iter()
2920                    .map(|(v, info)| self.apply_pending_canonicalization(*v, *info))
2921                    .collect::<Result<Vec<_>, _>>()?;
2922
2923                for (phi, value) in phis.iter().zip(param_stack) {
2924                    phi.add_incoming(&[(&value, current_block)]);
2925                }
2926
2927                let else_block = self.context.append_basic_block(self.function, "else");
2928
2929                let cond_value = err!(self.builder.build_int_compare(
2930                    IntPredicate::NE,
2931                    cond.into_int_value(),
2932                    self.intrinsics.i32_zero,
2933                    "",
2934                ));
2935                err!(self.builder.build_conditional_branch(
2936                    cond_value,
2937                    *frame.br_dest(),
2938                    else_block
2939                ));
2940                self.builder.position_at_end(else_block);
2941            }
2942            Operator::BrTable { ref targets } => {
2943                let current_block = self
2944                    .builder
2945                    .get_insert_block()
2946                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
2947
2948                let index = self.state.pop1()?;
2949
2950                let default_frame = self.state.frame_at_depth(targets.default())?;
2951
2952                let phis = if default_frame.is_loop() {
2953                    default_frame.loop_body_phis()
2954                } else {
2955                    default_frame.phis()
2956                };
2957                let args = self.state.peekn(phis.len())?;
2958
2959                for (phi, value) in phis.iter().zip(args.iter()) {
2960                    phi.add_incoming(&[(value, current_block)]);
2961                }
2962
2963                let cases: Vec<_> = targets
2964                    .targets()
2965                    .enumerate()
2966                    .map(|(case_index, depth)| {
2967                        let depth = depth.map_err(from_binaryreadererror_wasmerror)?;
2968                        let frame_result: Result<&ControlFrame, CompileError> =
2969                            self.state.frame_at_depth(depth);
2970                        let frame = match frame_result {
2971                            Ok(v) => v,
2972                            Err(e) => return Err(e),
2973                        };
2974                        let case_index_literal =
2975                            self.context.i32_type().const_int(case_index as u64, false);
2976                        let phis = if frame.is_loop() {
2977                            frame.loop_body_phis()
2978                        } else {
2979                            frame.phis()
2980                        };
2981                        for (phi, value) in phis.iter().zip(args.iter()) {
2982                            phi.add_incoming(&[(value, current_block)]);
2983                        }
2984
2985                        Ok((case_index_literal, *frame.br_dest()))
2986                    })
2987                    .collect::<Result<_, _>>()?;
2988
2989                err!(self.builder.build_switch(
2990                    index.into_int_value(),
2991                    *default_frame.br_dest(),
2992                    &cases[..],
2993                ));
2994
2995                let args_len = args.len();
2996                self.state.popn(args_len)?;
2997                self.state.reachable = false;
2998            }
2999            Operator::If { blockty } => {
3000                let current_block = self
3001                    .builder
3002                    .get_insert_block()
3003                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
3004                let if_then_block = self.context.append_basic_block(self.function, "if_then");
3005                let if_else_block = self.context.append_basic_block(self.function, "if_else");
3006                let end_block = self.context.append_basic_block(self.function, "if_end");
3007
3008                let end_phis = {
3009                    self.builder.position_at_end(end_block);
3010
3011                    let phis = self
3012                        .module_translation
3013                        .blocktype_params_results(&blockty)?
3014                        .1
3015                        .iter()
3016                        .map(|&wp_ty| {
3017                            err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
3018                                type_to_llvm(self.intrinsics, wasm_ty)
3019                                    .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
3020                            })
3021                        })
3022                        .collect::<Result<_, _>>()?;
3023
3024                    self.builder.position_at_end(current_block);
3025                    phis
3026                };
3027
3028                let block_param_types = self
3029                    .module_translation
3030                    .blocktype_params_results(&blockty)?
3031                    .0
3032                    .iter()
3033                    .map(|&wp_ty| {
3034                        err_nt!(wptype_to_type(wp_ty))
3035                            .and_then(|wasm_ty| type_to_llvm(self.intrinsics, wasm_ty))
3036                    })
3037                    .collect::<Result<Vec<_>, _>>()?;
3038
3039                // Build else_phis in if_else_block and then_phis in if_then_block.
3040                self.builder.position_at_end(if_else_block);
3041                let else_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
3042                    .iter()
3043                    .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
3044                    .collect::<Result<SmallVec<_>, _>>()?;
3045                self.builder.position_at_end(if_then_block);
3046                let then_phis: SmallVec<[PhiValue<'ctx>; 1]> = block_param_types
3047                    .iter()
3048                    .map(|&ty| err_nt!(self.builder.build_phi(ty, "")))
3049                    .collect::<Result<SmallVec<_>, _>>()?;
3050
3051                // Pop the condition.
3052                let cond = self.state.pop1()?;
3053
3054                // Pop the block parameters and canonicalize them in current_block
3055                // (before the terminator is emitted) so that the select instruction
3056                // dominates the phi uses.
3057                self.builder.position_at_end(current_block);
3058                for (else_phi, then_phi) in else_phis.iter().rev().zip(then_phis.iter().rev()) {
3059                    let (value, info) = self.state.pop1_extra()?;
3060                    let value = self.apply_pending_canonicalization(value, info)?;
3061                    else_phi.add_incoming(&[(&value, current_block)]);
3062                    then_phi.add_incoming(&[(&value, current_block)]);
3063                }
3064
3065                let cond_value = err!(self.builder.build_int_compare(
3066                    IntPredicate::NE,
3067                    cond.into_int_value(),
3068                    self.intrinsics.i32_zero,
3069                    "",
3070                ));
3071
3072                err!(self.builder.build_conditional_branch(
3073                    cond_value,
3074                    if_then_block,
3075                    if_else_block
3076                ));
3077
3078                self.builder.position_at_end(if_then_block);
3079                for phi in then_phis.iter() {
3080                    self.state.push1(phi.as_basic_value());
3081                }
3082
3083                self.state.push_if(
3084                    if_then_block,
3085                    if_else_block,
3086                    end_block,
3087                    then_phis,
3088                    else_phis,
3089                    end_phis,
3090                    block_param_types.len(),
3091                );
3092            }
3093            Operator::Else => {
3094                if self.state.reachable {
3095                    let frame = self.state.frame_at_depth(0)?;
3096                    let current_block = self.builder.get_insert_block().ok_or_else(|| {
3097                        CompileError::Codegen("not currently in a block".to_string())
3098                    })?;
3099
3100                    for phi in frame.phis().to_vec().iter().rev() {
3101                        let (value, info) = self.state.pop1_extra()?;
3102                        let value = self.apply_pending_canonicalization(value, info)?;
3103                        phi.add_incoming(&[(&value, current_block)])
3104                    }
3105
3106                    let frame = self.state.frame_at_depth(0)?;
3107                    err!(self.builder.build_unconditional_branch(*frame.code_after()));
3108                }
3109
3110                let (if_else_block, if_else_state) = if let ControlFrame::IfElse {
3111                    if_else,
3112                    if_else_state,
3113                    ..
3114                } = self.state.frame_at_depth_mut(0)?
3115                {
3116                    (if_else, if_else_state)
3117                } else {
3118                    unreachable!()
3119                };
3120
3121                *if_else_state = IfElseState::Else;
3122
3123                self.builder.position_at_end(*if_else_block);
3124                self.state.reachable = true;
3125
3126                if let ControlFrame::IfElse { else_phis, .. } = self.state.frame_at_depth(0)? {
3127                    // Push our own 'else' phi nodes to the stack.
3128                    for phi in else_phis.clone().iter() {
3129                        self.state.push1(phi.as_basic_value());
3130                    }
3131                };
3132            }
3133
3134            Operator::End => {
3135                let frame = self.state.pop_frame()?;
3136                let current_block = self
3137                    .builder
3138                    .get_insert_block()
3139                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
3140
3141                if self.state.reachable {
3142                    for phi in frame.phis().iter().rev() {
3143                        let (value, info) = self.state.pop1_extra()?;
3144                        let value = self.apply_pending_canonicalization(value, info)?;
3145                        phi.add_incoming(&[(&value, current_block)]);
3146                    }
3147
3148                    err!(self.builder.build_unconditional_branch(*frame.code_after()));
3149                }
3150
3151                if let ControlFrame::IfElse {
3152                    if_else,
3153                    next,
3154                    if_else_state: IfElseState::If,
3155                    else_phis,
3156                    ..
3157                } = &frame
3158                {
3159                    for (phi, else_phi) in frame.phis().iter().zip(else_phis.iter()) {
3160                        phi.add_incoming(&[(&else_phi.as_basic_value(), *if_else)]);
3161                    }
3162                    self.builder.position_at_end(*if_else);
3163                    err!(self.builder.build_unconditional_branch(*next));
3164                } else if let ControlFrame::Landingpad { .. } = &frame {
3165                    self.state.pop_landingpad();
3166                };
3167
3168                self.builder.position_at_end(*frame.code_after());
3169                self.state.reset_stack(&frame);
3170
3171                self.state.reachable = true;
3172
3173                // Push each phi value to the value stack.
3174                for phi in frame.phis() {
3175                    if phi.count_incoming() != 0 {
3176                        self.state.push1(phi.as_basic_value());
3177                    } else {
3178                        // TODO if there are no incoming phi values, it means
3179                        // this block has no predecessors, and we can skip it
3180                        // altogether. However, fixing this is non-trivial as
3181                        // some places in the code rely on code getting generated
3182                        // for unreachable end blocks. For now, we let LLVM remove
3183                        // the block during dead code elimination instead.
3184                        let basic_ty = phi.as_basic_value().get_type();
3185                        let placeholder_value = basic_ty.const_zero();
3186                        self.state.push1(placeholder_value);
3187                        phi.as_instruction().erase_from_basic_block();
3188                    }
3189                }
3190            }
3191            Operator::Return => {
3192                let current_block = self
3193                    .builder
3194                    .get_insert_block()
3195                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
3196
3197                let frame = self.state.outermost_frame()?;
3198                for phi in frame.phis().to_vec().iter().rev() {
3199                    let (arg, info) = self.state.pop1_extra()?;
3200                    let arg = self.apply_pending_canonicalization(arg, info)?;
3201                    phi.add_incoming(&[(&arg, current_block)]);
3202                }
3203                let frame = self.state.outermost_frame()?;
3204                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
3205
3206                self.state.reachable = false;
3207            }
3208
3209            Operator::Unreachable => {
3210                self.build_call_with_param_attributes(
3211                    self.intrinsics.throw_trap,
3212                    &[self.intrinsics.trap_unreachable.into()],
3213                    "throw",
3214                )?;
3215                err!(self.builder.build_unreachable());
3216
3217                self.state.reachable = false;
3218            }
3219            _ => unreachable!(),
3220        }
3221
3222        Ok(())
3223    }
3224
3225    // Basic instructions.
3226    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#basic-instructions
3227    fn translate_basic_operator(&mut self, op: Operator) -> Result<(), CompileError> {
3228        let vmctx = &self.ctx.basic().into_pointer_value();
3229
3230        match op {
3231            Operator::Nop => {
3232                // Do nothing.
3233            }
3234            Operator::Drop => {
3235                self.state.pop1()?;
3236            }
3237
3238            // Generate const values.
3239            Operator::I32Const { value } => {
3240                let i = self.intrinsics.i32_ty.const_int(value as u64, false);
3241                let info = if is_f32_arithmetic(value as u32) {
3242                    ExtraInfo::arithmetic_f32()
3243                } else {
3244                    Default::default()
3245                };
3246                self.state.push1_extra(i, info);
3247            }
3248            Operator::I64Const { value } => {
3249                let i = self.intrinsics.i64_ty.const_int(value as u64, false);
3250                let info = if is_f64_arithmetic(value as u64) {
3251                    ExtraInfo::arithmetic_f64()
3252                } else {
3253                    Default::default()
3254                };
3255                self.state.push1_extra(i, info);
3256            }
3257            Operator::F32Const { value } => {
3258                let bits = self.intrinsics.i32_ty.const_int(value.bits() as u64, false);
3259                let info = if is_f32_arithmetic(value.bits()) {
3260                    ExtraInfo::arithmetic_f32()
3261                } else {
3262                    Default::default()
3263                };
3264                let f = err!(
3265                    self.builder
3266                        .build_bit_cast(bits, self.intrinsics.f32_ty, "f")
3267                );
3268                self.state.push1_extra(f, info);
3269            }
3270            Operator::F64Const { value } => {
3271                let bits = self.intrinsics.i64_ty.const_int(value.bits(), false);
3272                let info = if is_f64_arithmetic(value.bits()) {
3273                    ExtraInfo::arithmetic_f64()
3274                } else {
3275                    Default::default()
3276                };
3277                let f = err!(
3278                    self.builder
3279                        .build_bit_cast(bits, self.intrinsics.f64_ty, "f")
3280                );
3281                self.state.push1_extra(f, info);
3282            }
3283            Operator::V128Const { value } => {
3284                let mut hi: [u8; 8] = Default::default();
3285                let mut lo: [u8; 8] = Default::default();
3286                hi.copy_from_slice(&value.bytes()[0..8]);
3287                lo.copy_from_slice(&value.bytes()[8..16]);
3288                let packed = [u64::from_le_bytes(hi), u64::from_le_bytes(lo)];
3289                let i = self
3290                    .intrinsics
3291                    .i128_ty
3292                    .const_int_arbitrary_precision(&packed);
3293                let mut quad1: [u8; 4] = Default::default();
3294                let mut quad2: [u8; 4] = Default::default();
3295                let mut quad3: [u8; 4] = Default::default();
3296                let mut quad4: [u8; 4] = Default::default();
3297                quad1.copy_from_slice(&value.bytes()[0..4]);
3298                quad2.copy_from_slice(&value.bytes()[4..8]);
3299                quad3.copy_from_slice(&value.bytes()[8..12]);
3300                quad4.copy_from_slice(&value.bytes()[12..16]);
3301                let mut info: ExtraInfo = Default::default();
3302                if is_f32_arithmetic(u32::from_le_bytes(quad1))
3303                    && is_f32_arithmetic(u32::from_le_bytes(quad2))
3304                    && is_f32_arithmetic(u32::from_le_bytes(quad3))
3305                    && is_f32_arithmetic(u32::from_le_bytes(quad4))
3306                {
3307                    info |= ExtraInfo::arithmetic_f32();
3308                }
3309                if is_f64_arithmetic(packed[0]) && is_f64_arithmetic(packed[1]) {
3310                    info |= ExtraInfo::arithmetic_f64();
3311                }
3312                self.state.push1_extra(i, info);
3313            }
3314
3315            Operator::I8x16Splat => {
3316                let (v, i) = self.state.pop1_extra()?;
3317                let v = v.into_int_value();
3318                let v = err!(
3319                    self.builder
3320                        .build_int_truncate(v, self.intrinsics.i8_ty, "")
3321                );
3322                let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
3323                let res = err!(
3324                    self.builder
3325                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3326                );
3327                self.state.push1_extra(res, i);
3328            }
3329            Operator::I16x8Splat => {
3330                let (v, i) = self.state.pop1_extra()?;
3331                let v = v.into_int_value();
3332                let v = err!(
3333                    self.builder
3334                        .build_int_truncate(v, self.intrinsics.i16_ty, "")
3335                );
3336                let res = self.splat_vector(v.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
3337                let res = err!(
3338                    self.builder
3339                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3340                );
3341                self.state.push1_extra(res, i);
3342            }
3343            Operator::I32x4Splat => {
3344                let (v, i) = self.state.pop1_extra()?;
3345                let res = self.splat_vector(v, self.intrinsics.i32x4_ty)?;
3346                let res = err!(
3347                    self.builder
3348                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3349                );
3350                self.state.push1_extra(res, i);
3351            }
3352            Operator::I64x2Splat => {
3353                let (v, i) = self.state.pop1_extra()?;
3354                let res = self.splat_vector(v, self.intrinsics.i64x2_ty)?;
3355                let res = err!(
3356                    self.builder
3357                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3358                );
3359                self.state.push1_extra(res, i);
3360            }
3361            Operator::F32x4Splat => {
3362                let (v, i) = self.state.pop1_extra()?;
3363                let res = self.splat_vector(v, self.intrinsics.f32x4_ty)?;
3364                let res = err!(
3365                    self.builder
3366                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3367                );
3368                // The spec is unclear, we interpret splat as preserving NaN
3369                // payload bits.
3370                self.state.push1_extra(res, i);
3371            }
3372            Operator::F64x2Splat => {
3373                let (v, i) = self.state.pop1_extra()?;
3374                let res = self.splat_vector(v, self.intrinsics.f64x2_ty)?;
3375                let res = err!(
3376                    self.builder
3377                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
3378                );
3379                // The spec is unclear, we interpret splat as preserving NaN
3380                // payload bits.
3381                self.state.push1_extra(res, i);
3382            }
3383
3384            // Operate on self.locals.
3385            Operator::LocalGet { local_index } => {
3386                let (type_value, pointer_value) = self.locals[local_index as usize];
3387                let v = err!(self.builder.build_load(
3388                    type_value,
3389                    pointer_value,
3390                    &format!("local_{local_index}_get")
3391                ));
3392                tbaa_label(
3393                    self.module,
3394                    self.intrinsics,
3395                    format!("local {local_index}"),
3396                    v.as_instruction_value().unwrap(),
3397                );
3398                self.state.push1(v);
3399            }
3400            Operator::LocalSet { local_index } => {
3401                let pointer_value = self.locals[local_index as usize].1;
3402                let (v, i) = self.state.pop1_extra()?;
3403                let v = self.apply_pending_canonicalization(v, i)?;
3404                let store = err!(self.builder.build_store(pointer_value, v));
3405                tbaa_label(
3406                    self.module,
3407                    self.intrinsics,
3408                    format!("local {local_index}"),
3409                    store,
3410                );
3411            }
3412            Operator::LocalTee { local_index } => {
3413                let pointer_value = self.locals[local_index as usize].1;
3414                let (v, i) = self.state.peek1_extra()?;
3415                let v = self.apply_pending_canonicalization(v, i)?;
3416                let store = err!(self.builder.build_store(pointer_value, v));
3417                tbaa_label(
3418                    self.module,
3419                    self.intrinsics,
3420                    format!("local {local_index}"),
3421                    store,
3422                );
3423            }
3424
3425            Operator::GlobalGet { global_index } => {
3426                let global_index = GlobalIndex::from_u32(global_index);
3427                match self
3428                    .ctx
3429                    .global(global_index, self.intrinsics, self.module)?
3430                {
3431                    GlobalCache::Const { value } => {
3432                        self.state.push1(*value);
3433                    }
3434                    GlobalCache::Mut {
3435                        ptr_to_value,
3436                        value_type,
3437                    } => {
3438                        let value = err!(self.builder.build_load(*value_type, *ptr_to_value, ""));
3439                        tbaa_label(
3440                            self.module,
3441                            self.intrinsics,
3442                            format!("global {}", global_index.as_u32()),
3443                            value.as_instruction_value().unwrap(),
3444                        );
3445                        self.state.push1(value);
3446                    }
3447                }
3448            }
3449            Operator::GlobalSet { global_index } => {
3450                let global_index = GlobalIndex::from_u32(global_index);
3451                match self
3452                    .ctx
3453                    .global(global_index, self.intrinsics, self.module)?
3454                {
3455                    GlobalCache::Const { value: _ } => {
3456                        return Err(CompileError::Codegen(format!(
3457                            "global.set on immutable global index {}",
3458                            global_index.as_u32()
3459                        )));
3460                    }
3461                    GlobalCache::Mut { ptr_to_value, .. } => {
3462                        let ptr_to_value = *ptr_to_value;
3463                        let (value, info) = self.state.pop1_extra()?;
3464                        let value = self.apply_pending_canonicalization(value, info)?;
3465                        let store = err!(self.builder.build_store(ptr_to_value, value));
3466                        tbaa_label(
3467                            self.module,
3468                            self.intrinsics,
3469                            format!("global {}", global_index.as_u32()),
3470                            store,
3471                        );
3472                    }
3473                }
3474            }
3475
3476            // `TypedSelect` must be used for extern refs so ref counting should
3477            // be done with TypedSelect. But otherwise they're the same.
3478            Operator::TypedSelect { .. } | Operator::Select => {
3479                let ((v1, i1), (v2, i2), (cond, _)) = self.state.pop3_extra()?;
3480                // We don't bother canonicalizing 'cond' here because we only
3481                // compare it to zero, and that's invariant under
3482                // canonicalization.
3483
3484                // If the pending bits of v1 and v2 are the same, we can pass
3485                // them along to the result. Otherwise, apply pending
3486                // canonicalization now.
3487                let (v1, i1, v2, i2) = if i1.has_pending_f32_nan() != i2.has_pending_f32_nan()
3488                    || i1.has_pending_f64_nan() != i2.has_pending_f64_nan()
3489                {
3490                    (
3491                        self.apply_pending_canonicalization(v1, i1)?,
3492                        i1.strip_pending(),
3493                        self.apply_pending_canonicalization(v2, i2)?,
3494                        i2.strip_pending(),
3495                    )
3496                } else {
3497                    (v1, i1, v2, i2)
3498                };
3499                let cond_value = err!(self.builder.build_int_compare(
3500                    IntPredicate::NE,
3501                    cond.into_int_value(),
3502                    self.intrinsics.i32_zero,
3503                    "",
3504                ));
3505                let res = err!(self.builder.build_select(cond_value, v1, v2, ""));
3506                let info = {
3507                    let mut info = (i1.strip_pending() & i2.strip_pending())?;
3508                    if i1.has_pending_f32_nan() {
3509                        debug_assert!(i2.has_pending_f32_nan());
3510                        info = (info | ExtraInfo::pending_f32_nan())?;
3511                    }
3512                    if i1.has_pending_f64_nan() {
3513                        debug_assert!(i2.has_pending_f64_nan());
3514                        info = (info | ExtraInfo::pending_f64_nan())?;
3515                    }
3516                    info
3517                };
3518                self.state.push1_extra(res, info);
3519            }
3520            Operator::Call { function_index } | Operator::ReturnCall { function_index } => {
3521                let is_return_call = matches!(op, Operator::ReturnCall { .. });
3522                let func_index = FunctionIndex::from_u32(function_index);
3523                let sigindex = &self.wasm_module.functions[func_index];
3524                let func_type = &self.wasm_module.signatures[*sigindex];
3525
3526                let FunctionCache {
3527                    func,
3528                    llvm_func_type,
3529                    vmctx: callee_vmctx,
3530                    imported_include_m0_param,
3531                    attrs,
3532                } = if let Some(local_func_index) = self.wasm_module.local_func_index(func_index) {
3533                    self.ctx.local_func(
3534                        local_func_index,
3535                        func_index,
3536                        self.intrinsics,
3537                        self.module,
3538                        self.context,
3539                        func_type,
3540                        &CompiledKind::Local(local_func_index, String::new()).linkage_name(),
3541                    )?
3542                } else {
3543                    self.ctx
3544                        .imported_func(func_index, self.intrinsics, self.context, func_type)?
3545                };
3546                let llvm_func_type = *llvm_func_type;
3547                let func = *func;
3548                let callee_vmctx = *callee_vmctx;
3549                let imported_include_m0_param = *imported_include_m0_param;
3550                let attrs = attrs.clone();
3551
3552                /*
3553                let func_ptr = self.llvm.functions.borrow_mut()[&func_index];
3554
3555                (params, func_ptr.as_global_value().as_pointer_value())
3556                */
3557                let params = self.state.popn_save_extra(func_type.params().len())?;
3558
3559                // Apply pending canonicalization.
3560                let params = params
3561                    .iter()
3562                    .zip(func_type.params().iter())
3563                    .map(|((v, info), wasm_ty)| match wasm_ty {
3564                        Type::F32 => err_nt!(self.builder.build_bit_cast(
3565                            self.apply_pending_canonicalization(*v, *info)?,
3566                            self.intrinsics.f32_ty,
3567                            "",
3568                        )),
3569                        Type::F64 => err_nt!(self.builder.build_bit_cast(
3570                            self.apply_pending_canonicalization(*v, *info)?,
3571                            self.intrinsics.f64_ty,
3572                            "",
3573                        )),
3574                        Type::V128 => self.apply_pending_canonicalization(*v, *info),
3575                        _ => Ok(*v),
3576                    })
3577                    .collect::<Result<Vec<_>, _>>()?;
3578
3579                if let (Some(m0_param), Some(include_m0_param)) =
3580                    (self.m0_param, imported_include_m0_param)
3581                {
3582                    /* For imported functions, we must be careful about when to include `g0_param`:
3583                    imports from another Wasm module expect it, while host-function imports do not.
3584                    We intentionally not leverage tail-calls for such function calls. */
3585                    let (llvm_func_type_no_m0, llvm_func_attrs_no_m0) =
3586                        self.abi.func_type_to_llvm(
3587                            self.context,
3588                            self.intrinsics,
3589                            Some(self.ctx.get_offsets()),
3590                            func_type,
3591                            false,
3592                        )?;
3593                    let params_with_m0 = self.abi.args_to_call(
3594                        &self.alloca_builder,
3595                        func_type,
3596                        &llvm_func_type,
3597                        callee_vmctx.into_pointer_value(),
3598                        params.as_slice(),
3599                        self.intrinsics,
3600                        Some(m0_param),
3601                        is_return_call
3602                            .then(|| self.current_sret_ptr(func_type))
3603                            .flatten(),
3604                    )?;
3605                    let params_no_m0 = self.abi.args_to_call(
3606                        &self.alloca_builder,
3607                        func_type,
3608                        &llvm_func_type_no_m0,
3609                        callee_vmctx.into_pointer_value(),
3610                        params.as_slice(),
3611                        self.intrinsics,
3612                        None,
3613                        is_return_call
3614                            .then(|| self.current_sret_ptr(func_type))
3615                            .flatten(),
3616                    )?;
3617
3618                    let include_m0_call_block = self
3619                        .context
3620                        .append_basic_block(self.function, "call_block_with_m0");
3621                    let skip_m0_call_block =
3622                        self.context.append_basic_block(self.function, "call_block");
3623                    let call_cont = self.context.append_basic_block(self.function, "call_cont");
3624                    err!(self.builder.build_conditional_branch(
3625                        include_m0_param,
3626                        include_m0_call_block,
3627                        skip_m0_call_block,
3628                    ));
3629
3630                    self.builder.position_at_end(include_m0_call_block);
3631                    let call_site_with_m0 = self.build_indirect_call_or_invoke(
3632                        llvm_func_type,
3633                        func,
3634                        params_with_m0.as_slice(),
3635                        "then_block_with_m0",
3636                        is_return_call,
3637                    )?;
3638                    for (attr, attr_loc) in &attrs {
3639                        call_site_with_m0.add_attribute(*attr_loc, *attr);
3640                    }
3641                    let rets_with_m0 = self.abi.rets_from_call(
3642                        &self.builder,
3643                        self.intrinsics,
3644                        call_site_with_m0,
3645                        func_type,
3646                    )?;
3647                    let with_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3648                        CompileError::Codegen(
3649                            "missing insertion block after call with m0".to_string(),
3650                        )
3651                    })?;
3652                    err!(self.builder.build_unconditional_branch(call_cont));
3653
3654                    self.builder.position_at_end(skip_m0_call_block);
3655                    let call_site_no_m0 = self.build_indirect_call_or_invoke(
3656                        llvm_func_type_no_m0,
3657                        func,
3658                        params_no_m0.as_slice(),
3659                        "then_block",
3660                        is_return_call,
3661                    )?;
3662                    for (attr, attr_loc) in &llvm_func_attrs_no_m0 {
3663                        call_site_no_m0.add_attribute(*attr_loc, *attr);
3664                    }
3665                    let rets_no_m0 = self.abi.rets_from_call(
3666                        &self.builder,
3667                        self.intrinsics,
3668                        call_site_no_m0,
3669                        func_type,
3670                    )?;
3671                    let no_m0_pred = self.builder.get_insert_block().ok_or_else(|| {
3672                        CompileError::Codegen(
3673                            "missing insertion block after call without m0".to_string(),
3674                        )
3675                    })?;
3676                    err!(self.builder.build_unconditional_branch(call_cont));
3677
3678                    self.builder.position_at_end(call_cont);
3679                    for i in 0..rets_with_m0.len() {
3680                        let with_m0 = rets_with_m0[i];
3681                        let no_m0 = rets_no_m0[i];
3682                        let phi = err!(self.builder.build_phi(with_m0.get_type(), ""));
3683                        phi.add_incoming(&[(&with_m0, with_m0_pred), (&no_m0, no_m0_pred)]);
3684                        self.state.push1(phi.as_basic_value());
3685                    }
3686                } else {
3687                    let params = self.abi.args_to_call(
3688                        &self.alloca_builder,
3689                        func_type,
3690                        &llvm_func_type,
3691                        callee_vmctx.into_pointer_value(),
3692                        params.as_slice(),
3693                        self.intrinsics,
3694                        self.m0_param,
3695                        if is_return_call {
3696                            self.current_sret_ptr(func_type)
3697                        } else {
3698                            None
3699                        },
3700                    )?;
3701
3702                    let call_site = self.build_indirect_call_or_invoke(
3703                        llvm_func_type,
3704                        func,
3705                        params.as_slice(),
3706                        "then_block",
3707                        is_return_call,
3708                    )?;
3709                    for (attr, attr_loc) in attrs {
3710                        call_site.add_attribute(attr_loc, attr);
3711                    }
3712
3713                    if is_return_call {
3714                        self.emit_return_call(call_site, llvm_func_type)?;
3715                        self.state.reachable = false;
3716                    } else {
3717                        self.abi
3718                            .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
3719                            .iter()
3720                            .for_each(|ret| self.state.push1(*ret));
3721                    }
3722                }
3723            }
3724            Operator::CallIndirect {
3725                type_index,
3726                table_index,
3727            }
3728            | Operator::ReturnCallIndirect {
3729                type_index,
3730                table_index,
3731            } => {
3732                let is_return_call = matches!(op, Operator::ReturnCallIndirect { .. });
3733                let sigindex = SignatureIndex::from_u32(type_index);
3734                let table_index = TableIndex::from_u32(table_index);
3735                let func_type = &self.wasm_module.signatures[sigindex];
3736                let table = self.wasm_module.tables.get(table_index).unwrap();
3737                let local_fixed_funcref_table = self
3738                    .wasm_module
3739                    .local_table_index(table_index)
3740                    .filter(|_| table.is_fixed_funcref_table());
3741                let expected_signature_hash = self
3742                    .intrinsics
3743                    .i32_ty
3744                    .const_int(u64::from(self.signature_hashes[sigindex].as_u32()), false);
3745
3746                let func_index = self.state.pop1()?.into_int_value();
3747                let generic_table = if local_fixed_funcref_table.is_none() {
3748                    Some(self.ctx.table(
3749                        table_index,
3750                        self.intrinsics,
3751                        self.module,
3752                        &self.builder,
3753                    )?)
3754                } else {
3755                    None
3756                };
3757
3758                let table_bound = if local_fixed_funcref_table.is_some() {
3759                    self.intrinsics
3760                        .i32_ty
3761                        .const_int(table.minimum.into(), false)
3762                } else {
3763                    let (_, table_bound) = *generic_table.as_ref().unwrap();
3764                    err!(self.builder.build_int_truncate(
3765                        table_bound,
3766                        self.intrinsics.i32_ty,
3767                        "truncated_table_bounds",
3768                    ))
3769                };
3770
3771                // First, check if the index is outside of the table bounds.
3772                let index_in_bounds = err!(self.builder.build_int_compare(
3773                    IntPredicate::ULT,
3774                    func_index,
3775                    table_bound,
3776                    "index_in_bounds",
3777                ));
3778
3779                let index_in_bounds = self
3780                    .build_call_with_param_attributes(
3781                        self.intrinsics.expect_i1,
3782                        &[
3783                            index_in_bounds.into(),
3784                            self.intrinsics.i1_ty.const_int(1, false).into(),
3785                        ],
3786                        "index_in_bounds_expect",
3787                    )?
3788                    .try_as_basic_value()
3789                    .unwrap_basic()
3790                    .into_int_value();
3791
3792                let in_bounds_continue_block = self
3793                    .context
3794                    .append_basic_block(self.function, "in_bounds_continue_block");
3795                let not_in_bounds_block = self
3796                    .context
3797                    .append_basic_block(self.function, "not_in_bounds_block");
3798                err!(self.builder.build_conditional_branch(
3799                    index_in_bounds,
3800                    in_bounds_continue_block,
3801                    not_in_bounds_block,
3802                ));
3803                self.builder.position_at_end(not_in_bounds_block);
3804                self.build_call_with_param_attributes(
3805                    self.intrinsics.throw_trap,
3806                    &[self.intrinsics.trap_table_access_oob.into()],
3807                    "throw",
3808                )?;
3809                err!(self.builder.build_unreachable());
3810                self.builder.position_at_end(in_bounds_continue_block);
3811
3812                let anyfunc_struct_ptr = if let Some(local_table_index) = local_fixed_funcref_table
3813                {
3814                    let anyfuncs = self.ctx.fixed_funcref_table_anyfuncs(
3815                        local_table_index,
3816                        self.intrinsics,
3817                        &self.builder,
3818                    )?;
3819                    unsafe {
3820                        err!(self.builder.build_in_bounds_gep(
3821                            self.intrinsics.anyfunc_ty,
3822                            anyfuncs,
3823                            &[func_index],
3824                            "anyfunc_struct_ptr",
3825                        ))
3826                    }
3827                } else {
3828                    let (table_base, _) = *generic_table.as_ref().unwrap();
3829
3830                    // We assume the table has the `funcref` (pointer to `anyfunc`)
3831                    // element type.
3832                    let casted_table_base = err!(self.builder.build_pointer_cast(
3833                        table_base,
3834                        self.context.ptr_type(AddressSpace::default()),
3835                        "casted_table_base",
3836                    ));
3837
3838                    let funcref_ptr = unsafe {
3839                        err!(self.builder.build_in_bounds_gep(
3840                            self.intrinsics.ptr_ty,
3841                            casted_table_base,
3842                            &[func_index],
3843                            "funcref_ptr",
3844                        ))
3845                    };
3846
3847                    // a funcref (pointer to `anyfunc`)
3848                    let anyfunc_struct_ptr = err!(self.builder.build_load(
3849                        self.intrinsics.ptr_ty,
3850                        funcref_ptr,
3851                        "anyfunc_struct_ptr",
3852                    ))
3853                    .into_pointer_value();
3854
3855                    if !table.readonly {
3856                        // trap if we're trying to call a null funcref
3857                        let funcref_not_null = err!(
3858                            self.builder
3859                                .build_is_not_null(anyfunc_struct_ptr, "null_funcref_check")
3860                        );
3861
3862                        let funcref_continue_deref_block = self
3863                            .context
3864                            .append_basic_block(self.function, "funcref_continue_deref_block");
3865
3866                        let funcref_is_null_block = self
3867                            .context
3868                            .append_basic_block(self.function, "funcref_is_null_block");
3869                        err!(self.builder.build_conditional_branch(
3870                            funcref_not_null,
3871                            funcref_continue_deref_block,
3872                            funcref_is_null_block,
3873                        ));
3874                        self.builder.position_at_end(funcref_is_null_block);
3875                        self.build_call_with_param_attributes(
3876                            self.intrinsics.throw_trap,
3877                            &[self.intrinsics.trap_call_indirect_null.into()],
3878                            "throw",
3879                        )?;
3880                        err!(self.builder.build_unreachable());
3881                        self.builder.position_at_end(funcref_continue_deref_block);
3882                    }
3883
3884                    anyfunc_struct_ptr
3885                };
3886
3887                // Load things from the anyfunc data structure.
3888                let sig_hash_ptr = self
3889                    .builder
3890                    .build_struct_gep(
3891                        self.intrinsics.anyfunc_ty,
3892                        anyfunc_struct_ptr,
3893                        1,
3894                        "sig_hash_ptr",
3895                    )
3896                    .unwrap();
3897                let func_ptr_ptr = self
3898                    .builder
3899                    .build_struct_gep(
3900                        self.intrinsics.anyfunc_ty,
3901                        anyfunc_struct_ptr,
3902                        0,
3903                        "func_ptr_ptr",
3904                    )
3905                    .unwrap();
3906                let (func_ptr, found_signature_hash) = (
3907                    err!(
3908                        self.builder
3909                            .build_load(self.intrinsics.ptr_ty, func_ptr_ptr, "func_ptr")
3910                    )
3911                    .into_pointer_value(),
3912                    err!(
3913                        self.builder
3914                            .build_load(self.intrinsics.i32_ty, sig_hash_ptr, "sig_hash")
3915                    )
3916                    .into_int_value(),
3917                );
3918
3919                // Next, check if the table element is initialized.
3920
3921                // TODO: we may not need this check anymore
3922                let elem_initialized = err!(self.builder.build_is_not_null(func_ptr, ""));
3923
3924                // Next, check if the signature id is correct.
3925
3926                let sig_hashes_equal = err!(self.builder.build_int_compare(
3927                    IntPredicate::EQ,
3928                    expected_signature_hash,
3929                    found_signature_hash,
3930                    "sig_hashes_equal",
3931                ));
3932
3933                let initialized_and_sig_hashes_match = err!(self.builder.build_and(
3934                    elem_initialized,
3935                    sig_hashes_equal,
3936                    ""
3937                ));
3938
3939                // Tell llvm that the expected and found signature hashes should match.
3940                let initialized_and_sig_hashes_match = self
3941                    .build_call_with_param_attributes(
3942                        self.intrinsics.expect_i1,
3943                        &[
3944                            initialized_and_sig_hashes_match.into(),
3945                            self.intrinsics.i1_ty.const_int(1, false).into(),
3946                        ],
3947                        "initialized_and_sig_hashes_match_expect",
3948                    )?
3949                    .try_as_basic_value()
3950                    .unwrap_basic()
3951                    .into_int_value();
3952
3953                let continue_block = self
3954                    .context
3955                    .append_basic_block(self.function, "continue_block");
3956                let sighashes_notequal_block = self
3957                    .context
3958                    .append_basic_block(self.function, "sighashes_notequal_block");
3959                err!(self.builder.build_conditional_branch(
3960                    initialized_and_sig_hashes_match,
3961                    continue_block,
3962                    sighashes_notequal_block,
3963                ));
3964
3965                self.builder.position_at_end(sighashes_notequal_block);
3966                let trap_code = err!(self.builder.build_select(
3967                    elem_initialized,
3968                    self.intrinsics.trap_call_indirect_sig,
3969                    self.intrinsics.trap_call_indirect_null,
3970                    "",
3971                ));
3972                self.build_call_with_param_attributes(
3973                    self.intrinsics.throw_trap,
3974                    &[trap_code.into()],
3975                    "throw",
3976                )?;
3977                err!(self.builder.build_unreachable());
3978                self.builder.position_at_end(continue_block);
3979
3980                let callee_vmctx = if table.readonly {
3981                    *vmctx
3982                } else {
3983                    let ctx_ptr_ptr = self
3984                        .builder
3985                        .build_struct_gep(
3986                            self.intrinsics.anyfunc_ty,
3987                            anyfunc_struct_ptr,
3988                            2,
3989                            "ctx_ptr_ptr",
3990                        )
3991                        .unwrap();
3992                    err!(
3993                        self.builder
3994                            .build_load(self.intrinsics.ptr_ty, ctx_ptr_ptr, "ctx_ptr")
3995                    )
3996                    .into_pointer_value()
3997                };
3998
3999                if self.m0_param.is_some() {
4000                    self.build_m0_indirect_call(
4001                        table_index.as_u32(),
4002                        callee_vmctx,
4003                        func_type,
4004                        func_ptr,
4005                        func_index,
4006                        is_return_call,
4007                    )?;
4008                } else {
4009                    let (call_site, llvm_func_type) = self.build_indirect_call(
4010                        callee_vmctx,
4011                        func_type,
4012                        func_ptr,
4013                        None,
4014                        is_return_call,
4015                    )?;
4016
4017                    if is_return_call {
4018                        self.emit_return_call(call_site, llvm_func_type)?;
4019                    } else {
4020                        self.abi
4021                            .rets_from_call(&self.builder, self.intrinsics, call_site, func_type)?
4022                            .iter()
4023                            .for_each(|ret| self.state.push1(*ret));
4024                    }
4025                }
4026
4027                if is_return_call {
4028                    self.state.reachable = false;
4029                }
4030            }
4031            _ => unreachable!(),
4032        }
4033        Ok(())
4034    }
4035
4036    // Integer Arithmetic instructions.
4037    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-arithmetic-instructions
4038    fn translate_integer_arithmetic_operator(&mut self, op: Operator) -> Result<(), CompileError> {
4039        match op {
4040            Operator::I32Add | Operator::I64Add => {
4041                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4042                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4043                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4044                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4045                let res = err!(self.builder.build_int_add(v1, v2, ""));
4046                self.state.push1(res);
4047            }
4048            Operator::I8x16Add => {
4049                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4050                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4051                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4052                let res = err!(self.builder.build_int_add(v1, v2, ""));
4053                let res = err!(
4054                    self.builder
4055                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4056                );
4057                self.state.push1(res);
4058            }
4059            Operator::I16x8Add => {
4060                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4061                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4062                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4063                let res = err!(self.builder.build_int_add(v1, v2, ""));
4064                let res = err!(
4065                    self.builder
4066                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4067                );
4068                self.state.push1(res);
4069            }
4070            Operator::I16x8ExtAddPairwiseI8x16S | Operator::I16x8ExtAddPairwiseI8x16U => {
4071                let extend_op = match op {
4072                    Operator::I16x8ExtAddPairwiseI8x16S => {
4073                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, "")
4074                    }
4075                    Operator::I16x8ExtAddPairwiseI8x16U => {
4076                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, "")
4077                    }
4078                    _ => unreachable!("Unhandled internal variant"),
4079                };
4080                let (v, i) = self.state.pop1_extra()?;
4081                let (v, _) = self.v128_into_i8x16(v, i)?;
4082
4083                let left = err!(self.builder.build_shuffle_vector(
4084                    v,
4085                    v.get_type().get_undef(),
4086                    VectorType::const_vector(&[
4087                        self.intrinsics.i32_consts[0],
4088                        self.intrinsics.i32_consts[2],
4089                        self.intrinsics.i32_consts[4],
4090                        self.intrinsics.i32_consts[6],
4091                        self.intrinsics.i32_consts[8],
4092                        self.intrinsics.i32_consts[10],
4093                        self.intrinsics.i32_consts[12],
4094                        self.intrinsics.i32_consts[14],
4095                    ]),
4096                    "",
4097                ));
4098                let left = err!(extend_op(self, left));
4099                let right = err!(self.builder.build_shuffle_vector(
4100                    v,
4101                    v.get_type().get_undef(),
4102                    VectorType::const_vector(&[
4103                        self.intrinsics.i32_consts[1],
4104                        self.intrinsics.i32_consts[3],
4105                        self.intrinsics.i32_consts[5],
4106                        self.intrinsics.i32_consts[7],
4107                        self.intrinsics.i32_consts[9],
4108                        self.intrinsics.i32_consts[11],
4109                        self.intrinsics.i32_consts[13],
4110                        self.intrinsics.i32_consts[15],
4111                    ]),
4112                    "",
4113                ));
4114                let right = err!(extend_op(self, right));
4115
4116                let res = err!(self.builder.build_int_add(left, right, ""));
4117                let res = err!(
4118                    self.builder
4119                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4120                );
4121                self.state.push1(res);
4122            }
4123            Operator::I32x4Add => {
4124                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4125                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4126                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4127                let res = err!(self.builder.build_int_add(v1, v2, ""));
4128                let res = err!(
4129                    self.builder
4130                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4131                );
4132                self.state.push1(res);
4133            }
4134            Operator::I32x4ExtAddPairwiseI16x8S | Operator::I32x4ExtAddPairwiseI16x8U => {
4135                let extend_op = match op {
4136                    Operator::I32x4ExtAddPairwiseI16x8S => {
4137                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
4138                    }
4139                    Operator::I32x4ExtAddPairwiseI16x8U => {
4140                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
4141                    }
4142                    _ => unreachable!("Unhandled internal variant"),
4143                };
4144                let (v, i) = self.state.pop1_extra()?;
4145                let (v, _) = self.v128_into_i16x8(v, i)?;
4146
4147                let left = err!(self.builder.build_shuffle_vector(
4148                    v,
4149                    v.get_type().get_undef(),
4150                    VectorType::const_vector(&[
4151                        self.intrinsics.i32_consts[0],
4152                        self.intrinsics.i32_consts[2],
4153                        self.intrinsics.i32_consts[4],
4154                        self.intrinsics.i32_consts[6],
4155                    ]),
4156                    "",
4157                ));
4158                let left = err!(extend_op(self, left));
4159                let right = err!(self.builder.build_shuffle_vector(
4160                    v,
4161                    v.get_type().get_undef(),
4162                    VectorType::const_vector(&[
4163                        self.intrinsics.i32_consts[1],
4164                        self.intrinsics.i32_consts[3],
4165                        self.intrinsics.i32_consts[5],
4166                        self.intrinsics.i32_consts[7],
4167                    ]),
4168                    "",
4169                ));
4170                let right = err!(extend_op(self, right));
4171
4172                let res = err!(self.builder.build_int_add(left, right, ""));
4173                let res = err!(
4174                    self.builder
4175                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4176                );
4177                self.state.push1(res);
4178            }
4179            Operator::I64x2Add => {
4180                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4181                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4182                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4183                let res = err!(self.builder.build_int_add(v1, v2, ""));
4184                let res = err!(
4185                    self.builder
4186                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4187                );
4188                self.state.push1(res);
4189            }
4190            Operator::I8x16AddSatS => {
4191                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4192                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4193                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4194                let res = self
4195                    .build_call_with_param_attributes(
4196                        self.intrinsics.sadd_sat_i8x16,
4197                        &[v1.into(), v2.into()],
4198                        "",
4199                    )?
4200                    .try_as_basic_value()
4201                    .unwrap_basic();
4202                let res = err!(
4203                    self.builder
4204                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4205                );
4206                self.state.push1(res);
4207            }
4208            Operator::I16x8AddSatS => {
4209                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4210                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4211                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4212                let res = self
4213                    .build_call_with_param_attributes(
4214                        self.intrinsics.sadd_sat_i16x8,
4215                        &[v1.into(), v2.into()],
4216                        "",
4217                    )?
4218                    .try_as_basic_value()
4219                    .unwrap_basic();
4220                let res = err!(
4221                    self.builder
4222                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4223                );
4224                self.state.push1(res);
4225            }
4226            Operator::I8x16AddSatU => {
4227                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4228                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4229                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4230                let res = self
4231                    .build_call_with_param_attributes(
4232                        self.intrinsics.uadd_sat_i8x16,
4233                        &[v1.into(), v2.into()],
4234                        "",
4235                    )?
4236                    .try_as_basic_value()
4237                    .unwrap_basic();
4238                let res = err!(
4239                    self.builder
4240                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4241                );
4242                self.state.push1(res);
4243            }
4244            Operator::I16x8AddSatU => {
4245                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4246                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4247                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4248                let res = self
4249                    .build_call_with_param_attributes(
4250                        self.intrinsics.uadd_sat_i16x8,
4251                        &[v1.into(), v2.into()],
4252                        "",
4253                    )?
4254                    .try_as_basic_value()
4255                    .unwrap_basic();
4256                let res = err!(
4257                    self.builder
4258                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4259                );
4260                self.state.push1(res);
4261            }
4262            Operator::I32Sub | Operator::I64Sub => {
4263                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4264                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4265                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4266                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4267                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4268                self.state.push1(res);
4269            }
4270            Operator::I8x16Sub => {
4271                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4272                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4273                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4274                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4275                let res = err!(
4276                    self.builder
4277                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4278                );
4279                self.state.push1(res);
4280            }
4281            Operator::I16x8Sub => {
4282                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4283                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4284                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4285                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4286                let res = err!(
4287                    self.builder
4288                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4289                );
4290                self.state.push1(res);
4291            }
4292            Operator::I32x4Sub => {
4293                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4294                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4295                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4296                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4297                let res = err!(
4298                    self.builder
4299                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4300                );
4301                self.state.push1(res);
4302            }
4303            Operator::I64x2Sub => {
4304                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4305                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4306                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4307                let res = err!(self.builder.build_int_sub(v1, v2, ""));
4308                let res = err!(
4309                    self.builder
4310                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4311                );
4312                self.state.push1(res);
4313            }
4314            Operator::I8x16SubSatS => {
4315                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4316                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4317                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4318                let res = self
4319                    .build_call_with_param_attributes(
4320                        self.intrinsics.ssub_sat_i8x16,
4321                        &[v1.into(), v2.into()],
4322                        "",
4323                    )?
4324                    .try_as_basic_value()
4325                    .unwrap_basic();
4326                let res = err!(
4327                    self.builder
4328                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4329                );
4330                self.state.push1(res);
4331            }
4332            Operator::I16x8SubSatS => {
4333                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4334                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4335                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4336                let res = self
4337                    .build_call_with_param_attributes(
4338                        self.intrinsics.ssub_sat_i16x8,
4339                        &[v1.into(), v2.into()],
4340                        "",
4341                    )?
4342                    .try_as_basic_value()
4343                    .unwrap_basic();
4344                let res = err!(
4345                    self.builder
4346                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4347                );
4348                self.state.push1(res);
4349            }
4350            Operator::I8x16SubSatU => {
4351                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4352                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4353                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4354                let res = self
4355                    .build_call_with_param_attributes(
4356                        self.intrinsics.usub_sat_i8x16,
4357                        &[v1.into(), v2.into()],
4358                        "",
4359                    )?
4360                    .try_as_basic_value()
4361                    .unwrap_basic();
4362                let res = err!(
4363                    self.builder
4364                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4365                );
4366                self.state.push1(res);
4367            }
4368            Operator::I16x8SubSatU => {
4369                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4370                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4371                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4372                let res = self
4373                    .build_call_with_param_attributes(
4374                        self.intrinsics.usub_sat_i16x8,
4375                        &[v1.into(), v2.into()],
4376                        "",
4377                    )?
4378                    .try_as_basic_value()
4379                    .unwrap_basic();
4380                let res = err!(
4381                    self.builder
4382                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4383                );
4384                self.state.push1(res);
4385            }
4386            Operator::I32Mul | Operator::I64Mul => {
4387                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4388                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4389                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4390                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4391                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4392                self.state.push1(res);
4393            }
4394            Operator::I16x8Mul => {
4395                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4396                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4397                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4398                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4399                let res = err!(
4400                    self.builder
4401                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4402                );
4403                self.state.push1(res);
4404            }
4405            Operator::I32x4Mul => {
4406                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4407                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4408                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4409                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4410                let res = err!(
4411                    self.builder
4412                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4413                );
4414                self.state.push1(res);
4415            }
4416            Operator::I64x2Mul => {
4417                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4418                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
4419                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
4420                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4421                let res = err!(
4422                    self.builder
4423                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4424                );
4425                self.state.push1(res);
4426            }
4427            Operator::I16x8RelaxedQ15mulrS if self.cpu_features.contains(CpuFeature::SSSE3) => {
4428                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4429                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4430                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4431                let res = self
4432                    .build_call_with_param_attributes(
4433                        self.intrinsics.x86_64.pmulhrsw128,
4434                        &[v1.into(), v2.into()],
4435                        "",
4436                    )?
4437                    .try_as_basic_value()
4438                    .unwrap_basic();
4439                let res = err!(
4440                    self.builder
4441                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4442                );
4443                self.state.push1(res);
4444            }
4445            Operator::I16x8Q15MulrSatS | Operator::I16x8RelaxedQ15mulrS => {
4446                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4447                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4448                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4449
4450                let max_value = self.intrinsics.i16_ty.const_int(i16::MAX as u64, false);
4451                let max_values = VectorType::const_vector(&[max_value; 8]);
4452
4453                let v1 = err!(
4454                    self.builder
4455                        .build_int_s_extend(v1, self.intrinsics.i32x8_ty, "")
4456                );
4457                let v2 = err!(
4458                    self.builder
4459                        .build_int_s_extend(v2, self.intrinsics.i32x8_ty, "")
4460                );
4461                let res = err!(self.builder.build_int_mul(v1, v2, ""));
4462
4463                // magic number specified by the spec
4464                let bit = self.intrinsics.i32_ty.const_int(0x4000, false);
4465                let bits = VectorType::const_vector(&[bit; 8]);
4466
4467                let res = err!(self.builder.build_int_add(res, bits, ""));
4468
4469                let fifteen = self.intrinsics.i32_consts[15];
4470                let fifteens = VectorType::const_vector(&[fifteen; 8]);
4471
4472                let res = err!(self.builder.build_right_shift(res, fifteens, true, ""));
4473                let saturate_up = {
4474                    let max_values = err!(self.builder.build_int_s_extend(
4475                        max_values,
4476                        self.intrinsics.i32x8_ty,
4477                        ""
4478                    ));
4479                    err!(
4480                        self.builder
4481                            .build_int_compare(IntPredicate::SGT, res, max_values, "")
4482                    )
4483                };
4484
4485                let res = err!(
4486                    self.builder
4487                        .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
4488                );
4489
4490                let res = err!(self.builder.build_select(saturate_up, max_values, res, ""))
4491                    .into_vector_value();
4492                let res = err!(
4493                    self.builder
4494                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4495                );
4496                self.state.push1(res);
4497            }
4498            Operator::I16x8ExtMulLowI8x16S
4499            | Operator::I16x8ExtMulLowI8x16U
4500            | Operator::I16x8ExtMulHighI8x16S
4501            | Operator::I16x8ExtMulHighI8x16U => {
4502                let extend_op = match op {
4503                    Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulHighI8x16S => {
4504                        |s: &Self, v| -> Result<VectorValue, CompileError> {
4505                            err_nt!(s.builder.build_int_s_extend(v, s.intrinsics.i16x8_ty, ""))
4506                        }
4507                    }
4508                    Operator::I16x8ExtMulLowI8x16U | Operator::I16x8ExtMulHighI8x16U => {
4509                        |s: &Self, v| -> Result<VectorValue, CompileError> {
4510                            err_nt!(s.builder.build_int_z_extend(v, s.intrinsics.i16x8_ty, ""))
4511                        }
4512                    }
4513                    _ => unreachable!("Unhandled internal variant"),
4514                };
4515                let shuffle_array = match op {
4516                    Operator::I16x8ExtMulLowI8x16S | Operator::I16x8ExtMulLowI8x16U => [
4517                        self.intrinsics.i32_consts[0],
4518                        self.intrinsics.i32_consts[1],
4519                        self.intrinsics.i32_consts[2],
4520                        self.intrinsics.i32_consts[3],
4521                        self.intrinsics.i32_consts[4],
4522                        self.intrinsics.i32_consts[5],
4523                        self.intrinsics.i32_consts[6],
4524                        self.intrinsics.i32_consts[7],
4525                    ],
4526                    Operator::I16x8ExtMulHighI8x16S | Operator::I16x8ExtMulHighI8x16U => [
4527                        self.intrinsics.i32_consts[8],
4528                        self.intrinsics.i32_consts[9],
4529                        self.intrinsics.i32_consts[10],
4530                        self.intrinsics.i32_consts[11],
4531                        self.intrinsics.i32_consts[12],
4532                        self.intrinsics.i32_consts[13],
4533                        self.intrinsics.i32_consts[14],
4534                        self.intrinsics.i32_consts[15],
4535                    ],
4536                    _ => unreachable!("Unhandled internal variant"),
4537                };
4538                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4539                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4540                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4541                let val1 = err!(self.builder.build_shuffle_vector(
4542                    v1,
4543                    v1.get_type().get_undef(),
4544                    VectorType::const_vector(&shuffle_array),
4545                    "",
4546                ));
4547                let val1 = err!(extend_op(self, val1));
4548                let val2 = err!(self.builder.build_shuffle_vector(
4549                    v2,
4550                    v2.get_type().get_undef(),
4551                    VectorType::const_vector(&shuffle_array),
4552                    "",
4553                ));
4554                let val2 = err!(extend_op(self, val2));
4555                let res = err!(self.builder.build_int_mul(val1, val2, ""));
4556                let res = err!(
4557                    self.builder
4558                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4559                );
4560                self.state.push1(res);
4561            }
4562            Operator::I32x4ExtMulLowI16x8S
4563            | Operator::I32x4ExtMulLowI16x8U
4564            | Operator::I32x4ExtMulHighI16x8S
4565            | Operator::I32x4ExtMulHighI16x8U => {
4566                let extend_op = match op {
4567                    Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulHighI16x8S => {
4568                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
4569                    }
4570                    Operator::I32x4ExtMulLowI16x8U | Operator::I32x4ExtMulHighI16x8U => {
4571                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
4572                    }
4573                    _ => unreachable!("Unhandled internal variant"),
4574                };
4575                let shuffle_array = match op {
4576                    Operator::I32x4ExtMulLowI16x8S | Operator::I32x4ExtMulLowI16x8U => [
4577                        self.intrinsics.i32_consts[0],
4578                        self.intrinsics.i32_consts[1],
4579                        self.intrinsics.i32_consts[2],
4580                        self.intrinsics.i32_consts[3],
4581                    ],
4582                    Operator::I32x4ExtMulHighI16x8S | Operator::I32x4ExtMulHighI16x8U => [
4583                        self.intrinsics.i32_consts[4],
4584                        self.intrinsics.i32_consts[5],
4585                        self.intrinsics.i32_consts[6],
4586                        self.intrinsics.i32_consts[7],
4587                    ],
4588                    _ => unreachable!("Unhandled internal variant"),
4589                };
4590                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4591                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4592                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4593                let val1 = err!(self.builder.build_shuffle_vector(
4594                    v1,
4595                    v1.get_type().get_undef(),
4596                    VectorType::const_vector(&shuffle_array),
4597                    "",
4598                ));
4599                let val1 = err!(extend_op(self, val1));
4600                let val2 = err!(self.builder.build_shuffle_vector(
4601                    v2,
4602                    v2.get_type().get_undef(),
4603                    VectorType::const_vector(&shuffle_array),
4604                    "",
4605                ));
4606                let val2 = err!(extend_op(self, val2));
4607                let res = err!(self.builder.build_int_mul(val1, val2, ""));
4608                let res = err!(
4609                    self.builder
4610                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4611                );
4612                self.state.push1(res);
4613            }
4614            Operator::I64x2ExtMulLowI32x4S
4615            | Operator::I64x2ExtMulLowI32x4U
4616            | Operator::I64x2ExtMulHighI32x4S
4617            | Operator::I64x2ExtMulHighI32x4U => {
4618                let extend_op = match op {
4619                    Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulHighI32x4S => {
4620                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
4621                    }
4622                    Operator::I64x2ExtMulLowI32x4U | Operator::I64x2ExtMulHighI32x4U => {
4623                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
4624                    }
4625                    _ => unreachable!("Unhandled internal variant"),
4626                };
4627                let shuffle_array = match op {
4628                    Operator::I64x2ExtMulLowI32x4S | Operator::I64x2ExtMulLowI32x4U => {
4629                        [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
4630                    }
4631                    Operator::I64x2ExtMulHighI32x4S | Operator::I64x2ExtMulHighI32x4U => {
4632                        [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
4633                    }
4634                    _ => unreachable!("Unhandled internal variant"),
4635                };
4636                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4637                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
4638                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
4639                let val1 = err!(self.builder.build_shuffle_vector(
4640                    v1,
4641                    v1.get_type().get_undef(),
4642                    VectorType::const_vector(&shuffle_array),
4643                    "",
4644                ));
4645                let val1 = err!(extend_op(self, val1));
4646                let val2 = err!(self.builder.build_shuffle_vector(
4647                    v2,
4648                    v2.get_type().get_undef(),
4649                    VectorType::const_vector(&shuffle_array),
4650                    "",
4651                ));
4652                let val2 = err!(extend_op(self, val2));
4653                let res = err!(self.builder.build_int_mul(val1, val2, ""));
4654                let res = err!(
4655                    self.builder
4656                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4657                );
4658                self.state.push1(res);
4659            }
4660            Operator::I32x4DotI16x8S => {
4661                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4662                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
4663                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
4664                let low_i16 = [
4665                    self.intrinsics.i32_consts[0],
4666                    self.intrinsics.i32_consts[2],
4667                    self.intrinsics.i32_consts[4],
4668                    self.intrinsics.i32_consts[6],
4669                ];
4670                let high_i16 = [
4671                    self.intrinsics.i32_consts[1],
4672                    self.intrinsics.i32_consts[3],
4673                    self.intrinsics.i32_consts[5],
4674                    self.intrinsics.i32_consts[7],
4675                ];
4676                let v1_low = err!(self.builder.build_shuffle_vector(
4677                    v1,
4678                    v1.get_type().get_undef(),
4679                    VectorType::const_vector(&low_i16),
4680                    "",
4681                ));
4682                let v1_low = err!(self.builder.build_int_s_extend(
4683                    v1_low,
4684                    self.intrinsics.i32x4_ty,
4685                    ""
4686                ));
4687                let v1_high = err!(self.builder.build_shuffle_vector(
4688                    v1,
4689                    v1.get_type().get_undef(),
4690                    VectorType::const_vector(&high_i16),
4691                    "",
4692                ));
4693                let v1_high = err!(self.builder.build_int_s_extend(
4694                    v1_high,
4695                    self.intrinsics.i32x4_ty,
4696                    ""
4697                ));
4698                let v2_low = err!(self.builder.build_shuffle_vector(
4699                    v2,
4700                    v2.get_type().get_undef(),
4701                    VectorType::const_vector(&low_i16),
4702                    "",
4703                ));
4704                let v2_low = err!(self.builder.build_int_s_extend(
4705                    v2_low,
4706                    self.intrinsics.i32x4_ty,
4707                    ""
4708                ));
4709                let v2_high = err!(self.builder.build_shuffle_vector(
4710                    v2,
4711                    v2.get_type().get_undef(),
4712                    VectorType::const_vector(&high_i16),
4713                    "",
4714                ));
4715                let v2_high = err!(self.builder.build_int_s_extend(
4716                    v2_high,
4717                    self.intrinsics.i32x4_ty,
4718                    ""
4719                ));
4720                let low_product = err!(self.builder.build_int_mul(v1_low, v2_low, ""));
4721                let high_product = err!(self.builder.build_int_mul(v1_high, v2_high, ""));
4722
4723                let res = err!(self.builder.build_int_add(low_product, high_product, ""));
4724                let res = err!(
4725                    self.builder
4726                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4727                );
4728                self.state.push1(res);
4729            }
4730            Operator::I16x8RelaxedDotI8x16I7x16S
4731                if self.cpu_features.contains(CpuFeature::SSSE3) =>
4732            {
4733                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4734                let (a, _) = self.v128_into_i8x16(v1, i1)?;
4735                let (b, _) = self.v128_into_i8x16(v2, i2)?;
4736
4737                let res = self
4738                    .build_call_with_param_attributes(
4739                        self.intrinsics.x86_64.pmaddubsw128,
4740                        &[b.into(), a.into()],
4741                        "",
4742                    )?
4743                    .try_as_basic_value()
4744                    .unwrap_basic()
4745                    .into_vector_value();
4746                let res = err!(
4747                    self.builder
4748                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4749                );
4750                self.state.push1(res);
4751            }
4752            Operator::I16x8RelaxedDotI8x16I7x16S => {
4753                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4754                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4755                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4756
4757                let left_indices = [
4758                    self.intrinsics.i32_consts[0],
4759                    self.intrinsics.i32_consts[2],
4760                    self.intrinsics.i32_consts[4],
4761                    self.intrinsics.i32_consts[6],
4762                    self.intrinsics.i32_consts[8],
4763                    self.intrinsics.i32_consts[10],
4764                    self.intrinsics.i32_consts[12],
4765                    self.intrinsics.i32_consts[14],
4766                ];
4767                let right_indices = [
4768                    self.intrinsics.i32_consts[1],
4769                    self.intrinsics.i32_consts[3],
4770                    self.intrinsics.i32_consts[5],
4771                    self.intrinsics.i32_consts[7],
4772                    self.intrinsics.i32_consts[9],
4773                    self.intrinsics.i32_consts[11],
4774                    self.intrinsics.i32_consts[13],
4775                    self.intrinsics.i32_consts[15],
4776                ];
4777
4778                let v1_left = err!(self.builder.build_shuffle_vector(
4779                    v1,
4780                    v1.get_type().get_undef(),
4781                    VectorType::const_vector(&left_indices),
4782                    "",
4783                ));
4784                let v1_left = err!(self.builder.build_int_s_extend(
4785                    v1_left,
4786                    self.intrinsics.i16x8_ty,
4787                    ""
4788                ));
4789                let v1_right = err!(self.builder.build_shuffle_vector(
4790                    v1,
4791                    v1.get_type().get_undef(),
4792                    VectorType::const_vector(&right_indices),
4793                    "",
4794                ));
4795                let v1_right = err!(self.builder.build_int_s_extend(
4796                    v1_right,
4797                    self.intrinsics.i16x8_ty,
4798                    ""
4799                ));
4800
4801                let v2_left = err!(self.builder.build_shuffle_vector(
4802                    v2,
4803                    v2.get_type().get_undef(),
4804                    VectorType::const_vector(&left_indices),
4805                    "",
4806                ));
4807                let v2_left = err!(self.builder.build_int_s_extend(
4808                    v2_left,
4809                    self.intrinsics.i16x8_ty,
4810                    ""
4811                ));
4812                let v2_right = err!(self.builder.build_shuffle_vector(
4813                    v2,
4814                    v2.get_type().get_undef(),
4815                    VectorType::const_vector(&right_indices),
4816                    "",
4817                ));
4818                let v2_right = err!(self.builder.build_int_s_extend(
4819                    v2_right,
4820                    self.intrinsics.i16x8_ty,
4821                    ""
4822                ));
4823
4824                let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4825                let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4826                let res = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4827                let res = err!(
4828                    self.builder
4829                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4830                );
4831                self.state.push1(res);
4832            }
4833            Operator::I32x4RelaxedDotI8x16I7x16AddS
4834                if self.cpu_features.contains(CpuFeature::SSSE3) =>
4835            {
4836                let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4837                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4838                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4839                let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4840
4841                // PMADDUBSW computes pairwise u8*i8 with i16 saturation, which
4842                // is one of the valid relaxed dot-product behaviors.
4843                let dot16 = self
4844                    .build_call_with_param_attributes(
4845                        self.intrinsics.x86_64.pmaddubsw128,
4846                        &[v2.into(), v1.into()],
4847                        "",
4848                    )?
4849                    .try_as_basic_value()
4850                    .unwrap_basic()
4851                    .into_vector_value();
4852                let ones =
4853                    VectorType::const_vector(&[self.intrinsics.i16_ty.const_int(1, false); 8]);
4854                let dot32 = self
4855                    .build_call_with_param_attributes(
4856                        self.intrinsics.x86_64.pmaddwd128,
4857                        &[dot16.into(), ones.into()],
4858                        "",
4859                    )?
4860                    .try_as_basic_value()
4861                    .unwrap_basic()
4862                    .into_vector_value();
4863                let res = err!(self.builder.build_int_add(dot32, acc, ""));
4864                let res = err!(
4865                    self.builder
4866                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4867                );
4868                self.state.push1(res);
4869            }
4870            Operator::I32x4RelaxedDotI8x16I7x16AddS => {
4871                let ((v1, i1), (v2, i2), (acc, acc_info)) = self.state.pop3_extra()?;
4872                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
4873                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
4874                let (acc, _) = self.v128_into_i32x4(acc, acc_info)?;
4875
4876                let left_indices = [
4877                    self.intrinsics.i32_consts[0],
4878                    self.intrinsics.i32_consts[2],
4879                    self.intrinsics.i32_consts[4],
4880                    self.intrinsics.i32_consts[6],
4881                    self.intrinsics.i32_consts[8],
4882                    self.intrinsics.i32_consts[10],
4883                    self.intrinsics.i32_consts[12],
4884                    self.intrinsics.i32_consts[14],
4885                ];
4886                let right_indices = [
4887                    self.intrinsics.i32_consts[1],
4888                    self.intrinsics.i32_consts[3],
4889                    self.intrinsics.i32_consts[5],
4890                    self.intrinsics.i32_consts[7],
4891                    self.intrinsics.i32_consts[9],
4892                    self.intrinsics.i32_consts[11],
4893                    self.intrinsics.i32_consts[13],
4894                    self.intrinsics.i32_consts[15],
4895                ];
4896
4897                let v1_left = err!(self.builder.build_shuffle_vector(
4898                    v1,
4899                    v1.get_type().get_undef(),
4900                    VectorType::const_vector(&left_indices),
4901                    "",
4902                ));
4903                let v1_left = err!(self.builder.build_int_s_extend(
4904                    v1_left,
4905                    self.intrinsics.i16x8_ty,
4906                    ""
4907                ));
4908                let v1_right = err!(self.builder.build_shuffle_vector(
4909                    v1,
4910                    v1.get_type().get_undef(),
4911                    VectorType::const_vector(&right_indices),
4912                    "",
4913                ));
4914                let v1_right = err!(self.builder.build_int_s_extend(
4915                    v1_right,
4916                    self.intrinsics.i16x8_ty,
4917                    ""
4918                ));
4919
4920                let v2_left = err!(self.builder.build_shuffle_vector(
4921                    v2,
4922                    v2.get_type().get_undef(),
4923                    VectorType::const_vector(&left_indices),
4924                    "",
4925                ));
4926                let v2_left = err!(self.builder.build_int_s_extend(
4927                    v2_left,
4928                    self.intrinsics.i16x8_ty,
4929                    ""
4930                ));
4931                let v2_right = err!(self.builder.build_shuffle_vector(
4932                    v2,
4933                    v2.get_type().get_undef(),
4934                    VectorType::const_vector(&right_indices),
4935                    "",
4936                ));
4937                let v2_right = err!(self.builder.build_int_s_extend(
4938                    v2_right,
4939                    self.intrinsics.i16x8_ty,
4940                    ""
4941                ));
4942
4943                let prod_left = err!(self.builder.build_int_mul(v1_left, v2_left, ""));
4944                let prod_right = err!(self.builder.build_int_mul(v1_right, v2_right, ""));
4945                let dot16 = err!(self.builder.build_int_add(prod_left, prod_right, ""));
4946
4947                let pair_left = err!(self.builder.build_shuffle_vector(
4948                    dot16,
4949                    dot16.get_type().get_undef(),
4950                    VectorType::const_vector(&[
4951                        self.intrinsics.i32_consts[0],
4952                        self.intrinsics.i32_consts[2],
4953                        self.intrinsics.i32_consts[4],
4954                        self.intrinsics.i32_consts[6],
4955                    ]),
4956                    "",
4957                ));
4958                let pair_left = err!(self.builder.build_int_s_extend(
4959                    pair_left,
4960                    self.intrinsics.i32x4_ty,
4961                    ""
4962                ));
4963                let pair_right = err!(self.builder.build_shuffle_vector(
4964                    dot16,
4965                    dot16.get_type().get_undef(),
4966                    VectorType::const_vector(&[
4967                        self.intrinsics.i32_consts[1],
4968                        self.intrinsics.i32_consts[3],
4969                        self.intrinsics.i32_consts[5],
4970                        self.intrinsics.i32_consts[7],
4971                    ]),
4972                    "",
4973                ));
4974                let pair_right = err!(self.builder.build_int_s_extend(
4975                    pair_right,
4976                    self.intrinsics.i32x4_ty,
4977                    ""
4978                ));
4979                let dot32 = err!(self.builder.build_int_add(pair_left, pair_right, ""));
4980                let res = err!(self.builder.build_int_add(dot32, acc, ""));
4981                let res = err!(
4982                    self.builder
4983                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
4984                );
4985                self.state.push1(res);
4986            }
4987            Operator::I32DivS | Operator::I64DivS => {
4988                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
4989                let v1 = self.apply_pending_canonicalization(v1, i1)?;
4990                let v2 = self.apply_pending_canonicalization(v2, i2)?;
4991                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
4992
4993                self.trap_if_zero_or_overflow(v1, v2)?;
4994
4995                let res = err!(self.builder.build_int_signed_div(v1, v2, ""));
4996                self.state.push1(res);
4997            }
4998            Operator::I32DivU | Operator::I64DivU => {
4999                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5000                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5001                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5002                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5003
5004                self.trap_if_zero(v2)?;
5005
5006                let res = err!(self.builder.build_int_unsigned_div(v1, v2, ""));
5007                self.state.push1(res);
5008            }
5009            Operator::I32RemS | Operator::I64RemS => {
5010                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5011                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5012                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5013                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5014                let int_type = v1.get_type();
5015                let (min_value, neg_one_value) = if int_type == self.intrinsics.i32_ty {
5016                    let min_value = int_type.const_int(i32::MIN as u64, false);
5017                    let neg_one_value = int_type.const_int(-1i32 as u32 as u64, false);
5018                    (min_value, neg_one_value)
5019                } else if int_type == self.intrinsics.i64_ty {
5020                    let min_value = int_type.const_int(i64::MIN as u64, false);
5021                    let neg_one_value = int_type.const_int(-1i64 as u64, false);
5022                    (min_value, neg_one_value)
5023                } else {
5024                    unreachable!()
5025                };
5026
5027                self.trap_if_zero(v2)?;
5028
5029                // "Overflow also leads to undefined behavior; this is a rare
5030                // case, but can occur, for example, by taking the remainder of
5031                // a 32-bit division of -2147483648 by -1. (The remainder
5032                // doesn’t actually overflow, but this rule lets srem be
5033                // implemented using instructions that return both the result
5034                // of the division and the remainder.)"
5035                //   -- https://llvm.org/docs/LangRef.html#srem-instruction
5036                //
5037                // In Wasm, the i32.rem_s i32.const -2147483648 i32.const -1 is
5038                // i32.const 0. We implement this by swapping out the left value
5039                // for 0 in this case.
5040                let will_overflow = err!(self.builder.build_and(
5041                    err!(self.builder.build_int_compare(
5042                        IntPredicate::EQ,
5043                        v1,
5044                        min_value,
5045                        "left_is_min"
5046                    )),
5047                    err!(self.builder.build_int_compare(
5048                        IntPredicate::EQ,
5049                        v2,
5050                        neg_one_value,
5051                        "right_is_neg_one",
5052                    )),
5053                    "srem_will_overflow",
5054                ));
5055                let v1 =
5056                    err!(
5057                        self.builder
5058                            .build_select(will_overflow, int_type.const_zero(), v1, "")
5059                    )
5060                    .into_int_value();
5061                let res = err!(self.builder.build_int_signed_rem(v1, v2, ""));
5062                self.state.push1(res);
5063            }
5064            Operator::I32RemU | Operator::I64RemU => {
5065                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5066                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5067                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5068                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5069
5070                self.trap_if_zero(v2)?;
5071
5072                let res = err!(self.builder.build_int_unsigned_rem(v1, v2, ""));
5073                self.state.push1(res);
5074            }
5075            Operator::I32And | Operator::I64And | Operator::V128And => {
5076                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5077                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5078                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5079                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5080                let res = err!(self.builder.build_and(v1, v2, ""));
5081                self.state.push1(res);
5082            }
5083            Operator::I32Or | Operator::I64Or | Operator::V128Or => {
5084                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5085                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5086                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5087                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5088                let res = err!(self.builder.build_or(v1, v2, ""));
5089                self.state.push1(res);
5090            }
5091            Operator::I32Xor | Operator::I64Xor | Operator::V128Xor => {
5092                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5093                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5094                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5095                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5096                let res = err!(self.builder.build_xor(v1, v2, ""));
5097                self.state.push1(res);
5098            }
5099            Operator::V128AndNot => {
5100                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5101                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5102                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5103                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5104                let v2 = err!(self.builder.build_not(v2, ""));
5105                let res = err!(self.builder.build_and(v1, v2, ""));
5106                self.state.push1(res);
5107            }
5108            Operator::I8x16RelaxedLaneselect
5109            | Operator::I16x8RelaxedLaneselect
5110            | Operator::I32x4RelaxedLaneselect
5111            | Operator::I64x2RelaxedLaneselect
5112                if self.cpu_features.contains(CpuFeature::SSE41) =>
5113            {
5114                let ((v1, i1), (v2, i2), (mask, mask_info)) = self.state.pop3_extra()?;
5115                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5116                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5117                let mask = self.apply_pending_canonicalization(mask, mask_info)?;
5118
5119                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5120                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5121                let (mask, _) = self.v128_into_i8x16(mask, mask_info)?;
5122                let res = self
5123                    .build_call_with_param_attributes(
5124                        self.intrinsics.x86_64.pblendvb,
5125                        &[v2.into(), v1.into(), mask.into()],
5126                        "",
5127                    )?
5128                    .try_as_basic_value()
5129                    .unwrap_basic();
5130                let res = err!(
5131                    self.builder
5132                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5133                );
5134                self.state.push1(res);
5135            }
5136            Operator::I8x16RelaxedLaneselect
5137            | Operator::I16x8RelaxedLaneselect
5138            | Operator::I32x4RelaxedLaneselect
5139            | Operator::I64x2RelaxedLaneselect
5140            | Operator::V128Bitselect => {
5141                let ((v1, i1), (v2, i2), (cond, cond_info)) = self.state.pop3_extra()?;
5142                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5143                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5144                let cond = self.apply_pending_canonicalization(cond, cond_info)?;
5145                let v1 = err!(
5146                    self.builder
5147                        .build_bit_cast(v1, self.intrinsics.i1x128_ty, "")
5148                )
5149                .into_vector_value();
5150                let v2 = err!(
5151                    self.builder
5152                        .build_bit_cast(v2, self.intrinsics.i1x128_ty, "")
5153                )
5154                .into_vector_value();
5155                let cond = err!(
5156                    self.builder
5157                        .build_bit_cast(cond, self.intrinsics.i1x128_ty, "")
5158                )
5159                .into_vector_value();
5160                let res = err!(self.builder.build_select(cond, v1, v2, ""));
5161                let res = err!(
5162                    self.builder
5163                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5164                );
5165                self.state.push1(res);
5166            }
5167            Operator::I8x16Bitmask => {
5168                let (v, i) = self.state.pop1_extra()?;
5169                let (v, _) = self.v128_into_i8x16(v, i)?;
5170
5171                let zeros = self.intrinsics.i8x16_ty.const_zero();
5172                let res = err!(
5173                    self.builder
5174                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
5175                );
5176                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i16_ty, ""))
5177                    .into_int_value();
5178                let res = err!(
5179                    self.builder
5180                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5181                );
5182                self.state.push1(res);
5183            }
5184            Operator::I16x8Bitmask => {
5185                let (v, i) = self.state.pop1_extra()?;
5186                let (v, _) = self.v128_into_i16x8(v, i)?;
5187
5188                let zeros = self.intrinsics.i16x8_ty.const_zero();
5189                let res = err!(
5190                    self.builder
5191                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
5192                );
5193                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i8_ty, ""))
5194                    .into_int_value();
5195                let res = err!(
5196                    self.builder
5197                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5198                );
5199                self.state.push1(res);
5200            }
5201            Operator::I32x4Bitmask => {
5202                let (v, i) = self.state.pop1_extra()?;
5203                let (v, _) = self.v128_into_i32x4(v, i)?;
5204
5205                let zeros = self.intrinsics.i32x4_ty.const_zero();
5206                let res = err!(
5207                    self.builder
5208                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
5209                );
5210                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i4_ty, ""))
5211                    .into_int_value();
5212                let res = err!(
5213                    self.builder
5214                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5215                );
5216                self.state.push1(res);
5217            }
5218            Operator::I64x2Bitmask => {
5219                let (v, i) = self.state.pop1_extra()?;
5220                let (v, _) = self.v128_into_i64x2(v, i)?;
5221
5222                let zeros = self.intrinsics.i64x2_ty.const_zero();
5223                let res = err!(
5224                    self.builder
5225                        .build_int_compare(IntPredicate::SLT, v, zeros, "")
5226                );
5227                let res = err!(self.builder.build_bit_cast(res, self.intrinsics.i2_ty, ""))
5228                    .into_int_value();
5229                let res = err!(
5230                    self.builder
5231                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
5232                );
5233                self.state.push1(res);
5234            }
5235            Operator::I32Shl => {
5236                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5237                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5238                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5239                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5240                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5241                let v2 = err!(self.builder.build_and(v2, mask, ""));
5242                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5243                self.state.push1(res);
5244            }
5245            Operator::I64Shl => {
5246                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5247                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5248                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5249                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5250                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5251                let v2 = err!(self.builder.build_and(v2, mask, ""));
5252                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5253                self.state.push1(res);
5254            }
5255            Operator::I8x16Shl => {
5256                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5257                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5258                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5259                let v2 = v2.into_int_value();
5260                let v2 = err!(
5261                    self.builder
5262                        .build_and(v2, self.intrinsics.i32_consts[7], "")
5263                );
5264                let v2 = err!(
5265                    self.builder
5266                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5267                );
5268                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5269                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5270                let res = err!(
5271                    self.builder
5272                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5273                );
5274                self.state.push1(res);
5275            }
5276            Operator::I16x8Shl => {
5277                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5278                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5279                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5280                let v2 = v2.into_int_value();
5281                let v2 = err!(
5282                    self.builder
5283                        .build_and(v2, self.intrinsics.i32_consts[15], "")
5284                );
5285                let v2 = err!(
5286                    self.builder
5287                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5288                );
5289                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5290                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5291                let res = err!(
5292                    self.builder
5293                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5294                );
5295                self.state.push1(res);
5296            }
5297            Operator::I32x4Shl => {
5298                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5299                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5300                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5301                let v2 = v2.into_int_value();
5302                let v2 = err!(self.builder.build_and(
5303                    v2,
5304                    self.intrinsics.i32_ty.const_int(31, false),
5305                    ""
5306                ));
5307                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5308                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5309                let res = err!(
5310                    self.builder
5311                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5312                );
5313                self.state.push1(res);
5314            }
5315            Operator::I64x2Shl => {
5316                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5317                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5318                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5319                let v2 = v2.into_int_value();
5320                let v2 = err!(self.builder.build_and(
5321                    v2,
5322                    self.intrinsics.i32_ty.const_int(63, false),
5323                    ""
5324                ));
5325                let v2 = err!(
5326                    self.builder
5327                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5328                );
5329                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5330                let res = err!(self.builder.build_left_shift(v1, v2, ""));
5331                let res = err!(
5332                    self.builder
5333                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5334                );
5335                self.state.push1(res);
5336            }
5337            Operator::I32ShrS => {
5338                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5339                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5340                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5341                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5342                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5343                let v2 = err!(self.builder.build_and(v2, mask, ""));
5344                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5345                self.state.push1(res);
5346            }
5347            Operator::I64ShrS => {
5348                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5349                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5350                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5351                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5352                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5353                let v2 = err!(self.builder.build_and(v2, mask, ""));
5354                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5355                self.state.push1(res);
5356            }
5357            Operator::I8x16ShrS => {
5358                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5359                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5360                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5361                let v2 = v2.into_int_value();
5362                let v2 = err!(
5363                    self.builder
5364                        .build_and(v2, self.intrinsics.i32_consts[7], "")
5365                );
5366                let v2 = err!(
5367                    self.builder
5368                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5369                );
5370                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5371                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5372                let res = err!(
5373                    self.builder
5374                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5375                );
5376                self.state.push1(res);
5377            }
5378            Operator::I16x8ShrS => {
5379                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5380                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5381                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5382                let v2 = v2.into_int_value();
5383                let v2 = err!(
5384                    self.builder
5385                        .build_and(v2, self.intrinsics.i32_consts[15], "")
5386                );
5387                let v2 = err!(
5388                    self.builder
5389                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5390                );
5391                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5392                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5393                let res = err!(
5394                    self.builder
5395                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5396                );
5397                self.state.push1(res);
5398            }
5399            Operator::I32x4ShrS => {
5400                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5401                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5402                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5403                let v2 = v2.into_int_value();
5404                let v2 = err!(self.builder.build_and(
5405                    v2,
5406                    self.intrinsics.i32_ty.const_int(31, false),
5407                    ""
5408                ));
5409                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5410                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5411                let res = err!(
5412                    self.builder
5413                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5414                );
5415                self.state.push1(res);
5416            }
5417            Operator::I64x2ShrS => {
5418                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5419                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5420                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5421                let v2 = v2.into_int_value();
5422                let v2 = err!(self.builder.build_and(
5423                    v2,
5424                    self.intrinsics.i32_ty.const_int(63, false),
5425                    ""
5426                ));
5427                let v2 = err!(
5428                    self.builder
5429                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5430                );
5431                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5432                let res = err!(self.builder.build_right_shift(v1, v2, true, ""));
5433                let res = err!(
5434                    self.builder
5435                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5436                );
5437                self.state.push1(res);
5438            }
5439            Operator::I32ShrU => {
5440                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5441                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5442                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5443                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5444                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5445                let v2 = err!(self.builder.build_and(v2, mask, ""));
5446                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5447                self.state.push1(res);
5448            }
5449            Operator::I64ShrU => {
5450                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5451                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5452                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5453                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5454                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5455                let v2 = err!(self.builder.build_and(v2, mask, ""));
5456                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5457                self.state.push1(res);
5458            }
5459            Operator::I8x16ShrU => {
5460                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5461                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5462                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5463                let v2 = v2.into_int_value();
5464                let v2 = err!(
5465                    self.builder
5466                        .build_and(v2, self.intrinsics.i32_consts[7], "")
5467                );
5468                let v2 = err!(
5469                    self.builder
5470                        .build_int_truncate(v2, self.intrinsics.i8_ty, "")
5471                );
5472                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
5473                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5474                let res = err!(
5475                    self.builder
5476                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5477                );
5478                self.state.push1(res);
5479            }
5480            Operator::I16x8ShrU => {
5481                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5482                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5483                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5484                let v2 = v2.into_int_value();
5485                let v2 = err!(
5486                    self.builder
5487                        .build_and(v2, self.intrinsics.i32_consts[15], "")
5488                );
5489                let v2 = err!(
5490                    self.builder
5491                        .build_int_truncate(v2, self.intrinsics.i16_ty, "")
5492                );
5493                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i16x8_ty)?;
5494                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5495                let res = err!(
5496                    self.builder
5497                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5498                );
5499                self.state.push1(res);
5500            }
5501            Operator::I32x4ShrU => {
5502                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5503                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5504                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5505                let v2 = v2.into_int_value();
5506                let v2 = err!(self.builder.build_and(
5507                    v2,
5508                    self.intrinsics.i32_ty.const_int(31, false),
5509                    ""
5510                ));
5511                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i32x4_ty)?;
5512                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5513                let res = err!(
5514                    self.builder
5515                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5516                );
5517                self.state.push1(res);
5518            }
5519            Operator::I64x2ShrU => {
5520                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5521                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
5522                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5523                let v2 = v2.into_int_value();
5524                let v2 = err!(self.builder.build_and(
5525                    v2,
5526                    self.intrinsics.i32_ty.const_int(63, false),
5527                    ""
5528                ));
5529                let v2 = err!(
5530                    self.builder
5531                        .build_int_z_extend(v2, self.intrinsics.i64_ty, "")
5532                );
5533                let v2 = self.splat_vector(v2.as_basic_value_enum(), self.intrinsics.i64x2_ty)?;
5534                let res = err!(self.builder.build_right_shift(v1, v2, false, ""));
5535                let res = err!(
5536                    self.builder
5537                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5538                );
5539                self.state.push1(res);
5540            }
5541            Operator::I32Rotl => {
5542                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5543                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5544                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5545                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5546                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5547                let v2 = err!(self.builder.build_and(v2, mask, ""));
5548                let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5549                let rhs = {
5550                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5551                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5552                    err!(self.builder.build_right_shift(v1, rhs, false, ""))
5553                };
5554                let res = err!(self.builder.build_or(lhs, rhs, ""));
5555                self.state.push1(res);
5556            }
5557            Operator::I64Rotl => {
5558                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5559                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5560                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5561                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5562                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5563                let v2 = err!(self.builder.build_and(v2, mask, ""));
5564                let lhs = err!(self.builder.build_left_shift(v1, v2, ""));
5565                let rhs = {
5566                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5567                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5568                    err!(self.builder.build_right_shift(v1, rhs, false, ""))
5569                };
5570                let res = err!(self.builder.build_or(lhs, rhs, ""));
5571                self.state.push1(res);
5572            }
5573            Operator::I32Rotr => {
5574                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5575                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5576                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5577                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5578                let mask = self.intrinsics.i32_ty.const_int(31u64, false);
5579                let v2 = err!(self.builder.build_and(v2, mask, ""));
5580                let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5581                let rhs = {
5582                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5583                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5584                    err!(self.builder.build_left_shift(v1, rhs, ""))
5585                };
5586                let res = err!(self.builder.build_or(lhs, rhs, ""));
5587                self.state.push1(res);
5588            }
5589            Operator::I64Rotr => {
5590                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5591                let v1 = self.apply_pending_canonicalization(v1, i1)?;
5592                let v2 = self.apply_pending_canonicalization(v2, i2)?;
5593                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
5594                let mask = self.intrinsics.i64_ty.const_int(63u64, false);
5595                let v2 = err!(self.builder.build_and(v2, mask, ""));
5596                let lhs = err!(self.builder.build_right_shift(v1, v2, false, ""));
5597                let rhs = {
5598                    let negv2 = err!(self.builder.build_int_neg(v2, ""));
5599                    let rhs = err!(self.builder.build_and(negv2, mask, ""));
5600                    err!(self.builder.build_left_shift(v1, rhs, ""))
5601                };
5602                let res = err!(self.builder.build_or(lhs, rhs, ""));
5603                self.state.push1(res);
5604            }
5605            Operator::I32Clz => {
5606                let (input, info) = self.state.pop1_extra()?;
5607                let input = self.apply_pending_canonicalization(input, info)?;
5608                let is_zero_undef = self.intrinsics.i1_zero;
5609                let res = self
5610                    .build_call_with_param_attributes(
5611                        self.intrinsics.ctlz_i32,
5612                        &[input.into(), is_zero_undef.into()],
5613                        "",
5614                    )?
5615                    .try_as_basic_value()
5616                    .unwrap_basic();
5617                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5618            }
5619            Operator::I64Clz => {
5620                let (input, info) = self.state.pop1_extra()?;
5621                let input = self.apply_pending_canonicalization(input, info)?;
5622                let is_zero_undef = self.intrinsics.i1_zero;
5623                let res = self
5624                    .build_call_with_param_attributes(
5625                        self.intrinsics.ctlz_i64,
5626                        &[input.into(), is_zero_undef.into()],
5627                        "",
5628                    )?
5629                    .try_as_basic_value()
5630                    .unwrap_basic();
5631                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5632            }
5633            Operator::I32Ctz => {
5634                let (input, info) = self.state.pop1_extra()?;
5635                let input = self.apply_pending_canonicalization(input, info)?;
5636                let is_zero_undef = self.intrinsics.i1_zero;
5637                let res = self
5638                    .build_call_with_param_attributes(
5639                        self.intrinsics.cttz_i32,
5640                        &[input.into(), is_zero_undef.into()],
5641                        "",
5642                    )?
5643                    .try_as_basic_value()
5644                    .unwrap_basic();
5645                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5646            }
5647            Operator::I64Ctz => {
5648                let (input, info) = self.state.pop1_extra()?;
5649                let input = self.apply_pending_canonicalization(input, info)?;
5650                let is_zero_undef = self.intrinsics.i1_zero;
5651                let res = self
5652                    .build_call_with_param_attributes(
5653                        self.intrinsics.cttz_i64,
5654                        &[input.into(), is_zero_undef.into()],
5655                        "",
5656                    )?
5657                    .try_as_basic_value()
5658                    .unwrap_basic();
5659                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5660            }
5661            Operator::I8x16Popcnt => {
5662                let (v, i) = self.state.pop1_extra()?;
5663                let (v, _) = self.v128_into_i8x16(v, i)?;
5664                let res = self
5665                    .build_call_with_param_attributes(self.intrinsics.ctpop_i8x16, &[v.into()], "")?
5666                    .try_as_basic_value()
5667                    .unwrap_basic();
5668                let res = err!(
5669                    self.builder
5670                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5671                );
5672                self.state.push1(res);
5673            }
5674            Operator::I32Popcnt => {
5675                let (input, info) = self.state.pop1_extra()?;
5676                let input = self.apply_pending_canonicalization(input, info)?;
5677                let res = self
5678                    .build_call_with_param_attributes(
5679                        self.intrinsics.ctpop_i32,
5680                        &[input.into()],
5681                        "",
5682                    )?
5683                    .try_as_basic_value()
5684                    .unwrap_basic();
5685                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5686            }
5687            Operator::I64Popcnt => {
5688                let (input, info) = self.state.pop1_extra()?;
5689                let input = self.apply_pending_canonicalization(input, info)?;
5690                let res = self
5691                    .build_call_with_param_attributes(
5692                        self.intrinsics.ctpop_i64,
5693                        &[input.into()],
5694                        "",
5695                    )?
5696                    .try_as_basic_value()
5697                    .unwrap_basic();
5698                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5699            }
5700            Operator::I32Eqz => {
5701                let input = self.state.pop1()?.into_int_value();
5702                let cond = err!(self.builder.build_int_compare(
5703                    IntPredicate::EQ,
5704                    input,
5705                    self.intrinsics.i32_zero,
5706                    "",
5707                ));
5708                let res = err!(
5709                    self.builder
5710                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5711                );
5712                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
5713            }
5714            Operator::I64Eqz => {
5715                let input = self.state.pop1()?.into_int_value();
5716                let cond = err!(self.builder.build_int_compare(
5717                    IntPredicate::EQ,
5718                    input,
5719                    self.intrinsics.i64_zero,
5720                    "",
5721                ));
5722                let res = err!(
5723                    self.builder
5724                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
5725                );
5726                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
5727            }
5728            Operator::I8x16Abs => {
5729                let (v, i) = self.state.pop1_extra()?;
5730                let (v, _) = self.v128_into_i8x16(v, i)?;
5731
5732                let seven = self.intrinsics.i8_ty.const_int(7, false);
5733                let seven = VectorType::const_vector(&[seven; 16]);
5734                let all_sign_bits = err!(self.builder.build_right_shift(v, seven, true, ""));
5735                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5736                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5737                let res = err!(
5738                    self.builder
5739                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5740                );
5741                self.state.push1(res);
5742            }
5743            Operator::I16x8Abs => {
5744                let (v, i) = self.state.pop1_extra()?;
5745                let (v, _) = self.v128_into_i16x8(v, i)?;
5746
5747                let fifteen = self.intrinsics.i16_ty.const_int(15, false);
5748                let fifteen = VectorType::const_vector(&[fifteen; 8]);
5749                let all_sign_bits = err!(self.builder.build_right_shift(v, fifteen, true, ""));
5750                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5751                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5752                let res = err!(
5753                    self.builder
5754                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5755                );
5756                self.state.push1(res);
5757            }
5758            Operator::I32x4Abs => {
5759                let (v, i) = self.state.pop1_extra()?;
5760                let (v, _) = self.v128_into_i32x4(v, i)?;
5761
5762                let thirtyone = self.intrinsics.i32_ty.const_int(31, false);
5763                let thirtyone = VectorType::const_vector(&[thirtyone; 4]);
5764                let all_sign_bits = err!(self.builder.build_right_shift(v, thirtyone, true, ""));
5765                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5766                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5767                let res = err!(
5768                    self.builder
5769                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5770                );
5771                self.state.push1(res);
5772            }
5773            Operator::I64x2Abs => {
5774                let (v, i) = self.state.pop1_extra()?;
5775                let (v, _) = self.v128_into_i64x2(v, i)?;
5776
5777                let sixtythree = self.intrinsics.i64_ty.const_int(63, false);
5778                let sixtythree = VectorType::const_vector(&[sixtythree; 2]);
5779                let all_sign_bits = err!(self.builder.build_right_shift(v, sixtythree, true, ""));
5780                let xor = err!(self.builder.build_xor(v, all_sign_bits, ""));
5781                let res = err!(self.builder.build_int_sub(xor, all_sign_bits, ""));
5782                let res = err!(
5783                    self.builder
5784                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5785                );
5786                self.state.push1(res);
5787            }
5788            Operator::I8x16MinS => {
5789                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5790                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5791                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5792                let cmp = err!(
5793                    self.builder
5794                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5795                );
5796                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5797                let res = err!(
5798                    self.builder
5799                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5800                );
5801                self.state.push1(res);
5802            }
5803            Operator::I8x16MinU => {
5804                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5805                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5806                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5807                let cmp = err!(
5808                    self.builder
5809                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5810                );
5811                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5812                let res = err!(
5813                    self.builder
5814                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5815                );
5816                self.state.push1(res);
5817            }
5818            Operator::I8x16MaxS => {
5819                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5820                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5821                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5822                let cmp = err!(
5823                    self.builder
5824                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5825                );
5826                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5827                let res = err!(
5828                    self.builder
5829                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5830                );
5831                self.state.push1(res);
5832            }
5833            Operator::I8x16MaxU => {
5834                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5835                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5836                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5837                let cmp = err!(
5838                    self.builder
5839                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5840                );
5841                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5842                let res = err!(
5843                    self.builder
5844                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5845                );
5846                self.state.push1(res);
5847            }
5848            Operator::I16x8MinS => {
5849                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5850                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5851                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5852                let cmp = err!(
5853                    self.builder
5854                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5855                );
5856                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5857                let res = err!(
5858                    self.builder
5859                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5860                );
5861                self.state.push1(res);
5862            }
5863            Operator::I16x8MinU => {
5864                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5865                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5866                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5867                let cmp = err!(
5868                    self.builder
5869                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5870                );
5871                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5872                let res = err!(
5873                    self.builder
5874                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5875                );
5876                self.state.push1(res);
5877            }
5878            Operator::I16x8MaxS => {
5879                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5880                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5881                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5882                let cmp = err!(
5883                    self.builder
5884                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5885                );
5886                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5887                let res = err!(
5888                    self.builder
5889                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5890                );
5891                self.state.push1(res);
5892            }
5893            Operator::I16x8MaxU => {
5894                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5895                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
5896                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
5897                let cmp = err!(
5898                    self.builder
5899                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5900                );
5901                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5902                let res = err!(
5903                    self.builder
5904                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5905                );
5906                self.state.push1(res);
5907            }
5908            Operator::I32x4MinS => {
5909                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5910                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5911                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5912                let cmp = err!(
5913                    self.builder
5914                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
5915                );
5916                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5917                let res = err!(
5918                    self.builder
5919                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5920                );
5921                self.state.push1(res);
5922            }
5923            Operator::I32x4MinU => {
5924                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5925                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5926                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5927                let cmp = err!(
5928                    self.builder
5929                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
5930                );
5931                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5932                let res = err!(
5933                    self.builder
5934                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5935                );
5936                self.state.push1(res);
5937            }
5938            Operator::I32x4MaxS => {
5939                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5940                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5941                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5942                let cmp = err!(
5943                    self.builder
5944                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
5945                );
5946                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5947                let res = err!(
5948                    self.builder
5949                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5950                );
5951                self.state.push1(res);
5952            }
5953            Operator::I32x4MaxU => {
5954                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5955                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
5956                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
5957                let cmp = err!(
5958                    self.builder
5959                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
5960                );
5961                let res = err!(self.builder.build_select(cmp, v1, v2, ""));
5962                let res = err!(
5963                    self.builder
5964                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
5965                );
5966                self.state.push1(res);
5967            }
5968            Operator::I8x16AvgrU => {
5969                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
5970                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
5971                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
5972
5973                // This approach is faster on x86-64 when the PAVG[BW]
5974                // instructions are available. On other platforms, an alternative
5975                // implementation appears likely to outperform, described here:
5976                //   %a = or %v1, %v2
5977                //   %b = and %a, 1
5978                //   %v1 = lshr %v1, 1
5979                //   %v2 = lshr %v2, 1
5980                //   %sum = add %v1, %v2
5981                //   %res = add %sum, %b
5982
5983                let ext_ty = self.intrinsics.i16_ty.vec_type(16);
5984                let one = self.intrinsics.i16_ty.const_int(1, false);
5985                let one = VectorType::const_vector(&[one; 16]);
5986
5987                let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
5988                let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
5989                let res = err!(self.builder.build_int_add(
5990                    err!(self.builder.build_int_add(one, v1, "")),
5991                    v2,
5992                    ""
5993                ));
5994                let res = err!(self.builder.build_right_shift(res, one, false, ""));
5995                let res = err!(
5996                    self.builder
5997                        .build_int_truncate(res, self.intrinsics.i8x16_ty, "")
5998                );
5999                let res = err!(
6000                    self.builder
6001                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6002                );
6003                self.state.push1(res);
6004            }
6005            Operator::I16x8AvgrU => {
6006                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6007                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
6008                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
6009
6010                // This approach is faster on x86-64 when the PAVG[BW]
6011                // instructions are available. On other platforms, an alternative
6012                // implementation appears likely to outperform, described here:
6013                //   %a = or %v1, %v2
6014                //   %b = and %a, 1
6015                //   %v1 = lshr %v1, 1
6016                //   %v2 = lshr %v2, 1
6017                //   %sum = add %v1, %v2
6018                //   %res = add %sum, %b
6019
6020                let ext_ty = self.intrinsics.i32_ty.vec_type(8);
6021                let one = self.intrinsics.i32_consts[1];
6022                let one = VectorType::const_vector(&[one; 8]);
6023
6024                let v1 = err!(self.builder.build_int_z_extend(v1, ext_ty, ""));
6025                let v2 = err!(self.builder.build_int_z_extend(v2, ext_ty, ""));
6026                let res = err!(self.builder.build_int_add(
6027                    err!(self.builder.build_int_add(one, v1, "")),
6028                    v2,
6029                    ""
6030                ));
6031                let res = err!(self.builder.build_right_shift(res, one, false, ""));
6032                let res = err!(
6033                    self.builder
6034                        .build_int_truncate(res, self.intrinsics.i16x8_ty, "")
6035                );
6036                let res = err!(
6037                    self.builder
6038                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6039                );
6040                self.state.push1(res);
6041            }
6042            Operator::I64Add128 | Operator::I64Sub128 => {
6043                let (rhs_hi, rhs_hi_info) = self.state.pop1_extra()?;
6044                let (rhs_lo, rhs_lo_info) = self.state.pop1_extra()?;
6045                let (lhs_hi, lhs_hi_info) = self.state.pop1_extra()?;
6046                let (lhs_lo, lhs_lo_info) = self.state.pop1_extra()?;
6047
6048                let lhs_lo = self
6049                    .apply_pending_canonicalization(lhs_lo, lhs_lo_info)?
6050                    .into_int_value();
6051                let lhs_hi = self
6052                    .apply_pending_canonicalization(lhs_hi, lhs_hi_info)?
6053                    .into_int_value();
6054                let rhs_lo = self
6055                    .apply_pending_canonicalization(rhs_lo, rhs_lo_info)?
6056                    .into_int_value();
6057                let rhs_hi = self
6058                    .apply_pending_canonicalization(rhs_hi, rhs_hi_info)?
6059                    .into_int_value();
6060
6061                let idx0 = self.intrinsics.i32_ty.const_zero();
6062                let idx1 = self.intrinsics.i32_ty.const_int(1, false);
6063
6064                let lhs = self.intrinsics.i64x2_ty.get_undef();
6065                let lhs = err!(self.builder.build_insert_element(lhs, lhs_lo, idx0, ""));
6066                let lhs = err!(self.builder.build_insert_element(lhs, lhs_hi, idx1, ""));
6067                let lhs = err!(
6068                    self.builder
6069                        .build_bit_cast(lhs, self.intrinsics.i128_ty, "a")
6070                )
6071                .into_int_value();
6072
6073                let rhs = self.intrinsics.i64x2_ty.get_undef();
6074                let rhs = err!(self.builder.build_insert_element(rhs, rhs_lo, idx0, ""));
6075                let rhs = err!(self.builder.build_insert_element(rhs, rhs_hi, idx1, ""));
6076                let rhs = err!(
6077                    self.builder
6078                        .build_bit_cast(rhs, self.intrinsics.i128_ty, "b")
6079                )
6080                .into_int_value();
6081
6082                let result = err!(match op {
6083                    Operator::I64Add128 => self.builder.build_int_add(lhs, rhs, ""),
6084                    Operator::I64Sub128 => self.builder.build_int_sub(lhs, rhs, ""),
6085                    _ => unreachable!(),
6086                });
6087                let result = err!(self.builder.build_bit_cast(
6088                    result,
6089                    self.intrinsics.i64x2_ty,
6090                    ""
6091                ))
6092                .into_vector_value();
6093                let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
6094                let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
6095
6096                self.state.push1(result_lo);
6097                self.state.push1(result_hi);
6098            }
6099            Operator::I64MulWideS | Operator::I64MulWideU => {
6100                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6101                let lhs = self
6102                    .apply_pending_canonicalization(lhs, lhs_info)?
6103                    .into_int_value();
6104                let rhs = self
6105                    .apply_pending_canonicalization(rhs, rhs_info)?
6106                    .into_int_value();
6107
6108                let lhs = err!(match op {
6109                    Operator::I64MulWideS => {
6110                        self.builder
6111                            .build_int_s_extend(lhs, self.intrinsics.i128_ty, "a")
6112                    }
6113                    Operator::I64MulWideU => {
6114                        self.builder
6115                            .build_int_z_extend(lhs, self.intrinsics.i128_ty, "a")
6116                    }
6117                    _ => unreachable!(),
6118                });
6119                let rhs = err!(match op {
6120                    Operator::I64MulWideS => {
6121                        self.builder
6122                            .build_int_s_extend(rhs, self.intrinsics.i128_ty, "b")
6123                    }
6124                    Operator::I64MulWideU => {
6125                        self.builder
6126                            .build_int_z_extend(rhs, self.intrinsics.i128_ty, "b")
6127                    }
6128                    _ => unreachable!(),
6129                });
6130
6131                let result = err!(self.builder.build_int_mul(lhs, rhs, ""));
6132                let result = err!(self.builder.build_bit_cast(
6133                    result,
6134                    self.intrinsics.i64x2_ty,
6135                    ""
6136                ))
6137                .into_vector_value();
6138                let idx0 = self.intrinsics.i32_ty.const_zero();
6139                let idx1 = self.intrinsics.i32_ty.const_int(1, false);
6140                let result_lo = err!(self.builder.build_extract_element(result, idx0, ""));
6141                let result_hi = err!(self.builder.build_extract_element(result, idx1, ""));
6142
6143                self.state.push1(result_lo);
6144                self.state.push1(result_hi);
6145            }
6146            _ => unreachable!(),
6147        }
6148        Ok(())
6149    }
6150
6151    // Floating-Point Arithmetic instructions.
6152    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-arithmetic-instructions
6153    fn translate_floating_point_arithmetic_operator(
6154        &mut self,
6155        op: Operator,
6156    ) -> Result<(), CompileError> {
6157        match op {
6158            Operator::F32Add => {
6159                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6160                let res = self
6161                    .build_call_with_param_attributes(
6162                        self.intrinsics.add_f32,
6163                        &[
6164                            v1.into(),
6165                            v2.into(),
6166                            self.intrinsics.fp_rounding_md,
6167                            self.intrinsics.fp_exception_md,
6168                        ],
6169                        "",
6170                    )?
6171                    .try_as_basic_value()
6172                    .unwrap_basic();
6173                self.state.push1_extra(
6174                    res,
6175                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6176                );
6177            }
6178            Operator::F64Add => {
6179                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6180                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6181                let res = self
6182                    .build_call_with_param_attributes(
6183                        self.intrinsics.add_f64,
6184                        &[
6185                            v1.into(),
6186                            v2.into(),
6187                            self.intrinsics.fp_rounding_md,
6188                            self.intrinsics.fp_exception_md,
6189                        ],
6190                        "",
6191                    )?
6192                    .try_as_basic_value()
6193                    .unwrap_basic();
6194                self.state.push1_extra(
6195                    res,
6196                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6197                );
6198            }
6199            Operator::F32x4Add => {
6200                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6201                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6202                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6203                let res = self
6204                    .build_call_with_param_attributes(
6205                        self.intrinsics.add_f32x4,
6206                        &[
6207                            v1.into(),
6208                            v2.into(),
6209                            self.intrinsics.fp_rounding_md,
6210                            self.intrinsics.fp_exception_md,
6211                        ],
6212                        "",
6213                    )?
6214                    .try_as_basic_value()
6215                    .unwrap_basic();
6216                let res = err!(
6217                    self.builder
6218                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6219                );
6220                self.state.push1_extra(
6221                    res,
6222                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6223                );
6224            }
6225            Operator::F64x2Add => {
6226                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6227                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6228                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6229                let res = self
6230                    .build_call_with_param_attributes(
6231                        self.intrinsics.add_f64x2,
6232                        &[
6233                            v1.into(),
6234                            v2.into(),
6235                            self.intrinsics.fp_rounding_md,
6236                            self.intrinsics.fp_exception_md,
6237                        ],
6238                        "",
6239                    )?
6240                    .try_as_basic_value()
6241                    .unwrap_basic();
6242                let res = err!(
6243                    self.builder
6244                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6245                );
6246                self.state.push1_extra(
6247                    res,
6248                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6249                );
6250            }
6251            Operator::F32Sub => {
6252                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6253                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6254                let res = self
6255                    .build_call_with_param_attributes(
6256                        self.intrinsics.sub_f32,
6257                        &[
6258                            v1.into(),
6259                            v2.into(),
6260                            self.intrinsics.fp_rounding_md,
6261                            self.intrinsics.fp_exception_md,
6262                        ],
6263                        "",
6264                    )?
6265                    .try_as_basic_value()
6266                    .unwrap_basic();
6267                self.state.push1_extra(
6268                    res,
6269                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6270                );
6271            }
6272            Operator::F64Sub => {
6273                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6274                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6275                let res = self
6276                    .build_call_with_param_attributes(
6277                        self.intrinsics.sub_f64,
6278                        &[
6279                            v1.into(),
6280                            v2.into(),
6281                            self.intrinsics.fp_rounding_md,
6282                            self.intrinsics.fp_exception_md,
6283                        ],
6284                        "",
6285                    )?
6286                    .try_as_basic_value()
6287                    .unwrap_basic();
6288                self.state.push1_extra(
6289                    res,
6290                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6291                );
6292            }
6293            Operator::F32x4Sub => {
6294                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6295                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6296                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6297                let res = self
6298                    .build_call_with_param_attributes(
6299                        self.intrinsics.sub_f32x4,
6300                        &[
6301                            v1.into(),
6302                            v2.into(),
6303                            self.intrinsics.fp_rounding_md,
6304                            self.intrinsics.fp_exception_md,
6305                        ],
6306                        "",
6307                    )?
6308                    .try_as_basic_value()
6309                    .unwrap_basic();
6310                let res = err!(
6311                    self.builder
6312                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6313                );
6314                self.state.push1_extra(
6315                    res,
6316                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6317                );
6318            }
6319            Operator::F64x2Sub => {
6320                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6321                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6322                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6323                let res = self
6324                    .build_call_with_param_attributes(
6325                        self.intrinsics.sub_f64x2,
6326                        &[
6327                            v1.into(),
6328                            v2.into(),
6329                            self.intrinsics.fp_rounding_md,
6330                            self.intrinsics.fp_exception_md,
6331                        ],
6332                        "",
6333                    )?
6334                    .try_as_basic_value()
6335                    .unwrap_basic();
6336                let res = err!(
6337                    self.builder
6338                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6339                );
6340                self.state.push1_extra(
6341                    res,
6342                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6343                );
6344            }
6345            Operator::F32Mul => {
6346                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6347                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6348                let res = self
6349                    .build_call_with_param_attributes(
6350                        self.intrinsics.mul_f32,
6351                        &[
6352                            v1.into(),
6353                            v2.into(),
6354                            self.intrinsics.fp_rounding_md,
6355                            self.intrinsics.fp_exception_md,
6356                        ],
6357                        "",
6358                    )?
6359                    .try_as_basic_value()
6360                    .unwrap_basic();
6361                self.state.push1_extra(
6362                    res,
6363                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6364                );
6365            }
6366            Operator::F64Mul => {
6367                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6368                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6369                let res = self
6370                    .build_call_with_param_attributes(
6371                        self.intrinsics.mul_f64,
6372                        &[
6373                            v1.into(),
6374                            v2.into(),
6375                            self.intrinsics.fp_rounding_md,
6376                            self.intrinsics.fp_exception_md,
6377                        ],
6378                        "",
6379                    )?
6380                    .try_as_basic_value()
6381                    .unwrap_basic();
6382                self.state.push1_extra(
6383                    res,
6384                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6385                );
6386            }
6387            Operator::F32x4Mul => {
6388                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6389                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6390                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6391                let res = self
6392                    .build_call_with_param_attributes(
6393                        self.intrinsics.mul_f32x4,
6394                        &[
6395                            v1.into(),
6396                            v2.into(),
6397                            self.intrinsics.fp_rounding_md,
6398                            self.intrinsics.fp_exception_md,
6399                        ],
6400                        "",
6401                    )?
6402                    .try_as_basic_value()
6403                    .unwrap_basic();
6404                let res = err!(
6405                    self.builder
6406                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6407                );
6408                self.state.push1_extra(
6409                    res,
6410                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6411                );
6412            }
6413            Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd
6414                if self.cpu_features.contains(CpuFeature::FMA) =>
6415            {
6416                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6417                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6418                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6419                let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
6420
6421                let v1 = match op {
6422                    Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6423                    _ => v1,
6424                };
6425                let res = self
6426                    .build_call_with_param_attributes(
6427                        self.intrinsics.muladd_f32x4,
6428                        &[
6429                            v1.into(),
6430                            v2.into(),
6431                            v3.into(),
6432                            self.intrinsics.fp_rounding_md,
6433                            self.intrinsics.fp_exception_md,
6434                        ],
6435                        "",
6436                    )?
6437                    .try_as_basic_value()
6438                    .unwrap_basic();
6439                let res = err!(
6440                    self.builder
6441                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6442                );
6443                let info = (i1.strip_pending() & i2.strip_pending())?;
6444                let info = (info & i3.strip_pending())?;
6445                let info = (info | ExtraInfo::pending_f32_nan())?;
6446                self.state.push1_extra(res, info);
6447            }
6448            Operator::F32x4RelaxedMadd | Operator::F32x4RelaxedNmadd => {
6449                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6450                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6451                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6452                let (v3, i3) = self.v128_into_f32x4(v3, i3)?;
6453
6454                let v1 = match op {
6455                    Operator::F32x4RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6456                    _ => v1,
6457                };
6458                let mul = self
6459                    .build_call_with_param_attributes(
6460                        self.intrinsics.mul_f32x4,
6461                        &[
6462                            v1.into(),
6463                            v2.into(),
6464                            self.intrinsics.fp_rounding_md,
6465                            self.intrinsics.fp_exception_md,
6466                        ],
6467                        "",
6468                    )?
6469                    .try_as_basic_value()
6470                    .unwrap_basic();
6471                let mul = mul.into_vector_value();
6472                let res = self
6473                    .build_call_with_param_attributes(
6474                        self.intrinsics.add_f32x4,
6475                        &[
6476                            mul.into(),
6477                            v3.into(),
6478                            self.intrinsics.fp_rounding_md,
6479                            self.intrinsics.fp_exception_md,
6480                        ],
6481                        "",
6482                    )?
6483                    .try_as_basic_value()
6484                    .unwrap_basic();
6485                let res = err!(
6486                    self.builder
6487                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6488                );
6489                let info = (i1.strip_pending() & i2.strip_pending())?;
6490                let info = (info & i3.strip_pending())?;
6491                let info = (info | ExtraInfo::pending_f32_nan())?;
6492                self.state.push1_extra(res, info);
6493            }
6494            Operator::F64x2Mul => {
6495                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6496                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6497                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6498                let res = self
6499                    .build_call_with_param_attributes(
6500                        self.intrinsics.mul_f64x2,
6501                        &[
6502                            v1.into(),
6503                            v2.into(),
6504                            self.intrinsics.fp_rounding_md,
6505                            self.intrinsics.fp_exception_md,
6506                        ],
6507                        "",
6508                    )?
6509                    .try_as_basic_value()
6510                    .unwrap_basic();
6511                let res = err!(
6512                    self.builder
6513                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6514                );
6515                self.state.push1_extra(
6516                    res,
6517                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6518                );
6519            }
6520            Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd
6521                if self.cpu_features.contains(CpuFeature::FMA) =>
6522            {
6523                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6524                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6525                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6526                let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
6527
6528                let v1 = match op {
6529                    Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6530                    _ => v1,
6531                };
6532                let res = self
6533                    .build_call_with_param_attributes(
6534                        self.intrinsics.muladd_f64x2,
6535                        &[
6536                            v1.into(),
6537                            v2.into(),
6538                            v3.into(),
6539                            self.intrinsics.fp_rounding_md,
6540                            self.intrinsics.fp_exception_md,
6541                        ],
6542                        "",
6543                    )?
6544                    .try_as_basic_value()
6545                    .unwrap_basic();
6546                let res = err!(
6547                    self.builder
6548                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6549                );
6550                let info = (i1.strip_pending() & i2.strip_pending())?;
6551                let info = (info & i3.strip_pending())?;
6552                let info = (info | ExtraInfo::pending_f64_nan())?;
6553                self.state.push1_extra(res, info);
6554            }
6555            Operator::F64x2RelaxedMadd | Operator::F64x2RelaxedNmadd => {
6556                let ((v1, i1), (v2, i2), (v3, i3)) = self.state.pop3_extra()?;
6557                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6558                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6559                let (v3, i3) = self.v128_into_f64x2(v3, i3)?;
6560
6561                let v1 = match op {
6562                    Operator::F64x2RelaxedNmadd => err!(self.builder.build_float_neg(v1, "")),
6563                    _ => v1,
6564                };
6565                let mul = self
6566                    .build_call_with_param_attributes(
6567                        self.intrinsics.mul_f64x2,
6568                        &[
6569                            v1.into(),
6570                            v2.into(),
6571                            self.intrinsics.fp_rounding_md,
6572                            self.intrinsics.fp_exception_md,
6573                        ],
6574                        "",
6575                    )?
6576                    .try_as_basic_value()
6577                    .unwrap_basic();
6578                let mul = mul.into_vector_value();
6579                let res = self
6580                    .build_call_with_param_attributes(
6581                        self.intrinsics.add_f64x2,
6582                        &[
6583                            mul.into(),
6584                            v3.into(),
6585                            self.intrinsics.fp_rounding_md,
6586                            self.intrinsics.fp_exception_md,
6587                        ],
6588                        "",
6589                    )?
6590                    .try_as_basic_value()
6591                    .unwrap_basic();
6592                let res = err!(
6593                    self.builder
6594                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6595                );
6596                let info = (i1.strip_pending() & i2.strip_pending())?;
6597                let info = (info & i3.strip_pending())?;
6598                let info = (info | ExtraInfo::pending_f64_nan())?;
6599                self.state.push1_extra(res, info);
6600            }
6601            Operator::F32Div => {
6602                let (v1, v2) = self.state.pop2()?;
6603                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6604                let res = self
6605                    .build_call_with_param_attributes(
6606                        self.intrinsics.div_f32,
6607                        &[
6608                            v1.into(),
6609                            v2.into(),
6610                            self.intrinsics.fp_rounding_md,
6611                            self.intrinsics.fp_exception_md,
6612                        ],
6613                        "",
6614                    )?
6615                    .try_as_basic_value()
6616                    .unwrap_basic();
6617                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6618            }
6619            Operator::F64Div => {
6620                let (v1, v2) = self.state.pop2()?;
6621                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
6622                let res = self
6623                    .build_call_with_param_attributes(
6624                        self.intrinsics.div_f64,
6625                        &[
6626                            v1.into(),
6627                            v2.into(),
6628                            self.intrinsics.fp_rounding_md,
6629                            self.intrinsics.fp_exception_md,
6630                        ],
6631                        "",
6632                    )?
6633                    .try_as_basic_value()
6634                    .unwrap_basic();
6635                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6636            }
6637            Operator::F32x4Div => {
6638                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6639                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
6640                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
6641                let res = self
6642                    .build_call_with_param_attributes(
6643                        self.intrinsics.div_f32x4,
6644                        &[
6645                            v1.into(),
6646                            v2.into(),
6647                            self.intrinsics.fp_rounding_md,
6648                            self.intrinsics.fp_exception_md,
6649                        ],
6650                        "",
6651                    )?
6652                    .try_as_basic_value()
6653                    .unwrap_basic();
6654                let res = err!(
6655                    self.builder
6656                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6657                );
6658                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6659            }
6660            Operator::F64x2Div => {
6661                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6662                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
6663                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
6664                let res = self
6665                    .build_call_with_param_attributes(
6666                        self.intrinsics.div_f64x2,
6667                        &[
6668                            v1.into(),
6669                            v2.into(),
6670                            self.intrinsics.fp_rounding_md,
6671                            self.intrinsics.fp_exception_md,
6672                        ],
6673                        "",
6674                    )?
6675                    .try_as_basic_value()
6676                    .unwrap_basic();
6677                let res = err!(
6678                    self.builder
6679                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6680                );
6681                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6682            }
6683            Operator::F32Sqrt => {
6684                let input = self.state.pop1()?;
6685                let res = self
6686                    .build_call_with_param_attributes(
6687                        self.intrinsics.sqrt_f32,
6688                        &[input.into()],
6689                        "",
6690                    )?
6691                    .try_as_basic_value()
6692                    .unwrap_basic();
6693                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6694            }
6695            Operator::F64Sqrt => {
6696                let input = self.state.pop1()?;
6697                let res = self
6698                    .build_call_with_param_attributes(
6699                        self.intrinsics.sqrt_f64,
6700                        &[input.into()],
6701                        "",
6702                    )?
6703                    .try_as_basic_value()
6704                    .unwrap_basic();
6705                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6706            }
6707            Operator::F32x4Sqrt => {
6708                let (v, i) = self.state.pop1_extra()?;
6709                let (v, _) = self.v128_into_f32x4(v, i)?;
6710                let res = self
6711                    .build_call_with_param_attributes(self.intrinsics.sqrt_f32x4, &[v.into()], "")?
6712                    .try_as_basic_value()
6713                    .unwrap_basic();
6714                let bits = err!(
6715                    self.builder
6716                        .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6717                );
6718                self.state.push1_extra(bits, ExtraInfo::pending_f32_nan());
6719            }
6720            Operator::F64x2Sqrt => {
6721                let (v, i) = self.state.pop1_extra()?;
6722                let (v, _) = self.v128_into_f64x2(v, i)?;
6723                let res = self
6724                    .build_call_with_param_attributes(self.intrinsics.sqrt_f64x2, &[v.into()], "")?
6725                    .try_as_basic_value()
6726                    .unwrap_basic();
6727                let bits = err!(
6728                    self.builder
6729                        .build_bit_cast(res, self.intrinsics.i128_ty, "bits")
6730                );
6731                self.state.push1(bits);
6732            }
6733            Operator::F32Min => {
6734                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6735                let lhs = self
6736                    .apply_pending_canonicalization(lhs, lhs_info)?
6737                    .into_float_value();
6738                let rhs = self
6739                    .apply_pending_canonicalization(rhs, rhs_info)?
6740                    .into_float_value();
6741
6742                let res = self
6743                    .build_call_with_param_attributes(
6744                        self.intrinsics.minimum_f32,
6745                        &[lhs.into(), rhs.into()],
6746                        "",
6747                    )?
6748                    .try_as_basic_value()
6749                    .unwrap_basic();
6750
6751                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6752                let res = res.into_float_value();
6753
6754                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6755            }
6756            Operator::F64Min => {
6757                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6758                let lhs = self
6759                    .apply_pending_canonicalization(lhs, lhs_info)?
6760                    .into_float_value();
6761                let rhs = self
6762                    .apply_pending_canonicalization(rhs, rhs_info)?
6763                    .into_float_value();
6764
6765                let res = self
6766                    .build_call_with_param_attributes(
6767                        self.intrinsics.minimum_f64,
6768                        &[lhs.into(), rhs.into()],
6769                        "",
6770                    )?
6771                    .try_as_basic_value()
6772                    .unwrap_basic();
6773
6774                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6775                let res = res.into_float_value();
6776
6777                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6778            }
6779            Operator::F32x4RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6780                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6781                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6782                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6783                let res = self
6784                    .build_call_with_param_attributes(
6785                        self.intrinsics.x86_64.min_ps,
6786                        &[v1.into(), v2.into()],
6787                        "",
6788                    )?
6789                    .try_as_basic_value()
6790                    .unwrap_basic();
6791                let res = err!(
6792                    self.builder
6793                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6794                );
6795                self.state.push1_extra(
6796                    res,
6797                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6798                );
6799            }
6800            Operator::F32x4Min | Operator::F32x4RelaxedMin => {
6801                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6802                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6803                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6804                let res = self
6805                    .build_call_with_param_attributes(
6806                        self.intrinsics.minimum_f32x4,
6807                        &[v1.into(), v2.into()],
6808                        "",
6809                    )?
6810                    .try_as_basic_value()
6811                    .unwrap_basic();
6812
6813                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6814                let res = res.into_vector_value();
6815
6816                let res = err!(
6817                    self.builder
6818                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6819                );
6820                self.state.push1_extra(
6821                    res,
6822                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6823                );
6824            }
6825            Operator::F32x4PMin => {
6826                // Pseudo-min: b < a ? b : a
6827                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6828                let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6829                let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
6830                let cmp = err!(
6831                    self.builder
6832                        .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6833                );
6834                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6835                let res = err!(
6836                    self.builder
6837                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6838                );
6839                self.state.push1(res);
6840            }
6841            Operator::F64x2RelaxedMin if self.cpu_features.contains(CpuFeature::SSE2) => {
6842                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6843                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6844                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6845                let res = self
6846                    .build_call_with_param_attributes(
6847                        self.intrinsics.x86_64.min_pd,
6848                        &[v1.into(), v2.into()],
6849                        "",
6850                    )?
6851                    .try_as_basic_value()
6852                    .unwrap_basic();
6853                let res = err!(
6854                    self.builder
6855                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6856                );
6857                self.state.push1_extra(
6858                    res,
6859                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6860                );
6861            }
6862            Operator::F64x2Min | Operator::F64x2RelaxedMin => {
6863                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6864                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
6865                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
6866                let res = self
6867                    .build_call_with_param_attributes(
6868                        self.intrinsics.minimum_f64x2,
6869                        &[v1.into(), v2.into()],
6870                        "",
6871                    )?
6872                    .try_as_basic_value()
6873                    .unwrap_basic();
6874
6875                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6876                let res = res.into_vector_value();
6877
6878                let res = err!(
6879                    self.builder
6880                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6881                );
6882                self.state.push1_extra(
6883                    res,
6884                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
6885                );
6886            }
6887            Operator::F64x2PMin => {
6888                // Pseudo-min: b < a ? b : a
6889                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6890                let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
6891                let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
6892                let cmp = err!(
6893                    self.builder
6894                        .build_float_compare(FloatPredicate::OLT, v2, v1, "")
6895                );
6896                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
6897                let res = err!(
6898                    self.builder
6899                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6900                );
6901                self.state.push1(res);
6902            }
6903            Operator::F32Max => {
6904                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6905                let lhs = self
6906                    .apply_pending_canonicalization(lhs, lhs_info)?
6907                    .into_float_value();
6908                let rhs = self
6909                    .apply_pending_canonicalization(rhs, rhs_info)?
6910                    .into_float_value();
6911
6912                let res = self
6913                    .build_call_with_param_attributes(
6914                        self.intrinsics.maximum_f32,
6915                        &[lhs.into(), rhs.into()],
6916                        "",
6917                    )?
6918                    .try_as_basic_value()
6919                    .unwrap_basic();
6920
6921                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6922                let res = res.into_float_value();
6923
6924                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
6925            }
6926            Operator::F64Max => {
6927                let ((lhs, lhs_info), (rhs, rhs_info)) = self.state.pop2_extra()?;
6928                let lhs = self
6929                    .apply_pending_canonicalization(lhs, lhs_info)?
6930                    .into_float_value();
6931                let rhs = self
6932                    .apply_pending_canonicalization(rhs, rhs_info)?
6933                    .into_float_value();
6934
6935                let res = self
6936                    .build_call_with_param_attributes(
6937                        self.intrinsics.maximum_f64,
6938                        &[lhs.into(), rhs.into()],
6939                        "",
6940                    )?
6941                    .try_as_basic_value()
6942                    .unwrap_basic();
6943
6944                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6945                let res = res.into_float_value();
6946
6947                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
6948            }
6949            Operator::F32x4RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
6950                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6951                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6952                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6953                let res = self
6954                    .build_call_with_param_attributes(
6955                        self.intrinsics.x86_64.max_ps,
6956                        &[v1.into(), v2.into()],
6957                        "",
6958                    )?
6959                    .try_as_basic_value()
6960                    .unwrap_basic();
6961                let res = err!(
6962                    self.builder
6963                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6964                );
6965                self.state.push1_extra(
6966                    res,
6967                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6968                );
6969            }
6970            Operator::F32x4Max | Operator::F32x4RelaxedMax => {
6971                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6972                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
6973                let (v2, i2) = self.v128_into_f32x4(v2, i2)?;
6974                let res = self
6975                    .build_call_with_param_attributes(
6976                        self.intrinsics.maximum_f32x4,
6977                        &[v1.into(), v2.into()],
6978                        "",
6979                    )?
6980                    .try_as_basic_value()
6981                    .unwrap_basic();
6982
6983                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
6984                let res = res.into_vector_value();
6985
6986                let res = err!(
6987                    self.builder
6988                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
6989                );
6990                self.state.push1_extra(
6991                    res,
6992                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f32_nan())?,
6993                );
6994            }
6995            Operator::F32x4PMax => {
6996                // Pseudo-max: a < b ? b : a
6997                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
6998                let (v1, _i1) = self.v128_into_f32x4(v1, i1)?;
6999                let (v2, _i2) = self.v128_into_f32x4(v2, i2)?;
7000                let cmp = err!(
7001                    self.builder
7002                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7003                );
7004                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
7005
7006                let res = err!(
7007                    self.builder
7008                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7009                );
7010                self.state.push1(res);
7011            }
7012            Operator::F64x2RelaxedMax if self.cpu_features.contains(CpuFeature::SSE2) => {
7013                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7014                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
7015                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
7016                let res = self
7017                    .build_call_with_param_attributes(
7018                        self.intrinsics.x86_64.max_pd,
7019                        &[v1.into(), v2.into()],
7020                        "",
7021                    )?
7022                    .try_as_basic_value()
7023                    .unwrap_basic();
7024                let res = err!(
7025                    self.builder
7026                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7027                );
7028                self.state.push1_extra(
7029                    res,
7030                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
7031                );
7032            }
7033            Operator::F64x2Max | Operator::F64x2RelaxedMax => {
7034                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7035                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
7036                let (v2, i2) = self.v128_into_f64x2(v2, i2)?;
7037                let res = self
7038                    .build_call_with_param_attributes(
7039                        self.intrinsics.maximum_f64x2,
7040                        &[v1.into(), v2.into()],
7041                        "",
7042                    )?
7043                    .try_as_basic_value()
7044                    .unwrap_basic();
7045
7046                let res = self.finalize_minmax_result(res.as_basic_value_enum())?;
7047                let res = res.into_vector_value();
7048
7049                let res = err!(
7050                    self.builder
7051                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7052                );
7053                self.state.push1_extra(
7054                    res,
7055                    ((i1.strip_pending() & i2.strip_pending())? | ExtraInfo::pending_f64_nan())?,
7056                );
7057            }
7058            Operator::F64x2PMax => {
7059                // Pseudo-max: a < b ? b : a
7060                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7061                let (v1, _i1) = self.v128_into_f64x2(v1, i1)?;
7062                let (v2, _i2) = self.v128_into_f64x2(v2, i2)?;
7063                let cmp = err!(
7064                    self.builder
7065                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
7066                );
7067                let res = err!(self.builder.build_select(cmp, v2, v1, ""));
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::F32Ceil => {
7075                let (input, info) = self.state.pop1_extra()?;
7076                let res = err!(self.build_call_with_param_attributes(
7077                    self.intrinsics.ceil_f32,
7078                    &[input.into()],
7079                    ""
7080                ))
7081                .try_as_basic_value()
7082                .unwrap_basic();
7083                let (res, info) = self.finalize_rounding_result(res, info)?;
7084                self.state.push1_extra(res, info);
7085            }
7086            Operator::F32x4Ceil => {
7087                let (v, i) = self.state.pop1_extra()?;
7088                let (v, i) = self.v128_into_f32x4(v, i)?;
7089                let res = err!(self.build_call_with_param_attributes(
7090                    self.intrinsics.ceil_f32x4,
7091                    &[v.into()],
7092                    ""
7093                ))
7094                .try_as_basic_value()
7095                .unwrap_basic();
7096                let (res, info) = self.finalize_rounding_result(res, i)?;
7097                let res = err!(
7098                    self.builder
7099                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7100                );
7101                self.state.push1_extra(res, info);
7102            }
7103            Operator::F64Ceil => {
7104                let (input, info) = self.state.pop1_extra()?;
7105                let res = err!(self.build_call_with_param_attributes(
7106                    self.intrinsics.ceil_f64,
7107                    &[input.into()],
7108                    ""
7109                ))
7110                .try_as_basic_value()
7111                .unwrap_basic();
7112                let (res, info) = self.finalize_rounding_result(res, info)?;
7113                self.state.push1_extra(res, info);
7114            }
7115            Operator::F64x2Ceil => {
7116                let (v, i) = self.state.pop1_extra()?;
7117                let (v, i) = self.v128_into_f64x2(v, i)?;
7118                let res = err!(self.build_call_with_param_attributes(
7119                    self.intrinsics.ceil_f64x2,
7120                    &[v.into()],
7121                    ""
7122                ))
7123                .try_as_basic_value()
7124                .unwrap_basic();
7125                let (res, info) = self.finalize_rounding_result(res, i)?;
7126                let res = err!(
7127                    self.builder
7128                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7129                );
7130                self.state.push1_extra(res, info);
7131            }
7132            Operator::F32Floor => {
7133                let (input, info) = self.state.pop1_extra()?;
7134                let res = err!(self.build_call_with_param_attributes(
7135                    self.intrinsics.floor_f32,
7136                    &[input.into()],
7137                    ""
7138                ))
7139                .try_as_basic_value()
7140                .unwrap_basic();
7141                let (res, info) = self.finalize_rounding_result(res, info)?;
7142                self.state.push1_extra(res, info);
7143            }
7144            Operator::F32x4Floor => {
7145                let (v, i) = self.state.pop1_extra()?;
7146                let (v, i) = self.v128_into_f32x4(v, i)?;
7147                let res = err!(self.build_call_with_param_attributes(
7148                    self.intrinsics.floor_f32x4,
7149                    &[v.into()],
7150                    ""
7151                ))
7152                .try_as_basic_value()
7153                .unwrap_basic();
7154                let (res, info) = self.finalize_rounding_result(res, i)?;
7155                let res = err!(
7156                    self.builder
7157                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7158                );
7159                self.state.push1_extra(res, info);
7160            }
7161            Operator::F64Floor => {
7162                let (input, info) = self.state.pop1_extra()?;
7163                let res = err!(self.build_call_with_param_attributes(
7164                    self.intrinsics.floor_f64,
7165                    &[input.into()],
7166                    ""
7167                ))
7168                .try_as_basic_value()
7169                .unwrap_basic();
7170                let (res, info) = self.finalize_rounding_result(res, info)?;
7171                self.state.push1_extra(res, info);
7172            }
7173            Operator::F64x2Floor => {
7174                let (v, i) = self.state.pop1_extra()?;
7175                let (v, i) = self.v128_into_f64x2(v, i)?;
7176                let res = err!(self.build_call_with_param_attributes(
7177                    self.intrinsics.floor_f64x2,
7178                    &[v.into()],
7179                    ""
7180                ))
7181                .try_as_basic_value()
7182                .unwrap_basic();
7183                let (res, info) = self.finalize_rounding_result(res, i)?;
7184                let res = err!(
7185                    self.builder
7186                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7187                );
7188                self.state.push1_extra(res, info);
7189            }
7190            Operator::F32Trunc => {
7191                let (v, info) = self.state.pop1_extra()?;
7192                let res = err!(
7193                    self.builder
7194                        .build_call(self.intrinsics.trunc_f32, &[v.into()], "")
7195                )
7196                .try_as_basic_value()
7197                .unwrap_basic();
7198                let (res, info) = self.finalize_rounding_result(res, info)?;
7199                self.state.push1_extra(res, info);
7200            }
7201            Operator::F32x4Trunc => {
7202                let (v, i) = self.state.pop1_extra()?;
7203                let (v, i) = self.v128_into_f32x4(v, i)?;
7204                let res = err!(self.build_call_with_param_attributes(
7205                    self.intrinsics.trunc_f32x4,
7206                    &[v.into()],
7207                    ""
7208                ))
7209                .try_as_basic_value()
7210                .unwrap_basic();
7211                let (res, info) = self.finalize_rounding_result(res, i)?;
7212                let res = err!(
7213                    self.builder
7214                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7215                );
7216                self.state.push1_extra(res, info);
7217            }
7218            Operator::F64Trunc => {
7219                let (v, info) = self.state.pop1_extra()?;
7220                let res = err!(
7221                    self.builder
7222                        .build_call(self.intrinsics.trunc_f64, &[v.into()], "")
7223                )
7224                .try_as_basic_value()
7225                .unwrap_basic();
7226                let (res, info) = self.finalize_rounding_result(res, info)?;
7227                self.state.push1_extra(res, info);
7228            }
7229            Operator::F64x2Trunc => {
7230                let (v, i) = self.state.pop1_extra()?;
7231                let (v, i) = self.v128_into_f64x2(v, i)?;
7232                let res = err!(self.build_call_with_param_attributes(
7233                    self.intrinsics.trunc_f64x2,
7234                    &[v.into()],
7235                    ""
7236                ))
7237                .try_as_basic_value()
7238                .unwrap_basic();
7239                let (res, info) = self.finalize_rounding_result(res, i)?;
7240                let res = err!(
7241                    self.builder
7242                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7243                );
7244                self.state.push1_extra(res, info);
7245            }
7246            Operator::F32Nearest => {
7247                let (v, info) = self.state.pop1_extra()?;
7248                let res = err!(self.build_call_with_param_attributes(
7249                    self.intrinsics.nearbyint_f32,
7250                    &[v.into()],
7251                    ""
7252                ))
7253                .try_as_basic_value()
7254                .unwrap_basic();
7255                let (res, info) = self.finalize_rounding_result(res, info)?;
7256                self.state.push1_extra(res, info);
7257            }
7258            Operator::F32x4Nearest => {
7259                let (v, i) = self.state.pop1_extra()?;
7260                let (v, i) = self.v128_into_f32x4(v, i)?;
7261                let res = err!(self.build_call_with_param_attributes(
7262                    self.intrinsics.nearbyint_f32x4,
7263                    &[v.into()],
7264                    ""
7265                ))
7266                .try_as_basic_value()
7267                .unwrap_basic();
7268                let (res, info) = self.finalize_rounding_result(res, i)?;
7269                let res = err!(
7270                    self.builder
7271                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7272                );
7273                self.state.push1_extra(res, info);
7274            }
7275            Operator::F64Nearest => {
7276                let (v, info) = self.state.pop1_extra()?;
7277                let res = err!(self.build_call_with_param_attributes(
7278                    self.intrinsics.nearbyint_f64,
7279                    &[v.into()],
7280                    ""
7281                ))
7282                .try_as_basic_value()
7283                .unwrap_basic();
7284                let (res, info) = self.finalize_rounding_result(res, info)?;
7285                self.state.push1_extra(res, info);
7286            }
7287            Operator::F64x2Nearest => {
7288                let (v, i) = self.state.pop1_extra()?;
7289                let (v, i) = self.v128_into_f64x2(v, i)?;
7290                let res = err!(self.build_call_with_param_attributes(
7291                    self.intrinsics.nearbyint_f64x2,
7292                    &[v.into()],
7293                    ""
7294                ))
7295                .try_as_basic_value()
7296                .unwrap_basic();
7297                let (res, info) = self.finalize_rounding_result(res, i)?;
7298                let res = err!(
7299                    self.builder
7300                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7301                );
7302                self.state.push1_extra(res, info);
7303            }
7304            Operator::F32Abs => {
7305                let (v, i) = self.state.pop1_extra()?;
7306                let v = self.apply_pending_canonicalization(v, i)?;
7307                let res = err!(
7308                    self.builder
7309                        .build_call(self.intrinsics.fabs_f32, &[v.into()], "")
7310                )
7311                .try_as_basic_value()
7312                .unwrap_basic();
7313                // The exact NaN returned by F32Abs is fully defined. Do not
7314                // adjust.
7315                self.state.push1_extra(res, i.strip_pending());
7316            }
7317            Operator::F64Abs => {
7318                let (v, i) = self.state.pop1_extra()?;
7319                let v = self.apply_pending_canonicalization(v, i)?;
7320                let res = err!(
7321                    self.builder
7322                        .build_call(self.intrinsics.fabs_f64, &[v.into()], "")
7323                )
7324                .try_as_basic_value()
7325                .unwrap_basic();
7326                // The exact NaN returned by F64Abs is fully defined. Do not
7327                // adjust.
7328                self.state.push1_extra(res, i.strip_pending());
7329            }
7330            Operator::F32x4Abs => {
7331                let (v, i) = self.state.pop1_extra()?;
7332                let v = err!(self.builder.build_bit_cast(
7333                    v.into_int_value(),
7334                    self.intrinsics.f32x4_ty,
7335                    ""
7336                ));
7337                let v = self.apply_pending_canonicalization(v, i)?;
7338                let res = self
7339                    .build_call_with_param_attributes(self.intrinsics.fabs_f32x4, &[v.into()], "")?
7340                    .try_as_basic_value()
7341                    .unwrap_basic();
7342                let res = err!(
7343                    self.builder
7344                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7345                );
7346                // The exact NaN returned by F32x4Abs is fully defined. Do not
7347                // adjust.
7348                self.state.push1_extra(res, i.strip_pending());
7349            }
7350            Operator::F64x2Abs => {
7351                let (v, i) = self.state.pop1_extra()?;
7352                let v = err!(self.builder.build_bit_cast(
7353                    v.into_int_value(),
7354                    self.intrinsics.f64x2_ty,
7355                    ""
7356                ));
7357                let v = self.apply_pending_canonicalization(v, i)?;
7358                let res = self
7359                    .build_call_with_param_attributes(self.intrinsics.fabs_f64x2, &[v.into()], "")?
7360                    .try_as_basic_value()
7361                    .unwrap_basic();
7362                let res = err!(
7363                    self.builder
7364                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7365                );
7366                // The exact NaN returned by F32x4Abs is fully defined. Do not
7367                // adjust.
7368                self.state.push1_extra(res, i.strip_pending());
7369            }
7370            Operator::F32x4Neg => {
7371                let (v, i) = self.state.pop1_extra()?;
7372                let v = err!(self.builder.build_bit_cast(
7373                    v.into_int_value(),
7374                    self.intrinsics.f32x4_ty,
7375                    ""
7376                ));
7377                let v = self
7378                    .apply_pending_canonicalization(v, i)?
7379                    .into_vector_value();
7380                let res = err!(self.builder.build_float_neg(v, ""));
7381                let res = err!(
7382                    self.builder
7383                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7384                );
7385                // The exact NaN returned by F32x4Neg is fully defined. Do not
7386                // adjust.
7387                self.state.push1_extra(res, i.strip_pending());
7388            }
7389            Operator::F64x2Neg => {
7390                let (v, i) = self.state.pop1_extra()?;
7391                let v = err!(self.builder.build_bit_cast(
7392                    v.into_int_value(),
7393                    self.intrinsics.f64x2_ty,
7394                    ""
7395                ));
7396                let v = self
7397                    .apply_pending_canonicalization(v, i)?
7398                    .into_vector_value();
7399                let res = err!(self.builder.build_float_neg(v, ""));
7400                let res = err!(
7401                    self.builder
7402                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7403                );
7404                // The exact NaN returned by F64x2Neg is fully defined. Do not
7405                // adjust.
7406                self.state.push1_extra(res, i.strip_pending());
7407            }
7408            Operator::F32Neg | Operator::F64Neg => {
7409                let (v, i) = self.state.pop1_extra()?;
7410                let v = self
7411                    .apply_pending_canonicalization(v, i)?
7412                    .into_float_value();
7413                let res = err!(self.builder.build_float_neg(v, ""));
7414                // The exact NaN returned by F32Neg and F64Neg are fully defined.
7415                // Do not adjust.
7416                self.state.push1_extra(res, i.strip_pending());
7417            }
7418            Operator::F32Copysign => {
7419                let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
7420                let mag = self.apply_pending_canonicalization(mag, mag_info)?;
7421                let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
7422                let res = self
7423                    .build_call_with_param_attributes(
7424                        self.intrinsics.copysign_f32,
7425                        &[mag.into(), sgn.into()],
7426                        "",
7427                    )?
7428                    .try_as_basic_value()
7429                    .unwrap_basic();
7430                // The exact NaN returned by F32Copysign is fully defined.
7431                // Do not adjust.
7432                self.state.push1_extra(res, mag_info.strip_pending());
7433            }
7434            Operator::F64Copysign => {
7435                let ((mag, mag_info), (sgn, sgn_info)) = self.state.pop2_extra()?;
7436                let mag = self.apply_pending_canonicalization(mag, mag_info)?;
7437                let sgn = self.apply_pending_canonicalization(sgn, sgn_info)?;
7438                let res = self
7439                    .build_call_with_param_attributes(
7440                        self.intrinsics.copysign_f64,
7441                        &[mag.into(), sgn.into()],
7442                        "",
7443                    )?
7444                    .try_as_basic_value()
7445                    .unwrap_basic();
7446                // The exact NaN returned by F32Copysign is fully defined.
7447                // Do not adjust.
7448                self.state.push1_extra(res, mag_info.strip_pending());
7449            }
7450            _ => unreachable!(),
7451        }
7452        Ok(())
7453    }
7454
7455    // Integer Comparison instructions.
7456    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#integer-comparison-instructions
7457    fn translate_integer_comparison_operator(&mut self, op: Operator) -> Result<(), CompileError> {
7458        match op {
7459            Operator::I32Eq | Operator::I64Eq => {
7460                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7461                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7462                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7463                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7464                let cond = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7465                let res = err!(
7466                    self.builder
7467                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7468                );
7469                self.state.push1_extra(
7470                    res,
7471                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7472                );
7473            }
7474            Operator::I8x16Eq => {
7475                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7476                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7477                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7478                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7479                let res = err!(
7480                    self.builder
7481                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7482                );
7483                let res = err!(
7484                    self.builder
7485                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7486                );
7487                self.state.push1(res);
7488            }
7489            Operator::I16x8Eq => {
7490                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7491                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7492                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7493                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7494                let res = err!(
7495                    self.builder
7496                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7497                );
7498                let res = err!(
7499                    self.builder
7500                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7501                );
7502                self.state.push1(res);
7503            }
7504            Operator::I32x4Eq => {
7505                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7506                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7507                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7508                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7509                let res = err!(
7510                    self.builder
7511                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7512                );
7513                let res = err!(
7514                    self.builder
7515                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7516                );
7517                self.state.push1(res);
7518            }
7519            Operator::I64x2Eq => {
7520                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7521                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7522                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7523                let res = err!(self.builder.build_int_compare(IntPredicate::EQ, v1, v2, ""));
7524                let res = err!(
7525                    self.builder
7526                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7527                );
7528                let res = err!(
7529                    self.builder
7530                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7531                );
7532                self.state.push1(res);
7533            }
7534            Operator::I32Ne | Operator::I64Ne => {
7535                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7536                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7537                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7538                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7539                let cond = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7540                let res = err!(
7541                    self.builder
7542                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7543                );
7544                self.state.push1_extra(
7545                    res,
7546                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7547                );
7548            }
7549            Operator::I8x16Ne => {
7550                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7551                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7552                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7553                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7554                let res = err!(
7555                    self.builder
7556                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7557                );
7558                let res = err!(
7559                    self.builder
7560                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7561                );
7562                self.state.push1(res);
7563            }
7564            Operator::I16x8Ne => {
7565                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7566                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7567                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7568                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7569                let res = err!(
7570                    self.builder
7571                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7572                );
7573                let res = err!(
7574                    self.builder
7575                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7576                );
7577                self.state.push1(res);
7578            }
7579            Operator::I32x4Ne => {
7580                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7581                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7582                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7583                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7584                let res = err!(
7585                    self.builder
7586                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7587                );
7588                let res = err!(
7589                    self.builder
7590                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7591                );
7592                self.state.push1(res);
7593            }
7594            Operator::I64x2Ne => {
7595                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7596                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7597                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7598                let res = err!(self.builder.build_int_compare(IntPredicate::NE, v1, v2, ""));
7599                let res = err!(
7600                    self.builder
7601                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7602                );
7603                let res = err!(
7604                    self.builder
7605                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7606                );
7607                self.state.push1(res);
7608            }
7609            Operator::I32LtS | Operator::I64LtS => {
7610                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7611                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7612                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7613                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7614                let cond = err!(
7615                    self.builder
7616                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7617                );
7618                let res = err!(
7619                    self.builder
7620                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7621                );
7622                self.state.push1_extra(
7623                    res,
7624                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7625                );
7626            }
7627            Operator::I8x16LtS => {
7628                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7629                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7630                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7631                let res = err!(
7632                    self.builder
7633                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7634                );
7635                let res = err!(
7636                    self.builder
7637                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7638                );
7639                let res = err!(
7640                    self.builder
7641                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7642                );
7643                self.state.push1(res);
7644            }
7645            Operator::I16x8LtS => {
7646                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7647                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7648                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7649                let res = err!(
7650                    self.builder
7651                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7652                );
7653                let res = err!(
7654                    self.builder
7655                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7656                );
7657                let res = err!(
7658                    self.builder
7659                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7660                );
7661                self.state.push1(res);
7662            }
7663            Operator::I32x4LtS => {
7664                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7665                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7666                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7667                let res = err!(
7668                    self.builder
7669                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7670                );
7671                let res = err!(
7672                    self.builder
7673                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7674                );
7675                let res = err!(
7676                    self.builder
7677                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7678                );
7679                self.state.push1(res);
7680            }
7681            Operator::I64x2LtS => {
7682                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7683                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7684                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7685                let res = err!(
7686                    self.builder
7687                        .build_int_compare(IntPredicate::SLT, v1, v2, "")
7688                );
7689                let res = err!(
7690                    self.builder
7691                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7692                );
7693                let res = err!(
7694                    self.builder
7695                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7696                );
7697                self.state.push1(res);
7698            }
7699            Operator::I32LtU | Operator::I64LtU => {
7700                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7701                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7702                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7703                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7704                let cond = err!(
7705                    self.builder
7706                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7707                );
7708                let res = err!(
7709                    self.builder
7710                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7711                );
7712                self.state.push1(res);
7713            }
7714            Operator::I8x16LtU => {
7715                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7716                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7717                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7718                let res = err!(
7719                    self.builder
7720                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7721                );
7722                let res = err!(
7723                    self.builder
7724                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7725                );
7726                let res = err!(
7727                    self.builder
7728                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7729                );
7730                self.state.push1(res);
7731            }
7732            Operator::I16x8LtU => {
7733                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7734                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7735                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7736                let res = err!(
7737                    self.builder
7738                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7739                );
7740                let res = err!(
7741                    self.builder
7742                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7743                );
7744                let res = err!(
7745                    self.builder
7746                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7747                );
7748                self.state.push1(res);
7749            }
7750            Operator::I32x4LtU => {
7751                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7752                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7753                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7754                let res = err!(
7755                    self.builder
7756                        .build_int_compare(IntPredicate::ULT, v1, v2, "")
7757                );
7758                let res = err!(
7759                    self.builder
7760                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7761                );
7762                let res = err!(
7763                    self.builder
7764                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7765                );
7766                self.state.push1(res);
7767            }
7768            Operator::I32LeS | Operator::I64LeS => {
7769                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7770                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7771                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7772                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7773                let cond = err!(
7774                    self.builder
7775                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7776                );
7777                let res = err!(
7778                    self.builder
7779                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7780                );
7781                self.state.push1_extra(
7782                    res,
7783                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7784                );
7785            }
7786            Operator::I8x16LeS => {
7787                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7788                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7789                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7790                let res = err!(
7791                    self.builder
7792                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7793                );
7794                let res = err!(
7795                    self.builder
7796                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7797                );
7798                let res = err!(
7799                    self.builder
7800                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7801                );
7802                self.state.push1(res);
7803            }
7804            Operator::I16x8LeS => {
7805                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7806                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7807                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7808                let res = err!(
7809                    self.builder
7810                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7811                );
7812                let res = err!(
7813                    self.builder
7814                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7815                );
7816                let res = err!(
7817                    self.builder
7818                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7819                );
7820                self.state.push1(res);
7821            }
7822            Operator::I32x4LeS => {
7823                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7824                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7825                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7826                let res = err!(
7827                    self.builder
7828                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7829                );
7830                let res = err!(
7831                    self.builder
7832                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7833                );
7834                let res = err!(
7835                    self.builder
7836                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7837                );
7838                self.state.push1(res);
7839            }
7840            Operator::I64x2LeS => {
7841                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7842                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
7843                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
7844                let res = err!(
7845                    self.builder
7846                        .build_int_compare(IntPredicate::SLE, v1, v2, "")
7847                );
7848                let res = err!(
7849                    self.builder
7850                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
7851                );
7852                let res = err!(
7853                    self.builder
7854                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7855                );
7856                self.state.push1(res);
7857            }
7858            Operator::I32LeU | Operator::I64LeU => {
7859                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7860                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7861                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7862                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7863                let cond = err!(
7864                    self.builder
7865                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7866                );
7867                let res = err!(
7868                    self.builder
7869                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7870                );
7871                self.state.push1_extra(
7872                    res,
7873                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7874                );
7875            }
7876            Operator::I8x16LeU => {
7877                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7878                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7879                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7880                let res = err!(
7881                    self.builder
7882                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7883                );
7884                let res = err!(
7885                    self.builder
7886                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7887                );
7888                let res = err!(
7889                    self.builder
7890                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7891                );
7892                self.state.push1(res);
7893            }
7894            Operator::I16x8LeU => {
7895                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7896                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7897                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7898                let res = err!(
7899                    self.builder
7900                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7901                );
7902                let res = err!(
7903                    self.builder
7904                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7905                );
7906                let res = err!(
7907                    self.builder
7908                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7909                );
7910                self.state.push1(res);
7911            }
7912            Operator::I32x4LeU => {
7913                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7914                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7915                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7916                let res = err!(
7917                    self.builder
7918                        .build_int_compare(IntPredicate::ULE, v1, v2, "")
7919                );
7920                let res = err!(
7921                    self.builder
7922                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7923                );
7924                let res = err!(
7925                    self.builder
7926                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7927                );
7928                self.state.push1(res);
7929            }
7930            Operator::I32GtS | Operator::I64GtS => {
7931                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7932                let v1 = self.apply_pending_canonicalization(v1, i1)?;
7933                let v2 = self.apply_pending_canonicalization(v2, i2)?;
7934                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
7935                let cond = err!(
7936                    self.builder
7937                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7938                );
7939                let res = err!(
7940                    self.builder
7941                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
7942                );
7943                self.state.push1_extra(
7944                    res,
7945                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
7946                );
7947            }
7948            Operator::I8x16GtS => {
7949                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7950                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
7951                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
7952                let res = err!(
7953                    self.builder
7954                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7955                );
7956                let res = err!(
7957                    self.builder
7958                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
7959                );
7960                let res = err!(
7961                    self.builder
7962                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7963                );
7964                self.state.push1(res);
7965            }
7966            Operator::I16x8GtS => {
7967                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7968                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
7969                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
7970                let res = err!(
7971                    self.builder
7972                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7973                );
7974                let res = err!(
7975                    self.builder
7976                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
7977                );
7978                let res = err!(
7979                    self.builder
7980                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7981                );
7982                self.state.push1(res);
7983            }
7984            Operator::I32x4GtS => {
7985                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
7986                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
7987                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
7988                let res = err!(
7989                    self.builder
7990                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
7991                );
7992                let res = err!(
7993                    self.builder
7994                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
7995                );
7996                let res = err!(
7997                    self.builder
7998                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
7999                );
8000                self.state.push1(res);
8001            }
8002            Operator::I64x2GtS => {
8003                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8004                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
8005                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
8006                let res = err!(
8007                    self.builder
8008                        .build_int_compare(IntPredicate::SGT, v1, v2, "")
8009                );
8010                let res = err!(
8011                    self.builder
8012                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8013                );
8014                let res = err!(
8015                    self.builder
8016                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8017                );
8018                self.state.push1(res);
8019            }
8020            Operator::I32GtU | Operator::I64GtU => {
8021                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8022                let v1 = self.apply_pending_canonicalization(v1, i1)?;
8023                let v2 = self.apply_pending_canonicalization(v2, i2)?;
8024                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
8025                let cond = err!(
8026                    self.builder
8027                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
8028                );
8029                let res = err!(
8030                    self.builder
8031                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8032                );
8033                self.state.push1_extra(
8034                    res,
8035                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8036                );
8037            }
8038            Operator::I8x16GtU => {
8039                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8040                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
8041                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
8042                let res = err!(
8043                    self.builder
8044                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
8045                );
8046                let res = err!(
8047                    self.builder
8048                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
8049                );
8050                let res = err!(
8051                    self.builder
8052                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8053                );
8054                self.state.push1(res);
8055            }
8056            Operator::I16x8GtU => {
8057                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8058                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8059                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8060                let res = err!(
8061                    self.builder
8062                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
8063                );
8064                let res = err!(
8065                    self.builder
8066                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
8067                );
8068                let res = err!(
8069                    self.builder
8070                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8071                );
8072                self.state.push1(res);
8073            }
8074            Operator::I32x4GtU => {
8075                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8076                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8077                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8078                let res = err!(
8079                    self.builder
8080                        .build_int_compare(IntPredicate::UGT, v1, v2, "")
8081                );
8082                let res = err!(
8083                    self.builder
8084                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8085                );
8086                let res = err!(
8087                    self.builder
8088                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8089                );
8090                self.state.push1(res);
8091            }
8092            Operator::I32GeS | Operator::I64GeS => {
8093                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8094                let v1 = self.apply_pending_canonicalization(v1, i1)?;
8095                let v2 = self.apply_pending_canonicalization(v2, i2)?;
8096                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
8097                let cond = err!(
8098                    self.builder
8099                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
8100                );
8101                let res = err!(
8102                    self.builder
8103                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8104                );
8105                self.state.push1(res);
8106            }
8107            Operator::I8x16GeS => {
8108                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8109                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
8110                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
8111                let res = err!(
8112                    self.builder
8113                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
8114                );
8115                let res = err!(
8116                    self.builder
8117                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
8118                );
8119                let res = err!(
8120                    self.builder
8121                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8122                );
8123                self.state.push1(res);
8124            }
8125            Operator::I16x8GeS => {
8126                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8127                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8128                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8129                let res = err!(
8130                    self.builder
8131                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
8132                );
8133                let res = err!(
8134                    self.builder
8135                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
8136                );
8137                let res = err!(
8138                    self.builder
8139                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8140                );
8141                self.state.push1(res);
8142            }
8143            Operator::I32x4GeS => {
8144                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8145                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8146                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8147                let res = err!(
8148                    self.builder
8149                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
8150                );
8151                let res = err!(
8152                    self.builder
8153                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8154                );
8155                let res = err!(
8156                    self.builder
8157                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8158                );
8159                self.state.push1(res);
8160            }
8161            Operator::I64x2GeS => {
8162                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8163                let (v1, _) = self.v128_into_i64x2(v1, i1)?;
8164                let (v2, _) = self.v128_into_i64x2(v2, i2)?;
8165                let res = err!(
8166                    self.builder
8167                        .build_int_compare(IntPredicate::SGE, v1, v2, "")
8168                );
8169                let res = err!(
8170                    self.builder
8171                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8172                );
8173                let res = err!(
8174                    self.builder
8175                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8176                );
8177                self.state.push1(res);
8178            }
8179            Operator::I32GeU | Operator::I64GeU => {
8180                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8181                let v1 = self.apply_pending_canonicalization(v1, i1)?;
8182                let v2 = self.apply_pending_canonicalization(v2, i2)?;
8183                let (v1, v2) = (v1.into_int_value(), v2.into_int_value());
8184                let cond = err!(
8185                    self.builder
8186                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
8187                );
8188                let res = err!(
8189                    self.builder
8190                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8191                );
8192                self.state.push1_extra(
8193                    res,
8194                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8195                );
8196            }
8197            Operator::I8x16GeU => {
8198                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8199                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
8200                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
8201                let res = err!(
8202                    self.builder
8203                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
8204                );
8205                let res = err!(
8206                    self.builder
8207                        .build_int_s_extend(res, self.intrinsics.i8x16_ty, "")
8208                );
8209                let res = err!(
8210                    self.builder
8211                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8212                );
8213                self.state.push1(res);
8214            }
8215            Operator::I16x8GeU => {
8216                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8217                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8218                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8219                let res = err!(
8220                    self.builder
8221                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
8222                );
8223                let res = err!(
8224                    self.builder
8225                        .build_int_s_extend(res, self.intrinsics.i16x8_ty, "")
8226                );
8227                let res = err!(
8228                    self.builder
8229                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8230                );
8231                self.state.push1(res);
8232            }
8233            Operator::I32x4GeU => {
8234                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8235                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
8236                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
8237                let res = err!(
8238                    self.builder
8239                        .build_int_compare(IntPredicate::UGE, v1, v2, "")
8240                );
8241                let res = err!(
8242                    self.builder
8243                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8244                );
8245                let res = err!(
8246                    self.builder
8247                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8248                );
8249                self.state.push1(res);
8250            }
8251            _ => unreachable!(),
8252        }
8253        Ok(())
8254    }
8255
8256    // Floating-Point Comparison instructions.
8257    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#floating-point-comparison-instructions
8258    fn translate_floating_point_comparison_operator(
8259        &mut self,
8260        op: Operator,
8261    ) -> Result<(), CompileError> {
8262        match op {
8263            Operator::F32Eq | Operator::F64Eq => {
8264                let (v1, v2) = self.state.pop2()?;
8265                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8266                let cond = err!(
8267                    self.builder
8268                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8269                );
8270                let res = err!(
8271                    self.builder
8272                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8273                );
8274                self.state.push1_extra(
8275                    res,
8276                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8277                );
8278            }
8279            Operator::F32x4Eq => {
8280                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8281                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8282                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8283                let res = err!(
8284                    self.builder
8285                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8286                );
8287                let res = err!(
8288                    self.builder
8289                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8290                );
8291                let res = err!(
8292                    self.builder
8293                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8294                );
8295                self.state.push1(res);
8296            }
8297            Operator::F64x2Eq => {
8298                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8299                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8300                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8301                let res = err!(
8302                    self.builder
8303                        .build_float_compare(FloatPredicate::OEQ, v1, v2, "")
8304                );
8305                let res = err!(
8306                    self.builder
8307                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8308                );
8309                let res = err!(
8310                    self.builder
8311                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8312                );
8313                self.state.push1(res);
8314            }
8315            Operator::F32Ne | Operator::F64Ne => {
8316                let (v1, v2) = self.state.pop2()?;
8317                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8318                let cond = err!(
8319                    self.builder
8320                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8321                );
8322                let res = err!(
8323                    self.builder
8324                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8325                );
8326                self.state.push1_extra(
8327                    res,
8328                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8329                );
8330            }
8331            Operator::F32x4Ne => {
8332                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8333                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8334                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8335                let res = err!(
8336                    self.builder
8337                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8338                );
8339                let res = err!(
8340                    self.builder
8341                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8342                );
8343                let res = err!(
8344                    self.builder
8345                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8346                );
8347                self.state.push1(res);
8348            }
8349            Operator::F64x2Ne => {
8350                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8351                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8352                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8353                let res = err!(
8354                    self.builder
8355                        .build_float_compare(FloatPredicate::UNE, v1, v2, "")
8356                );
8357                let res = err!(
8358                    self.builder
8359                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8360                );
8361                let res = err!(
8362                    self.builder
8363                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8364                );
8365                self.state.push1(res);
8366            }
8367            Operator::F32Lt | Operator::F64Lt => {
8368                let (v1, v2) = self.state.pop2()?;
8369                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8370                let cond = err!(
8371                    self.builder
8372                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8373                );
8374                let res = err!(
8375                    self.builder
8376                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8377                );
8378                self.state.push1_extra(
8379                    res,
8380                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8381                );
8382            }
8383            Operator::F32x4Lt => {
8384                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8385                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8386                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8387                let res = err!(
8388                    self.builder
8389                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8390                );
8391                let res = err!(
8392                    self.builder
8393                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8394                );
8395                let res = err!(
8396                    self.builder
8397                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8398                );
8399                self.state.push1(res);
8400            }
8401            Operator::F64x2Lt => {
8402                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8403                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8404                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8405                let res = err!(
8406                    self.builder
8407                        .build_float_compare(FloatPredicate::OLT, v1, v2, "")
8408                );
8409                let res = err!(
8410                    self.builder
8411                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8412                );
8413                let res = err!(
8414                    self.builder
8415                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8416                );
8417                self.state.push1(res);
8418            }
8419            Operator::F32Le | Operator::F64Le => {
8420                let (v1, v2) = self.state.pop2()?;
8421                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8422                let cond = err!(
8423                    self.builder
8424                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8425                );
8426                let res = err!(
8427                    self.builder
8428                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8429                );
8430                self.state.push1_extra(
8431                    res,
8432                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8433                );
8434            }
8435            Operator::F32x4Le => {
8436                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8437                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8438                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8439                let res = err!(
8440                    self.builder
8441                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8442                );
8443                let res = err!(
8444                    self.builder
8445                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8446                );
8447                let res = err!(
8448                    self.builder
8449                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8450                );
8451                self.state.push1(res);
8452            }
8453            Operator::F64x2Le => {
8454                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8455                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8456                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8457                let res = err!(
8458                    self.builder
8459                        .build_float_compare(FloatPredicate::OLE, v1, v2, "")
8460                );
8461                let res = err!(
8462                    self.builder
8463                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8464                );
8465                let res = err!(
8466                    self.builder
8467                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8468                );
8469                self.state.push1(res);
8470            }
8471            Operator::F32Gt | Operator::F64Gt => {
8472                let (v1, v2) = self.state.pop2()?;
8473                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8474                let cond = err!(
8475                    self.builder
8476                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8477                );
8478                let res = err!(
8479                    self.builder
8480                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8481                );
8482                self.state.push1_extra(
8483                    res,
8484                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8485                );
8486            }
8487            Operator::F32x4Gt => {
8488                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8489                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8490                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8491                let res = err!(
8492                    self.builder
8493                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8494                );
8495                let res = err!(
8496                    self.builder
8497                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8498                );
8499                let res = err!(
8500                    self.builder
8501                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8502                );
8503                self.state.push1(res);
8504            }
8505            Operator::F64x2Gt => {
8506                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8507                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8508                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8509                let res = err!(
8510                    self.builder
8511                        .build_float_compare(FloatPredicate::OGT, v1, v2, "")
8512                );
8513                let res = err!(
8514                    self.builder
8515                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8516                );
8517                let res = err!(
8518                    self.builder
8519                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8520                );
8521                self.state.push1(res);
8522            }
8523            Operator::F32Ge | Operator::F64Ge => {
8524                let (v1, v2) = self.state.pop2()?;
8525                let (v1, v2) = (v1.into_float_value(), v2.into_float_value());
8526                let cond = err!(
8527                    self.builder
8528                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8529                );
8530                let res = err!(
8531                    self.builder
8532                        .build_int_z_extend(cond, self.intrinsics.i32_ty, "")
8533                );
8534                self.state.push1_extra(
8535                    res,
8536                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
8537                );
8538            }
8539            Operator::F32x4Ge => {
8540                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8541                let (v1, _) = self.v128_into_f32x4(v1, i1)?;
8542                let (v2, _) = self.v128_into_f32x4(v2, i2)?;
8543                let res = err!(
8544                    self.builder
8545                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8546                );
8547                let res = err!(
8548                    self.builder
8549                        .build_int_s_extend(res, self.intrinsics.i32x4_ty, "")
8550                );
8551                let res = err!(
8552                    self.builder
8553                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8554                );
8555                self.state.push1(res);
8556            }
8557            Operator::F64x2Ge => {
8558                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8559                let (v1, _) = self.v128_into_f64x2(v1, i1)?;
8560                let (v2, _) = self.v128_into_f64x2(v2, i2)?;
8561                let res = err!(
8562                    self.builder
8563                        .build_float_compare(FloatPredicate::OGE, v1, v2, "")
8564                );
8565                let res = err!(
8566                    self.builder
8567                        .build_int_s_extend(res, self.intrinsics.i64x2_ty, "")
8568                );
8569                let res = err!(
8570                    self.builder
8571                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8572                );
8573                self.state.push1(res);
8574            }
8575            _ => unreachable!(),
8576        }
8577        Ok(())
8578    }
8579
8580    // Conversion instructions.
8581    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#conversion-instructions
8582    fn translate_conversion_operator(&mut self, op: Operator) -> Result<(), CompileError> {
8583        match op {
8584            Operator::I32WrapI64 => {
8585                let (v, i) = self.state.pop1_extra()?;
8586                let v = self.apply_pending_canonicalization(v, i)?;
8587                let v = v.into_int_value();
8588                let res = err!(
8589                    self.builder
8590                        .build_int_truncate(v, self.intrinsics.i32_ty, "")
8591                );
8592                self.state.push1(res);
8593            }
8594            Operator::I64ExtendI32S => {
8595                let (v, i) = self.state.pop1_extra()?;
8596                let v = self.apply_pending_canonicalization(v, i)?;
8597                let v = v.into_int_value();
8598                let res = err!(
8599                    self.builder
8600                        .build_int_s_extend(v, self.intrinsics.i64_ty, "")
8601                );
8602                self.state.push1(res);
8603            }
8604            Operator::I64ExtendI32U => {
8605                let (v, i) = self.state.pop1_extra()?;
8606                let v = self.apply_pending_canonicalization(v, i)?;
8607                let v = v.into_int_value();
8608                let res = err!(
8609                    self.builder
8610                        .build_int_z_extend(v, self.intrinsics.i64_ty, "")
8611                );
8612                self.state.push1_extra(res, ExtraInfo::arithmetic_f64());
8613            }
8614            Operator::I16x8ExtendLowI8x16S => {
8615                let (v, i) = self.state.pop1_extra()?;
8616                let (v, _) = self.v128_into_i8x16(v, i)?;
8617                let low = err!(self.builder.build_shuffle_vector(
8618                    v,
8619                    v.get_type().get_undef(),
8620                    VectorType::const_vector(&[
8621                        self.intrinsics.i32_consts[0],
8622                        self.intrinsics.i32_consts[1],
8623                        self.intrinsics.i32_consts[2],
8624                        self.intrinsics.i32_consts[3],
8625                        self.intrinsics.i32_consts[4],
8626                        self.intrinsics.i32_consts[5],
8627                        self.intrinsics.i32_consts[6],
8628                        self.intrinsics.i32_consts[7],
8629                    ]),
8630                    "",
8631                ));
8632                let res = err!(
8633                    self.builder
8634                        .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
8635                );
8636                let res = err!(
8637                    self.builder
8638                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8639                );
8640                self.state.push1(res);
8641            }
8642            Operator::I16x8ExtendHighI8x16S => {
8643                let (v, i) = self.state.pop1_extra()?;
8644                let (v, _) = self.v128_into_i8x16(v, i)?;
8645                let low = err!(self.builder.build_shuffle_vector(
8646                    v,
8647                    v.get_type().get_undef(),
8648                    VectorType::const_vector(&[
8649                        self.intrinsics.i32_consts[8],
8650                        self.intrinsics.i32_consts[9],
8651                        self.intrinsics.i32_consts[10],
8652                        self.intrinsics.i32_consts[11],
8653                        self.intrinsics.i32_consts[12],
8654                        self.intrinsics.i32_consts[13],
8655                        self.intrinsics.i32_consts[14],
8656                        self.intrinsics.i32_consts[15],
8657                    ]),
8658                    "",
8659                ));
8660                let res = err!(
8661                    self.builder
8662                        .build_int_s_extend(low, self.intrinsics.i16x8_ty, "")
8663                );
8664                let res = err!(
8665                    self.builder
8666                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8667                );
8668                self.state.push1(res);
8669            }
8670            Operator::I16x8ExtendLowI8x16U => {
8671                let (v, i) = self.state.pop1_extra()?;
8672                let (v, _) = self.v128_into_i8x16(v, i)?;
8673                let low = err!(self.builder.build_shuffle_vector(
8674                    v,
8675                    v.get_type().get_undef(),
8676                    VectorType::const_vector(&[
8677                        self.intrinsics.i32_consts[0],
8678                        self.intrinsics.i32_consts[1],
8679                        self.intrinsics.i32_consts[2],
8680                        self.intrinsics.i32_consts[3],
8681                        self.intrinsics.i32_consts[4],
8682                        self.intrinsics.i32_consts[5],
8683                        self.intrinsics.i32_consts[6],
8684                        self.intrinsics.i32_consts[7],
8685                    ]),
8686                    "",
8687                ));
8688                let res = err!(
8689                    self.builder
8690                        .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8691                );
8692                let res = err!(
8693                    self.builder
8694                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8695                );
8696                self.state.push1(res);
8697            }
8698            Operator::I16x8ExtendHighI8x16U => {
8699                let (v, i) = self.state.pop1_extra()?;
8700                let (v, _) = self.v128_into_i8x16(v, i)?;
8701                let low = err!(self.builder.build_shuffle_vector(
8702                    v,
8703                    v.get_type().get_undef(),
8704                    VectorType::const_vector(&[
8705                        self.intrinsics.i32_consts[8],
8706                        self.intrinsics.i32_consts[9],
8707                        self.intrinsics.i32_consts[10],
8708                        self.intrinsics.i32_consts[11],
8709                        self.intrinsics.i32_consts[12],
8710                        self.intrinsics.i32_consts[13],
8711                        self.intrinsics.i32_consts[14],
8712                        self.intrinsics.i32_consts[15],
8713                    ]),
8714                    "",
8715                ));
8716                let res = err!(
8717                    self.builder
8718                        .build_int_z_extend(low, self.intrinsics.i16x8_ty, "")
8719                );
8720                let res = err!(
8721                    self.builder
8722                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8723                );
8724                self.state.push1(res);
8725            }
8726            Operator::I32x4ExtendLowI16x8S => {
8727                let (v, i) = self.state.pop1_extra()?;
8728                let (v, _) = self.v128_into_i16x8(v, i)?;
8729                let low = err!(self.builder.build_shuffle_vector(
8730                    v,
8731                    v.get_type().get_undef(),
8732                    VectorType::const_vector(&[
8733                        self.intrinsics.i32_consts[0],
8734                        self.intrinsics.i32_consts[1],
8735                        self.intrinsics.i32_consts[2],
8736                        self.intrinsics.i32_consts[3],
8737                    ]),
8738                    "",
8739                ));
8740                let res = err!(
8741                    self.builder
8742                        .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8743                );
8744                let res = err!(
8745                    self.builder
8746                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8747                );
8748                self.state.push1(res);
8749            }
8750            Operator::I32x4ExtendHighI16x8S => {
8751                let (v, i) = self.state.pop1_extra()?;
8752                let (v, _) = self.v128_into_i16x8(v, i)?;
8753                let low = err!(self.builder.build_shuffle_vector(
8754                    v,
8755                    v.get_type().get_undef(),
8756                    VectorType::const_vector(&[
8757                        self.intrinsics.i32_consts[4],
8758                        self.intrinsics.i32_consts[5],
8759                        self.intrinsics.i32_consts[6],
8760                        self.intrinsics.i32_consts[7],
8761                    ]),
8762                    "",
8763                ));
8764                let res = err!(
8765                    self.builder
8766                        .build_int_s_extend(low, self.intrinsics.i32x4_ty, "")
8767                );
8768                let res = err!(
8769                    self.builder
8770                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8771                );
8772                self.state.push1(res);
8773            }
8774            Operator::I32x4ExtendLowI16x8U => {
8775                let (v, i) = self.state.pop1_extra()?;
8776                let (v, _) = self.v128_into_i16x8(v, i)?;
8777                let low = err!(self.builder.build_shuffle_vector(
8778                    v,
8779                    v.get_type().get_undef(),
8780                    VectorType::const_vector(&[
8781                        self.intrinsics.i32_consts[0],
8782                        self.intrinsics.i32_consts[1],
8783                        self.intrinsics.i32_consts[2],
8784                        self.intrinsics.i32_consts[3],
8785                    ]),
8786                    "",
8787                ));
8788                let res = err!(
8789                    self.builder
8790                        .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8791                );
8792                let res = err!(
8793                    self.builder
8794                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8795                );
8796                self.state.push1(res);
8797            }
8798            Operator::I32x4ExtendHighI16x8U => {
8799                let (v, i) = self.state.pop1_extra()?;
8800                let (v, _) = self.v128_into_i16x8(v, i)?;
8801                let low = err!(self.builder.build_shuffle_vector(
8802                    v,
8803                    v.get_type().get_undef(),
8804                    VectorType::const_vector(&[
8805                        self.intrinsics.i32_consts[4],
8806                        self.intrinsics.i32_consts[5],
8807                        self.intrinsics.i32_consts[6],
8808                        self.intrinsics.i32_consts[7],
8809                    ]),
8810                    "",
8811                ));
8812                let res = err!(
8813                    self.builder
8814                        .build_int_z_extend(low, self.intrinsics.i32x4_ty, "")
8815                );
8816                let res = err!(
8817                    self.builder
8818                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8819                );
8820                self.state.push1(res);
8821            }
8822            Operator::I64x2ExtendLowI32x4U
8823            | Operator::I64x2ExtendLowI32x4S
8824            | Operator::I64x2ExtendHighI32x4U
8825            | Operator::I64x2ExtendHighI32x4S => {
8826                let extend = match op {
8827                    Operator::I64x2ExtendLowI32x4U | Operator::I64x2ExtendHighI32x4U => {
8828                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
8829                    }
8830                    Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendHighI32x4S => {
8831                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
8832                    }
8833                    _ => unreachable!("Unhandled inner case"),
8834                };
8835                let indices = match op {
8836                    Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendLowI32x4U => {
8837                        [self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
8838                    }
8839                    Operator::I64x2ExtendHighI32x4S | Operator::I64x2ExtendHighI32x4U => {
8840                        [self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
8841                    }
8842                    _ => unreachable!("Unhandled inner case"),
8843                };
8844                let (v, i) = self.state.pop1_extra()?;
8845                let (v, _) = self.v128_into_i32x4(v, i)?;
8846                let low = err!(self.builder.build_shuffle_vector(
8847                    v,
8848                    v.get_type().get_undef(),
8849                    VectorType::const_vector(&indices),
8850                    "",
8851                ));
8852                let res = err!(extend(self, low));
8853                let res = err!(
8854                    self.builder
8855                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8856                );
8857                self.state.push1(res);
8858            }
8859            Operator::I8x16NarrowI16x8S => {
8860                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8861                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8862                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8863                let min = self.intrinsics.i16_ty.const_int(0xff80, false);
8864                let max = self.intrinsics.i16_ty.const_int(0x007f, false);
8865                let min = VectorType::const_vector(&[min; 8]);
8866                let max = VectorType::const_vector(&[max; 8]);
8867                let apply_min_clamp_v1 =
8868                    err!(
8869                        self.builder
8870                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8871                    );
8872                let apply_max_clamp_v1 =
8873                    err!(
8874                        self.builder
8875                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8876                    );
8877                let apply_min_clamp_v2 =
8878                    err!(
8879                        self.builder
8880                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8881                    );
8882                let apply_max_clamp_v2 =
8883                    err!(
8884                        self.builder
8885                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8886                    );
8887                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8888                    .into_vector_value();
8889                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8890                    .into_vector_value();
8891                let v1 = err!(self.builder.build_int_truncate(
8892                    v1,
8893                    self.intrinsics.i8_ty.vec_type(8),
8894                    ""
8895                ));
8896                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8897                    .into_vector_value();
8898                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8899                    .into_vector_value();
8900                let v2 = err!(self.builder.build_int_truncate(
8901                    v2,
8902                    self.intrinsics.i8_ty.vec_type(8),
8903                    ""
8904                ));
8905                let res = err!(self.builder.build_shuffle_vector(
8906                    v1,
8907                    v2,
8908                    VectorType::const_vector(&[
8909                        self.intrinsics.i32_consts[0],
8910                        self.intrinsics.i32_consts[1],
8911                        self.intrinsics.i32_consts[2],
8912                        self.intrinsics.i32_consts[3],
8913                        self.intrinsics.i32_consts[4],
8914                        self.intrinsics.i32_consts[5],
8915                        self.intrinsics.i32_consts[6],
8916                        self.intrinsics.i32_consts[7],
8917                        self.intrinsics.i32_consts[8],
8918                        self.intrinsics.i32_consts[9],
8919                        self.intrinsics.i32_consts[10],
8920                        self.intrinsics.i32_consts[11],
8921                        self.intrinsics.i32_consts[12],
8922                        self.intrinsics.i32_consts[13],
8923                        self.intrinsics.i32_consts[14],
8924                        self.intrinsics.i32_consts[15],
8925                    ]),
8926                    "",
8927                ));
8928                let res = err!(
8929                    self.builder
8930                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
8931                );
8932                self.state.push1(res);
8933            }
8934            Operator::I8x16NarrowI16x8U => {
8935                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
8936                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
8937                let (v2, _) = self.v128_into_i16x8(v2, i2)?;
8938                let min = self.intrinsics.i16x8_ty.const_zero();
8939                let max = self.intrinsics.i16_ty.const_int(0x00ff, false);
8940                let max = VectorType::const_vector(&[max; 8]);
8941                let apply_min_clamp_v1 =
8942                    err!(
8943                        self.builder
8944                            .build_int_compare(IntPredicate::SLT, v1, min, "")
8945                    );
8946                let apply_max_clamp_v1 =
8947                    err!(
8948                        self.builder
8949                            .build_int_compare(IntPredicate::SGT, v1, max, "")
8950                    );
8951                let apply_min_clamp_v2 =
8952                    err!(
8953                        self.builder
8954                            .build_int_compare(IntPredicate::SLT, v2, min, "")
8955                    );
8956                let apply_max_clamp_v2 =
8957                    err!(
8958                        self.builder
8959                            .build_int_compare(IntPredicate::SGT, v2, max, "")
8960                    );
8961                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
8962                    .into_vector_value();
8963                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
8964                    .into_vector_value();
8965                let v1 = err!(self.builder.build_int_truncate(
8966                    v1,
8967                    self.intrinsics.i8_ty.vec_type(8),
8968                    ""
8969                ));
8970                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
8971                    .into_vector_value();
8972                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
8973                    .into_vector_value();
8974                let v2 = err!(self.builder.build_int_truncate(
8975                    v2,
8976                    self.intrinsics.i8_ty.vec_type(8),
8977                    ""
8978                ));
8979                let res = err!(self.builder.build_shuffle_vector(
8980                    v1,
8981                    v2,
8982                    VectorType::const_vector(&[
8983                        self.intrinsics.i32_consts[0],
8984                        self.intrinsics.i32_consts[1],
8985                        self.intrinsics.i32_consts[2],
8986                        self.intrinsics.i32_consts[3],
8987                        self.intrinsics.i32_consts[4],
8988                        self.intrinsics.i32_consts[5],
8989                        self.intrinsics.i32_consts[6],
8990                        self.intrinsics.i32_consts[7],
8991                        self.intrinsics.i32_consts[8],
8992                        self.intrinsics.i32_consts[9],
8993                        self.intrinsics.i32_consts[10],
8994                        self.intrinsics.i32_consts[11],
8995                        self.intrinsics.i32_consts[12],
8996                        self.intrinsics.i32_consts[13],
8997                        self.intrinsics.i32_consts[14],
8998                        self.intrinsics.i32_consts[15],
8999                    ]),
9000                    "",
9001                ));
9002                let res = err!(
9003                    self.builder
9004                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9005                );
9006                self.state.push1(res);
9007            }
9008            Operator::I16x8NarrowI32x4S => {
9009                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
9010                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
9011                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
9012                let min = self.intrinsics.i32_ty.const_int(0xffff8000, false);
9013                let max = self.intrinsics.i32_ty.const_int(0x00007fff, false);
9014                let min = VectorType::const_vector(&[min; 4]);
9015                let max = VectorType::const_vector(&[max; 4]);
9016                let apply_min_clamp_v1 =
9017                    err!(
9018                        self.builder
9019                            .build_int_compare(IntPredicate::SLT, v1, min, "")
9020                    );
9021                let apply_max_clamp_v1 =
9022                    err!(
9023                        self.builder
9024                            .build_int_compare(IntPredicate::SGT, v1, max, "")
9025                    );
9026                let apply_min_clamp_v2 =
9027                    err!(
9028                        self.builder
9029                            .build_int_compare(IntPredicate::SLT, v2, min, "")
9030                    );
9031                let apply_max_clamp_v2 =
9032                    err!(
9033                        self.builder
9034                            .build_int_compare(IntPredicate::SGT, v2, max, "")
9035                    );
9036                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
9037                    .into_vector_value();
9038                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
9039                    .into_vector_value();
9040                let v1 = err!(self.builder.build_int_truncate(
9041                    v1,
9042                    self.intrinsics.i16_ty.vec_type(4),
9043                    ""
9044                ));
9045                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
9046                    .into_vector_value();
9047                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
9048                    .into_vector_value();
9049                let v2 = err!(self.builder.build_int_truncate(
9050                    v2,
9051                    self.intrinsics.i16_ty.vec_type(4),
9052                    ""
9053                ));
9054                let res = err!(self.builder.build_shuffle_vector(
9055                    v1,
9056                    v2,
9057                    VectorType::const_vector(&[
9058                        self.intrinsics.i32_consts[0],
9059                        self.intrinsics.i32_consts[1],
9060                        self.intrinsics.i32_consts[2],
9061                        self.intrinsics.i32_consts[3],
9062                        self.intrinsics.i32_consts[4],
9063                        self.intrinsics.i32_consts[5],
9064                        self.intrinsics.i32_consts[6],
9065                        self.intrinsics.i32_consts[7],
9066                    ]),
9067                    "",
9068                ));
9069                let res = err!(
9070                    self.builder
9071                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9072                );
9073                self.state.push1(res);
9074            }
9075            Operator::I16x8NarrowI32x4U => {
9076                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
9077                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
9078                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
9079                let min = self.intrinsics.i32x4_ty.const_zero();
9080                let max = self.intrinsics.i32_ty.const_int(0xffff, false);
9081                let max = VectorType::const_vector(&[max; 4]);
9082                let apply_min_clamp_v1 =
9083                    err!(
9084                        self.builder
9085                            .build_int_compare(IntPredicate::SLT, v1, min, "")
9086                    );
9087                let apply_max_clamp_v1 =
9088                    err!(
9089                        self.builder
9090                            .build_int_compare(IntPredicate::SGT, v1, max, "")
9091                    );
9092                let apply_min_clamp_v2 =
9093                    err!(
9094                        self.builder
9095                            .build_int_compare(IntPredicate::SLT, v2, min, "")
9096                    );
9097                let apply_max_clamp_v2 =
9098                    err!(
9099                        self.builder
9100                            .build_int_compare(IntPredicate::SGT, v2, max, "")
9101                    );
9102                let v1 = err!(self.builder.build_select(apply_min_clamp_v1, min, v1, ""))
9103                    .into_vector_value();
9104                let v1 = err!(self.builder.build_select(apply_max_clamp_v1, max, v1, ""))
9105                    .into_vector_value();
9106                let v1 = err!(self.builder.build_int_truncate(
9107                    v1,
9108                    self.intrinsics.i16_ty.vec_type(4),
9109                    ""
9110                ));
9111                let v2 = err!(self.builder.build_select(apply_min_clamp_v2, min, v2, ""))
9112                    .into_vector_value();
9113                let v2 = err!(self.builder.build_select(apply_max_clamp_v2, max, v2, ""))
9114                    .into_vector_value();
9115                let v2 = err!(self.builder.build_int_truncate(
9116                    v2,
9117                    self.intrinsics.i16_ty.vec_type(4),
9118                    ""
9119                ));
9120                let res = err!(self.builder.build_shuffle_vector(
9121                    v1,
9122                    v2,
9123                    VectorType::const_vector(&[
9124                        self.intrinsics.i32_consts[0],
9125                        self.intrinsics.i32_consts[1],
9126                        self.intrinsics.i32_consts[2],
9127                        self.intrinsics.i32_consts[3],
9128                        self.intrinsics.i32_consts[4],
9129                        self.intrinsics.i32_consts[5],
9130                        self.intrinsics.i32_consts[6],
9131                        self.intrinsics.i32_consts[7],
9132                    ]),
9133                    "",
9134                ));
9135                let res = err!(
9136                    self.builder
9137                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9138                );
9139                self.state.push1(res);
9140            }
9141            Operator::I32x4RelaxedTruncF32x4S if self.cpu_features.contains(CpuFeature::SSE2) => {
9142                let (v, i) = self.state.pop1_extra()?;
9143                let (v, _) = self.v128_into_f32x4(v, i)?;
9144                let res = self
9145                    .build_call_with_param_attributes(
9146                        self.intrinsics.x86_64.cvttps2dq,
9147                        &[v.into()],
9148                        "",
9149                    )?
9150                    .try_as_basic_value()
9151                    .unwrap_basic();
9152                let res = err!(
9153                    self.builder
9154                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9155                );
9156                self.state.push1(res);
9157            }
9158            Operator::I32x4TruncSatF32x4S | Operator::I32x4RelaxedTruncF32x4S => {
9159                let (v, i) = self.state.pop1_extra()?;
9160                let v = self.apply_pending_canonicalization(v, i)?;
9161                let v = v.into_int_value();
9162                let res = self.trunc_sat_into_int(
9163                    self.intrinsics.f32x4_ty,
9164                    self.intrinsics.i32x4_ty,
9165                    LEF32_GEQ_I32_MIN,
9166                    GEF32_LEQ_I32_MAX,
9167                    i32::MIN as u64,
9168                    i32::MAX as u64,
9169                    v,
9170                )?;
9171                self.state.push1(res);
9172            }
9173            Operator::I32x4RelaxedTruncF32x4U
9174                if self.cpu_features.contains(CpuFeature::AVX512F)
9175                    && self.cpu_features.contains(CpuFeature::AVX512VL) =>
9176            {
9177                let (v, i) = self.state.pop1_extra()?;
9178                let (v, _) = self.v128_into_f32x4(v, i)?;
9179                let res = self
9180                    .build_call_with_param_attributes(
9181                        self.intrinsics.x86_64.cvtps2udq128,
9182                        &[
9183                            v.into(),
9184                            self.intrinsics.i32x4_ty.const_zero().into(),
9185                            self.intrinsics.i8_ty.const_int(0xff, false).into(),
9186                        ],
9187                        "",
9188                    )?
9189                    .try_as_basic_value()
9190                    .unwrap_basic();
9191                let res = err!(
9192                    self.builder
9193                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9194                );
9195                self.state.push1(res);
9196            }
9197            Operator::I32x4TruncSatF32x4U | Operator::I32x4RelaxedTruncF32x4U => {
9198                let (v, i) = self.state.pop1_extra()?;
9199                let v = self.apply_pending_canonicalization(v, i)?;
9200                let v = v.into_int_value();
9201                let res = self.trunc_sat_into_int(
9202                    self.intrinsics.f32x4_ty,
9203                    self.intrinsics.i32x4_ty,
9204                    LEF32_GEQ_U32_MIN,
9205                    GEF32_LEQ_U32_MAX,
9206                    u32::MIN as u64,
9207                    u32::MAX as u64,
9208                    v,
9209                )?;
9210                self.state.push1(res);
9211            }
9212            Operator::I32x4RelaxedTruncF64x2SZero
9213                if self.cpu_features.contains(CpuFeature::SSE2) =>
9214            {
9215                let (v, i) = self.state.pop1_extra()?;
9216                let (v, _) = self.v128_into_f64x2(v, i)?;
9217                let res = self
9218                    .build_call_with_param_attributes(
9219                        self.intrinsics.x86_64.cvtpd2dq,
9220                        &[v.into()],
9221                        "",
9222                    )?
9223                    .try_as_basic_value()
9224                    .unwrap_basic();
9225                let res = err!(
9226                    self.builder
9227                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9228                );
9229                self.state.push1(res);
9230            }
9231            Operator::I32x4RelaxedTruncF64x2UZero
9232                if self.cpu_features.contains(CpuFeature::AVX512F)
9233                    && self.cpu_features.contains(CpuFeature::AVX512VL) =>
9234            {
9235                let (v, i) = self.state.pop1_extra()?;
9236                let (v, _) = self.v128_into_f64x2(v, i)?;
9237                let res = self
9238                    .build_call_with_param_attributes(
9239                        self.intrinsics.x86_64.cvtpd2udq128,
9240                        &[
9241                            v.into(),
9242                            self.intrinsics.i32x4_ty.const_zero().into(),
9243                            self.intrinsics.i8_ty.const_int(0xff, false).into(),
9244                        ],
9245                        "",
9246                    )?
9247                    .try_as_basic_value()
9248                    .unwrap_basic();
9249                let res = err!(
9250                    self.builder
9251                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9252                );
9253                self.state.push1(res);
9254            }
9255            Operator::I32x4TruncSatF64x2SZero
9256            | Operator::I32x4TruncSatF64x2UZero
9257            | Operator::I32x4RelaxedTruncF64x2SZero
9258            | Operator::I32x4RelaxedTruncF64x2UZero => {
9259                let ((min, max), (cmp_min, cmp_max)) = match op {
9260                    Operator::I32x4TruncSatF64x2SZero => (
9261                        (i32::MIN as u64, i32::MAX as u64),
9262                        (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
9263                    ),
9264                    Operator::I32x4TruncSatF64x2UZero => (
9265                        (u32::MIN as u64, u32::MAX as u64),
9266                        (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
9267                    ),
9268                    Operator::I32x4RelaxedTruncF64x2SZero => (
9269                        (i32::MIN as u64, i32::MAX as u64),
9270                        (LEF64_GEQ_I32_MIN, GEF64_LEQ_I32_MAX),
9271                    ),
9272                    Operator::I32x4RelaxedTruncF64x2UZero => (
9273                        (u32::MIN as u64, u32::MAX as u64),
9274                        (LEF64_GEQ_U32_MIN, GEF64_LEQ_U32_MAX),
9275                    ),
9276                    _ => unreachable!("Unhandled internal variant"),
9277                };
9278                let (v, i) = self.state.pop1_extra()?;
9279                let v = self.apply_pending_canonicalization(v, i)?;
9280                let v = v.into_int_value();
9281                let res = self.trunc_sat(
9282                    self.intrinsics.f64x2_ty,
9283                    self.intrinsics.i32_ty.vec_type(2),
9284                    cmp_min,
9285                    cmp_max,
9286                    min,
9287                    max,
9288                    v,
9289                )?;
9290
9291                let zero = self.intrinsics.i32_consts[0];
9292                let zeros = VectorType::const_vector(&[zero; 2]);
9293                let res = err!(self.builder.build_shuffle_vector(
9294                    res,
9295                    zeros,
9296                    VectorType::const_vector(&[
9297                        self.intrinsics.i32_consts[0],
9298                        self.intrinsics.i32_consts[1],
9299                        self.intrinsics.i32_consts[2],
9300                        self.intrinsics.i32_consts[3],
9301                    ]),
9302                    "",
9303                ));
9304                let res = err!(
9305                    self.builder
9306                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9307                );
9308                self.state.push1(res);
9309            }
9310            // Operator::I64x2TruncSatF64x2S => {
9311            //     let (v, i) = self.state.pop1_extra()?;
9312            //     let v = self.apply_pending_canonicalization(v, i)?;
9313            //     let v = v.into_int_value();
9314            //     let res = self.trunc_sat_into_int(
9315            //         self.intrinsics.f64x2_ty,
9316            //         self.intrinsics.i64x2_ty,
9317            //         i64::MIN as u64,
9318            //         i64::MAX as u64,
9319            //         i64::MIN as u64,
9320            //         i64::MAX as u64,
9321            //         v,
9322            //     )?;
9323            //     self.state.push1(res);
9324            // }
9325            // Operator::I64x2TruncSatF64x2U => {
9326            //     let (v, i) = self.state.pop1_extra()?;
9327            //     let v = self.apply_pending_canonicalization(v, i)?;
9328            //     let v = v.into_int_value();
9329            //     let res = self.trunc_sat_into_int(
9330            //         self.intrinsics.f64x2_ty,
9331            //         self.intrinsics.i64x2_ty,
9332            //         u64::MIN,
9333            //         u64::MAX,
9334            //         u64::MIN,
9335            //         u64::MAX,
9336            //         v,
9337            //     )?;
9338            //     self.state.push1(res);
9339            // }
9340            Operator::I32TruncF32S => {
9341                let v1 = self.state.pop1()?.into_float_value();
9342                self.trap_if_not_representable_as_int(
9343                    0xcf000000, // -2147483600.0
9344                    0x4effffff, // 2147483500.0
9345                    v1,
9346                )?;
9347                let res = err!(self.builder.build_float_to_signed_int(
9348                    v1,
9349                    self.intrinsics.i32_ty,
9350                    ""
9351                ));
9352                self.state.push1(res);
9353            }
9354            Operator::I32TruncF64S => {
9355                let v1 = self.state.pop1()?.into_float_value();
9356                self.trap_if_not_representable_as_int(
9357                    0xc1e00000001fffff, // -2147483648.9999995
9358                    0x41dfffffffffffff, // 2147483647.9999998
9359                    v1,
9360                )?;
9361                let res = err!(self.builder.build_float_to_signed_int(
9362                    v1,
9363                    self.intrinsics.i32_ty,
9364                    ""
9365                ));
9366                self.state.push1(res);
9367            }
9368            Operator::I32TruncSatF32S => {
9369                let (v, i) = self.state.pop1_extra()?;
9370                let v = self.apply_pending_canonicalization(v, i)?;
9371                let v = v.into_float_value();
9372                let res = self.trunc_sat_scalar(
9373                    self.intrinsics.i32_ty,
9374                    LEF32_GEQ_I32_MIN,
9375                    GEF32_LEQ_I32_MAX,
9376                    i32::MIN as u32 as u64,
9377                    i32::MAX as u32 as u64,
9378                    v,
9379                )?;
9380                self.state.push1(res);
9381            }
9382            Operator::I32TruncSatF64S => {
9383                let (v, i) = self.state.pop1_extra()?;
9384                let v = self.apply_pending_canonicalization(v, i)?;
9385                let v = v.into_float_value();
9386                let res = self.trunc_sat_scalar(
9387                    self.intrinsics.i32_ty,
9388                    LEF64_GEQ_I32_MIN,
9389                    GEF64_LEQ_I32_MAX,
9390                    i32::MIN as u64,
9391                    i32::MAX as u64,
9392                    v,
9393                )?;
9394                self.state.push1(res);
9395            }
9396            Operator::I64TruncF32S => {
9397                let v1 = self.state.pop1()?.into_float_value();
9398                self.trap_if_not_representable_as_int(
9399                    0xdf000000, // -9223372000000000000.0
9400                    0x5effffff, // 9223371500000000000.0
9401                    v1,
9402                )?;
9403                let res = err!(self.builder.build_float_to_signed_int(
9404                    v1,
9405                    self.intrinsics.i64_ty,
9406                    ""
9407                ));
9408                self.state.push1(res);
9409            }
9410            Operator::I64TruncF64S => {
9411                let v1 = self.state.pop1()?.into_float_value();
9412                self.trap_if_not_representable_as_int(
9413                    0xc3e0000000000000, // -9223372036854776000.0
9414                    0x43dfffffffffffff, // 9223372036854775000.0
9415                    v1,
9416                )?;
9417                let res = err!(self.builder.build_float_to_signed_int(
9418                    v1,
9419                    self.intrinsics.i64_ty,
9420                    ""
9421                ));
9422                self.state.push1(res);
9423            }
9424            Operator::I64TruncSatF32S => {
9425                let (v, i) = self.state.pop1_extra()?;
9426                let v = self.apply_pending_canonicalization(v, i)?;
9427                let v = v.into_float_value();
9428                let res = self.trunc_sat_scalar(
9429                    self.intrinsics.i64_ty,
9430                    LEF32_GEQ_I64_MIN,
9431                    GEF32_LEQ_I64_MAX,
9432                    i64::MIN as u64,
9433                    i64::MAX as u64,
9434                    v,
9435                )?;
9436                self.state.push1(res);
9437            }
9438            Operator::I64TruncSatF64S => {
9439                let (v, i) = self.state.pop1_extra()?;
9440                let v = self.apply_pending_canonicalization(v, i)?;
9441                let v = v.into_float_value();
9442                let res = self.trunc_sat_scalar(
9443                    self.intrinsics.i64_ty,
9444                    LEF64_GEQ_I64_MIN,
9445                    GEF64_LEQ_I64_MAX,
9446                    i64::MIN as u64,
9447                    i64::MAX as u64,
9448                    v,
9449                )?;
9450                self.state.push1(res);
9451            }
9452            Operator::I32TruncF32U => {
9453                let v1 = self.state.pop1()?.into_float_value();
9454                self.trap_if_not_representable_as_int(
9455                    0xbf7fffff, // -0.99999994
9456                    0x4f7fffff, // 4294967000.0
9457                    v1,
9458                )?;
9459                let res = err!(self.builder.build_float_to_unsigned_int(
9460                    v1,
9461                    self.intrinsics.i32_ty,
9462                    ""
9463                ));
9464                self.state.push1(res);
9465            }
9466            Operator::I32TruncF64U => {
9467                let v1 = self.state.pop1()?.into_float_value();
9468                self.trap_if_not_representable_as_int(
9469                    0xbfefffffffffffff, // -0.9999999999999999
9470                    0x41efffffffffffff, // 4294967295.9999995
9471                    v1,
9472                )?;
9473                let res = err!(self.builder.build_float_to_unsigned_int(
9474                    v1,
9475                    self.intrinsics.i32_ty,
9476                    ""
9477                ));
9478                self.state.push1(res);
9479            }
9480            Operator::I32TruncSatF32U => {
9481                let (v, i) = self.state.pop1_extra()?;
9482                let v = self.apply_pending_canonicalization(v, i)?;
9483                let v = v.into_float_value();
9484                let res = self.trunc_sat_scalar(
9485                    self.intrinsics.i32_ty,
9486                    LEF32_GEQ_U32_MIN,
9487                    GEF32_LEQ_U32_MAX,
9488                    u32::MIN as u64,
9489                    u32::MAX as u64,
9490                    v,
9491                )?;
9492                self.state.push1(res);
9493            }
9494            Operator::I32TruncSatF64U => {
9495                let (v, i) = self.state.pop1_extra()?;
9496                let v = self.apply_pending_canonicalization(v, i)?;
9497                let v = v.into_float_value();
9498                let res = self.trunc_sat_scalar(
9499                    self.intrinsics.i32_ty,
9500                    LEF64_GEQ_U32_MIN,
9501                    GEF64_LEQ_U32_MAX,
9502                    u32::MIN as u64,
9503                    u32::MAX as u64,
9504                    v,
9505                )?;
9506                self.state.push1(res);
9507            }
9508            Operator::I64TruncF32U => {
9509                let v1 = self.state.pop1()?.into_float_value();
9510                self.trap_if_not_representable_as_int(
9511                    0xbf7fffff, // -0.99999994
9512                    0x5f7fffff, // 18446743000000000000.0
9513                    v1,
9514                )?;
9515                let res = err!(self.builder.build_float_to_unsigned_int(
9516                    v1,
9517                    self.intrinsics.i64_ty,
9518                    ""
9519                ));
9520                self.state.push1(res);
9521            }
9522            Operator::I64TruncF64U => {
9523                let v1 = self.state.pop1()?.into_float_value();
9524                self.trap_if_not_representable_as_int(
9525                    0xbfefffffffffffff, // -0.9999999999999999
9526                    0x43efffffffffffff, // 18446744073709550000.0
9527                    v1,
9528                )?;
9529                let res = err!(self.builder.build_float_to_unsigned_int(
9530                    v1,
9531                    self.intrinsics.i64_ty,
9532                    ""
9533                ));
9534                self.state.push1(res);
9535            }
9536            Operator::I64TruncSatF32U => {
9537                let (v, i) = self.state.pop1_extra()?;
9538                let v = self.apply_pending_canonicalization(v, i)?;
9539                let v = v.into_float_value();
9540                let res = self.trunc_sat_scalar(
9541                    self.intrinsics.i64_ty,
9542                    LEF32_GEQ_U64_MIN,
9543                    GEF32_LEQ_U64_MAX,
9544                    u64::MIN,
9545                    u64::MAX,
9546                    v,
9547                )?;
9548                self.state.push1(res);
9549            }
9550            Operator::I64TruncSatF64U => {
9551                let (v, i) = self.state.pop1_extra()?;
9552                let v = self.apply_pending_canonicalization(v, i)?;
9553                let v = v.into_float_value();
9554                let res = self.trunc_sat_scalar(
9555                    self.intrinsics.i64_ty,
9556                    LEF64_GEQ_U64_MIN,
9557                    GEF64_LEQ_U64_MAX,
9558                    u64::MIN,
9559                    u64::MAX,
9560                    v,
9561                )?;
9562                self.state.push1(res);
9563            }
9564            Operator::F32DemoteF64 => {
9565                let v = self.state.pop1()?;
9566                let v = v.into_float_value();
9567                let res = self
9568                    .build_call_with_param_attributes(
9569                        self.intrinsics.fptrunc_f64,
9570                        &[
9571                            v.into(),
9572                            self.intrinsics.fp_rounding_md,
9573                            self.intrinsics.fp_exception_md,
9574                        ],
9575                        "",
9576                    )?
9577                    .try_as_basic_value()
9578                    .unwrap_basic();
9579                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9580            }
9581            Operator::F64PromoteF32 => {
9582                let v = self.state.pop1()?;
9583                let v = v.into_float_value();
9584                let res = self
9585                    .build_call_with_param_attributes(
9586                        self.intrinsics.fpext_f32,
9587                        &[v.into(), self.intrinsics.fp_exception_md],
9588                        "",
9589                    )?
9590                    .try_as_basic_value()
9591                    .unwrap_basic();
9592                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9593            }
9594            Operator::F32ConvertI32S | Operator::F32ConvertI64S => {
9595                let (v, i) = self.state.pop1_extra()?;
9596                let v = self.apply_pending_canonicalization(v, i)?;
9597                let v = v.into_int_value();
9598                let res = err!(self.builder.build_signed_int_to_float(
9599                    v,
9600                    self.intrinsics.f32_ty,
9601                    ""
9602                ));
9603                self.state.push1(res);
9604            }
9605            Operator::F64ConvertI32S | Operator::F64ConvertI64S => {
9606                let (v, i) = self.state.pop1_extra()?;
9607                let v = self.apply_pending_canonicalization(v, i)?;
9608                let v = v.into_int_value();
9609                let res = err!(self.builder.build_signed_int_to_float(
9610                    v,
9611                    self.intrinsics.f64_ty,
9612                    ""
9613                ));
9614                self.state.push1(res);
9615            }
9616            Operator::F32ConvertI32U | Operator::F32ConvertI64U => {
9617                let (v, i) = self.state.pop1_extra()?;
9618                let v = self.apply_pending_canonicalization(v, i)?;
9619                let v = v.into_int_value();
9620                let res = err!(self.builder.build_unsigned_int_to_float(
9621                    v,
9622                    self.intrinsics.f32_ty,
9623                    ""
9624                ));
9625                self.state.push1(res);
9626            }
9627            Operator::F64ConvertI32U | Operator::F64ConvertI64U => {
9628                let (v, i) = self.state.pop1_extra()?;
9629                let v = self.apply_pending_canonicalization(v, i)?;
9630                let v = v.into_int_value();
9631                let res = err!(self.builder.build_unsigned_int_to_float(
9632                    v,
9633                    self.intrinsics.f64_ty,
9634                    ""
9635                ));
9636                self.state.push1(res);
9637            }
9638            Operator::F32x4ConvertI32x4S => {
9639                let v = self.state.pop1()?;
9640                let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
9641                    .into_vector_value();
9642                let res = err!(self.builder.build_signed_int_to_float(
9643                    v,
9644                    self.intrinsics.f32x4_ty,
9645                    ""
9646                ));
9647                let res = err!(
9648                    self.builder
9649                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9650                );
9651                self.state.push1(res);
9652            }
9653            Operator::F32x4ConvertI32x4U => {
9654                let v = self.state.pop1()?;
9655                let v = err!(self.builder.build_bit_cast(v, self.intrinsics.i32x4_ty, ""))
9656                    .into_vector_value();
9657                let res = err!(self.builder.build_unsigned_int_to_float(
9658                    v,
9659                    self.intrinsics.f32x4_ty,
9660                    ""
9661                ));
9662                let res = err!(
9663                    self.builder
9664                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9665                );
9666                self.state.push1(res);
9667            }
9668            Operator::F64x2ConvertLowI32x4S | Operator::F64x2ConvertLowI32x4U => {
9669                let extend = match op {
9670                    Operator::F64x2ConvertLowI32x4U => {
9671                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
9672                    }
9673                    Operator::F64x2ConvertLowI32x4S => {
9674                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
9675                    }
9676                    _ => unreachable!("Unhandled inner case"),
9677                };
9678                let (v, i) = self.state.pop1_extra()?;
9679                let (v, _) = self.v128_into_i32x4(v, i)?;
9680                let low = err!(self.builder.build_shuffle_vector(
9681                    v,
9682                    v.get_type().get_undef(),
9683                    VectorType::const_vector(&[
9684                        self.intrinsics.i32_consts[0],
9685                        self.intrinsics.i32_consts[1],
9686                    ]),
9687                    "",
9688                ));
9689                let res = err!(extend(self, low));
9690                let res = err!(self.builder.build_signed_int_to_float(
9691                    res,
9692                    self.intrinsics.f64x2_ty,
9693                    ""
9694                ));
9695                let res = err!(
9696                    self.builder
9697                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9698                );
9699                self.state.push1(res);
9700            }
9701            Operator::F64x2PromoteLowF32x4 => {
9702                let (v, i) = self.state.pop1_extra()?;
9703                let (v, _) = self.v128_into_f32x4(v, i)?;
9704                let low = err!(self.builder.build_shuffle_vector(
9705                    v,
9706                    v.get_type().get_undef(),
9707                    VectorType::const_vector(&[
9708                        self.intrinsics.i32_consts[0],
9709                        self.intrinsics.i32_consts[1],
9710                    ]),
9711                    "",
9712                ));
9713                let res = err!(
9714                    self.builder
9715                        .build_float_ext(low, self.intrinsics.f64x2_ty, "")
9716                );
9717                let res = err!(
9718                    self.builder
9719                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9720                );
9721                self.state.push1_extra(res, ExtraInfo::pending_f64_nan());
9722            }
9723            Operator::F32x4DemoteF64x2Zero => {
9724                let (v, i) = self.state.pop1_extra()?;
9725                let (v, _) = self.v128_into_f64x2(v, i)?;
9726                let f32x2_ty = self.intrinsics.f32_ty.vec_type(2);
9727                let res = err!(self.builder.build_float_trunc(v, f32x2_ty, ""));
9728                let zeros = f32x2_ty.const_zero();
9729                let res = err!(self.builder.build_shuffle_vector(
9730                    res,
9731                    zeros,
9732                    VectorType::const_vector(&[
9733                        self.intrinsics.i32_consts[0],
9734                        self.intrinsics.i32_consts[1],
9735                        self.intrinsics.i32_consts[2],
9736                        self.intrinsics.i32_consts[3],
9737                    ]),
9738                    "",
9739                ));
9740                let res = err!(
9741                    self.builder
9742                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9743                );
9744                self.state.push1_extra(res, ExtraInfo::pending_f32_nan());
9745            }
9746            // Operator::F64x2ConvertI64x2S => {
9747            //     let v = self.state.pop1()?;
9748            //     let v = self
9749            //         .builder
9750            //         .build_bit_cast(v, self.intrinsics.i64x2_ty, "")
9751            //         .into_vector_value();
9752            //     let res = self
9753            //         .builder
9754            //         .build_signed_int_to_float(v, self.intrinsics.f64x2_ty, "");
9755            //     let res = check_err!(self.builder.build_bit_cast(res, self.intrinsics.i128_ty, ""));
9756            //     self.state.push1(res);
9757            // }
9758            // Operator::F64x2ConvertI64x2U => {
9759            //     let v = self.state.pop1()?;
9760            //     let v = self
9761            //         .builder
9762            //         .build_bit_cast(v, self.intrinsics.i64x2_ty, "")
9763            //         .into_vector_value();
9764            //     let res = self
9765            //         .builder
9766            //         .build_unsigned_int_to_float(v, self.intrinsics.f64x2_ty, "");
9767            //     let res = check_err!(self.builder.build_bit_cast(res, self.intrinsics.i128_ty, ""));
9768            //     self.state.push1(res);
9769            // }
9770            Operator::I32ReinterpretF32 => {
9771                let (v, i) = self.state.pop1_extra()?;
9772                let v = self.apply_pending_canonicalization(v, i)?;
9773                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i32_ty, ""));
9774                self.state.push1_extra(ret, ExtraInfo::arithmetic_f32());
9775            }
9776            Operator::I64ReinterpretF64 => {
9777                let (v, i) = self.state.pop1_extra()?;
9778                let v = self.apply_pending_canonicalization(v, i)?;
9779                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.i64_ty, ""));
9780                self.state.push1_extra(ret, ExtraInfo::arithmetic_f64());
9781            }
9782            Operator::F32ReinterpretI32 => {
9783                let (v, i) = self.state.pop1_extra()?;
9784                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f32_ty, ""));
9785                self.state.push1_extra(ret, i);
9786            }
9787            Operator::F64ReinterpretI64 => {
9788                let (v, i) = self.state.pop1_extra()?;
9789                let ret = err!(self.builder.build_bit_cast(v, self.intrinsics.f64_ty, ""));
9790                self.state.push1_extra(ret, i);
9791            }
9792            _ => unreachable!(),
9793        }
9794        Ok(())
9795    }
9796
9797    // Sign-extension operators.
9798    // https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md
9799    fn translate_sign_extension_operator(&mut self, op: Operator) -> Result<(), CompileError> {
9800        match op {
9801            Operator::I32Extend8S => {
9802                let value = self.state.pop1()?.into_int_value();
9803                let narrow_value = err!(self.builder.build_int_truncate(
9804                    value,
9805                    self.intrinsics.i8_ty,
9806                    ""
9807                ));
9808                let extended_value = err!(self.builder.build_int_s_extend(
9809                    narrow_value,
9810                    self.intrinsics.i32_ty,
9811                    ""
9812                ));
9813                self.state.push1(extended_value);
9814            }
9815            Operator::I32Extend16S => {
9816                let value = self.state.pop1()?.into_int_value();
9817                let narrow_value = err!(self.builder.build_int_truncate(
9818                    value,
9819                    self.intrinsics.i16_ty,
9820                    ""
9821                ));
9822                let extended_value = err!(self.builder.build_int_s_extend(
9823                    narrow_value,
9824                    self.intrinsics.i32_ty,
9825                    ""
9826                ));
9827                self.state.push1(extended_value);
9828            }
9829            Operator::I64Extend8S => {
9830                let value = self.state.pop1()?.into_int_value();
9831                let narrow_value = err!(self.builder.build_int_truncate(
9832                    value,
9833                    self.intrinsics.i8_ty,
9834                    ""
9835                ));
9836                let extended_value = err!(self.builder.build_int_s_extend(
9837                    narrow_value,
9838                    self.intrinsics.i64_ty,
9839                    ""
9840                ));
9841                self.state.push1(extended_value);
9842            }
9843            Operator::I64Extend16S => {
9844                let value = self.state.pop1()?.into_int_value();
9845                let narrow_value = err!(self.builder.build_int_truncate(
9846                    value,
9847                    self.intrinsics.i16_ty,
9848                    ""
9849                ));
9850                let extended_value = err!(self.builder.build_int_s_extend(
9851                    narrow_value,
9852                    self.intrinsics.i64_ty,
9853                    ""
9854                ));
9855                self.state.push1(extended_value);
9856            }
9857            Operator::I64Extend32S => {
9858                let value = self.state.pop1()?.into_int_value();
9859                let narrow_value = err!(self.builder.build_int_truncate(
9860                    value,
9861                    self.intrinsics.i32_ty,
9862                    ""
9863                ));
9864                let extended_value = err!(self.builder.build_int_s_extend(
9865                    narrow_value,
9866                    self.intrinsics.i64_ty,
9867                    ""
9868                ));
9869                self.state.push1(extended_value);
9870            }
9871            _ => unreachable!(),
9872        }
9873        Ok(())
9874    }
9875
9876    // Load and Store instructions.
9877    // https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#load-and-store-instructions
9878    fn translate_memory_operator(&mut self, op: Operator) -> Result<(), CompileError> {
9879        let vmctx = &self.ctx.basic().into_pointer_value();
9880
9881        match op {
9882            Operator::I32Load { ref memarg } => {
9883                let offset = self.state.pop1()?.into_int_value();
9884                let result =
9885                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9886                self.state.push1(result);
9887            }
9888            Operator::I64Load { ref memarg } => {
9889                let offset = self.state.pop1()?.into_int_value();
9890                let result =
9891                    self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
9892                self.state.push1(result);
9893            }
9894            Operator::F32Load { ref memarg } => {
9895                let offset = self.state.pop1()?.into_int_value();
9896                let result =
9897                    self.build_annotated_load(self.intrinsics.f32_ty, offset, memarg, 1)?;
9898                self.state.push1(result);
9899            }
9900            Operator::F64Load { ref memarg } => {
9901                let offset = self.state.pop1()?.into_int_value();
9902                let result =
9903                    self.build_annotated_load(self.intrinsics.f64_ty, offset, memarg, 1)?;
9904                self.state.push1(result);
9905            }
9906            Operator::V128Load { ref memarg } => {
9907                let offset = self.state.pop1()?.into_int_value();
9908                let result =
9909                    self.build_annotated_load(self.intrinsics.i128_ty, offset, memarg, 1)?;
9910                self.state.push1(result);
9911            }
9912            Operator::V128Load8Lane { ref memarg, lane } => {
9913                let (v, i) = self.state.pop1_extra()?;
9914                let (v, _i) = self.v128_into_i8x16(v, i)?;
9915                let offset = self.state.pop1()?.into_int_value();
9916                let element =
9917                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
9918                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9919                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9920                let res = err!(
9921                    self.builder
9922                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9923                );
9924                self.state.push1(res);
9925            }
9926            Operator::V128Load16Lane { ref memarg, lane } => {
9927                let (v, i) = self.state.pop1_extra()?;
9928                let (v, i) = self.v128_into_i16x8(v, i)?;
9929                let offset = self.state.pop1()?.into_int_value();
9930                let element =
9931                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
9932                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9933                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9934                let res = err!(
9935                    self.builder
9936                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9937                );
9938                self.state.push1_extra(res, i);
9939            }
9940            Operator::V128Load32Lane { ref memarg, lane } => {
9941                let (v, i) = self.state.pop1_extra()?;
9942                let (v, i) = self.v128_into_i32x4(v, i)?;
9943                let offset = self.state.pop1()?.into_int_value();
9944                let element =
9945                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
9946                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9947                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9948                let res = err!(
9949                    self.builder
9950                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9951                );
9952                self.state.push1_extra(res, i);
9953            }
9954            Operator::V128Load64Lane { ref memarg, lane } => {
9955                let (v, i) = self.state.pop1_extra()?;
9956                let (v, i) = self.v128_into_i64x2(v, i)?;
9957                let offset = self.state.pop1()?.into_int_value();
9958                let element =
9959                    self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
9960                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
9961                let res = err!(self.builder.build_insert_element(v, element, idx, ""));
9962                let res = err!(
9963                    self.builder
9964                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
9965                );
9966                self.state.push1_extra(res, i);
9967            }
9968
9969            Operator::I32Store { ref memarg } => {
9970                let value = self.state.pop1()?;
9971                let offset = self.state.pop1()?.into_int_value();
9972                self.build_annotated_store(self.intrinsics.i32_ty, offset, value, memarg, 1)?;
9973            }
9974            Operator::I64Store { ref memarg } => {
9975                let value = self.state.pop1()?;
9976                let offset = self.state.pop1()?.into_int_value();
9977                self.build_annotated_store(self.intrinsics.i64_ty, offset, value, memarg, 1)?;
9978            }
9979            Operator::F32Store { ref memarg } => {
9980                let (v, i) = self.state.pop1_extra()?;
9981                let v = self.apply_pending_canonicalization(v, i)?;
9982                let offset = self.state.pop1()?.into_int_value();
9983                self.build_annotated_store(self.intrinsics.f32_ty, offset, v, memarg, 1)?;
9984            }
9985            Operator::F64Store { ref memarg } => {
9986                let (v, i) = self.state.pop1_extra()?;
9987                let v = self.apply_pending_canonicalization(v, i)?;
9988                let offset = self.state.pop1()?.into_int_value();
9989                self.build_annotated_store(self.intrinsics.f64_ty, offset, v, memarg, 1)?;
9990            }
9991            Operator::V128Store { ref memarg } => {
9992                let (v, i) = self.state.pop1_extra()?;
9993                let v = self.apply_pending_canonicalization(v, i)?;
9994                let offset = self.state.pop1()?.into_int_value();
9995                self.build_annotated_store(self.intrinsics.i128_ty, offset, v, memarg, 1)?;
9996            }
9997            Operator::V128Store8Lane { ref memarg, lane } => {
9998                let (v, i) = self.state.pop1_extra()?;
9999                let (v, _i) = self.v128_into_i8x16(v, i)?;
10000                let offset = self.state.pop1()?.into_int_value();
10001                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10002                let val = err!(self.builder.build_extract_element(v, idx, ""));
10003                self.build_annotated_store(self.intrinsics.i8_ty, offset, val, memarg, 1)?;
10004            }
10005            Operator::V128Store16Lane { ref memarg, lane } => {
10006                let (v, i) = self.state.pop1_extra()?;
10007                let (v, _i) = self.v128_into_i16x8(v, i)?;
10008                let offset = self.state.pop1()?.into_int_value();
10009                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10010                let val = err!(self.builder.build_extract_element(v, idx, ""));
10011                self.build_annotated_store(self.intrinsics.i16_ty, offset, val, memarg, 1)?;
10012            }
10013            Operator::V128Store32Lane { ref memarg, lane } => {
10014                let (v, i) = self.state.pop1_extra()?;
10015                let (v, _i) = self.v128_into_i32x4(v, i)?;
10016                let offset = self.state.pop1()?.into_int_value();
10017                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10018                let val = err!(self.builder.build_extract_element(v, idx, ""));
10019                self.build_annotated_store(self.intrinsics.i32_ty, offset, val, memarg, 1)?;
10020            }
10021            Operator::V128Store64Lane { ref memarg, lane } => {
10022                let (v, i) = self.state.pop1_extra()?;
10023                let (v, _i) = self.v128_into_i64x2(v, i)?;
10024                let offset = self.state.pop1()?.into_int_value();
10025                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10026                let val = err!(self.builder.build_extract_element(v, idx, ""));
10027                self.build_annotated_store(self.intrinsics.i64_ty, offset, val, memarg, 1)?;
10028            }
10029            Operator::I32Load8S { ref memarg } => {
10030                let offset = self.state.pop1()?.into_int_value();
10031                let narrow_result =
10032                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
10033                let result = err!(self.builder.build_int_s_extend(
10034                    narrow_result.into_int_value(),
10035                    self.intrinsics.i32_ty,
10036                    "",
10037                ));
10038                self.state.push1(result);
10039            }
10040            Operator::I32Load16S { ref memarg } => {
10041                let offset = self.state.pop1()?.into_int_value();
10042                let narrow_result =
10043                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10044                let result = err!(self.builder.build_int_s_extend(
10045                    narrow_result.into_int_value(),
10046                    self.intrinsics.i32_ty,
10047                    "",
10048                ));
10049                self.state.push1(result);
10050            }
10051            Operator::I64Load8S { ref memarg } => {
10052                let offset = self.state.pop1()?.into_int_value();
10053                let narrow_result =
10054                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
10055                let result = err!(self.builder.build_int_s_extend(
10056                    narrow_result.into_int_value(),
10057                    self.intrinsics.i64_ty,
10058                    ""
10059                ));
10060                self.state.push1(result);
10061            }
10062            Operator::I64Load16S { ref memarg } => {
10063                let offset = self.state.pop1()?.into_int_value();
10064                let narrow_result =
10065                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10066                let result = err!(self.builder.build_int_s_extend(
10067                    narrow_result.into_int_value(),
10068                    self.intrinsics.i64_ty,
10069                    ""
10070                ));
10071                self.state.push1(result);
10072            }
10073            Operator::I64Load32S { ref memarg } => {
10074                let offset = self.state.pop1()?.into_int_value();
10075                let narrow_result =
10076                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10077                let result = err!(self.builder.build_int_s_extend(
10078                    narrow_result.into_int_value(),
10079                    self.intrinsics.i64_ty,
10080                    "",
10081                ));
10082                self.state.push1(result);
10083            }
10084
10085            Operator::I32Load8U { ref memarg } => {
10086                let offset = self.state.pop1()?.into_int_value();
10087                let narrow_result =
10088                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
10089                let result = err!(self.builder.build_int_z_extend(
10090                    narrow_result.into_int_value(),
10091                    self.intrinsics.i32_ty,
10092                    "",
10093                ));
10094                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10095            }
10096            Operator::I32Load16U { ref memarg } => {
10097                let offset = self.state.pop1()?.into_int_value();
10098                let narrow_result =
10099                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10100                let result = err!(self.builder.build_int_z_extend(
10101                    narrow_result.into_int_value(),
10102                    self.intrinsics.i32_ty,
10103                    "",
10104                ));
10105                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10106            }
10107            Operator::I64Load8U { ref memarg } => {
10108                let offset = self.state.pop1()?.into_int_value();
10109                let narrow_result =
10110                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
10111                let result = err!(self.builder.build_int_z_extend(
10112                    narrow_result.into_int_value(),
10113                    self.intrinsics.i64_ty,
10114                    "",
10115                ));
10116                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10117            }
10118            Operator::I64Load16U { ref memarg } => {
10119                let offset = self.state.pop1()?.into_int_value();
10120                let narrow_result =
10121                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10122                let result = err!(self.builder.build_int_z_extend(
10123                    narrow_result.into_int_value(),
10124                    self.intrinsics.i64_ty,
10125                    "",
10126                ));
10127                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10128            }
10129            Operator::I64Load32U { ref memarg } => {
10130                let offset = self.state.pop1()?.into_int_value();
10131                let narrow_result =
10132                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10133                let result = err!(self.builder.build_int_z_extend(
10134                    narrow_result.into_int_value(),
10135                    self.intrinsics.i64_ty,
10136                    "",
10137                ));
10138                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10139            }
10140
10141            Operator::I32Store8 { ref memarg } | Operator::I64Store8 { ref memarg } => {
10142                let value = self.state.pop1()?.into_int_value();
10143                let offset = self.state.pop1()?.into_int_value();
10144                let narrow_value = err!(self.builder.build_int_truncate(
10145                    value,
10146                    self.intrinsics.i8_ty,
10147                    ""
10148                ));
10149                self.build_annotated_store(
10150                    self.intrinsics.i8_ty,
10151                    offset,
10152                    narrow_value.into(),
10153                    memarg,
10154                    1,
10155                )?;
10156            }
10157            Operator::I32Store16 { ref memarg } | Operator::I64Store16 { ref memarg } => {
10158                let value = self.state.pop1()?.into_int_value();
10159                let offset = self.state.pop1()?.into_int_value();
10160                let narrow_value = err!(self.builder.build_int_truncate(
10161                    value,
10162                    self.intrinsics.i16_ty,
10163                    ""
10164                ));
10165                self.build_annotated_store(
10166                    self.intrinsics.i16_ty,
10167                    offset,
10168                    narrow_value.into(),
10169                    memarg,
10170                    1,
10171                )?;
10172            }
10173            Operator::I64Store32 { ref memarg } => {
10174                let value = self.state.pop1()?.into_int_value();
10175                let offset = self.state.pop1()?.into_int_value();
10176                let narrow_value = err!(self.builder.build_int_truncate(
10177                    value,
10178                    self.intrinsics.i32_ty,
10179                    ""
10180                ));
10181                self.build_annotated_store(
10182                    self.intrinsics.i32_ty,
10183                    offset,
10184                    narrow_value.into(),
10185                    memarg,
10186                    1,
10187                )?;
10188            }
10189            Operator::I8x16Neg => {
10190                let (v, i) = self.state.pop1_extra()?;
10191                let (v, _) = self.v128_into_i8x16(v, i)?;
10192                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10193                let res = err!(
10194                    self.builder
10195                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10196                );
10197                self.state.push1(res);
10198            }
10199            Operator::I16x8Neg => {
10200                let (v, i) = self.state.pop1_extra()?;
10201                let (v, _) = self.v128_into_i16x8(v, i)?;
10202                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10203                let res = err!(
10204                    self.builder
10205                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10206                );
10207                self.state.push1(res);
10208            }
10209            Operator::I32x4Neg => {
10210                let (v, i) = self.state.pop1_extra()?;
10211                let (v, _) = self.v128_into_i32x4(v, i)?;
10212                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10213                let res = err!(
10214                    self.builder
10215                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10216                );
10217                self.state.push1(res);
10218            }
10219            Operator::I64x2Neg => {
10220                let (v, i) = self.state.pop1_extra()?;
10221                let (v, _) = self.v128_into_i64x2(v, i)?;
10222                let res = err!(self.builder.build_int_sub(v.get_type().const_zero(), v, ""));
10223                let res = err!(
10224                    self.builder
10225                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10226                );
10227                self.state.push1(res);
10228            }
10229            Operator::V128Not => {
10230                let (v, i) = self.state.pop1_extra()?;
10231                let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10232                let res = err!(self.builder.build_not(v, ""));
10233                self.state.push1(res);
10234            }
10235            Operator::V128AnyTrue => {
10236                // | Operator::I64x2AnyTrue
10237                // Skip canonicalization, it never changes non-zero values to zero or vice versa.
10238                let v = self.state.pop1()?.into_int_value();
10239                let res = err!(self.builder.build_int_compare(
10240                    IntPredicate::NE,
10241                    v,
10242                    v.get_type().const_zero(),
10243                    "",
10244                ));
10245                let res = err!(
10246                    self.builder
10247                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10248                );
10249                self.state.push1_extra(
10250                    res,
10251                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10252                );
10253            }
10254            Operator::I8x16AllTrue
10255            | Operator::I16x8AllTrue
10256            | Operator::I32x4AllTrue
10257            | Operator::I64x2AllTrue => {
10258                let vec_ty = match op {
10259                    Operator::I8x16AllTrue => self.intrinsics.i8x16_ty,
10260                    Operator::I16x8AllTrue => self.intrinsics.i16x8_ty,
10261                    Operator::I32x4AllTrue => self.intrinsics.i32x4_ty,
10262                    Operator::I64x2AllTrue => self.intrinsics.i64x2_ty,
10263                    _ => unreachable!(),
10264                };
10265                let (v, i) = self.state.pop1_extra()?;
10266                let v = self.apply_pending_canonicalization(v, i)?.into_int_value();
10267                let lane_int_ty = self
10268                    .context
10269                    .custom_width_int_type(NonZero::new(vec_ty.get_size()).unwrap())
10270                    .unwrap();
10271                let vec = err!(self.builder.build_bit_cast(v, vec_ty, "vec")).into_vector_value();
10272                let mask = err!(self.builder.build_int_compare(
10273                    IntPredicate::NE,
10274                    vec,
10275                    vec_ty.const_zero(),
10276                    "mask",
10277                ));
10278                let cmask =
10279                    err!(self.builder.build_bit_cast(mask, lane_int_ty, "cmask")).into_int_value();
10280                let res = err!(self.builder.build_int_compare(
10281                    IntPredicate::EQ,
10282                    cmask,
10283                    lane_int_ty.const_int(u64::MAX, true),
10284                    "",
10285                ));
10286                let res = err!(
10287                    self.builder
10288                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10289                );
10290                self.state.push1_extra(
10291                    res,
10292                    (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,
10293                );
10294            }
10295            Operator::I8x16ExtractLaneS { lane } => {
10296                let (v, i) = self.state.pop1_extra()?;
10297                let (v, _) = self.v128_into_i8x16(v, i)?;
10298                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10299                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10300                let res = err!(
10301                    self.builder
10302                        .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10303                );
10304                self.state.push1(res);
10305            }
10306            Operator::I8x16ExtractLaneU { lane } => {
10307                let (v, i) = self.state.pop1_extra()?;
10308                let (v, _) = self.v128_into_i8x16(v, i)?;
10309                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10310                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10311                let res = err!(
10312                    self.builder
10313                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10314                );
10315                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10316            }
10317            Operator::I16x8ExtractLaneS { lane } => {
10318                let (v, i) = self.state.pop1_extra()?;
10319                let (v, _) = self.v128_into_i16x8(v, i)?;
10320                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10321                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10322                let res = err!(
10323                    self.builder
10324                        .build_int_s_extend(res, self.intrinsics.i32_ty, "")
10325                );
10326                self.state.push1(res);
10327            }
10328            Operator::I16x8ExtractLaneU { lane } => {
10329                let (v, i) = self.state.pop1_extra()?;
10330                let (v, _) = self.v128_into_i16x8(v, i)?;
10331                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10332                let res = err!(self.builder.build_extract_element(v, idx, "")).into_int_value();
10333                let res = err!(
10334                    self.builder
10335                        .build_int_z_extend(res, self.intrinsics.i32_ty, "")
10336                );
10337                self.state.push1_extra(res, ExtraInfo::arithmetic_f32());
10338            }
10339            Operator::I32x4ExtractLane { lane } => {
10340                let (v, i) = self.state.pop1_extra()?;
10341                let (v, i) = self.v128_into_i32x4(v, i)?;
10342                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10343                let res = err!(self.builder.build_extract_element(v, idx, ""));
10344                self.state.push1_extra(res, i);
10345            }
10346            Operator::I64x2ExtractLane { lane } => {
10347                let (v, i) = self.state.pop1_extra()?;
10348                let (v, i) = self.v128_into_i64x2(v, i)?;
10349                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10350                let res = err!(self.builder.build_extract_element(v, idx, ""));
10351                self.state.push1_extra(res, i);
10352            }
10353            Operator::F32x4ExtractLane { lane } => {
10354                let (v, i) = self.state.pop1_extra()?;
10355                let (v, i) = self.v128_into_f32x4(v, i)?;
10356                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10357                let res = err!(self.builder.build_extract_element(v, idx, ""));
10358                self.state.push1_extra(res, i);
10359            }
10360            Operator::F64x2ExtractLane { lane } => {
10361                let (v, i) = self.state.pop1_extra()?;
10362                let (v, i) = self.v128_into_f64x2(v, i)?;
10363                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10364                let res = err!(self.builder.build_extract_element(v, idx, ""));
10365                self.state.push1_extra(res, i);
10366            }
10367            Operator::I8x16ReplaceLane { lane } => {
10368                let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10369                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10370                let v2 = v2.into_int_value();
10371                let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i8_ty, ""));
10372                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10373                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10374                let res = err!(
10375                    self.builder
10376                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10377                );
10378                self.state.push1(res);
10379            }
10380            Operator::I16x8ReplaceLane { lane } => {
10381                let ((v1, i1), (v2, _)) = self.state.pop2_extra()?;
10382                let (v1, _) = self.v128_into_i16x8(v1, i1)?;
10383                let v2 = v2.into_int_value();
10384                let v2 = err!(self.builder.build_int_cast(v2, self.intrinsics.i16_ty, ""));
10385                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10386                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10387                let res = err!(
10388                    self.builder
10389                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10390                );
10391                self.state.push1(res);
10392            }
10393            Operator::I32x4ReplaceLane { lane } => {
10394                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10395                let (v1, i1) = self.v128_into_i32x4(v1, i1)?;
10396                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10397                let v2 = v2.into_int_value();
10398                let i2 = i2.strip_pending();
10399                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10400                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10401                let res = err!(
10402                    self.builder
10403                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10404                );
10405                self.state
10406                    .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f32())?);
10407            }
10408            Operator::I64x2ReplaceLane { lane } => {
10409                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10410                let (v1, i1) = self.v128_into_i64x2(v1, i1)?;
10411                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10412                let v2 = v2.into_int_value();
10413                let i2 = i2.strip_pending();
10414                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10415                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10416                let res = err!(
10417                    self.builder
10418                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10419                );
10420                self.state
10421                    .push1_extra(res, ((i1 & i2)? & ExtraInfo::arithmetic_f64())?);
10422            }
10423            Operator::F32x4ReplaceLane { lane } => {
10424                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10425                let (v1, i1) = self.v128_into_f32x4(v1, i1)?;
10426                let push_pending_f32_nan_to_result =
10427                    i1.has_pending_f32_nan() && i2.has_pending_f32_nan();
10428                let (v1, v2) = if !push_pending_f32_nan_to_result {
10429                    (
10430                        self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10431                            .into_vector_value(),
10432                        self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10433                            .into_float_value(),
10434                    )
10435                } else {
10436                    (v1, v2.into_float_value())
10437                };
10438                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10439                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10440                let res = err!(
10441                    self.builder
10442                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10443                );
10444                let info = if push_pending_f32_nan_to_result {
10445                    ExtraInfo::pending_f32_nan()
10446                } else {
10447                    (i1.strip_pending() & i2.strip_pending())?
10448                };
10449                self.state.push1_extra(res, info);
10450            }
10451            Operator::F64x2ReplaceLane { lane } => {
10452                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10453                let (v1, i1) = self.v128_into_f64x2(v1, i1)?;
10454                let push_pending_f64_nan_to_result =
10455                    i1.has_pending_f64_nan() && i2.has_pending_f64_nan();
10456                let (v1, v2) = if !push_pending_f64_nan_to_result {
10457                    (
10458                        self.apply_pending_canonicalization(v1.as_basic_value_enum(), i1)?
10459                            .into_vector_value(),
10460                        self.apply_pending_canonicalization(v2.as_basic_value_enum(), i2)?
10461                            .into_float_value(),
10462                    )
10463                } else {
10464                    (v1, v2.into_float_value())
10465                };
10466                let idx = self.intrinsics.i32_ty.const_int(lane.into(), false);
10467                let res = err!(self.builder.build_insert_element(v1, v2, idx, ""));
10468                let res = err!(
10469                    self.builder
10470                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10471                );
10472                let info = if push_pending_f64_nan_to_result {
10473                    ExtraInfo::pending_f64_nan()
10474                } else {
10475                    (i1.strip_pending() & i2.strip_pending())?
10476                };
10477                self.state.push1_extra(res, info);
10478            }
10479            Operator::I8x16RelaxedSwizzle if self.cpu_features.contains(CpuFeature::SSSE3) => {
10480                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10481                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10482                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10483
10484                let (v1, _) = self.v128_into_i8x16(v1, i1)?;
10485                let (v2, _) = self.v128_into_i8x16(v2, i2)?;
10486                let res = self
10487                    .build_call_with_param_attributes(
10488                        self.intrinsics.x86_64.pshufb128,
10489                        &[v1.into(), v2.into()],
10490                        "",
10491                    )?
10492                    .try_as_basic_value()
10493                    .unwrap_basic();
10494                let res = err!(
10495                    self.builder
10496                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10497                );
10498                self.state.push1(res);
10499            }
10500            Operator::I8x16Swizzle | Operator::I8x16RelaxedSwizzle => {
10501                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10502                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10503                let v1 = err!(
10504                    self.builder
10505                        .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10506                )
10507                .into_vector_value();
10508                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10509                let v2 = err!(
10510                    self.builder
10511                        .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10512                )
10513                .into_vector_value();
10514                let lanes = self.intrinsics.i8_ty.const_int(16, false);
10515                let lanes =
10516                    self.splat_vector(lanes.as_basic_value_enum(), self.intrinsics.i8x16_ty)?;
10517                let mut res = self.intrinsics.i8x16_ty.get_undef();
10518                let idx_out_of_range = err!(self.builder.build_int_compare(
10519                    IntPredicate::UGE,
10520                    v2,
10521                    lanes,
10522                    "idx_out_of_range",
10523                ));
10524                let idx_clamped = err!(self.builder.build_select(
10525                    idx_out_of_range,
10526                    self.intrinsics.i8x16_ty.const_zero(),
10527                    v2,
10528                    "idx_clamped",
10529                ))
10530                .into_vector_value();
10531                for i in 0..16 {
10532                    let idx = err!(self.builder.build_extract_element(
10533                        idx_clamped,
10534                        self.intrinsics.i32_ty.const_int(i, false),
10535                        "idx",
10536                    ))
10537                    .into_int_value();
10538                    let replace_with_zero = err!(self.builder.build_extract_element(
10539                        idx_out_of_range,
10540                        self.intrinsics.i32_ty.const_int(i, false),
10541                        "replace_with_zero",
10542                    ))
10543                    .into_int_value();
10544                    let elem =
10545                        err!(self.builder.build_extract_element(v1, idx, "elem")).into_int_value();
10546                    let elem_or_zero = err!(self.builder.build_select(
10547                        replace_with_zero,
10548                        self.intrinsics.i8_zero,
10549                        elem,
10550                        "elem_or_zero",
10551                    ));
10552                    res = err!(self.builder.build_insert_element(
10553                        res,
10554                        elem_or_zero,
10555                        self.intrinsics.i32_ty.const_int(i, false),
10556                        "",
10557                    ));
10558                }
10559                let res = err!(
10560                    self.builder
10561                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10562                );
10563                self.state.push1(res);
10564            }
10565            Operator::I8x16Shuffle { lanes } => {
10566                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
10567                let v1 = self.apply_pending_canonicalization(v1, i1)?;
10568                let v1 = err!(
10569                    self.builder
10570                        .build_bit_cast(v1, self.intrinsics.i8x16_ty, "")
10571                )
10572                .into_vector_value();
10573                let v2 = self.apply_pending_canonicalization(v2, i2)?;
10574                let v2 = err!(
10575                    self.builder
10576                        .build_bit_cast(v2, self.intrinsics.i8x16_ty, "")
10577                )
10578                .into_vector_value();
10579                let mask = VectorType::const_vector(
10580                    lanes
10581                        .iter()
10582                        .map(|l| self.intrinsics.i32_ty.const_int((*l).into(), false))
10583                        .collect::<Vec<IntValue>>()
10584                        .as_slice(),
10585                );
10586                let res = err!(self.builder.build_shuffle_vector(v1, v2, mask, ""));
10587                let res = err!(
10588                    self.builder
10589                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10590                );
10591                self.state.push1(res);
10592            }
10593            Operator::V128Load8x8S { ref memarg } => {
10594                let offset = self.state.pop1()?.into_int_value();
10595                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10596                let v = err!(
10597                    self.builder
10598                        .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10599                )
10600                .into_vector_value();
10601                let res = err!(
10602                    self.builder
10603                        .build_int_s_extend(v, self.intrinsics.i16x8_ty, "")
10604                );
10605                let res = err!(
10606                    self.builder
10607                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10608                );
10609                self.state.push1(res);
10610            }
10611            Operator::V128Load8x8U { ref memarg } => {
10612                let offset = self.state.pop1()?.into_int_value();
10613                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10614                let v = err!(
10615                    self.builder
10616                        .build_bit_cast(v, self.intrinsics.i8_ty.vec_type(8), "")
10617                )
10618                .into_vector_value();
10619                let res = err!(
10620                    self.builder
10621                        .build_int_z_extend(v, self.intrinsics.i16x8_ty, "")
10622                );
10623                let res = err!(
10624                    self.builder
10625                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10626                );
10627                self.state.push1(res);
10628            }
10629            Operator::V128Load16x4S { ref memarg } => {
10630                let offset = self.state.pop1()?.into_int_value();
10631                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10632                let v = err!(self.builder.build_bit_cast(
10633                    v,
10634                    self.intrinsics.i16_ty.vec_type(4),
10635                    ""
10636                ))
10637                .into_vector_value();
10638                let res = err!(
10639                    self.builder
10640                        .build_int_s_extend(v, self.intrinsics.i32x4_ty, "")
10641                );
10642                let res = err!(
10643                    self.builder
10644                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10645                );
10646                self.state.push1(res);
10647            }
10648            Operator::V128Load16x4U { ref memarg } => {
10649                let offset = self.state.pop1()?.into_int_value();
10650                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10651                let v = err!(self.builder.build_bit_cast(
10652                    v,
10653                    self.intrinsics.i16_ty.vec_type(4),
10654                    ""
10655                ))
10656                .into_vector_value();
10657                let res = err!(
10658                    self.builder
10659                        .build_int_z_extend(v, self.intrinsics.i32x4_ty, "")
10660                );
10661                let res = err!(
10662                    self.builder
10663                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10664                );
10665                self.state.push1(res);
10666            }
10667            Operator::V128Load32x2S { ref memarg } => {
10668                let offset = self.state.pop1()?.into_int_value();
10669                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10670                let v = err!(self.builder.build_bit_cast(
10671                    v,
10672                    self.intrinsics.i32_ty.vec_type(2),
10673                    ""
10674                ))
10675                .into_vector_value();
10676                let res = err!(
10677                    self.builder
10678                        .build_int_s_extend(v, self.intrinsics.i64x2_ty, "")
10679                );
10680                let res = err!(
10681                    self.builder
10682                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10683                );
10684                self.state.push1(res);
10685            }
10686            Operator::V128Load32x2U { ref memarg } => {
10687                let offset = self.state.pop1()?.into_int_value();
10688                let v = self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10689                let v = err!(self.builder.build_bit_cast(
10690                    v,
10691                    self.intrinsics.i32_ty.vec_type(2),
10692                    ""
10693                ))
10694                .into_vector_value();
10695                let res = err!(
10696                    self.builder
10697                        .build_int_z_extend(v, self.intrinsics.i64x2_ty, "")
10698                );
10699                let res = err!(
10700                    self.builder
10701                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10702                );
10703                self.state.push1(res);
10704            }
10705            Operator::V128Load32Zero { ref memarg } => {
10706                let offset = self.state.pop1()?.into_int_value();
10707                let element =
10708                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10709                let res = err!(self.builder.build_int_z_extend(
10710                    element.into_int_value(),
10711                    self.intrinsics.i128_ty,
10712                    "",
10713                ));
10714                self.state.push1(res);
10715            }
10716            Operator::V128Load64Zero { ref memarg } => {
10717                let offset = self.state.pop1()?.into_int_value();
10718                let element =
10719                    self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10720                let res = err!(self.builder.build_int_z_extend(
10721                    element.into_int_value(),
10722                    self.intrinsics.i128_ty,
10723                    "",
10724                ));
10725                self.state.push1(res);
10726            }
10727            Operator::V128Load8Splat { ref memarg } => {
10728                let offset = self.state.pop1()?.into_int_value();
10729                let element =
10730                    self.build_annotated_load(self.intrinsics.i8_ty, offset, memarg, 1)?;
10731                let res = self.splat_vector(element, self.intrinsics.i8x16_ty)?;
10732                let res = err!(
10733                    self.builder
10734                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10735                );
10736                self.state.push1(res);
10737            }
10738            Operator::V128Load16Splat { ref memarg } => {
10739                let offset = self.state.pop1()?.into_int_value();
10740                let element =
10741                    self.build_annotated_load(self.intrinsics.i16_ty, offset, memarg, 1)?;
10742                let res = self.splat_vector(element, self.intrinsics.i16x8_ty)?;
10743                let res = err!(
10744                    self.builder
10745                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10746                );
10747                self.state.push1(res);
10748            }
10749            Operator::V128Load32Splat { ref memarg } => {
10750                let offset = self.state.pop1()?.into_int_value();
10751                let element =
10752                    self.build_annotated_load(self.intrinsics.i32_ty, offset, memarg, 1)?;
10753                let res = self.splat_vector(element, self.intrinsics.i32x4_ty)?;
10754                let res = err!(
10755                    self.builder
10756                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10757                );
10758                self.state.push1(res);
10759            }
10760            Operator::V128Load64Splat { ref memarg } => {
10761                let offset = self.state.pop1()?.into_int_value();
10762                let element =
10763                    self.build_annotated_load(self.intrinsics.i64_ty, offset, memarg, 1)?;
10764                let res = self.splat_vector(element, self.intrinsics.i64x2_ty)?;
10765                let res = err!(
10766                    self.builder
10767                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
10768                );
10769                self.state.push1(res);
10770            }
10771
10772            Operator::MemoryGrow { mem } => {
10773                let memory_index = MemoryIndex::from_u32(mem);
10774                let index_arg = self
10775                    .wasm_module
10776                    .local_memory_index(memory_index)
10777                    .map_or(mem, |index| index.as_u32());
10778                let delta = self.state.pop1()?;
10779                let grow_fn_ptr = self.ctx.memory_grow(memory_index, self.intrinsics)?;
10780                let grow = err!(
10781                    self.builder.build_indirect_call(
10782                        self.intrinsics.memory_grow_ty,
10783                        grow_fn_ptr,
10784                        &[
10785                            vmctx.as_basic_value_enum().into(),
10786                            delta.into(),
10787                            self.intrinsics
10788                                .i32_ty
10789                                .const_int(index_arg.into(), false)
10790                                .into(),
10791                        ],
10792                        "",
10793                    )
10794                );
10795                self.state.push1(grow.try_as_basic_value().unwrap_basic());
10796            }
10797            Operator::MemorySize { mem } => {
10798                let memory_index = MemoryIndex::from_u32(mem);
10799                let index_arg = self
10800                    .wasm_module
10801                    .local_memory_index(memory_index)
10802                    .map_or(mem, |index| index.as_u32());
10803                let size_fn_ptr = self.ctx.memory_size(memory_index, self.intrinsics)?;
10804                let size = err!(
10805                    self.builder.build_indirect_call(
10806                        self.intrinsics.memory_size_ty,
10807                        size_fn_ptr,
10808                        &[
10809                            vmctx.as_basic_value_enum().into(),
10810                            self.intrinsics
10811                                .i32_ty
10812                                .const_int(index_arg.into(), false)
10813                                .into(),
10814                        ],
10815                        "",
10816                    )
10817                );
10818                //size.add_attribute(AttributeLoc::Function, self.intrinsics.readonly);
10819                self.state.push1(size.try_as_basic_value().unwrap_basic());
10820            }
10821            Operator::MemoryInit { data_index, mem } => {
10822                let (dest, src, len) = self.state.pop3()?;
10823                let mem = self.intrinsics.i32_ty.const_int(mem.into(), false);
10824                let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
10825                self.build_call_with_param_attributes(
10826                    self.intrinsics.memory_init,
10827                    &[
10828                        vmctx.as_basic_value_enum().into(),
10829                        mem.into(),
10830                        segment.into(),
10831                        dest.into(),
10832                        src.into(),
10833                        len.into(),
10834                    ],
10835                    "",
10836                )?;
10837            }
10838            Operator::DataDrop { data_index } => {
10839                let segment = self.intrinsics.i32_ty.const_int(data_index.into(), false);
10840                self.build_call_with_param_attributes(
10841                    self.intrinsics.data_drop,
10842                    &[vmctx.as_basic_value_enum().into(), segment.into()],
10843                    "",
10844                )?;
10845            }
10846            Operator::MemoryCopy { dst_mem, src_mem } => {
10847                let (dest_pos, src_pos, len) = self.state.pop3()?;
10848                let dst_index = self.intrinsics.i32_ty.const_int(dst_mem.into(), false);
10849                let src_index = self.intrinsics.i32_ty.const_int(src_mem.into(), false);
10850                self.build_call_with_param_attributes(
10851                    self.intrinsics.memory_copy,
10852                    &[
10853                        vmctx.as_basic_value_enum().into(),
10854                        dst_index.into(),
10855                        src_index.into(),
10856                        dest_pos.into(),
10857                        src_pos.into(),
10858                        len.into(),
10859                    ],
10860                    "",
10861                )?;
10862            }
10863            Operator::MemoryFill { mem } => {
10864                let (memory_fill, mem) = if let Some(local_memory_index) = self
10865                    .wasm_module
10866                    .local_memory_index(MemoryIndex::from_u32(mem))
10867                {
10868                    (self.intrinsics.memory_fill, local_memory_index.as_u32())
10869                } else {
10870                    (self.intrinsics.imported_memory_fill, mem)
10871                };
10872
10873                let (dst, val, len) = self.state.pop3()?;
10874                let mem_index = self.intrinsics.i32_ty.const_int(mem.into(), false);
10875                self.build_call_with_param_attributes(
10876                    memory_fill,
10877                    &[
10878                        vmctx.as_basic_value_enum().into(),
10879                        mem_index.into(),
10880                        dst.into(),
10881                        val.into(),
10882                        len.into(),
10883                    ],
10884                    "",
10885                )?;
10886            }
10887            _ => unreachable!(),
10888        }
10889        Ok(())
10890    }
10891
10892    // Atomic memory operations.
10893    fn translate_atomic_memory_operator(&mut self, op: Operator) -> Result<(), CompileError> {
10894        let vmctx = &self.ctx.basic().into_pointer_value();
10895
10896        match op {
10897            Operator::AtomicFence => {
10898                // Fence is a nop.
10899                //
10900                // Fence was added to preserve information about fences from
10901                // source languages. If in the future Wasm extends the memory
10902                // model, and if we hadn't recorded what fences used to be there,
10903                // it would lead to data races that weren't present in the
10904                // original source language.
10905            }
10906            Operator::I32AtomicLoad { ref memarg } => {
10907                let offset = self.state.pop1()?.into_int_value();
10908                let result = self.build_annotated_atomic_load(
10909                    self.intrinsics.i32_ty,
10910                    self.intrinsics.i32_ty,
10911                    offset,
10912                    memarg,
10913                )?;
10914                self.state.push1(result);
10915            }
10916            Operator::I64AtomicLoad { ref memarg } => {
10917                let offset = self.state.pop1()?.into_int_value();
10918                let result = self.build_annotated_atomic_load(
10919                    self.intrinsics.i64_ty,
10920                    self.intrinsics.i64_ty,
10921                    offset,
10922                    memarg,
10923                )?;
10924                self.state.push1(result);
10925            }
10926            Operator::I32AtomicLoad8U { ref memarg } => {
10927                let offset = self.state.pop1()?.into_int_value();
10928                let result = self.build_annotated_atomic_load(
10929                    self.intrinsics.i32_ty,
10930                    self.intrinsics.i8_ty,
10931                    offset,
10932                    memarg,
10933                )?;
10934                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10935            }
10936            Operator::I32AtomicLoad16U { ref memarg } => {
10937                let offset = self.state.pop1()?.into_int_value();
10938                let result = self.build_annotated_atomic_load(
10939                    self.intrinsics.i32_ty,
10940                    self.intrinsics.i16_ty,
10941                    offset,
10942                    memarg,
10943                )?;
10944                self.state.push1_extra(result, ExtraInfo::arithmetic_f32());
10945            }
10946            Operator::I64AtomicLoad8U { ref memarg } => {
10947                let offset = self.state.pop1()?.into_int_value();
10948                let result = self.build_annotated_atomic_load(
10949                    self.intrinsics.i64_ty,
10950                    self.intrinsics.i8_ty,
10951                    offset,
10952                    memarg,
10953                )?;
10954                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10955            }
10956            Operator::I64AtomicLoad16U { ref memarg } => {
10957                let offset = self.state.pop1()?.into_int_value();
10958                let result = self.build_annotated_atomic_load(
10959                    self.intrinsics.i64_ty,
10960                    self.intrinsics.i16_ty,
10961                    offset,
10962                    memarg,
10963                )?;
10964                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10965            }
10966            Operator::I64AtomicLoad32U { ref memarg } => {
10967                let offset = self.state.pop1()?.into_int_value();
10968                let result = self.build_annotated_atomic_load(
10969                    self.intrinsics.i64_ty,
10970                    self.intrinsics.i32_ty,
10971                    offset,
10972                    memarg,
10973                )?;
10974                self.state.push1_extra(result, ExtraInfo::arithmetic_f64());
10975            }
10976            Operator::I32AtomicStore { ref memarg } => {
10977                let value = self.state.pop1()?.into_int_value();
10978                let offset = self.state.pop1()?.into_int_value();
10979                self.build_annotated_atomic_store(
10980                    self.intrinsics.i32_ty,
10981                    self.intrinsics.i32_ty,
10982                    offset,
10983                    value,
10984                    memarg,
10985                )?;
10986            }
10987            Operator::I64AtomicStore { ref memarg } => {
10988                let value = self.state.pop1()?.into_int_value();
10989                let offset = self.state.pop1()?.into_int_value();
10990                self.build_annotated_atomic_store(
10991                    self.intrinsics.i64_ty,
10992                    self.intrinsics.i64_ty,
10993                    offset,
10994                    value,
10995                    memarg,
10996                )?;
10997            }
10998            Operator::I32AtomicStore8 { ref memarg } | Operator::I64AtomicStore8 { ref memarg } => {
10999                let value = self.state.pop1()?.into_int_value();
11000                let offset = self.state.pop1()?.into_int_value();
11001                self.build_annotated_atomic_store(
11002                    value.get_type(),
11003                    self.intrinsics.i8_ty,
11004                    offset,
11005                    value,
11006                    memarg,
11007                )?;
11008            }
11009            Operator::I32AtomicStore16 { ref memarg }
11010            | Operator::I64AtomicStore16 { ref memarg } => {
11011                let value = self.state.pop1()?.into_int_value();
11012                let offset = self.state.pop1()?.into_int_value();
11013                self.build_annotated_atomic_store(
11014                    value.get_type(),
11015                    self.intrinsics.i16_ty,
11016                    offset,
11017                    value,
11018                    memarg,
11019                )?;
11020            }
11021            Operator::I64AtomicStore32 { ref memarg } => {
11022                let value = self.state.pop1()?.into_int_value();
11023                let offset = self.state.pop1()?.into_int_value();
11024                self.build_annotated_atomic_store(
11025                    self.intrinsics.i64_ty,
11026                    self.intrinsics.i32_ty,
11027                    offset,
11028                    value,
11029                    memarg,
11030                )?;
11031            }
11032            Operator::I32AtomicRmw8AddU { ref memarg } => self.translate_atomic_rmw(
11033                self.intrinsics.i32_ty,
11034                self.intrinsics.i8_ty,
11035                memarg,
11036                AtomicRMWBinOp::Add,
11037                Some(ExtraInfo::arithmetic_f32()),
11038            )?,
11039            Operator::I32AtomicRmw16AddU { ref memarg } => self.translate_atomic_rmw(
11040                self.intrinsics.i32_ty,
11041                self.intrinsics.i16_ty,
11042                memarg,
11043                AtomicRMWBinOp::Add,
11044                Some(ExtraInfo::arithmetic_f32()),
11045            )?,
11046            Operator::I32AtomicRmwAdd { ref memarg } => self.translate_atomic_rmw(
11047                self.intrinsics.i32_ty,
11048                self.intrinsics.i32_ty,
11049                memarg,
11050                AtomicRMWBinOp::Add,
11051                None,
11052            )?,
11053            Operator::I64AtomicRmw8AddU { ref memarg } => self.translate_atomic_rmw(
11054                self.intrinsics.i64_ty,
11055                self.intrinsics.i8_ty,
11056                memarg,
11057                AtomicRMWBinOp::Add,
11058                Some(ExtraInfo::arithmetic_f64()),
11059            )?,
11060            Operator::I64AtomicRmw16AddU { ref memarg } => self.translate_atomic_rmw(
11061                self.intrinsics.i64_ty,
11062                self.intrinsics.i16_ty,
11063                memarg,
11064                AtomicRMWBinOp::Add,
11065                Some(ExtraInfo::arithmetic_f64()),
11066            )?,
11067            Operator::I64AtomicRmw32AddU { ref memarg } => self.translate_atomic_rmw(
11068                self.intrinsics.i64_ty,
11069                self.intrinsics.i32_ty,
11070                memarg,
11071                AtomicRMWBinOp::Add,
11072                Some(ExtraInfo::arithmetic_f64()),
11073            )?,
11074            Operator::I64AtomicRmwAdd { ref memarg } => self.translate_atomic_rmw(
11075                self.intrinsics.i64_ty,
11076                self.intrinsics.i64_ty,
11077                memarg,
11078                AtomicRMWBinOp::Add,
11079                None,
11080            )?,
11081            Operator::I32AtomicRmw8SubU { ref memarg } => self.translate_atomic_rmw(
11082                self.intrinsics.i32_ty,
11083                self.intrinsics.i8_ty,
11084                memarg,
11085                AtomicRMWBinOp::Sub,
11086                Some(ExtraInfo::arithmetic_f32()),
11087            )?,
11088            Operator::I32AtomicRmw16SubU { ref memarg } => self.translate_atomic_rmw(
11089                self.intrinsics.i32_ty,
11090                self.intrinsics.i16_ty,
11091                memarg,
11092                AtomicRMWBinOp::Sub,
11093                Some(ExtraInfo::arithmetic_f32()),
11094            )?,
11095            Operator::I32AtomicRmwSub { ref memarg } => self.translate_atomic_rmw(
11096                self.intrinsics.i32_ty,
11097                self.intrinsics.i32_ty,
11098                memarg,
11099                AtomicRMWBinOp::Sub,
11100                None,
11101            )?,
11102            Operator::I64AtomicRmw8SubU { ref memarg } => self.translate_atomic_rmw(
11103                self.intrinsics.i64_ty,
11104                self.intrinsics.i8_ty,
11105                memarg,
11106                AtomicRMWBinOp::Sub,
11107                Some(ExtraInfo::arithmetic_f32()),
11108            )?,
11109            Operator::I64AtomicRmw16SubU { ref memarg } => self.translate_atomic_rmw(
11110                self.intrinsics.i64_ty,
11111                self.intrinsics.i16_ty,
11112                memarg,
11113                AtomicRMWBinOp::Sub,
11114                Some(ExtraInfo::arithmetic_f64()),
11115            )?,
11116            Operator::I64AtomicRmw32SubU { ref memarg } => self.translate_atomic_rmw(
11117                self.intrinsics.i64_ty,
11118                self.intrinsics.i32_ty,
11119                memarg,
11120                AtomicRMWBinOp::Sub,
11121                Some(ExtraInfo::arithmetic_f64()),
11122            )?,
11123            Operator::I64AtomicRmwSub { ref memarg } => self.translate_atomic_rmw(
11124                self.intrinsics.i64_ty,
11125                self.intrinsics.i64_ty,
11126                memarg,
11127                AtomicRMWBinOp::Sub,
11128                None,
11129            )?,
11130            Operator::I32AtomicRmw8AndU { ref memarg } => self.translate_atomic_rmw(
11131                self.intrinsics.i32_ty,
11132                self.intrinsics.i8_ty,
11133                memarg,
11134                AtomicRMWBinOp::And,
11135                Some(ExtraInfo::arithmetic_f32()),
11136            )?,
11137            Operator::I32AtomicRmw16AndU { ref memarg } => self.translate_atomic_rmw(
11138                self.intrinsics.i32_ty,
11139                self.intrinsics.i16_ty,
11140                memarg,
11141                AtomicRMWBinOp::And,
11142                Some(ExtraInfo::arithmetic_f32()),
11143            )?,
11144            Operator::I32AtomicRmwAnd { ref memarg } => self.translate_atomic_rmw(
11145                self.intrinsics.i32_ty,
11146                self.intrinsics.i32_ty,
11147                memarg,
11148                AtomicRMWBinOp::And,
11149                None,
11150            )?,
11151            Operator::I64AtomicRmw8AndU { ref memarg } => self.translate_atomic_rmw(
11152                self.intrinsics.i64_ty,
11153                self.intrinsics.i8_ty,
11154                memarg,
11155                AtomicRMWBinOp::And,
11156                Some(ExtraInfo::arithmetic_f64()),
11157            )?,
11158            Operator::I64AtomicRmw16AndU { ref memarg } => self.translate_atomic_rmw(
11159                self.intrinsics.i64_ty,
11160                self.intrinsics.i16_ty,
11161                memarg,
11162                AtomicRMWBinOp::And,
11163                Some(ExtraInfo::arithmetic_f64()),
11164            )?,
11165            Operator::I64AtomicRmw32AndU { ref memarg } => self.translate_atomic_rmw(
11166                self.intrinsics.i64_ty,
11167                self.intrinsics.i32_ty,
11168                memarg,
11169                AtomicRMWBinOp::And,
11170                Some(ExtraInfo::arithmetic_f64()),
11171            )?,
11172            Operator::I64AtomicRmwAnd { ref memarg } => self.translate_atomic_rmw(
11173                self.intrinsics.i64_ty,
11174                self.intrinsics.i64_ty,
11175                memarg,
11176                AtomicRMWBinOp::And,
11177                None,
11178            )?,
11179            Operator::I32AtomicRmw8OrU { ref memarg } => self.translate_atomic_rmw(
11180                self.intrinsics.i32_ty,
11181                self.intrinsics.i8_ty,
11182                memarg,
11183                AtomicRMWBinOp::Or,
11184                Some(ExtraInfo::arithmetic_f32()),
11185            )?,
11186            Operator::I32AtomicRmw16OrU { ref memarg } => self.translate_atomic_rmw(
11187                self.intrinsics.i32_ty,
11188                self.intrinsics.i16_ty,
11189                memarg,
11190                AtomicRMWBinOp::Or,
11191                Some(ExtraInfo::arithmetic_f32()),
11192            )?,
11193            Operator::I32AtomicRmwOr { ref memarg } => self.translate_atomic_rmw(
11194                self.intrinsics.i32_ty,
11195                self.intrinsics.i32_ty,
11196                memarg,
11197                AtomicRMWBinOp::Or,
11198                Some(ExtraInfo::arithmetic_f32()),
11199            )?,
11200            Operator::I64AtomicRmw8OrU { ref memarg } => self.translate_atomic_rmw(
11201                self.intrinsics.i64_ty,
11202                self.intrinsics.i8_ty,
11203                memarg,
11204                AtomicRMWBinOp::Or,
11205                Some(ExtraInfo::arithmetic_f64()),
11206            )?,
11207            Operator::I64AtomicRmw16OrU { ref memarg } => self.translate_atomic_rmw(
11208                self.intrinsics.i64_ty,
11209                self.intrinsics.i16_ty,
11210                memarg,
11211                AtomicRMWBinOp::Or,
11212                Some(ExtraInfo::arithmetic_f64()),
11213            )?,
11214            Operator::I64AtomicRmw32OrU { ref memarg } => self.translate_atomic_rmw(
11215                self.intrinsics.i64_ty,
11216                self.intrinsics.i32_ty,
11217                memarg,
11218                AtomicRMWBinOp::Or,
11219                Some(ExtraInfo::arithmetic_f64()),
11220            )?,
11221            Operator::I64AtomicRmwOr { ref memarg } => self.translate_atomic_rmw(
11222                self.intrinsics.i64_ty,
11223                self.intrinsics.i64_ty,
11224                memarg,
11225                AtomicRMWBinOp::Or,
11226                None,
11227            )?,
11228            Operator::I32AtomicRmw8XorU { ref memarg } => self.translate_atomic_rmw(
11229                self.intrinsics.i32_ty,
11230                self.intrinsics.i8_ty,
11231                memarg,
11232                AtomicRMWBinOp::Xor,
11233                Some(ExtraInfo::arithmetic_f32()),
11234            )?,
11235            Operator::I32AtomicRmw16XorU { ref memarg } => self.translate_atomic_rmw(
11236                self.intrinsics.i32_ty,
11237                self.intrinsics.i16_ty,
11238                memarg,
11239                AtomicRMWBinOp::Xor,
11240                Some(ExtraInfo::arithmetic_f32()),
11241            )?,
11242            Operator::I32AtomicRmwXor { ref memarg } => self.translate_atomic_rmw(
11243                self.intrinsics.i32_ty,
11244                self.intrinsics.i32_ty,
11245                memarg,
11246                AtomicRMWBinOp::Xor,
11247                None,
11248            )?,
11249            Operator::I64AtomicRmw8XorU { ref memarg } => self.translate_atomic_rmw(
11250                self.intrinsics.i64_ty,
11251                self.intrinsics.i8_ty,
11252                memarg,
11253                AtomicRMWBinOp::Xor,
11254                Some(ExtraInfo::arithmetic_f64()),
11255            )?,
11256            Operator::I64AtomicRmw16XorU { ref memarg } => self.translate_atomic_rmw(
11257                self.intrinsics.i64_ty,
11258                self.intrinsics.i16_ty,
11259                memarg,
11260                AtomicRMWBinOp::Xor,
11261                Some(ExtraInfo::arithmetic_f64()),
11262            )?,
11263            Operator::I64AtomicRmw32XorU { ref memarg } => self.translate_atomic_rmw(
11264                self.intrinsics.i64_ty,
11265                self.intrinsics.i32_ty,
11266                memarg,
11267                AtomicRMWBinOp::Xor,
11268                Some(ExtraInfo::arithmetic_f64()),
11269            )?,
11270            Operator::I64AtomicRmwXor { ref memarg } => self.translate_atomic_rmw(
11271                self.intrinsics.i64_ty,
11272                self.intrinsics.i64_ty,
11273                memarg,
11274                AtomicRMWBinOp::Xor,
11275                None,
11276            )?,
11277            Operator::I32AtomicRmw8XchgU { ref memarg } => self.translate_atomic_rmw(
11278                self.intrinsics.i32_ty,
11279                self.intrinsics.i8_ty,
11280                memarg,
11281                AtomicRMWBinOp::Xchg,
11282                Some(ExtraInfo::arithmetic_f32()),
11283            )?,
11284            Operator::I32AtomicRmw16XchgU { ref memarg } => self.translate_atomic_rmw(
11285                self.intrinsics.i32_ty,
11286                self.intrinsics.i16_ty,
11287                memarg,
11288                AtomicRMWBinOp::Xchg,
11289                Some(ExtraInfo::arithmetic_f32()),
11290            )?,
11291            Operator::I32AtomicRmwXchg { ref memarg } => self.translate_atomic_rmw(
11292                self.intrinsics.i32_ty,
11293                self.intrinsics.i32_ty,
11294                memarg,
11295                AtomicRMWBinOp::Xchg,
11296                None,
11297            )?,
11298            Operator::I64AtomicRmw8XchgU { ref memarg } => self.translate_atomic_rmw(
11299                self.intrinsics.i64_ty,
11300                self.intrinsics.i8_ty,
11301                memarg,
11302                AtomicRMWBinOp::Xchg,
11303                Some(ExtraInfo::arithmetic_f64()),
11304            )?,
11305            Operator::I64AtomicRmw16XchgU { ref memarg } => self.translate_atomic_rmw(
11306                self.intrinsics.i64_ty,
11307                self.intrinsics.i16_ty,
11308                memarg,
11309                AtomicRMWBinOp::Xchg,
11310                Some(ExtraInfo::arithmetic_f64()),
11311            )?,
11312            Operator::I64AtomicRmw32XchgU { ref memarg } => self.translate_atomic_rmw(
11313                self.intrinsics.i64_ty,
11314                self.intrinsics.i32_ty,
11315                memarg,
11316                AtomicRMWBinOp::Xchg,
11317                Some(ExtraInfo::arithmetic_f64()),
11318            )?,
11319            Operator::I64AtomicRmwXchg { ref memarg } => self.translate_atomic_rmw(
11320                self.intrinsics.i64_ty,
11321                self.intrinsics.i64_ty,
11322                memarg,
11323                AtomicRMWBinOp::Xchg,
11324                None,
11325            )?,
11326            Operator::I32AtomicRmw8CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11327                self.intrinsics.i32_ty,
11328                self.intrinsics.i8_ty,
11329                memarg,
11330                Some(ExtraInfo::arithmetic_f32()),
11331            )?,
11332            Operator::I32AtomicRmw16CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11333                self.intrinsics.i32_ty,
11334                self.intrinsics.i16_ty,
11335                memarg,
11336                Some(ExtraInfo::arithmetic_f32()),
11337            )?,
11338            Operator::I32AtomicRmwCmpxchg { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11339                self.intrinsics.i32_ty,
11340                self.intrinsics.i32_ty,
11341                memarg,
11342                None,
11343            )?,
11344            Operator::I64AtomicRmw8CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11345                self.intrinsics.i64_ty,
11346                self.intrinsics.i8_ty,
11347                memarg,
11348                Some(ExtraInfo::arithmetic_f64()),
11349            )?,
11350            Operator::I64AtomicRmw16CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11351                self.intrinsics.i64_ty,
11352                self.intrinsics.i16_ty,
11353                memarg,
11354                Some(ExtraInfo::arithmetic_f64()),
11355            )?,
11356            Operator::I64AtomicRmw32CmpxchgU { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11357                self.intrinsics.i64_ty,
11358                self.intrinsics.i32_ty,
11359                memarg,
11360                Some(ExtraInfo::arithmetic_f64()),
11361            )?,
11362            Operator::I64AtomicRmwCmpxchg { ref memarg } => self.translate_atomic_rmw_cmpxchg(
11363                self.intrinsics.i64_ty,
11364                self.intrinsics.i64_ty,
11365                memarg,
11366                None,
11367            )?,
11368            Operator::MemoryAtomicWait32 { memarg } => {
11369                let memory_index = MemoryIndex::from_u32(memarg.memory);
11370                let index_arg = self
11371                    .wasm_module
11372                    .local_memory_index(memory_index)
11373                    .map_or(memarg.memory, |index| index.as_u32());
11374                let (dst, val, timeout) = self.state.pop3()?;
11375                let dst = self.fold_atomic_mem_addr(dst, &memarg)?;
11376                let wait32_fn_ptr = self.ctx.memory_wait32(memory_index, self.intrinsics)?;
11377                let ret = err!(
11378                    self.builder.build_indirect_call(
11379                        self.intrinsics.memory_wait32_ty,
11380                        wait32_fn_ptr,
11381                        &[
11382                            vmctx.as_basic_value_enum().into(),
11383                            self.intrinsics
11384                                .i32_ty
11385                                .const_int(index_arg as u64, false)
11386                                .into(),
11387                            dst.into(),
11388                            val.into(),
11389                            timeout.into(),
11390                        ],
11391                        "",
11392                    )
11393                );
11394                self.state.push1(ret.try_as_basic_value().unwrap_basic());
11395            }
11396            Operator::MemoryAtomicWait64 { memarg } => {
11397                let memory_index = MemoryIndex::from_u32(memarg.memory);
11398                let index_arg = self
11399                    .wasm_module
11400                    .local_memory_index(memory_index)
11401                    .map_or(memarg.memory, |index| index.as_u32());
11402                let (dst, val, timeout) = self.state.pop3()?;
11403                let dst = self.fold_atomic_mem_addr(dst, &memarg)?;
11404                let wait64_fn_ptr = self.ctx.memory_wait64(memory_index, self.intrinsics)?;
11405                let ret = err!(
11406                    self.builder.build_indirect_call(
11407                        self.intrinsics.memory_wait64_ty,
11408                        wait64_fn_ptr,
11409                        &[
11410                            vmctx.as_basic_value_enum().into(),
11411                            self.intrinsics
11412                                .i32_ty
11413                                .const_int(index_arg as u64, false)
11414                                .into(),
11415                            dst.into(),
11416                            val.into(),
11417                            timeout.into(),
11418                        ],
11419                        "",
11420                    )
11421                );
11422                self.state.push1(ret.try_as_basic_value().unwrap_basic());
11423            }
11424            Operator::MemoryAtomicNotify { memarg } => {
11425                let memory_index = MemoryIndex::from_u32(memarg.memory);
11426                let index_arg = self
11427                    .wasm_module
11428                    .local_memory_index(memory_index)
11429                    .map_or(memarg.memory, |index| index.as_u32());
11430                let (dst, count) = self.state.pop2()?;
11431                let dst = self.fold_atomic_mem_addr(dst, &memarg)?;
11432                let notify_fn_ptr = self.ctx.memory_notify(memory_index, self.intrinsics)?;
11433                let cnt = err!(
11434                    self.builder.build_indirect_call(
11435                        self.intrinsics.memory_notify_ty,
11436                        notify_fn_ptr,
11437                        &[
11438                            vmctx.as_basic_value_enum().into(),
11439                            self.intrinsics
11440                                .i32_ty
11441                                .const_int(index_arg as u64, false)
11442                                .into(),
11443                            dst.into(),
11444                            count.into(),
11445                        ],
11446                        "",
11447                    )
11448                );
11449                self.state.push1(cnt.try_as_basic_value().unwrap_basic());
11450            }
11451            _ => unreachable!(),
11452        }
11453        Ok(())
11454    }
11455
11456    // Reference types.
11457    // https://github.com/WebAssembly/reference-types/blob/master/proposals/reference-types/Overview.md
11458    fn translate_reference_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11459        match op {
11460            Operator::RefNull { hty } => {
11461                let ty = err!(wpheaptype_to_type(hty));
11462                let ty = type_to_llvm(self.intrinsics, ty)?;
11463                self.state.push1(ty.const_zero());
11464            }
11465            Operator::RefIsNull => {
11466                let value = self.state.pop1()?;
11467                let is_null = match value {
11468                    BasicValueEnum::IntValue(value) => err!(self.builder.build_int_compare(
11469                        IntPredicate::EQ,
11470                        value,
11471                        value.get_type().const_zero(),
11472                        "",
11473                    )),
11474                    BasicValueEnum::PointerValue(value) => {
11475                        err!(self.builder.build_is_null(value, ""))
11476                    }
11477                    _ => unreachable!("ref.is_null only accepts reference types"),
11478                };
11479                let is_null = err!(self.builder.build_int_z_extend(
11480                    is_null,
11481                    self.intrinsics.i32_ty,
11482                    ""
11483                ));
11484                self.state.push1(is_null);
11485            }
11486            Operator::RefFunc { function_index } => {
11487                let index = self
11488                    .intrinsics
11489                    .i32_ty
11490                    .const_int(function_index.into(), false);
11491                let value = self
11492                    .build_call_with_param_attributes(
11493                        self.intrinsics.func_ref,
11494                        &[self.ctx.basic().into(), index.into()],
11495                        "",
11496                    )?
11497                    .try_as_basic_value()
11498                    .unwrap_basic();
11499                self.state.push1(value);
11500            }
11501            _ => unreachable!(),
11502        }
11503        Ok(())
11504    }
11505
11506    // Table operators.
11507    fn translate_table_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11508        match op {
11509            Operator::TableGet { table } => {
11510                let elem = self.state.pop1()?;
11511                let (table_get, table_index) = if let Some(local_table_index) = self
11512                    .wasm_module
11513                    .local_table_index(TableIndex::from_u32(table))
11514                {
11515                    (self.intrinsics.table_get, local_table_index.as_u32())
11516                } else {
11517                    (self.intrinsics.imported_table_get, table)
11518                };
11519                let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11520                let value = self
11521                    .build_call_with_param_attributes(
11522                        table_get,
11523                        &[self.ctx.basic().into(), table_index.into(), elem.into()],
11524                        "",
11525                    )?
11526                    .try_as_basic_value()
11527                    .unwrap_basic();
11528                let value = err!(
11529                    self.builder.build_bit_cast(
11530                        value,
11531                        type_to_llvm(
11532                            self.intrinsics,
11533                            self.wasm_module
11534                                .tables
11535                                .get(TableIndex::from_u32(table))
11536                                .unwrap()
11537                                .ty,
11538                        )?,
11539                        "",
11540                    )
11541                );
11542                self.state.push1(value);
11543            }
11544            Operator::TableSet { table } => {
11545                let (elem, value) = self.state.pop2()?;
11546                let value = err!(
11547                    self.builder
11548                        .build_bit_cast(value, self.intrinsics.ptr_ty, "")
11549                );
11550                let (table_set, table_index) = if let Some(local_table_index) = self
11551                    .wasm_module
11552                    .local_table_index(TableIndex::from_u32(table))
11553                {
11554                    (self.intrinsics.table_set, local_table_index.as_u32())
11555                } else {
11556                    (self.intrinsics.imported_table_set, table)
11557                };
11558                let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11559                self.build_call_with_param_attributes(
11560                    table_set,
11561                    &[
11562                        self.ctx.basic().into(),
11563                        table_index.into(),
11564                        elem.into(),
11565                        value.into(),
11566                    ],
11567                    "",
11568                )?;
11569            }
11570            Operator::TableCopy {
11571                dst_table,
11572                src_table,
11573            } => {
11574                let (dst, src, len) = self.state.pop3()?;
11575                let dst_table = self.intrinsics.i32_ty.const_int(dst_table as u64, false);
11576                let src_table = self.intrinsics.i32_ty.const_int(src_table as u64, false);
11577                self.build_call_with_param_attributes(
11578                    self.intrinsics.table_copy,
11579                    &[
11580                        self.ctx.basic().into(),
11581                        dst_table.into(),
11582                        src_table.into(),
11583                        dst.into(),
11584                        src.into(),
11585                        len.into(),
11586                    ],
11587                    "",
11588                )?;
11589            }
11590            Operator::TableInit { elem_index, table } => {
11591                let (dst, src, len) = self.state.pop3()?;
11592                let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
11593                let table = self.intrinsics.i32_ty.const_int(table as u64, false);
11594                self.build_call_with_param_attributes(
11595                    self.intrinsics.table_init,
11596                    &[
11597                        self.ctx.basic().into(),
11598                        table.into(),
11599                        segment.into(),
11600                        dst.into(),
11601                        src.into(),
11602                        len.into(),
11603                    ],
11604                    "",
11605                )?;
11606            }
11607            Operator::ElemDrop { elem_index } => {
11608                let segment = self.intrinsics.i32_ty.const_int(elem_index as u64, false);
11609                self.build_call_with_param_attributes(
11610                    self.intrinsics.elem_drop,
11611                    &[self.ctx.basic().into(), segment.into()],
11612                    "",
11613                )?;
11614            }
11615            Operator::TableFill { table } => {
11616                let table = self.intrinsics.i32_ty.const_int(table as u64, false);
11617                let (start, elem, len) = self.state.pop3()?;
11618                let elem = err!(
11619                    self.builder
11620                        .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
11621                );
11622                self.build_call_with_param_attributes(
11623                    self.intrinsics.table_fill,
11624                    &[
11625                        self.ctx.basic().into(),
11626                        table.into(),
11627                        start.into(),
11628                        elem.into(),
11629                        len.into(),
11630                    ],
11631                    "",
11632                )?;
11633            }
11634            Operator::TableGrow { table } => {
11635                let (elem, delta) = self.state.pop2()?;
11636                let elem = err!(
11637                    self.builder
11638                        .build_bit_cast(elem, self.intrinsics.ptr_ty, "")
11639                );
11640                let (table_grow, table_index) = if let Some(local_table_index) = self
11641                    .wasm_module
11642                    .local_table_index(TableIndex::from_u32(table))
11643                {
11644                    (self.intrinsics.table_grow, local_table_index.as_u32())
11645                } else {
11646                    (self.intrinsics.imported_table_grow, table)
11647                };
11648                let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11649                let size = self
11650                    .build_call_with_param_attributes(
11651                        table_grow,
11652                        &[
11653                            self.ctx.basic().into(),
11654                            elem.into(),
11655                            delta.into(),
11656                            table_index.into(),
11657                        ],
11658                        "",
11659                    )?
11660                    .try_as_basic_value()
11661                    .unwrap_basic();
11662                self.state.push1(size);
11663            }
11664            Operator::TableSize { table } => {
11665                let (table_size, table_index) = if let Some(local_table_index) = self
11666                    .wasm_module
11667                    .local_table_index(TableIndex::from_u32(table))
11668                {
11669                    (self.intrinsics.table_size, local_table_index.as_u32())
11670                } else {
11671                    (self.intrinsics.imported_table_size, table)
11672                };
11673                let table_index = self.intrinsics.i32_ty.const_int(table_index as u64, false);
11674                let size = self
11675                    .build_call_with_param_attributes(
11676                        table_size,
11677                        &[self.ctx.basic().into(), table_index.into()],
11678                        "",
11679                    )?
11680                    .try_as_basic_value()
11681                    .unwrap_basic();
11682                self.state.push1(size);
11683            }
11684            _ => unreachable!(),
11685        }
11686        Ok(())
11687    }
11688
11689    // Exception handling.
11690    // https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md
11691    fn translate_eh_operator(&mut self, op: Operator) -> Result<(), CompileError> {
11692        match op {
11693            Operator::TryTable { try_table } => {
11694                let current_block = self
11695                    .builder
11696                    .get_insert_block()
11697                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
11698
11699                self.builder.position_at_end(current_block);
11700
11701                let end_block = self.context.append_basic_block(self.function, "try_end");
11702
11703                let end_phis = {
11704                    self.builder.position_at_end(end_block);
11705
11706                    let phis = self
11707                        .module_translation
11708                        .blocktype_params_results(&try_table.ty)?
11709                        .1
11710                        .iter()
11711                        .map(|&wp_ty| {
11712                            err_nt!(wptype_to_type(wp_ty)).and_then(|wasm_ty| {
11713                                type_to_llvm(self.intrinsics, wasm_ty)
11714                                    .and_then(|ty| err_nt!(self.builder.build_phi(ty, "")))
11715                            })
11716                        })
11717                        .collect::<Result<_, _>>()?;
11718
11719                    self.builder.position_at_end(current_block);
11720                    phis
11721                };
11722
11723                // Collect unique catches. It is not a "hard" error on the wasm side,
11724                // but LLVM will definitely complain about having the same identifier
11725                // match two different branches in the switch below.
11726                let catches: Vec<_> = try_table
11727                    .catches
11728                    .into_iter()
11729                    .unique_by(|v| match v {
11730                        Catch::One { tag, .. } | Catch::OneRef { tag, .. } => *tag as i32,
11731                        Catch::All { .. } | Catch::AllRef { .. } => CATCH_ALL_TAG_VALUE,
11732                    })
11733                    .collect();
11734
11735                // Build the landing pad.
11736                let null = self.intrinsics.ptr_ty.const_zero();
11737
11738                let mut catch_tag_values = vec![];
11739                let mut lpad_clauses: Vec<BasicValueEnum<'ctx>> = catches
11740                    .iter()
11741                    .map(|catch| match catch {
11742                        Catch::All { .. } | Catch::AllRef { .. } => {
11743                            catch_tag_values.push(CATCH_ALL_TAG_VALUE as u32);
11744                            Ok(null.into())
11745                        }
11746                        Catch::One { tag, .. } | Catch::OneRef { tag, .. } => {
11747                            catch_tag_values.push(*tag);
11748                            Ok(self.get_or_insert_tag_type_info_global(*tag as i32))
11749                        }
11750                    })
11751                    .collect::<Result<Vec<BasicValueEnum<'ctx>>, CompileError>>()?;
11752
11753                // Since jumping between landingpads is not possible, we need to collect
11754                // all tags from outer try_tables as well to build a clause for *every*
11755                // possible tag that might be caught.
11756                let mut outer_catch_blocks = vec![];
11757                for outer_landingpad in self.state.landingpads.iter().rev() {
11758                    for catch_info @ TagCatchInfo { tag, .. } in &outer_landingpad.tags {
11759                        if !catch_tag_values.contains(tag) {
11760                            catch_tag_values.push(*tag);
11761                            lpad_clauses.push(if *tag as i32 == CATCH_ALL_TAG_VALUE {
11762                                null.into()
11763                            } else {
11764                                *self.tags_cache.get(&(*tag as i32)).expect(
11765                                    "If a previous try_table encountered a tag, \
11766                                    it should be in the cache",
11767                                )
11768                            });
11769                            outer_catch_blocks.push(*catch_info);
11770                        }
11771                    }
11772                }
11773
11774                // If there are no catch clauses, we have to skip everything, since
11775                // an lpad without catch clauses is invalid (and won't ever be jumped
11776                // to anyway)
11777                let mut maybe_lpad_block = None;
11778                let mut catch_blocks = vec![];
11779                if !lpad_clauses.is_empty() {
11780                    let lpad_block = self.context.append_basic_block(self.function, "catch");
11781                    let catch_all_block =
11782                        self.context.append_basic_block(self.function, "catch_all");
11783                    let catch_specific_block = self
11784                        .context
11785                        .append_basic_block(self.function, "catch_specific");
11786                    let catch_end_block =
11787                        self.context.append_basic_block(self.function, "catch_end");
11788                    let rethrow_block = self.context.append_basic_block(self.function, "rethrow");
11789
11790                    self.builder.position_at_end(lpad_block);
11791
11792                    let res = err!(self.builder.build_landing_pad(
11793                        self.intrinsics.lpad_exception_ty,
11794                        self.intrinsics.personality,
11795                        &lpad_clauses,
11796                        false,
11797                        "exc_struct",
11798                    ));
11799
11800                    let res = res.into_struct_value();
11801
11802                    let uw_exc = err!(self.builder.build_extract_value(res, 0, "exc_ptr"));
11803                    let pre_selector =
11804                        err!(self.builder.build_extract_value(res, 1, "pre_selector"));
11805
11806                    // The pre-selector can be either 0 (for catch-all) or 1 (for a
11807                    // specific, but as-yet-unknown tag).
11808                    let pre_selector_is_zero = err!(self.builder.build_int_compare(
11809                        IntPredicate::EQ,
11810                        pre_selector.into_int_value(),
11811                        self.intrinsics.i32_zero,
11812                        "pre_selector_is_zero"
11813                    ));
11814                    err!(self.builder.build_conditional_branch(
11815                        pre_selector_is_zero,
11816                        catch_all_block,
11817                        catch_specific_block
11818                    ));
11819
11820                    self.builder.position_at_end(catch_all_block);
11821                    err!(self.builder.build_unconditional_branch(catch_end_block));
11822
11823                    self.builder.position_at_end(catch_specific_block);
11824                    let selector_value = self.build_call_with_param_attributes(
11825                        self.intrinsics.personality2,
11826                        &[self.ctx.basic().into(), uw_exc.into()],
11827                        "selector",
11828                    )?;
11829                    err!(self.builder.build_unconditional_branch(catch_end_block));
11830
11831                    self.builder.position_at_end(catch_end_block);
11832                    let selector = err!(self.builder.build_phi(self.intrinsics.i32_ty, "selector"));
11833                    selector.add_incoming(&[
11834                        (
11835                            &self
11836                                .intrinsics
11837                                .i32_ty
11838                                .const_int(CATCH_ALL_TAG_VALUE as u64, false),
11839                            catch_all_block,
11840                        ),
11841                        (
11842                            &selector_value
11843                                .try_as_basic_value()
11844                                .unwrap_basic()
11845                                .into_int_value(),
11846                            catch_specific_block,
11847                        ),
11848                    ]);
11849
11850                    // Now we're done looking at the exception, it's time to deallocate and get
11851                    // the exnref out of it. When an exception is caught, "rethrowing" simply
11852                    // means starting another unwind by calling _Unwind_RaiseException with the
11853                    // same exception bits. Instead of keeping the same exception around, we
11854                    // deallocate the exception once it's caught, and if we need to rethrow, we
11855                    // just re-allocate a new exception.
11856                    //
11857                    // Note that this is different from how it's done in C++ land, where the
11858                    // exception object is kept around for rethrowing; this discrepancy exists
11859                    // because in C++, exception handling is lexical (i.e. there's an implicit
11860                    // "current exception" in catch blocks) whereas in WASM, you rethrow with
11861                    // an exnref that may very well have come from somewhere else; consider this
11862                    // (badly implemented and erroneous) pseudo-module:
11863                    //
11864                    // (module
11865                    //   (global $e (mut exnref) (ref.null exn))
11866                    //   ;; Store the given exnref, return the previous one
11867                    //   (func $delay_exnref (param exnref) (result exnref)
11868                    //     (global.get $e)
11869                    //     (local.get 0)
11870                    //     (global.set $e)
11871                    //   )
11872                    //   (func foo
11873                    //     (block $catch (result exnref)
11874                    //       (try_table (catch_all_ref $catch)
11875                    //         ...
11876                    //       )
11877                    //     )
11878                    //     (call $delay_exnref) ;; store the exnref caught above
11879                    //     throw_ref ;; throw the previous exnref
11880                    //   )
11881                    // )
11882                    //
11883                    // Here, it's impossible to reuse the same exception object since the
11884                    // exnref given to throw_ref is a different one than the one we caught
11885                    // with the try_table.
11886                    //
11887                    // Another difference is that C++ exceptions may well carry lots of data
11888                    // around; a WASM exception is just an exnref, backed by a u32, which is
11889                    // just 4 bytes, and is cheap to reallocate. C++ exceptions may also carry
11890                    // things with dtors around; another thing that doesn't exist in WASM.
11891                    //
11892                    // All of this is to say that putting exception deallocation and exnref
11893                    // retrieval in the same function has been a very deliberate choice.
11894                    let uw_exc = uw_exc.into_pointer_value();
11895                    let exnref = self.build_call_with_param_attributes(
11896                        self.intrinsics.exception_into_exnref,
11897                        &[uw_exc.into()],
11898                        "exnref",
11899                    )?;
11900
11901                    let exnref = exnref.try_as_basic_value().unwrap_basic().into_int_value();
11902                    let selector = selector.as_basic_value().into_int_value();
11903
11904                    for catch in catches.iter() {
11905                        match catch {
11906                            Catch::All { label } => {
11907                                let b = self
11908                                    .context
11909                                    .append_basic_block(self.function, "catch_all_clause");
11910                                self.builder.position_at_end(b);
11911                                let frame = self.state.frame_at_depth(*label)?;
11912
11913                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11914
11915                                self.builder.position_at_end(catch_end_block);
11916                                catch_blocks.push((b, None));
11917                            }
11918                            Catch::One { tag, label } => {
11919                                let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
11920                                let signature = &self.wasm_module.signatures[tag_idx];
11921                                let params = signature.params();
11922
11923                                let b = self.context.append_basic_block(
11924                                    self.function,
11925                                    format!("catch_one_clause_{tag}").as_str(),
11926                                );
11927                                self.builder.position_at_end(b);
11928
11929                                let exnref_phi = err!(
11930                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11931                                );
11932                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11933
11934                                // Get the payload pointer.
11935                                let exn_payload_ptr = err!(self.builder.build_direct_call(
11936                                    self.intrinsics.read_exnref,
11937                                    &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
11938                                    "exn_ptr",
11939                                ));
11940                                let exn_payload_ptr = exn_payload_ptr
11941                                    .try_as_basic_value()
11942                                    .unwrap_basic()
11943                                    .into_pointer_value();
11944
11945                                // Read each value from the data ptr.
11946                                let values = params
11947                                    .iter()
11948                                    .enumerate()
11949                                    .map(|(i, v)| {
11950                                        let name = format!("value_{i}");
11951                                        let ptr = err!(unsafe {
11952                                            self.builder.build_gep(
11953                                                self.intrinsics.i128_ty,
11954                                                exn_payload_ptr,
11955                                                &[self
11956                                                    .intrinsics
11957                                                    .i32_ty
11958                                                    .const_int(i as u64, false)],
11959                                                format!("{name}_ptr").as_str(),
11960                                            )
11961                                        });
11962                                        err_nt!(self.builder.build_load(
11963                                            type_to_llvm(self.intrinsics, *v)?,
11964                                            ptr,
11965                                            &name,
11966                                        ))
11967                                    })
11968                                    .collect::<Result<Vec<_>, CompileError>>()?;
11969
11970                                let frame = self.state.frame_at_depth(*label)?;
11971
11972                                for (phi, value) in frame.phis().iter().zip(values.iter()) {
11973                                    phi.add_incoming(&[(value, b)])
11974                                }
11975
11976                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
11977
11978                                self.builder.position_at_end(catch_end_block);
11979                                catch_blocks.push((b, Some(exnref_phi)));
11980                            }
11981                            Catch::OneRef { label, tag } => {
11982                                let tag_idx = self.wasm_module.tags[TagIndex::from_u32(*tag)];
11983                                let signature = &self.wasm_module.signatures[tag_idx];
11984                                let params = signature.params();
11985
11986                                let b = self.context.append_basic_block(
11987                                    self.function,
11988                                    format!("catch_one_ref_clause_{tag}").as_str(),
11989                                );
11990                                self.builder.position_at_end(b);
11991
11992                                let exnref_phi = err!(
11993                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
11994                                );
11995                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
11996
11997                                // Get the payload pointer.
11998                                let exn_payload_ptr = err!(self.builder.build_direct_call(
11999                                    self.intrinsics.read_exnref,
12000                                    &[self.ctx.basic().into(), exnref_phi.as_basic_value().into()],
12001                                    "exn_ptr",
12002                                ));
12003                                let exn_payload_ptr = exn_payload_ptr
12004                                    .try_as_basic_value()
12005                                    .unwrap_basic()
12006                                    .into_pointer_value();
12007
12008                                // Read each value from the data ptr.
12009                                let mut values = params
12010                                    .iter()
12011                                    .enumerate()
12012                                    .map(|(i, v)| {
12013                                        let name = format!("value_{i}");
12014                                        let ptr = err!(unsafe {
12015                                            self.builder.build_gep(
12016                                                self.intrinsics.i128_ty,
12017                                                exn_payload_ptr,
12018                                                &[self
12019                                                    .intrinsics
12020                                                    .i32_ty
12021                                                    .const_int(i as u64, false)],
12022                                                format!("{name}_ptr").as_str(),
12023                                            )
12024                                        });
12025                                        err_nt!(self.builder.build_load(
12026                                            type_to_llvm(self.intrinsics, *v)?,
12027                                            ptr,
12028                                            &name,
12029                                        ))
12030                                    })
12031                                    .collect::<Result<Vec<_>, CompileError>>()?;
12032
12033                                values.push(exnref_phi.as_basic_value());
12034
12035                                let frame = self.state.frame_at_depth(*label)?;
12036
12037                                for (phi, value) in frame.phis().iter().zip(values.iter()) {
12038                                    phi.add_incoming(&[(value, b)])
12039                                }
12040
12041                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
12042
12043                                self.builder.position_at_end(catch_end_block);
12044                                catch_blocks.push((b, Some(exnref_phi)));
12045                            }
12046                            Catch::AllRef { label } => {
12047                                let b = self
12048                                    .context
12049                                    .append_basic_block(self.function, "catch_all_ref_clause");
12050                                self.builder.position_at_end(b);
12051
12052                                let exnref_phi = err!(
12053                                    self.builder.build_phi(self.intrinsics.i32_ty, "exnref_phi")
12054                                );
12055                                exnref_phi.add_incoming(&[(&exnref, catch_end_block)]);
12056
12057                                let frame = self.state.frame_at_depth(*label)?;
12058
12059                                let phis = frame.phis();
12060
12061                                assert_eq!(phis.len(), 1);
12062                                phis[0].add_incoming(&[(&exnref_phi.as_basic_value(), b)]);
12063
12064                                err!(self.builder.build_unconditional_branch(*frame.br_dest()));
12065
12066                                self.builder.position_at_end(catch_end_block);
12067                                catch_blocks.push((b, Some(exnref_phi)));
12068                            }
12069                        }
12070                    }
12071
12072                    for catch_info in &outer_catch_blocks {
12073                        if let Some(phi) = catch_info.exnref_phi {
12074                            phi.add_incoming(&[(&exnref, catch_end_block)]);
12075                        }
12076                    }
12077
12078                    err!(
12079                        self.builder.build_switch(
12080                            selector,
12081                            rethrow_block,
12082                            catch_blocks
12083                                .iter()
12084                                .enumerate()
12085                                .map(|(i, v)| (
12086                                    self.intrinsics
12087                                        .i32_ty
12088                                        .const_int(catch_tag_values[i] as _, false),
12089                                    v.0
12090                                ))
12091                                .chain(outer_catch_blocks.iter().map(|catch_info| (
12092                                    self.intrinsics.i32_ty.const_int(catch_info.tag as _, false),
12093                                    catch_info.catch_block
12094                                )))
12095                                .collect::<Vec<_>>()
12096                                .as_slice()
12097                        )
12098                    );
12099
12100                    // -- end
12101
12102                    // -- The rethrow block
12103                    self.builder.position_at_end(rethrow_block);
12104
12105                    self.build_call_with_param_attributes(
12106                        self.intrinsics.throw,
12107                        &[self.ctx.basic().into(), exnref.into()],
12108                        "rethrow",
12109                    )?;
12110                    // can't reach after an explicit throw!
12111                    err!(self.builder.build_unreachable());
12112
12113                    maybe_lpad_block = Some(lpad_block);
12114                }
12115
12116                // Move back to current block
12117                self.builder.position_at_end(current_block);
12118
12119                // Note: catch_tag_values also contains outer tags, but zipping with
12120                // catch_blocks will let us ignore the extra ones.
12121                let catch_tags_and_blocks = catch_tag_values
12122                    .into_iter()
12123                    .zip(catch_blocks)
12124                    .map(|(tag, (block, exnref_phi))| TagCatchInfo {
12125                        tag,
12126                        catch_block: block,
12127                        exnref_phi,
12128                    })
12129                    .collect::<Vec<_>>();
12130                self.state.push_landingpad(
12131                    maybe_lpad_block,
12132                    end_block,
12133                    end_phis,
12134                    &catch_tags_and_blocks,
12135                    self.module_translation
12136                        .blocktype_params_results(&try_table.ty)?
12137                        .0
12138                        .len(),
12139                );
12140            }
12141            Operator::Throw { tag_index } => {
12142                let current_block = self
12143                    .builder
12144                    .get_insert_block()
12145                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
12146
12147                let sig_index = self.wasm_module.tags[TagIndex::from_u32(tag_index)];
12148                let signature = &self.wasm_module.signatures[sig_index];
12149                let params = signature.params();
12150                let values = self.state.popn_save_extra(params.len())?;
12151
12152                values.iter().enumerate().try_for_each(|(i, (v, _))| {
12153                    let t = type_to_llvm(self.intrinsics, params[i])?;
12154                    if t != v.get_type() {
12155                        return Err(CompileError::Codegen(format!(
12156                            "Incompatible types: {:?} != {:?}",
12157                            t,
12158                            v.get_type()
12159                        )));
12160                    }
12161
12162                    Ok(())
12163                })?;
12164
12165                // Allocate the necessary bytes for the exception.
12166                let exnref = err!(
12167                    self.builder.build_direct_call(
12168                        self.intrinsics.alloc_exception,
12169                        &[
12170                            self.ctx.basic().into(),
12171                            self.intrinsics
12172                                .i32_ty
12173                                .const_int(tag_index as _, false)
12174                                .into()
12175                        ],
12176                        "exnref",
12177                    )
12178                );
12179                let exnref = exnref.try_as_basic_value().unwrap_basic();
12180
12181                let exn_payload_ptr = err!(self.builder.build_direct_call(
12182                    self.intrinsics.read_exnref,
12183                    &[self.ctx.basic().into(), exnref.into()],
12184                    "exn_ptr",
12185                ));
12186                let exn_payload_ptr = exn_payload_ptr
12187                    .try_as_basic_value()
12188                    .unwrap_basic()
12189                    .into_pointer_value();
12190
12191                for (i, value) in values.into_iter().enumerate() {
12192                    let ptr = err!(unsafe {
12193                        self.builder.build_gep(
12194                            self.intrinsics.i128_ty,
12195                            exn_payload_ptr,
12196                            &[self.intrinsics.i32_ty.const_int(i as u64, false)],
12197                            format!("value_{i}_ptr").as_str(),
12198                        )
12199                    });
12200                    err!(self.builder.build_store(ptr, value.0));
12201                }
12202
12203                if let Some(pad) = self.state.get_innermost_landingpad() {
12204                    let unreachable_block = self
12205                        .context
12206                        .append_basic_block(self.function, "_throw_unreachable");
12207
12208                    err!(self.builder.build_invoke(
12209                        self.intrinsics.throw,
12210                        &[self.ctx.basic(), exnref],
12211                        unreachable_block,
12212                        pad,
12213                        "throw",
12214                    ));
12215
12216                    self.builder.position_at_end(unreachable_block);
12217                    // can't reach after an explicit throw!
12218                    err!(self.builder.build_unreachable());
12219
12220                    self.builder.position_at_end(current_block);
12221                } else {
12222                    self.build_call_with_param_attributes(
12223                        self.intrinsics.throw,
12224                        &[self.ctx.basic().into(), exnref.into()],
12225                        "throw",
12226                    )?;
12227                    // can't reach after an explicit throw!
12228                    err!(self.builder.build_unreachable());
12229                }
12230
12231                self.state.reachable = false;
12232            }
12233            Operator::ThrowRef => {
12234                let current_block = self
12235                    .builder
12236                    .get_insert_block()
12237                    .ok_or_else(|| CompileError::Codegen("not currently in a block".to_string()))?;
12238
12239                let exnref = self.state.pop1()?;
12240
12241                if let Some(pad) = self.state.get_innermost_landingpad() {
12242                    let unreachable_block = self
12243                        .context
12244                        .append_basic_block(self.function, "_rethrow_unreachable");
12245
12246                    err!(self.builder.build_invoke(
12247                        self.intrinsics.throw,
12248                        &[self.ctx.basic(), exnref],
12249                        unreachable_block,
12250                        pad,
12251                        "throw",
12252                    ));
12253
12254                    self.builder.position_at_end(unreachable_block);
12255                    // can't reach after an explicit throw!
12256                    err!(self.builder.build_unreachable());
12257
12258                    self.builder.position_at_end(current_block);
12259                } else {
12260                    self.build_call_with_param_attributes(
12261                        self.intrinsics.throw,
12262                        &[self.ctx.basic().into(), exnref.into()],
12263                        "throw",
12264                    )?;
12265                    // can't reach after an explicit throw!
12266                    err!(self.builder.build_unreachable());
12267                }
12268
12269                self.state.reachable = false;
12270            }
12271            _ => unreachable!(),
12272        }
12273        Ok(())
12274    }
12275
12276    fn translate_operator(&mut self, op: Operator, _source_loc: u32) -> Result<(), CompileError> {
12277        //let opcode_offset: Option<usize> = None;
12278
12279        if !self.state.reachable {
12280            match op {
12281                Operator::Block { blockty: _ }
12282                | Operator::Loop { blockty: _ }
12283                | Operator::If { blockty: _ }
12284                | Operator::TryTable { .. } => {
12285                    self.unreachable_depth += 1;
12286                    return Ok(());
12287                }
12288                Operator::Else => {
12289                    if self.unreachable_depth != 0 {
12290                        return Ok(());
12291                    }
12292                }
12293                Operator::End => {
12294                    if self.unreachable_depth != 0 {
12295                        self.unreachable_depth -= 1;
12296                        return Ok(());
12297                    }
12298                }
12299                _ => {
12300                    return Ok(());
12301                }
12302            }
12303        }
12304
12305        match op {
12306            Operator::Block { .. }
12307            | Operator::Loop { .. }
12308            | Operator::Br { .. }
12309            | Operator::BrIf { .. }
12310            | Operator::BrTable { .. }
12311            | Operator::If { .. }
12312            | Operator::Else
12313            | Operator::End
12314            | Operator::Return
12315            | Operator::Unreachable => {
12316                self.translate_control_flow_operator(op)?;
12317            }
12318            Operator::Nop
12319            | Operator::Drop
12320            | Operator::I32Const { .. }
12321            | Operator::I64Const { .. }
12322            | Operator::F32Const { .. }
12323            | Operator::F64Const { .. }
12324            | Operator::V128Const { .. }
12325            | Operator::I8x16Splat
12326            | Operator::I16x8Splat
12327            | Operator::I32x4Splat
12328            | Operator::I64x2Splat
12329            | Operator::F32x4Splat
12330            | Operator::F64x2Splat
12331            | Operator::LocalGet { .. }
12332            | Operator::LocalSet { .. }
12333            | Operator::LocalTee { .. }
12334            | Operator::GlobalGet { .. }
12335            | Operator::GlobalSet { .. }
12336            | Operator::Call { .. }
12337            | Operator::ReturnCall { .. }
12338            | Operator::CallIndirect { .. }
12339            | Operator::ReturnCallIndirect { .. }
12340            | Operator::TypedSelect { .. }
12341            | Operator::Select => {
12342                self.translate_basic_operator(op)?;
12343            }
12344            Operator::I32Add
12345            | Operator::I64Add
12346            | Operator::I8x16Add
12347            | Operator::I16x8Add
12348            | Operator::I16x8ExtAddPairwiseI8x16S
12349            | Operator::I16x8ExtAddPairwiseI8x16U
12350            | Operator::I32x4Add
12351            | Operator::I32x4ExtAddPairwiseI16x8S
12352            | Operator::I32x4ExtAddPairwiseI16x8U
12353            | Operator::I64x2Add
12354            | Operator::I8x16AddSatS
12355            | Operator::I16x8AddSatS
12356            | Operator::I8x16AddSatU
12357            | Operator::I16x8AddSatU
12358            | Operator::I32Sub
12359            | Operator::I64Sub
12360            | Operator::I8x16Sub
12361            | Operator::I16x8Sub
12362            | Operator::I32x4Sub
12363            | Operator::I64x2Sub
12364            | Operator::I8x16SubSatS
12365            | Operator::I16x8SubSatS
12366            | Operator::I8x16SubSatU
12367            | Operator::I16x8SubSatU
12368            | Operator::I32Mul
12369            | Operator::I64Mul
12370            | Operator::I16x8Mul
12371            | Operator::I32x4Mul
12372            | Operator::I64x2Mul
12373            | Operator::I16x8RelaxedQ15mulrS
12374            | Operator::I16x8Q15MulrSatS
12375            | Operator::I16x8ExtMulLowI8x16S
12376            | Operator::I16x8ExtMulLowI8x16U
12377            | Operator::I16x8ExtMulHighI8x16S
12378            | Operator::I16x8ExtMulHighI8x16U
12379            | Operator::I32x4ExtMulLowI16x8S
12380            | Operator::I32x4ExtMulLowI16x8U
12381            | Operator::I32x4ExtMulHighI16x8S
12382            | Operator::I32x4ExtMulHighI16x8U
12383            | Operator::I64x2ExtMulLowI32x4S
12384            | Operator::I64x2ExtMulLowI32x4U
12385            | Operator::I64x2ExtMulHighI32x4S
12386            | Operator::I64x2ExtMulHighI32x4U
12387            | Operator::I32x4DotI16x8S
12388            | Operator::I16x8RelaxedDotI8x16I7x16S
12389            | Operator::I32x4RelaxedDotI8x16I7x16AddS
12390            | Operator::I32DivS
12391            | Operator::I64DivS
12392            | Operator::I32DivU
12393            | Operator::I64DivU
12394            | Operator::I32RemS
12395            | Operator::I64RemS
12396            | Operator::I32RemU
12397            | Operator::I64RemU
12398            | Operator::I32And
12399            | Operator::I64And
12400            | Operator::V128And
12401            | Operator::I32Or
12402            | Operator::I64Or
12403            | Operator::V128Or
12404            | Operator::I32Xor
12405            | Operator::I64Xor
12406            | Operator::V128Xor
12407            | Operator::V128AndNot
12408            | Operator::I8x16RelaxedLaneselect
12409            | Operator::I16x8RelaxedLaneselect
12410            | Operator::I32x4RelaxedLaneselect
12411            | Operator::I64x2RelaxedLaneselect
12412            | Operator::V128Bitselect
12413            | Operator::I8x16Bitmask
12414            | Operator::I16x8Bitmask
12415            | Operator::I32x4Bitmask
12416            | Operator::I64x2Bitmask
12417            | Operator::I32Shl
12418            | Operator::I64Shl
12419            | Operator::I8x16Shl
12420            | Operator::I16x8Shl
12421            | Operator::I32x4Shl
12422            | Operator::I64x2Shl
12423            | Operator::I32ShrS
12424            | Operator::I64ShrS
12425            | Operator::I8x16ShrS
12426            | Operator::I16x8ShrS
12427            | Operator::I32x4ShrS
12428            | Operator::I64x2ShrS
12429            | Operator::I32ShrU
12430            | Operator::I64ShrU
12431            | Operator::I8x16ShrU
12432            | Operator::I16x8ShrU
12433            | Operator::I32x4ShrU
12434            | Operator::I64x2ShrU
12435            | Operator::I32Rotl
12436            | Operator::I64Rotl
12437            | Operator::I32Rotr
12438            | Operator::I64Rotr
12439            | Operator::I32Clz
12440            | Operator::I64Clz
12441            | Operator::I32Ctz
12442            | Operator::I64Ctz
12443            | Operator::I8x16Popcnt
12444            | Operator::I32Popcnt
12445            | Operator::I64Popcnt
12446            | Operator::I32Eqz
12447            | Operator::I64Eqz
12448            | Operator::I8x16Abs
12449            | Operator::I16x8Abs
12450            | Operator::I32x4Abs
12451            | Operator::I64x2Abs
12452            | Operator::I8x16MinS
12453            | Operator::I8x16MinU
12454            | Operator::I8x16MaxS
12455            | Operator::I8x16MaxU
12456            | Operator::I16x8MinS
12457            | Operator::I16x8MinU
12458            | Operator::I16x8MaxS
12459            | Operator::I16x8MaxU
12460            | Operator::I32x4MinS
12461            | Operator::I32x4MinU
12462            | Operator::I32x4MaxS
12463            | Operator::I32x4MaxU
12464            | Operator::I8x16AvgrU
12465            | Operator::I16x8AvgrU
12466            | Operator::I64Add128
12467            | Operator::I64Sub128
12468            | Operator::I64MulWideS
12469            | Operator::I64MulWideU => self.translate_integer_arithmetic_operator(op)?,
12470            Operator::F32Add
12471            | Operator::F64Add
12472            | Operator::F32x4Add
12473            | Operator::F64x2Add
12474            | Operator::F32Sub
12475            | Operator::F64Sub
12476            | Operator::F32x4Sub
12477            | Operator::F64x2Sub
12478            | Operator::F32Mul
12479            | Operator::F64Mul
12480            | Operator::F32x4Mul
12481            | Operator::F32x4RelaxedMadd
12482            | Operator::F32x4RelaxedNmadd
12483            | Operator::F64x2Mul
12484            | Operator::F64x2RelaxedMadd
12485            | Operator::F64x2RelaxedNmadd
12486            | Operator::F32Div
12487            | Operator::F64Div
12488            | Operator::F32x4Div
12489            | Operator::F64x2Div
12490            | Operator::F32Sqrt
12491            | Operator::F64Sqrt
12492            | Operator::F32x4Sqrt
12493            | Operator::F64x2Sqrt
12494            | Operator::F32Min
12495            | Operator::F64Min
12496            | Operator::F32x4RelaxedMin
12497            | Operator::F32x4Min
12498            | Operator::F32x4PMin
12499            | Operator::F64x2RelaxedMin
12500            | Operator::F64x2Min
12501            | Operator::F64x2PMin
12502            | Operator::F32Max
12503            | Operator::F64Max
12504            | Operator::F32x4RelaxedMax
12505            | Operator::F32x4Max
12506            | Operator::F32x4PMax
12507            | Operator::F64x2RelaxedMax
12508            | Operator::F64x2Max
12509            | Operator::F64x2PMax
12510            | Operator::F32Ceil
12511            | Operator::F32x4Ceil
12512            | Operator::F64Ceil
12513            | Operator::F64x2Ceil
12514            | Operator::F32Floor
12515            | Operator::F32x4Floor
12516            | Operator::F64Floor
12517            | Operator::F64x2Floor
12518            | Operator::F32Trunc
12519            | Operator::F32x4Trunc
12520            | Operator::F64Trunc
12521            | Operator::F64x2Trunc
12522            | Operator::F32Nearest
12523            | Operator::F32x4Nearest
12524            | Operator::F64Nearest
12525            | Operator::F64x2Nearest
12526            | Operator::F32Abs
12527            | Operator::F64Abs
12528            | Operator::F32x4Abs
12529            | Operator::F64x2Abs
12530            | Operator::F32x4Neg
12531            | Operator::F64x2Neg
12532            | Operator::F32Neg
12533            | Operator::F64Neg
12534            | Operator::F32Copysign
12535            | Operator::F64Copysign => self.translate_floating_point_arithmetic_operator(op)?,
12536            Operator::I32Eq
12537            | Operator::I64Eq
12538            | Operator::I8x16Eq
12539            | Operator::I16x8Eq
12540            | Operator::I32x4Eq
12541            | Operator::I64x2Eq
12542            | Operator::I32Ne
12543            | Operator::I64Ne
12544            | Operator::I8x16Ne
12545            | Operator::I16x8Ne
12546            | Operator::I32x4Ne
12547            | Operator::I64x2Ne
12548            | Operator::I32LtS
12549            | Operator::I64LtS
12550            | Operator::I8x16LtS
12551            | Operator::I16x8LtS
12552            | Operator::I32x4LtS
12553            | Operator::I64x2LtS
12554            | Operator::I32LtU
12555            | Operator::I64LtU
12556            | Operator::I8x16LtU
12557            | Operator::I16x8LtU
12558            | Operator::I32x4LtU
12559            | Operator::I32LeS
12560            | Operator::I64LeS
12561            | Operator::I8x16LeS
12562            | Operator::I16x8LeS
12563            | Operator::I32x4LeS
12564            | Operator::I64x2LeS
12565            | Operator::I32LeU
12566            | Operator::I64LeU
12567            | Operator::I8x16LeU
12568            | Operator::I16x8LeU
12569            | Operator::I32x4LeU
12570            | Operator::I32GtS
12571            | Operator::I64GtS
12572            | Operator::I8x16GtS
12573            | Operator::I16x8GtS
12574            | Operator::I32x4GtS
12575            | Operator::I64x2GtS
12576            | Operator::I32GtU
12577            | Operator::I64GtU
12578            | Operator::I8x16GtU
12579            | Operator::I16x8GtU
12580            | Operator::I32x4GtU
12581            | Operator::I32GeS
12582            | Operator::I64GeS
12583            | Operator::I8x16GeS
12584            | Operator::I16x8GeS
12585            | Operator::I32x4GeS
12586            | Operator::I64x2GeS
12587            | Operator::I32GeU
12588            | Operator::I64GeU
12589            | Operator::I8x16GeU
12590            | Operator::I16x8GeU
12591            | Operator::I32x4GeU => self.translate_integer_comparison_operator(op)?,
12592            Operator::F32Eq
12593            | Operator::F64Eq
12594            | Operator::F32x4Eq
12595            | Operator::F64x2Eq
12596            | Operator::F32Ne
12597            | Operator::F64Ne
12598            | Operator::F32x4Ne
12599            | Operator::F64x2Ne
12600            | Operator::F32Lt
12601            | Operator::F64Lt
12602            | Operator::F32x4Lt
12603            | Operator::F64x2Lt
12604            | Operator::F32Le
12605            | Operator::F64Le
12606            | Operator::F32x4Le
12607            | Operator::F64x2Le
12608            | Operator::F32Gt
12609            | Operator::F64Gt
12610            | Operator::F32x4Gt
12611            | Operator::F64x2Gt
12612            | Operator::F32Ge
12613            | Operator::F64Ge
12614            | Operator::F32x4Ge
12615            | Operator::F64x2Ge => self.translate_floating_point_comparison_operator(op)?,
12616            Operator::I32WrapI64
12617            | Operator::I64ExtendI32S
12618            | Operator::I64ExtendI32U
12619            | Operator::I16x8ExtendLowI8x16S
12620            | Operator::I16x8ExtendHighI8x16S
12621            | Operator::I16x8ExtendLowI8x16U
12622            | Operator::I16x8ExtendHighI8x16U
12623            | Operator::I32x4ExtendLowI16x8S
12624            | Operator::I32x4ExtendHighI16x8S
12625            | Operator::I32x4ExtendLowI16x8U
12626            | Operator::I32x4ExtendHighI16x8U
12627            | Operator::I64x2ExtendLowI32x4U
12628            | Operator::I64x2ExtendLowI32x4S
12629            | Operator::I64x2ExtendHighI32x4U
12630            | Operator::I64x2ExtendHighI32x4S
12631            | Operator::I8x16NarrowI16x8S
12632            | Operator::I8x16NarrowI16x8U
12633            | Operator::I16x8NarrowI32x4S
12634            | Operator::I16x8NarrowI32x4U
12635            | Operator::I32x4RelaxedTruncF32x4S
12636            | Operator::I32x4TruncSatF32x4S
12637            | Operator::I32x4RelaxedTruncF32x4U
12638            | Operator::I32x4TruncSatF32x4U
12639            | Operator::I32x4RelaxedTruncF64x2SZero
12640            | Operator::I32x4RelaxedTruncF64x2UZero
12641            | Operator::I32x4TruncSatF64x2SZero
12642            | Operator::I32x4TruncSatF64x2UZero
12643            | Operator::I32TruncF32S
12644            | Operator::I32TruncF64S
12645            | Operator::I32TruncSatF32S
12646            | Operator::I32TruncSatF64S
12647            | Operator::I64TruncF32S
12648            | Operator::I64TruncF64S
12649            | Operator::I64TruncSatF32S
12650            | Operator::I64TruncSatF64S
12651            | Operator::I32TruncF32U
12652            | Operator::I32TruncF64U
12653            | Operator::I32TruncSatF32U
12654            | Operator::I32TruncSatF64U
12655            | Operator::I64TruncF32U
12656            | Operator::I64TruncF64U
12657            | Operator::I64TruncSatF32U
12658            | Operator::I64TruncSatF64U
12659            | Operator::F32DemoteF64
12660            | Operator::F64PromoteF32
12661            | Operator::F32ConvertI32S
12662            | Operator::F32ConvertI64S
12663            | Operator::F64ConvertI32S
12664            | Operator::F64ConvertI64S
12665            | Operator::F32ConvertI32U
12666            | Operator::F32ConvertI64U
12667            | Operator::F64ConvertI32U
12668            | Operator::F64ConvertI64U
12669            | Operator::F32x4ConvertI32x4S
12670            | Operator::F32x4ConvertI32x4U
12671            | Operator::F64x2ConvertLowI32x4S
12672            | Operator::F64x2ConvertLowI32x4U
12673            | Operator::F64x2PromoteLowF32x4
12674            | Operator::F32x4DemoteF64x2Zero
12675            | Operator::I32ReinterpretF32
12676            | Operator::I64ReinterpretF64
12677            | Operator::F32ReinterpretI32
12678            | Operator::F64ReinterpretI64 => self.translate_conversion_operator(op)?,
12679            Operator::I32Extend8S
12680            | Operator::I32Extend16S
12681            | Operator::I64Extend8S
12682            | Operator::I64Extend16S
12683            | Operator::I64Extend32S => self.translate_sign_extension_operator(op)?,
12684            Operator::I32Load { .. }
12685            | Operator::I64Load { .. }
12686            | Operator::F32Load { .. }
12687            | Operator::F64Load { .. }
12688            | Operator::V128Load { .. }
12689            | Operator::V128Load8Lane { .. }
12690            | Operator::V128Load16Lane { .. }
12691            | Operator::V128Load32Lane { .. }
12692            | Operator::V128Load64Lane { .. }
12693            | Operator::I32Store { .. }
12694            | Operator::I64Store { .. }
12695            | Operator::F32Store { .. }
12696            | Operator::F64Store { .. }
12697            | Operator::V128Store { .. }
12698            | Operator::V128Store8Lane { .. }
12699            | Operator::V128Store16Lane { .. }
12700            | Operator::V128Store32Lane { .. }
12701            | Operator::V128Store64Lane { .. }
12702            | Operator::I32Load8S { .. }
12703            | Operator::I32Load16S { .. }
12704            | Operator::I64Load8S { .. }
12705            | Operator::I64Load16S { .. }
12706            | Operator::I64Load32S { .. }
12707            | Operator::I32Load8U { .. }
12708            | Operator::I32Load16U { .. }
12709            | Operator::I64Load8U { .. }
12710            | Operator::I64Load16U { .. }
12711            | Operator::I64Load32U { .. }
12712            | Operator::I32Store8 { .. }
12713            | Operator::I64Store8 { .. }
12714            | Operator::I32Store16 { .. }
12715            | Operator::I64Store16 { .. }
12716            | Operator::I64Store32 { .. }
12717            | Operator::I8x16Neg
12718            | Operator::I16x8Neg
12719            | Operator::I32x4Neg
12720            | Operator::I64x2Neg
12721            | Operator::V128Not
12722            | Operator::V128AnyTrue
12723            | Operator::I8x16AllTrue
12724            | Operator::I16x8AllTrue
12725            | Operator::I32x4AllTrue
12726            | Operator::I64x2AllTrue
12727            | Operator::I8x16ExtractLaneS { .. }
12728            | Operator::I8x16ExtractLaneU { .. }
12729            | Operator::I16x8ExtractLaneS { .. }
12730            | Operator::I16x8ExtractLaneU { .. }
12731            | Operator::I32x4ExtractLane { .. }
12732            | Operator::I64x2ExtractLane { .. }
12733            | Operator::F32x4ExtractLane { .. }
12734            | Operator::F64x2ExtractLane { .. }
12735            | Operator::I8x16ReplaceLane { .. }
12736            | Operator::I16x8ReplaceLane { .. }
12737            | Operator::I32x4ReplaceLane { .. }
12738            | Operator::I64x2ReplaceLane { .. }
12739            | Operator::F32x4ReplaceLane { .. }
12740            | Operator::F64x2ReplaceLane { .. }
12741            | Operator::I8x16RelaxedSwizzle
12742            | Operator::I8x16Swizzle
12743            | Operator::I8x16Shuffle { .. }
12744            | Operator::V128Load8x8S { .. }
12745            | Operator::V128Load8x8U { .. }
12746            | Operator::V128Load16x4S { .. }
12747            | Operator::V128Load16x4U { .. }
12748            | Operator::V128Load32x2S { .. }
12749            | Operator::V128Load32x2U { .. }
12750            | Operator::V128Load32Zero { .. }
12751            | Operator::V128Load64Zero { .. }
12752            | Operator::V128Load8Splat { .. }
12753            | Operator::V128Load16Splat { .. }
12754            | Operator::V128Load32Splat { .. }
12755            | Operator::V128Load64Splat { .. }
12756            | Operator::MemoryGrow { .. }
12757            | Operator::MemorySize { .. }
12758            | Operator::MemoryInit { .. }
12759            | Operator::DataDrop { .. }
12760            | Operator::MemoryCopy { .. }
12761            | Operator::MemoryFill { .. } => self.translate_memory_operator(op)?,
12762            Operator::AtomicFence { .. }
12763            | Operator::I32AtomicLoad { .. }
12764            | Operator::I64AtomicLoad { .. }
12765            | Operator::I32AtomicLoad8U { .. }
12766            | Operator::I32AtomicLoad16U { .. }
12767            | Operator::I64AtomicLoad8U { .. }
12768            | Operator::I64AtomicLoad16U { .. }
12769            | Operator::I64AtomicLoad32U { .. }
12770            | Operator::I32AtomicStore { .. }
12771            | Operator::I64AtomicStore { .. }
12772            | Operator::I32AtomicStore8 { .. }
12773            | Operator::I64AtomicStore8 { .. }
12774            | Operator::I32AtomicStore16 { .. }
12775            | Operator::I64AtomicStore16 { .. }
12776            | Operator::I64AtomicStore32 { .. }
12777            | Operator::I32AtomicRmw8AddU { .. }
12778            | Operator::I32AtomicRmw16AddU { .. }
12779            | Operator::I32AtomicRmwAdd { .. }
12780            | Operator::I64AtomicRmw8AddU { .. }
12781            | Operator::I64AtomicRmw16AddU { .. }
12782            | Operator::I64AtomicRmw32AddU { .. }
12783            | Operator::I64AtomicRmwAdd { .. }
12784            | Operator::I32AtomicRmw8SubU { .. }
12785            | Operator::I32AtomicRmw16SubU { .. }
12786            | Operator::I32AtomicRmwSub { .. }
12787            | Operator::I64AtomicRmw8SubU { .. }
12788            | Operator::I64AtomicRmw16SubU { .. }
12789            | Operator::I64AtomicRmw32SubU { .. }
12790            | Operator::I64AtomicRmwSub { .. }
12791            | Operator::I32AtomicRmw8AndU { .. }
12792            | Operator::I32AtomicRmw16AndU { .. }
12793            | Operator::I32AtomicRmwAnd { .. }
12794            | Operator::I64AtomicRmw8AndU { .. }
12795            | Operator::I64AtomicRmw16AndU { .. }
12796            | Operator::I64AtomicRmw32AndU { .. }
12797            | Operator::I64AtomicRmwAnd { .. }
12798            | Operator::I32AtomicRmw8OrU { .. }
12799            | Operator::I32AtomicRmw16OrU { .. }
12800            | Operator::I32AtomicRmwOr { .. }
12801            | Operator::I64AtomicRmw8OrU { .. }
12802            | Operator::I64AtomicRmw16OrU { .. }
12803            | Operator::I64AtomicRmw32OrU { .. }
12804            | Operator::I64AtomicRmwOr { .. }
12805            | Operator::I32AtomicRmw8XorU { .. }
12806            | Operator::I32AtomicRmw16XorU { .. }
12807            | Operator::I32AtomicRmwXor { .. }
12808            | Operator::I64AtomicRmw8XorU { .. }
12809            | Operator::I64AtomicRmw16XorU { .. }
12810            | Operator::I64AtomicRmw32XorU { .. }
12811            | Operator::I64AtomicRmwXor { .. }
12812            | Operator::I32AtomicRmw8XchgU { .. }
12813            | Operator::I32AtomicRmw16XchgU { .. }
12814            | Operator::I32AtomicRmwXchg { .. }
12815            | Operator::I64AtomicRmw8XchgU { .. }
12816            | Operator::I64AtomicRmw16XchgU { .. }
12817            | Operator::I64AtomicRmw32XchgU { .. }
12818            | Operator::I64AtomicRmwXchg { .. }
12819            | Operator::I32AtomicRmw8CmpxchgU { .. }
12820            | Operator::I32AtomicRmw16CmpxchgU { .. }
12821            | Operator::I32AtomicRmwCmpxchg { .. }
12822            | Operator::I64AtomicRmw8CmpxchgU { .. }
12823            | Operator::I64AtomicRmw16CmpxchgU { .. }
12824            | Operator::I64AtomicRmw32CmpxchgU { .. }
12825            | Operator::I64AtomicRmwCmpxchg { .. }
12826            | Operator::MemoryAtomicWait32 { .. }
12827            | Operator::MemoryAtomicWait64 { .. }
12828            | Operator::MemoryAtomicNotify { .. } => self.translate_atomic_memory_operator(op)?,
12829            Operator::RefNull { .. } | Operator::RefIsNull | Operator::RefFunc { .. } => {
12830                self.translate_reference_operator(op)?;
12831            }
12832            Operator::TableGet { .. }
12833            | Operator::TableSet { .. }
12834            | Operator::TableCopy { .. }
12835            | Operator::TableInit { .. }
12836            | Operator::ElemDrop { .. }
12837            | Operator::TableFill { .. }
12838            | Operator::TableGrow { .. }
12839            | Operator::TableSize { .. } => self.translate_table_operator(op)?,
12840            Operator::TryTable { .. } | Operator::Throw { .. } | Operator::ThrowRef => {
12841                self.translate_eh_operator(op)?;
12842            }
12843            _ => {
12844                return Err(CompileError::Codegen(format!(
12845                    "Operator {op:?} unimplemented",
12846                )));
12847            }
12848        }
12849
12850        Ok(())
12851    }
12852
12853    fn build_call_with_param_attributes(
12854        &self,
12855        function: FunctionValue<'ctx>,
12856        args: &[BasicMetadataValueEnum<'ctx>],
12857        name: &str,
12858    ) -> Result<CallSiteValue<'ctx>, CompileError> {
12859        let call = self
12860            .builder
12861            .build_call(function, args, name)
12862            .map_err(|e| CompileError::Codegen(e.to_string()))?;
12863
12864        // https://five-embeddev.com/riscv-user-isa-manual/Priv-v1.12/rv64.html
12865        // > The compiler and calling convention maintain an invariant that all 32-bit values are held in a sign-extended format in 64-bit registers.
12866        // > Even 32-bit unsigned integers extend bit 31 into bits 63 through 32. Consequently, conversion between unsigned and signed 32-bit integers
12867        // > is a no-op, as is conversion from a signed 32-bit integer to a signed 64-bit integer.
12868        if matches!(self.target_triple.architecture, Architecture::Riscv64(..)) {
12869            let param_types = function.get_type().get_param_types();
12870            for (i, ty) in param_types.into_iter().enumerate() {
12871                if ty == self.context.i32_type().into() {
12872                    call.add_attribute(
12873                        AttributeLoc::Param(i as u32),
12874                        self.context
12875                            .create_enum_attribute(Attribute::get_named_enum_kind_id("signext"), 0),
12876                    );
12877                    call.add_attribute(
12878                        AttributeLoc::Param(i as u32),
12879                        self.context
12880                            .create_enum_attribute(Attribute::get_named_enum_kind_id("noundef"), 0),
12881                    );
12882                }
12883            }
12884        }
12885
12886        Ok(call)
12887    }
12888}
12889
12890fn is_f32_arithmetic(bits: u32) -> bool {
12891    // Mask off sign bit.
12892    let bits = bits & 0x7FFF_FFFF;
12893    bits < 0x7FC0_0000
12894}
12895
12896fn is_f64_arithmetic(bits: u64) -> bool {
12897    // Mask off sign bit.
12898    let bits = bits & 0x7FFF_FFFF_FFFF_FFFF;
12899    bits < 0x7FF8_0000_0000_0000
12900}