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