1#[macro_export]
7#[doc(hidden)]
8macro_rules! isle_common_prelude_methods {
9 () => {
10 isle_numerics_methods!();
11
12 #[inline]
14 fn unit(&mut self) -> Unit {
15 ()
16 }
17
18 #[inline]
19 fn checked_add_with_type(&mut self, ty: Type, a: u64, b: u64) -> Option<u64> {
20 let c = a.checked_add(b)?;
21 let ty_mask = self.ty_mask(ty);
22 if (c & !ty_mask) == 0 { Some(c) } else { None }
23 }
24
25 #[inline]
26 fn add_overflows_with_type(&mut self, ty: Type, a: u64, b: u64) -> bool {
27 self.checked_add_with_type(ty, a, b).is_none()
28 }
29
30 #[inline]
31 fn imm64_sdiv(&mut self, ty: Type, x: Imm64, y: Imm64) -> Option<Imm64> {
32 let shift = u32::checked_sub(64, ty.bits()).unwrap_or(0);
34 let x = (x.bits() << shift) >> shift;
35 let y = (y.bits() << shift) >> shift;
36
37 let min = ((self.ty_smin(ty) as i64) << shift) >> shift;
43 if x == min && y == -1 {
44 return None;
45 }
46
47 let ty_mask = self.ty_mask(ty) as i64;
48 let result = x.checked_div(y)? & ty_mask;
49 Some(Imm64::new(result))
50 }
51
52 #[inline]
53 fn imm64_shl(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
54 let shift_mask = (ty.bits() - 1) as u64;
56 let y = (y.bits() as u64) & shift_mask;
57
58 let ty_mask = self.ty_mask(ty) as i64;
60 Imm64::new((x.bits() << y) & ty_mask)
61 }
62
63 #[inline]
64 fn imm64_ushr(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
65 let ty_mask = self.ty_mask(ty);
66 let x = (x.bits() as u64) & ty_mask;
67
68 let shift_mask = (ty.bits() - 1) as u64;
70 let y = (y.bits() as u64) & shift_mask;
71
72 Imm64::new((x >> y) as i64)
74 }
75
76 #[inline]
77 fn imm64_sshr(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
78 let shift = u32::checked_sub(64, ty.bits()).unwrap_or(0);
80 let x = (x.bits() << shift) >> shift;
81
82 let shift_mask = (ty.bits() - 1) as i64;
84 let y = y.bits() & shift_mask;
85
86 let ty_mask = self.ty_mask(ty) as i64;
88 Imm64::new((x >> y) & ty_mask)
89 }
90
91 #[inline]
92 fn i64_sextend_u64(&mut self, ty: Type, x: u64) -> i64 {
93 let shift_amt = std::cmp::max(0, 64 - ty.bits());
94 ((x as i64) << shift_amt) >> shift_amt
95 }
96
97 #[inline]
98 fn i64_sextend_imm64(&mut self, ty: Type, x: Imm64) -> i64 {
99 x.sign_extend_from_width(ty.bits()).bits()
100 }
101
102 #[inline]
103 fn u64_uextend_imm64(&mut self, ty: Type, x: Imm64) -> u64 {
104 (x.bits() as u64) & self.ty_mask(ty)
105 }
106
107 #[inline]
108 fn imm64_icmp(&mut self, ty: Type, cc: &IntCC, x: Imm64, y: Imm64) -> Imm64 {
109 let ux = self.u64_uextend_imm64(ty, x);
110 let uy = self.u64_uextend_imm64(ty, y);
111 let sx = self.i64_sextend_imm64(ty, x);
112 let sy = self.i64_sextend_imm64(ty, y);
113 let result = match cc {
114 IntCC::Equal => ux == uy,
115 IntCC::NotEqual => ux != uy,
116 IntCC::UnsignedGreaterThanOrEqual => ux >= uy,
117 IntCC::UnsignedGreaterThan => ux > uy,
118 IntCC::UnsignedLessThanOrEqual => ux <= uy,
119 IntCC::UnsignedLessThan => ux < uy,
120 IntCC::SignedGreaterThanOrEqual => sx >= sy,
121 IntCC::SignedGreaterThan => sx > sy,
122 IntCC::SignedLessThanOrEqual => sx <= sy,
123 IntCC::SignedLessThan => sx < sy,
124 };
125 Imm64::new(result.into())
126 }
127
128 #[inline]
129 fn ty_bits(&mut self, ty: Type) -> u8 {
130 use std::convert::TryInto;
131 ty.bits().try_into().unwrap()
132 }
133
134 #[inline]
135 fn ty_bits_u16(&mut self, ty: Type) -> u16 {
136 ty.bits() as u16
137 }
138
139 #[inline]
140 fn ty_bits_u64(&mut self, ty: Type) -> u64 {
141 ty.bits() as u64
142 }
143
144 #[inline]
145 fn ty_bytes(&mut self, ty: Type) -> u16 {
146 u16::try_from(ty.bytes()).unwrap()
147 }
148
149 #[inline]
150 fn ty_mask(&mut self, ty: Type) -> u64 {
151 let ty_bits = ty.bits();
152 debug_assert_ne!(ty_bits, 0);
153 let shift = 64_u64
154 .checked_sub(ty_bits.into())
155 .expect("unimplemented for > 64 bits");
156 u64::MAX >> shift
157 }
158
159 #[inline]
160 fn ty_lane_mask(&mut self, ty: Type) -> u64 {
161 let ty_lane_count = ty.lane_count();
162 debug_assert_ne!(ty_lane_count, 0);
163 let shift = 64_u64
164 .checked_sub(ty_lane_count.into())
165 .expect("unimplemented for > 64 bits");
166 u64::MAX >> shift
167 }
168
169 #[inline]
170 fn ty_lane_count(&mut self, ty: Type) -> u64 {
171 ty.lane_count() as u64
172 }
173
174 #[inline]
175 fn ty_umin(&mut self, _ty: Type) -> u64 {
176 0
177 }
178
179 #[inline]
180 fn ty_umax(&mut self, ty: Type) -> u64 {
181 self.ty_mask(ty)
182 }
183
184 #[inline]
185 fn ty_smin(&mut self, ty: Type) -> u64 {
186 let ty_bits = ty.bits();
187 debug_assert_ne!(ty_bits, 0);
188 let shift = 64_u64
189 .checked_sub(ty_bits.into())
190 .expect("unimplemented for > 64 bits");
191 (i64::MIN as u64) >> shift
192 }
193
194 #[inline]
195 fn ty_smax(&mut self, ty: Type) -> u64 {
196 let ty_bits = ty.bits();
197 debug_assert_ne!(ty_bits, 0);
198 let shift = 64_u64
199 .checked_sub(ty_bits.into())
200 .expect("unimplemented for > 64 bits");
201 (i64::MAX as u64) >> shift
202 }
203
204 fn fits_in_16(&mut self, ty: Type) -> Option<Type> {
205 if ty.bits() <= 16 && !ty.is_dynamic_vector() {
206 Some(ty)
207 } else {
208 None
209 }
210 }
211
212 #[inline]
213 fn fits_in_32(&mut self, ty: Type) -> Option<Type> {
214 if ty.bits() <= 32 && !ty.is_dynamic_vector() {
215 Some(ty)
216 } else {
217 None
218 }
219 }
220
221 #[inline]
222 fn lane_fits_in_32(&mut self, ty: Type) -> Option<Type> {
223 if !ty.is_vector() && !ty.is_dynamic_vector() {
224 None
225 } else if ty.lane_type().bits() <= 32 {
226 Some(ty)
227 } else {
228 None
229 }
230 }
231
232 #[inline]
233 fn fits_in_64(&mut self, ty: Type) -> Option<Type> {
234 if ty.bits() <= 64 && !ty.is_dynamic_vector() {
235 Some(ty)
236 } else {
237 None
238 }
239 }
240
241 #[inline]
242 fn ty_int_ref_scalar_64(&mut self, ty: Type) -> Option<Type> {
243 if ty.bits() <= 64 && !ty.is_float() && !ty.is_vector() {
244 Some(ty)
245 } else {
246 None
247 }
248 }
249
250 #[inline]
251 fn ty_int_ref_scalar_64_extract(&mut self, ty: Type) -> Option<Type> {
252 self.ty_int_ref_scalar_64(ty)
253 }
254
255 #[inline]
256 fn ty_16(&mut self, ty: Type) -> Option<Type> {
257 if ty.bits() == 16 { Some(ty) } else { None }
258 }
259
260 #[inline]
261 fn ty_32(&mut self, ty: Type) -> Option<Type> {
262 if ty.bits() == 32 { Some(ty) } else { None }
263 }
264
265 #[inline]
266 fn ty_64(&mut self, ty: Type) -> Option<Type> {
267 if ty.bits() == 64 { Some(ty) } else { None }
268 }
269
270 #[inline]
271 fn ty_128(&mut self, ty: Type) -> Option<Type> {
272 if ty.bits() == 128 { Some(ty) } else { None }
273 }
274
275 #[inline]
276 fn ty_32_or_64(&mut self, ty: Type) -> Option<Type> {
277 if ty.bits() == 32 || ty.bits() == 64 {
278 Some(ty)
279 } else {
280 None
281 }
282 }
283
284 #[inline]
285 fn ty_8_or_16(&mut self, ty: Type) -> Option<Type> {
286 if ty.bits() == 8 || ty.bits() == 16 {
287 Some(ty)
288 } else {
289 None
290 }
291 }
292
293 #[inline]
294 fn ty_16_or_32(&mut self, ty: Type) -> Option<Type> {
295 if ty.bits() == 16 || ty.bits() == 32 {
296 Some(ty)
297 } else {
298 None
299 }
300 }
301
302 #[inline]
303 fn int_fits_in_32(&mut self, ty: Type) -> Option<Type> {
304 match ty {
305 I8 | I16 | I32 => Some(ty),
306 _ => None,
307 }
308 }
309
310 #[inline]
311 fn ty_int_ref_64(&mut self, ty: Type) -> Option<Type> {
312 match ty {
313 I64 => Some(ty),
314 _ => None,
315 }
316 }
317
318 #[inline]
319 fn ty_int_ref_16_to_64(&mut self, ty: Type) -> Option<Type> {
320 match ty {
321 I16 | I32 | I64 => Some(ty),
322 _ => None,
323 }
324 }
325
326 #[inline]
327 fn ty_int(&mut self, ty: Type) -> Option<Type> {
328 ty.is_int().then(|| ty)
329 }
330
331 #[inline]
332 fn ty_scalar(&mut self, ty: Type) -> Option<Type> {
333 if ty.lane_count() == 1 { Some(ty) } else { None }
334 }
335
336 #[inline]
337 fn ty_scalar_float(&mut self, ty: Type) -> Option<Type> {
338 if ty.is_float() { Some(ty) } else { None }
339 }
340
341 #[inline]
342 fn ty_float_or_vec(&mut self, ty: Type) -> Option<Type> {
343 if ty.is_float() || ty.is_vector() {
344 Some(ty)
345 } else {
346 None
347 }
348 }
349
350 fn ty_vector_float(&mut self, ty: Type) -> Option<Type> {
351 if ty.is_vector() && ty.lane_type().is_float() {
352 Some(ty)
353 } else {
354 None
355 }
356 }
357
358 #[inline]
359 fn ty_vector_not_float(&mut self, ty: Type) -> Option<Type> {
360 if ty.is_vector() && !ty.lane_type().is_float() {
361 Some(ty)
362 } else {
363 None
364 }
365 }
366
367 #[inline]
368 fn ty_vec64_ctor(&mut self, ty: Type) -> Option<Type> {
369 if ty.is_vector() && ty.bits() == 64 {
370 Some(ty)
371 } else {
372 None
373 }
374 }
375
376 #[inline]
377 fn ty_vec64(&mut self, ty: Type) -> Option<Type> {
378 if ty.is_vector() && ty.bits() == 64 {
379 Some(ty)
380 } else {
381 None
382 }
383 }
384
385 #[inline]
386 fn ty_vec128(&mut self, ty: Type) -> Option<Type> {
387 if ty.is_vector() && ty.bits() == 128 {
388 Some(ty)
389 } else {
390 None
391 }
392 }
393
394 #[inline]
395 fn ty_dyn_vec64(&mut self, ty: Type) -> Option<Type> {
396 if ty.is_dynamic_vector() && dynamic_to_fixed(ty).bits() == 64 {
397 Some(ty)
398 } else {
399 None
400 }
401 }
402
403 #[inline]
404 fn ty_dyn_vec128(&mut self, ty: Type) -> Option<Type> {
405 if ty.is_dynamic_vector() && dynamic_to_fixed(ty).bits() == 128 {
406 Some(ty)
407 } else {
408 None
409 }
410 }
411
412 #[inline]
413 fn ty_vec64_int(&mut self, ty: Type) -> Option<Type> {
414 if ty.is_vector() && ty.bits() == 64 && ty.lane_type().is_int() {
415 Some(ty)
416 } else {
417 None
418 }
419 }
420
421 #[inline]
422 fn ty_vec128_int(&mut self, ty: Type) -> Option<Type> {
423 if ty.is_vector() && ty.bits() == 128 && ty.lane_type().is_int() {
424 Some(ty)
425 } else {
426 None
427 }
428 }
429
430 #[inline]
431 fn ty_addr64(&mut self, ty: Type) -> Option<Type> {
432 match ty {
433 I64 => Some(ty),
434 _ => None,
435 }
436 }
437
438 #[inline]
439 fn u64_from_imm64(&mut self, imm: Imm64) -> u64 {
440 imm.bits() as u64
441 }
442
443 #[inline]
444 fn imm64_power_of_two(&mut self, x: Imm64) -> Option<u64> {
445 let x = i64::from(x);
446 let x = u64::try_from(x).ok()?;
447 if x.is_power_of_two() {
448 Some(x.trailing_zeros().into())
449 } else {
450 None
451 }
452 }
453
454 #[inline]
455 fn u64_from_bool(&mut self, b: bool) -> u64 {
456 if b { u64::MAX } else { 0 }
457 }
458
459 #[inline]
460 fn multi_lane(&mut self, ty: Type) -> Option<(u32, u32)> {
461 if ty.lane_count() > 1 {
462 Some((ty.lane_bits(), ty.lane_count()))
463 } else {
464 None
465 }
466 }
467
468 #[inline]
469 fn dynamic_lane(&mut self, ty: Type) -> Option<(u32, u32)> {
470 if ty.is_dynamic_vector() {
471 Some((ty.lane_bits(), ty.min_lane_count()))
472 } else {
473 None
474 }
475 }
476
477 #[inline]
478 fn ty_dyn64_int(&mut self, ty: Type) -> Option<Type> {
479 if ty.is_dynamic_vector() && ty.min_bits() == 64 && ty.lane_type().is_int() {
480 Some(ty)
481 } else {
482 None
483 }
484 }
485
486 #[inline]
487 fn ty_dyn128_int(&mut self, ty: Type) -> Option<Type> {
488 if ty.is_dynamic_vector() && ty.min_bits() == 128 && ty.lane_type().is_int() {
489 Some(ty)
490 } else {
491 None
492 }
493 }
494
495 fn u16_from_ieee16(&mut self, val: Ieee16) -> u16 {
496 val.bits()
497 }
498
499 fn u32_from_ieee32(&mut self, val: Ieee32) -> u32 {
500 val.bits()
501 }
502
503 fn u64_from_ieee64(&mut self, val: Ieee64) -> u64 {
504 val.bits()
505 }
506
507 fn u8_from_uimm8(&mut self, val: Uimm8) -> u8 {
508 val
509 }
510
511 fn not_vec32x2(&mut self, ty: Type) -> Option<Type> {
512 if ty.lane_bits() == 32 && ty.lane_count() == 2 {
513 None
514 } else {
515 Some(ty)
516 }
517 }
518
519 fn not_i64x2(&mut self, ty: Type) -> Option<()> {
520 if ty == I64X2 { None } else { Some(()) }
521 }
522
523 fn trap_code_division_by_zero(&mut self) -> TrapCode {
524 TrapCode::INTEGER_DIVISION_BY_ZERO
525 }
526
527 fn trap_code_integer_overflow(&mut self) -> TrapCode {
528 TrapCode::INTEGER_OVERFLOW
529 }
530
531 fn trap_code_bad_conversion_to_integer(&mut self) -> TrapCode {
532 TrapCode::BAD_CONVERSION_TO_INTEGER
533 }
534
535 fn nonzero_u64_from_imm64(&mut self, val: Imm64) -> Option<u64> {
536 match val.bits() {
537 0 => None,
538 n => Some(n as u64),
539 }
540 }
541
542 #[inline]
543 fn u32_nonnegative(&mut self, x: u32) -> Option<u32> {
544 if (x as i32) >= 0 { Some(x) } else { None }
545 }
546
547 #[inline]
548 fn imm64(&mut self, x: u64) -> Imm64 {
549 Imm64::new(x as i64)
550 }
551
552 #[inline]
553 fn imm64_masked(&mut self, ty: Type, x: u64) -> Imm64 {
554 Imm64::new((x & self.ty_mask(ty)) as i64)
555 }
556
557 #[inline]
558 fn offset32(&mut self, x: Offset32) -> i32 {
559 x.into()
560 }
561
562 #[inline]
563 fn lane_type(&mut self, ty: Type) -> Type {
564 ty.lane_type()
565 }
566
567 #[inline]
568 fn ty_half_lanes(&mut self, ty: Type) -> Option<Type> {
569 if ty.lane_count() == 1 {
570 None
571 } else {
572 ty.lane_type().by(ty.lane_count() / 2)
573 }
574 }
575
576 #[inline]
577 fn ty_half_width(&mut self, ty: Type) -> Option<Type> {
578 ty.half_width()
579 }
580
581 #[inline]
582 fn ty_equal(&mut self, lhs: Type, rhs: Type) -> bool {
583 lhs == rhs
584 }
585
586 #[inline]
587 fn offset32_to_i32(&mut self, offset: Offset32) -> i32 {
588 offset.into()
589 }
590
591 #[inline]
592 fn i32_to_offset32(&mut self, offset: i32) -> Offset32 {
593 Offset32::new(offset)
594 }
595
596 #[inline]
597 fn mem_flags_trusted(&mut self) -> MemFlags {
598 MemFlags::trusted()
599 }
600
601 #[inline]
602 fn little_or_native_endian(&mut self, flags: MemFlags) -> Option<MemFlags> {
603 match flags.explicit_endianness() {
604 Some(crate::ir::Endianness::Little) | None => Some(flags),
605 Some(crate::ir::Endianness::Big) => None,
606 }
607 }
608
609 #[inline]
610 fn intcc_unsigned(&mut self, x: &IntCC) -> IntCC {
611 x.unsigned()
612 }
613
614 #[inline]
615 fn signed_cond_code(&mut self, cc: &IntCC) -> Option<IntCC> {
616 match cc {
617 IntCC::Equal
618 | IntCC::UnsignedGreaterThanOrEqual
619 | IntCC::UnsignedGreaterThan
620 | IntCC::UnsignedLessThanOrEqual
621 | IntCC::UnsignedLessThan
622 | IntCC::NotEqual => None,
623 IntCC::SignedGreaterThanOrEqual
624 | IntCC::SignedGreaterThan
625 | IntCC::SignedLessThanOrEqual
626 | IntCC::SignedLessThan => Some(*cc),
627 }
628 }
629
630 #[inline]
631 fn intcc_swap_args(&mut self, cc: &IntCC) -> IntCC {
632 cc.swap_args()
633 }
634
635 #[inline]
636 fn intcc_complement(&mut self, cc: &IntCC) -> IntCC {
637 cc.complement()
638 }
639
640 #[inline]
641 fn intcc_without_eq(&mut self, x: &IntCC) -> IntCC {
642 x.without_equal()
643 }
644
645 #[inline]
646 fn floatcc_swap_args(&mut self, cc: &FloatCC) -> FloatCC {
647 cc.swap_args()
648 }
649
650 #[inline]
651 fn floatcc_complement(&mut self, cc: &FloatCC) -> FloatCC {
652 cc.complement()
653 }
654
655 fn floatcc_unordered(&mut self, cc: &FloatCC) -> bool {
656 match *cc {
657 FloatCC::Unordered
658 | FloatCC::UnorderedOrEqual
659 | FloatCC::UnorderedOrLessThan
660 | FloatCC::UnorderedOrLessThanOrEqual
661 | FloatCC::UnorderedOrGreaterThan
662 | FloatCC::UnorderedOrGreaterThanOrEqual => true,
663 _ => false,
664 }
665 }
666
667 #[inline]
668 fn unpack_value_array_2(&mut self, arr: &ValueArray2) -> (Value, Value) {
669 let [a, b] = *arr;
670 (a, b)
671 }
672
673 #[inline]
674 fn pack_value_array_2(&mut self, a: Value, b: Value) -> ValueArray2 {
675 [a, b]
676 }
677
678 #[inline]
679 fn unpack_value_array_3(&mut self, arr: &ValueArray3) -> (Value, Value, Value) {
680 let [a, b, c] = *arr;
681 (a, b, c)
682 }
683
684 #[inline]
685 fn pack_value_array_3(&mut self, a: Value, b: Value, c: Value) -> ValueArray3 {
686 [a, b, c]
687 }
688
689 #[inline]
690 fn unpack_block_array_2(&mut self, arr: &BlockArray2) -> (BlockCall, BlockCall) {
691 let [a, b] = *arr;
692 (a, b)
693 }
694
695 #[inline]
696 fn pack_block_array_2(&mut self, a: BlockCall, b: BlockCall) -> BlockArray2 {
697 [a, b]
698 }
699
700 fn u128_replicated_u64(&mut self, val: u128) -> Option<u64> {
701 let low64 = val as u64 as u128;
702 if (low64 | (low64 << 64)) == val {
703 Some(low64 as u64)
704 } else {
705 None
706 }
707 }
708
709 fn u64_replicated_u32(&mut self, val: u64) -> Option<u64> {
710 let low32 = val as u32 as u64;
711 if (low32 | (low32 << 32)) == val {
712 Some(low32)
713 } else {
714 None
715 }
716 }
717
718 fn u32_replicated_u16(&mut self, val: u64) -> Option<u64> {
719 let val = val as u32;
720 let low16 = val as u16 as u32;
721 if (low16 | (low16 << 16)) == val {
722 Some(low16.into())
723 } else {
724 None
725 }
726 }
727
728 fn u16_replicated_u8(&mut self, val: u64) -> Option<u8> {
729 let val = val as u16;
730 let low8 = val as u8 as u16;
731 if (low8 | (low8 << 8)) == val {
732 Some(low8 as u8)
733 } else {
734 None
735 }
736 }
737
738 fn u128_low_bits(&mut self, val: u128) -> u64 {
739 val as u64
740 }
741
742 fn u128_high_bits(&mut self, val: u128) -> u64 {
743 (val >> 64) as u64
744 }
745
746 fn f16_min(&mut self, a: Ieee16, b: Ieee16) -> Option<Ieee16> {
747 a.minimum(b).non_nan()
748 }
749
750 fn f16_max(&mut self, a: Ieee16, b: Ieee16) -> Option<Ieee16> {
751 a.maximum(b).non_nan()
752 }
753
754 fn f16_neg(&mut self, n: Ieee16) -> Ieee16 {
755 -n
756 }
757
758 fn f16_abs(&mut self, n: Ieee16) -> Ieee16 {
759 n.abs()
760 }
761
762 fn f16_copysign(&mut self, a: Ieee16, b: Ieee16) -> Ieee16 {
763 a.copysign(b)
764 }
765
766 fn f32_add(&mut self, lhs: Ieee32, rhs: Ieee32) -> Option<Ieee32> {
767 (lhs + rhs).non_nan()
768 }
769
770 fn f32_sub(&mut self, lhs: Ieee32, rhs: Ieee32) -> Option<Ieee32> {
771 (lhs - rhs).non_nan()
772 }
773
774 fn f32_mul(&mut self, lhs: Ieee32, rhs: Ieee32) -> Option<Ieee32> {
775 (lhs * rhs).non_nan()
776 }
777
778 fn f32_div(&mut self, lhs: Ieee32, rhs: Ieee32) -> Option<Ieee32> {
779 (lhs / rhs).non_nan()
780 }
781
782 fn f32_sqrt(&mut self, n: Ieee32) -> Option<Ieee32> {
783 n.sqrt().non_nan()
784 }
785
786 fn f32_ceil(&mut self, n: Ieee32) -> Option<Ieee32> {
787 n.ceil().non_nan()
788 }
789
790 fn f32_floor(&mut self, n: Ieee32) -> Option<Ieee32> {
791 n.floor().non_nan()
792 }
793
794 fn f32_trunc(&mut self, n: Ieee32) -> Option<Ieee32> {
795 n.trunc().non_nan()
796 }
797
798 fn f32_nearest(&mut self, n: Ieee32) -> Option<Ieee32> {
799 n.round_ties_even().non_nan()
800 }
801
802 fn f32_min(&mut self, a: Ieee32, b: Ieee32) -> Option<Ieee32> {
803 a.minimum(b).non_nan()
804 }
805
806 fn f32_max(&mut self, a: Ieee32, b: Ieee32) -> Option<Ieee32> {
807 a.maximum(b).non_nan()
808 }
809
810 fn f32_neg(&mut self, n: Ieee32) -> Ieee32 {
811 -n
812 }
813
814 fn f32_abs(&mut self, n: Ieee32) -> Ieee32 {
815 n.abs()
816 }
817
818 fn f32_copysign(&mut self, a: Ieee32, b: Ieee32) -> Ieee32 {
819 a.copysign(b)
820 }
821
822 fn f64_add(&mut self, lhs: Ieee64, rhs: Ieee64) -> Option<Ieee64> {
823 (lhs + rhs).non_nan()
824 }
825
826 fn f64_sub(&mut self, lhs: Ieee64, rhs: Ieee64) -> Option<Ieee64> {
827 (lhs - rhs).non_nan()
828 }
829
830 fn f64_mul(&mut self, lhs: Ieee64, rhs: Ieee64) -> Option<Ieee64> {
831 (lhs * rhs).non_nan()
832 }
833
834 fn f64_div(&mut self, lhs: Ieee64, rhs: Ieee64) -> Option<Ieee64> {
835 (lhs / rhs).non_nan()
836 }
837
838 fn f64_sqrt(&mut self, n: Ieee64) -> Option<Ieee64> {
839 n.sqrt().non_nan()
840 }
841
842 fn f64_ceil(&mut self, n: Ieee64) -> Option<Ieee64> {
843 n.ceil().non_nan()
844 }
845
846 fn f64_floor(&mut self, n: Ieee64) -> Option<Ieee64> {
847 n.floor().non_nan()
848 }
849
850 fn f64_trunc(&mut self, n: Ieee64) -> Option<Ieee64> {
851 n.trunc().non_nan()
852 }
853
854 fn f64_nearest(&mut self, n: Ieee64) -> Option<Ieee64> {
855 n.round_ties_even().non_nan()
856 }
857
858 fn f64_min(&mut self, a: Ieee64, b: Ieee64) -> Option<Ieee64> {
859 a.minimum(b).non_nan()
860 }
861
862 fn f64_max(&mut self, a: Ieee64, b: Ieee64) -> Option<Ieee64> {
863 a.maximum(b).non_nan()
864 }
865
866 fn f64_neg(&mut self, n: Ieee64) -> Ieee64 {
867 -n
868 }
869
870 fn f64_abs(&mut self, n: Ieee64) -> Ieee64 {
871 n.abs()
872 }
873
874 fn f64_copysign(&mut self, a: Ieee64, b: Ieee64) -> Ieee64 {
875 a.copysign(b)
876 }
877
878 fn f128_min(&mut self, a: Ieee128, b: Ieee128) -> Option<Ieee128> {
879 a.minimum(b).non_nan()
880 }
881
882 fn f128_max(&mut self, a: Ieee128, b: Ieee128) -> Option<Ieee128> {
883 a.maximum(b).non_nan()
884 }
885
886 fn f128_neg(&mut self, n: Ieee128) -> Ieee128 {
887 -n
888 }
889
890 fn f128_abs(&mut self, n: Ieee128) -> Ieee128 {
891 n.abs()
892 }
893
894 fn f128_copysign(&mut self, a: Ieee128, b: Ieee128) -> Ieee128 {
895 a.copysign(b)
896 }
897
898 #[inline]
899 fn def_inst(&mut self, val: Value) -> Option<Inst> {
900 self.dfg().value_def(val).inst()
901 }
902 };
903}