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 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
73const CATCH_ALL_TAG_VALUE: i32 = i32::MAX;
79
80const 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 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 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 && 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 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(§ion));
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 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 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 Cow::Borrowed(llvm_opt_passes[1].as_str())
542 }
543 OptimizationStyle::ForSpeed => {
544 passes.push("sccp");
545 passes.push("early-cse");
546 passes.push("adce");
548 passes.push("sroa");
549 passes.push("aggressive-instcombine");
550 passes.push("jump-threading");
551 passes.push("simplifycfg");
553 passes.push("reassociate");
554 passes.push("loop-rotate");
555 passes.push("indvars");
556 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("reassociate");
568 passes.push("simplifycfg");
569 passes.push("mem2reg");
570 Cow::Owned(passes.join(","))
571 }
572 };
573
574 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 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 fn splat_vector(
677 &self,
678 value: BasicValueEnum<'ctx>,
679 vec_ty: VectorType<'ctx>,
680 ) -> Result<VectorValue<'ctx>, CompileError> {
681 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 #[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, upper_bound: u64, int_min_value: u64,
711 int_max_value: u64,
712 value: IntValue<'ctx>,
713 ) -> Result<VectorValue<'ctx>, CompileError> {
714 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 #[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, upper_bound: u64, 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 fn trunc_sat_scalar(
858 &self,
859 int_ty: IntType<'ctx>,
860 lower_bound: u64, upper_bound: u64, int_min_value: u64,
863 int_max_value: u64,
864 value: FloatValue<'ctx>,
865 ) -> Result<IntValue<'ctx>, CompileError> {
866 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, upper_bound: u64, 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 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 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 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 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 let MemoryCache::Static { base_ptr: _ } = self.ctx.memory(
1423 memory_index,
1424 self.intrinsics,
1425 self.module,
1426 self.memory_styles,
1427 )? {
1428 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 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 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 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 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 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 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 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 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 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 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 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 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 ¶ms,
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 ¶ms,
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 ¶ms,
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 ¶ms,
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 ¶ms,
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 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 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>)>, 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 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 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 (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 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 let cond = self.state.pop1()?;
3053
3054 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 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 for phi in frame.phis() {
3175 if phi.count_incoming() != 0 {
3176 self.state.push1(phi.as_basic_value());
3177 } else {
3178 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 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 }
3234 Operator::Drop => {
3235 self.state.pop1()?;
3236 }
3237
3238 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 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 self.state.push1_extra(res, i);
3382 }
3383
3384 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 Operator::TypedSelect { .. } | Operator::Select => {
3479 let ((v1, i1), (v2, i2), (cond, _)) = self.state.pop3_extra()?;
3480 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 let params = self.state.popn_save_extra(func_type.params().len())?;
3558
3559 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 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 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 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 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 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 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 let elem_initialized = err!(self.builder.build_is_not_null(func_ptr, ""));
3923
3924 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 self.state.push1_extra(res, mag_info.strip_pending());
7449 }
7450 _ => unreachable!(),
7451 }
7452 Ok(())
7453 }
7454
7455 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 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 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::I32TruncF32S => {
9341 let v1 = self.state.pop1()?.into_float_value();
9342 self.trap_if_not_representable_as_int(
9343 0xcf000000, 0x4effffff, 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, 0x41dfffffffffffff, 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, 0x5effffff, 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, 0x43dfffffffffffff, 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, 0x4f7fffff, 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, 0x41efffffffffffff, 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, 0x5f7fffff, 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, 0x43efffffffffffff, 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::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 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 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 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 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 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 }
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 err!(self.builder.build_unreachable());
12112
12113 maybe_lpad_block = Some(lpad_block);
12114 }
12115
12116 self.builder.position_at_end(current_block);
12118
12119 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 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 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 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 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 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 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 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 let bits = bits & 0x7FFF_FFFF;
12893 bits < 0x7FC0_0000
12894}
12895
12896fn is_f64_arithmetic(bits: u64) -> bool {
12897 let bits = bits & 0x7FFF_FFFF_FFFF_FFFF;
12899 bits < 0x7FF8_0000_0000_0000
12900}