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 /// We don't have a way of making a `()` value in isle directly. 11 #[inline] 12 fn unit(&mut self) -> Unit { 13 () 14 } 15 16 #[inline] 17 fn u8_as_u32(&mut self, x: u8) -> u32 { 18 x.into() 19 } 20 21 #[inline] 22 fn u8_as_u64(&mut self, x: u8) -> u64 { 23 x.into() 24 } 25 26 #[inline] 27 fn u16_as_i16(&mut self, x: u16) -> i16 { 28 x as i16 29 } 30 31 #[inline] 32 fn u16_as_u32(&mut self, x: u16) -> u32 { 33 x.into() 34 } 35 36 #[inline] 37 fn u16_as_u64(&mut self, x: u16) -> u64 { 38 x.into() 39 } 40 41 #[inline] 42 fn u32_as_u64(&mut self, x: u32) -> u64 { 43 x.into() 44 } 45 46 #[inline] 47 fn i64_as_u64(&mut self, x: i64) -> u64 { 48 x as u64 49 } 50 51 #[inline] 52 fn u64_as_i32(&mut self, x: u64) -> i32 { 53 x as i32 54 } 55 56 #[inline] 57 fn u64_as_i64(&mut self, x: u64) -> i64 { 58 x as i64 59 } 60 61 #[inline] 62 fn i32_as_u32(&mut self, x: i32) -> u32 { 63 x as u32 64 } 65 66 #[inline] 67 fn i32_as_i64(&mut self, x: i32) -> i64 { 68 x.into() 69 } 70 71 #[inline] 72 fn i64_neg(&mut self, x: i64) -> i64 { 73 x.wrapping_neg() 74 } 75 76 #[inline] 77 fn i8_neg(&mut self, x: i8) -> i8 { 78 x.wrapping_neg() 79 } 80 81 #[inline] 82 fn checked_add_with_type(&mut self, ty: Type, a: u64, b: u64) -> Option<u64> { 83 let c = a.checked_add(b)?; 84 let ty_mask = self.ty_mask(ty); 85 if (c & !ty_mask) == 0 { Some(c) } else { None } 86 } 87 88 #[inline] 89 fn add_overflows_with_type(&mut self, ty: Type, a: u64, b: u64) -> bool { 90 self.checked_add_with_type(ty, a, b).is_none() 91 } 92 93 #[inline] 94 fn u64_add(&mut self, x: u64, y: u64) -> u64 { 95 x.wrapping_add(y) 96 } 97 98 #[inline] 99 fn u64_sub(&mut self, x: u64, y: u64) -> u64 { 100 x.wrapping_sub(y) 101 } 102 103 #[inline] 104 fn u64_mul(&mut self, x: u64, y: u64) -> u64 { 105 x.wrapping_mul(y) 106 } 107 108 #[inline] 109 fn imm64_sdiv(&mut self, ty: Type, x: Imm64, y: Imm64) -> Option<Imm64> { 110 // Sign extend `x` and `y`. 111 let shift = u32::checked_sub(64, ty.bits()).unwrap_or(0); 112 let x = (x.bits() << shift) >> shift; 113 let y = (y.bits() << shift) >> shift; 114 115 // NB: We can't rely on `checked_div` to detect `ty::MIN / -1` 116 // (which overflows and should trap) because we are working with 117 // `i64` values here, and `i32::MIN != i64::MIN`, for 118 // example. Therefore, we have to explicitly check for this case 119 // ourselves. 120 let min = ((self.ty_smin(ty) as i64) << shift) >> shift; 121 if x == min && y == -1 { 122 return None; 123 } 124 125 let ty_mask = self.ty_mask(ty) as i64; 126 let result = x.checked_div(y)? & ty_mask; 127 Some(Imm64::new(result)) 128 } 129 130 #[inline] 131 fn u64_udiv(&mut self, x: u64, y: u64) -> Option<u64> { 132 x.checked_div(y) 133 } 134 135 #[inline] 136 fn u64_and(&mut self, x: u64, y: u64) -> u64 { 137 x & y 138 } 139 140 #[inline] 141 fn u64_or(&mut self, x: u64, y: u64) -> u64 { 142 x | y 143 } 144 145 #[inline] 146 fn u64_xor(&mut self, x: u64, y: u64) -> u64 { 147 x ^ y 148 } 149 150 #[inline] 151 fn u64_shl(&mut self, x: u64, y: u64) -> u64 { 152 x << y 153 } 154 155 #[inline] 156 fn imm64_shl(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 { 157 // Mask off any excess shift bits. 158 let shift_mask = (ty.bits() - 1) as u64; 159 let y = (y.bits() as u64) & shift_mask; 160 161 // Mask the result to `ty` bits. 162 let ty_mask = self.ty_mask(ty) as i64; 163 Imm64::new((x.bits() << y) & ty_mask) 164 } 165 166 #[inline] 167 fn imm64_ushr(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 { 168 let ty_mask = self.ty_mask(ty); 169 let x = (x.bits() as u64) & ty_mask; 170 171 // Mask off any excess shift bits. 172 let shift_mask = (ty.bits() - 1) as u64; 173 let y = (y.bits() as u64) & shift_mask; 174 175 // NB: No need to mask off high bits because they are already zero. 176 Imm64::new((x >> y) as i64) 177 } 178 179 #[inline] 180 fn imm64_sshr(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 { 181 // Sign extend `x` from `ty.bits()`-width to the full 64 bits. 182 let shift = u32::checked_sub(64, ty.bits()).unwrap_or(0); 183 let x = (x.bits() << shift) >> shift; 184 185 // Mask off any excess shift bits. 186 let shift_mask = (ty.bits() - 1) as i64; 187 let y = y.bits() & shift_mask; 188 189 // Mask off sign bits that aren't part of `ty`. 190 let ty_mask = self.ty_mask(ty) as i64; 191 Imm64::new((x >> y) & ty_mask) 192 } 193 194 #[inline] 195 fn u64_not(&mut self, x: u64) -> u64 { 196 !x 197 } 198 199 #[inline] 200 fn i64_not(&mut self, x: i64) -> i64 { 201 !x 202 } 203 204 #[inline] 205 fn u64_eq(&mut self, x: u64, y: u64) -> bool { 206 x == y 207 } 208 209 #[inline] 210 fn u64_le(&mut self, x: u64, y: u64) -> bool { 211 x <= y 212 } 213 214 #[inline] 215 fn u64_lt(&mut self, x: u64, y: u64) -> bool { 216 x < y 217 } 218 219 #[inline] 220 fn u64_is_zero(&mut self, value: u64) -> bool { 221 0 == value 222 } 223 224 fn i64_is_zero(&mut self, value: i64) -> bool { 225 0 == value 226 } 227 228 #[inline] 229 fn u64_is_odd(&mut self, x: u64) -> bool { 230 x & 1 == 1 231 } 232 233 fn i64_shr(&mut self, a: i64, b: i64) -> i64 { 234 a >> b 235 } 236 237 fn i64_ctz(&mut self, a: i64) -> i64 { 238 a.trailing_zeros().into() 239 } 240 241 #[inline] 242 fn i64_sextend_u64(&mut self, ty: Type, x: u64) -> i64 { 243 let shift_amt = std::cmp::max(0, 64 - ty.bits()); 244 ((x as i64) << shift_amt) >> shift_amt 245 } 246 247 #[inline] 248 fn i64_sextend_imm64(&mut self, ty: Type, x: Imm64) -> i64 { 249 x.sign_extend_from_width(ty.bits()).bits() 250 } 251 252 #[inline] 253 fn u64_uextend_imm64(&mut self, ty: Type, x: Imm64) -> u64 { 254 (x.bits() as u64) & self.ty_mask(ty) 255 } 256 257 #[inline] 258 fn imm64_icmp(&mut self, ty: Type, cc: &IntCC, x: Imm64, y: Imm64) -> Imm64 { 259 let ux = self.u64_uextend_imm64(ty, x); 260 let uy = self.u64_uextend_imm64(ty, y); 261 let sx = self.i64_sextend_imm64(ty, x); 262 let sy = self.i64_sextend_imm64(ty, y); 263 let result = match cc { 264 IntCC::Equal => ux == uy, 265 IntCC::NotEqual => ux != uy, 266 IntCC::UnsignedGreaterThanOrEqual => ux >= uy, 267 IntCC::UnsignedGreaterThan => ux > uy, 268 IntCC::UnsignedLessThanOrEqual => ux <= uy, 269 IntCC::UnsignedLessThan => ux < uy, 270 IntCC::SignedGreaterThanOrEqual => sx >= sy, 271 IntCC::SignedGreaterThan => sx > sy, 272 IntCC::SignedLessThanOrEqual => sx <= sy, 273 IntCC::SignedLessThan => sx < sy, 274 }; 275 Imm64::new(result.into()) 276 } 277 278 #[inline] 279 fn ty_bits(&mut self, ty: Type) -> u8 { 280 use std::convert::TryInto; 281 ty.bits().try_into().unwrap() 282 } 283 284 #[inline] 285 fn ty_bits_u16(&mut self, ty: Type) -> u16 { 286 ty.bits() as u16 287 } 288 289 #[inline] 290 fn ty_bits_u64(&mut self, ty: Type) -> u64 { 291 ty.bits() as u64 292 } 293 294 #[inline] 295 fn ty_bytes(&mut self, ty: Type) -> u16 { 296 u16::try_from(ty.bytes()).unwrap() 297 } 298 299 #[inline] 300 fn ty_mask(&mut self, ty: Type) -> u64 { 301 let ty_bits = ty.bits(); 302 debug_assert_ne!(ty_bits, 0); 303 let shift = 64_u64 304 .checked_sub(ty_bits.into()) 305 .expect("unimplemented for > 64 bits"); 306 u64::MAX >> shift 307 } 308 309 #[inline] 310 fn ty_lane_mask(&mut self, ty: Type) -> u64 { 311 let ty_lane_count = ty.lane_count(); 312 debug_assert_ne!(ty_lane_count, 0); 313 let shift = 64_u64 314 .checked_sub(ty_lane_count.into()) 315 .expect("unimplemented for > 64 bits"); 316 u64::MAX >> shift 317 } 318 319 #[inline] 320 fn ty_lane_count(&mut self, ty: Type) -> u64 { 321 ty.lane_count() as u64 322 } 323 324 #[inline] 325 fn ty_umin(&mut self, _ty: Type) -> u64 { 326 0 327 } 328 329 #[inline] 330 fn ty_umax(&mut self, ty: Type) -> u64 { 331 self.ty_mask(ty) 332 } 333 334 #[inline] 335 fn ty_smin(&mut self, ty: Type) -> u64 { 336 let ty_bits = ty.bits(); 337 debug_assert_ne!(ty_bits, 0); 338 let shift = 64_u64 339 .checked_sub(ty_bits.into()) 340 .expect("unimplemented for > 64 bits"); 341 (i64::MIN as u64) >> shift 342 } 343 344 #[inline] 345 fn ty_smax(&mut self, ty: Type) -> u64 { 346 let ty_bits = ty.bits(); 347 debug_assert_ne!(ty_bits, 0); 348 let shift = 64_u64 349 .checked_sub(ty_bits.into()) 350 .expect("unimplemented for > 64 bits"); 351 (i64::MAX as u64) >> shift 352 } 353 354 fn fits_in_16(&mut self, ty: Type) -> Option<Type> { 355 if ty.bits() <= 16 && !ty.is_dynamic_vector() { 356 Some(ty) 357 } else { 358 None 359 } 360 } 361 362 #[inline] 363 fn fits_in_32(&mut self, ty: Type) -> Option<Type> { 364 if ty.bits() <= 32 && !ty.is_dynamic_vector() { 365 Some(ty) 366 } else { 367 None 368 } 369 } 370 371 #[inline] 372 fn lane_fits_in_32(&mut self, ty: Type) -> Option<Type> { 373 if !ty.is_vector() && !ty.is_dynamic_vector() { 374 None 375 } else if ty.lane_type().bits() <= 32 { 376 Some(ty) 377 } else { 378 None 379 } 380 } 381 382 #[inline] 383 fn fits_in_64(&mut self, ty: Type) -> Option<Type> { 384 if ty.bits() <= 64 && !ty.is_dynamic_vector() { 385 Some(ty) 386 } else { 387 None 388 } 389 } 390 391 #[inline] 392 fn ty_int_ref_scalar_64(&mut self, ty: Type) -> Option<Type> { 393 if ty.bits() <= 64 && !ty.is_float() && !ty.is_vector() { 394 Some(ty) 395 } else { 396 None 397 } 398 } 399 400 #[inline] 401 fn ty_int_ref_scalar_64_extract(&mut self, ty: Type) -> Option<Type> { 402 self.ty_int_ref_scalar_64(ty) 403 } 404 405 #[inline] 406 fn ty_16(&mut self, ty: Type) -> Option<Type> { 407 if ty.bits() == 16 { Some(ty) } else { None } 408 } 409 410 #[inline] 411 fn ty_32(&mut self, ty: Type) -> Option<Type> { 412 if ty.bits() == 32 { Some(ty) } else { None } 413 } 414 415 #[inline] 416 fn ty_64(&mut self, ty: Type) -> Option<Type> { 417 if ty.bits() == 64 { Some(ty) } else { None } 418 } 419 420 #[inline] 421 fn ty_128(&mut self, ty: Type) -> Option<Type> { 422 if ty.bits() == 128 { Some(ty) } else { None } 423 } 424 425 #[inline] 426 fn ty_32_or_64(&mut self, ty: Type) -> Option<Type> { 427 if ty.bits() == 32 || ty.bits() == 64 { 428 Some(ty) 429 } else { 430 None 431 } 432 } 433 434 #[inline] 435 fn ty_8_or_16(&mut self, ty: Type) -> Option<Type> { 436 if ty.bits() == 8 || ty.bits() == 16 { 437 Some(ty) 438 } else { 439 None 440 } 441 } 442 443 #[inline] 444 fn ty_16_or_32(&mut self, ty: Type) -> Option<Type> { 445 if ty.bits() == 16 || ty.bits() == 32 { 446 Some(ty) 447 } else { 448 None 449 } 450 } 451 452 #[inline] 453 fn int_fits_in_32(&mut self, ty: Type) -> Option<Type> { 454 match ty { 455 I8 | I16 | I32 => Some(ty), 456 _ => None, 457 } 458 } 459 460 #[inline] 461 fn ty_int_ref_64(&mut self, ty: Type) -> Option<Type> { 462 match ty { 463 I64 => Some(ty), 464 _ => None, 465 } 466 } 467 468 #[inline] 469 fn ty_int_ref_16_to_64(&mut self, ty: Type) -> Option<Type> { 470 match ty { 471 I16 | I32 | I64 => Some(ty), 472 _ => None, 473 } 474 } 475 476 #[inline] 477 fn ty_int(&mut self, ty: Type) -> Option<Type> { 478 ty.is_int().then(|| ty) 479 } 480 481 #[inline] 482 fn ty_scalar(&mut self, ty: Type) -> Option<Type> { 483 if ty.lane_count() == 1 { Some(ty) } else { None } 484 } 485 486 #[inline] 487 fn ty_scalar_float(&mut self, ty: Type) -> Option<Type> { 488 if ty.is_float() { Some(ty) } else { None } 489 } 490 491 #[inline] 492 fn ty_float_or_vec(&mut self, ty: Type) -> Option<Type> { 493 if ty.is_float() || ty.is_vector() { 494 Some(ty) 495 } else { 496 None 497 } 498 } 499 500 fn ty_vector_float(&mut self, ty: Type) -> Option<Type> { 501 if ty.is_vector() && ty.lane_type().is_float() { 502 Some(ty) 503 } else { 504 None 505 } 506 } 507 508 #[inline] 509 fn ty_vector_not_float(&mut self, ty: Type) -> Option<Type> { 510 if ty.is_vector() && !ty.lane_type().is_float() { 511 Some(ty) 512 } else { 513 None 514 } 515 } 516 517 #[inline] 518 fn ty_vec64_ctor(&mut self, ty: Type) -> Option<Type> { 519 if ty.is_vector() && ty.bits() == 64 { 520 Some(ty) 521 } else { 522 None 523 } 524 } 525 526 #[inline] 527 fn ty_vec64(&mut self, ty: Type) -> Option<Type> { 528 if ty.is_vector() && ty.bits() == 64 { 529 Some(ty) 530 } else { 531 None 532 } 533 } 534 535 #[inline] 536 fn ty_vec128(&mut self, ty: Type) -> Option<Type> { 537 if ty.is_vector() && ty.bits() == 128 { 538 Some(ty) 539 } else { 540 None 541 } 542 } 543 544 #[inline] 545 fn ty_dyn_vec64(&mut self, ty: Type) -> Option<Type> { 546 if ty.is_dynamic_vector() && dynamic_to_fixed(ty).bits() == 64 { 547 Some(ty) 548 } else { 549 None 550 } 551 } 552 553 #[inline] 554 fn ty_dyn_vec128(&mut self, ty: Type) -> Option<Type> { 555 if ty.is_dynamic_vector() && dynamic_to_fixed(ty).bits() == 128 { 556 Some(ty) 557 } else { 558 None 559 } 560 } 561 562 #[inline] 563 fn ty_vec64_int(&mut self, ty: Type) -> Option<Type> { 564 if ty.is_vector() && ty.bits() == 64 && ty.lane_type().is_int() { 565 Some(ty) 566 } else { 567 None 568 } 569 } 570 571 #[inline] 572 fn ty_vec128_int(&mut self, ty: Type) -> Option<Type> { 573 if ty.is_vector() && ty.bits() == 128 && ty.lane_type().is_int() { 574 Some(ty) 575 } else { 576 None 577 } 578 } 579 580 #[inline] 581 fn ty_addr64(&mut self, ty: Type) -> Option<Type> { 582 match ty { 583 I64 => Some(ty), 584 _ => None, 585 } 586 } 587 588 #[inline] 589 fn u64_from_imm64(&mut self, imm: Imm64) -> u64 { 590 imm.bits() as u64 591 } 592 593 #[inline] 594 fn imm64_power_of_two(&mut self, x: Imm64) -> Option<u64> { 595 let x = i64::from(x); 596 let x = u64::try_from(x).ok()?; 597 if x.is_power_of_two() { 598 Some(x.trailing_zeros().into()) 599 } else { 600 None 601 } 602 } 603 604 #[inline] 605 fn u64_from_bool(&mut self, b: bool) -> u64 { 606 if b { u64::MAX } else { 0 } 607 } 608 609 #[inline] 610 fn multi_lane(&mut self, ty: Type) -> Option<(u32, u32)> { 611 if ty.lane_count() > 1 { 612 Some((ty.lane_bits(), ty.lane_count())) 613 } else { 614 None 615 } 616 } 617 618 #[inline] 619 fn dynamic_lane(&mut self, ty: Type) -> Option<(u32, u32)> { 620 if ty.is_dynamic_vector() { 621 Some((ty.lane_bits(), ty.min_lane_count())) 622 } else { 623 None 624 } 625 } 626 627 #[inline] 628 fn ty_dyn64_int(&mut self, ty: Type) -> Option<Type> { 629 if ty.is_dynamic_vector() && ty.min_bits() == 64 && ty.lane_type().is_int() { 630 Some(ty) 631 } else { 632 None 633 } 634 } 635 636 #[inline] 637 fn ty_dyn128_int(&mut self, ty: Type) -> Option<Type> { 638 if ty.is_dynamic_vector() && ty.min_bits() == 128 && ty.lane_type().is_int() { 639 Some(ty) 640 } else { 641 None 642 } 643 } 644 645 fn u16_from_ieee16(&mut self, val: Ieee16) -> u16 { 646 val.bits() 647 } 648 649 fn u32_from_ieee32(&mut self, val: Ieee32) -> u32 { 650 val.bits() 651 } 652 653 fn u64_from_ieee64(&mut self, val: Ieee64) -> u64 { 654 val.bits() 655 } 656 657 fn u8_from_uimm8(&mut self, val: Uimm8) -> u8 { 658 val 659 } 660 661 fn not_vec32x2(&mut self, ty: Type) -> Option<Type> { 662 if ty.lane_bits() == 32 && ty.lane_count() == 2 { 663 None 664 } else { 665 Some(ty) 666 } 667 } 668 669 fn not_i64x2(&mut self, ty: Type) -> Option<()> { 670 if ty == I64X2 { None } else { Some(()) } 671 } 672 673 fn trap_code_division_by_zero(&mut self) -> TrapCode { 674 TrapCode::INTEGER_DIVISION_BY_ZERO 675 } 676 677 fn trap_code_integer_overflow(&mut self) -> TrapCode { 678 TrapCode::INTEGER_OVERFLOW 679 } 680 681 fn trap_code_bad_conversion_to_integer(&mut self) -> TrapCode { 682 TrapCode::BAD_CONVERSION_TO_INTEGER 683 } 684 685 fn nonzero_u64_from_imm64(&mut self, val: Imm64) -> Option<u64> { 686 match val.bits() { 687 0 => None, 688 n => Some(n as u64), 689 } 690 } 691 692 #[inline] 693 fn u32_add(&mut self, a: u32, b: u32) -> u32 { 694 a.wrapping_add(b) 695 } 696 697 #[inline] 698 fn u32_sub(&mut self, a: u32, b: u32) -> u32 { 699 a.wrapping_sub(b) 700 } 701 702 #[inline] 703 fn u32_and(&mut self, a: u32, b: u32) -> u32 { 704 a & b 705 } 706 707 #[inline] 708 fn u32_shl(&mut self, x: u32, y: u32) -> u32 { 709 x << y 710 } 711 712 #[inline] 713 fn s32_add_fallible(&mut self, a: i32, b: i32) -> Option<i32> { 714 a.checked_add(b) 715 } 716 717 #[inline] 718 fn u32_nonnegative(&mut self, x: u32) -> Option<u32> { 719 if (x as i32) >= 0 { Some(x) } else { None } 720 } 721 722 #[inline] 723 fn u32_lteq(&mut self, a: u32, b: u32) -> Option<()> { 724 if a <= b { Some(()) } else { None } 725 } 726 727 #[inline] 728 fn u8_lteq(&mut self, a: u8, b: u8) -> Option<()> { 729 if a <= b { Some(()) } else { None } 730 } 731 732 #[inline] 733 fn u8_lt(&mut self, a: u8, b: u8) -> Option<()> { 734 if a < b { Some(()) } else { None } 735 } 736 737 #[inline] 738 fn imm64(&mut self, x: u64) -> Imm64 { 739 Imm64::new(x as i64) 740 } 741 742 #[inline] 743 fn imm64_masked(&mut self, ty: Type, x: u64) -> Imm64 { 744 Imm64::new((x & self.ty_mask(ty)) as i64) 745 } 746 747 #[inline] 748 fn offset32(&mut self, x: Offset32) -> i32 { 749 x.into() 750 } 751 752 #[inline] 753 fn u8_and(&mut self, a: u8, b: u8) -> u8 { 754 a & b 755 } 756 757 #[inline] 758 fn u8_shl(&mut self, a: u8, b: u8) -> u8 { 759 a << b 760 } 761 762 #[inline] 763 fn u8_shr(&mut self, a: u8, b: u8) -> u8 { 764 a >> b 765 } 766 767 #[inline] 768 fn u8_sub(&mut self, a: u8, b: u8) -> u8 { 769 a.wrapping_sub(b) 770 } 771 772 #[inline] 773 fn lane_type(&mut self, ty: Type) -> Type { 774 ty.lane_type() 775 } 776 777 #[inline] 778 fn ty_half_lanes(&mut self, ty: Type) -> Option<Type> { 779 if ty.lane_count() == 1 { 780 None 781 } else { 782 ty.lane_type().by(ty.lane_count() / 2) 783 } 784 } 785 786 #[inline] 787 fn ty_half_width(&mut self, ty: Type) -> Option<Type> { 788 ty.half_width() 789 } 790 791 #[inline] 792 fn ty_equal(&mut self, lhs: Type, rhs: Type) -> bool { 793 lhs == rhs 794 } 795 796 #[inline] 797 fn offset32_to_i32(&mut self, offset: Offset32) -> i32 { 798 offset.into() 799 } 800 801 #[inline] 802 fn i32_to_offset32(&mut self, offset: i32) -> Offset32 { 803 Offset32::new(offset) 804 } 805 806 #[inline] 807 fn mem_flags_trusted(&mut self) -> MemFlags { 808 MemFlags::trusted() 809 } 810 811 #[inline] 812 fn little_or_native_endian(&mut self, flags: MemFlags) -> Option<MemFlags> { 813 match flags.explicit_endianness() { 814 Some(crate::ir::Endianness::Little) | None => Some(flags), 815 Some(crate::ir::Endianness::Big) => None, 816 } 817 } 818 819 #[inline] 820 fn intcc_unsigned(&mut self, x: &IntCC) -> IntCC { 821 x.unsigned() 822 } 823 824 #[inline] 825 fn signed_cond_code(&mut self, cc: &IntCC) -> Option<IntCC> { 826 match cc { 827 IntCC::Equal 828 | IntCC::UnsignedGreaterThanOrEqual 829 | IntCC::UnsignedGreaterThan 830 | IntCC::UnsignedLessThanOrEqual 831 | IntCC::UnsignedLessThan 832 | IntCC::NotEqual => None, 833 IntCC::SignedGreaterThanOrEqual 834 | IntCC::SignedGreaterThan 835 | IntCC::SignedLessThanOrEqual 836 | IntCC::SignedLessThan => Some(*cc), 837 } 838 } 839 840 #[inline] 841 fn intcc_swap_args(&mut self, cc: &IntCC) -> IntCC { 842 cc.swap_args() 843 } 844 845 #[inline] 846 fn intcc_complement(&mut self, cc: &IntCC) -> IntCC { 847 cc.complement() 848 } 849 850 #[inline] 851 fn intcc_without_eq(&mut self, x: &IntCC) -> IntCC { 852 x.without_equal() 853 } 854 855 #[inline] 856 fn floatcc_swap_args(&mut self, cc: &FloatCC) -> FloatCC { 857 cc.swap_args() 858 } 859 860 #[inline] 861 fn floatcc_complement(&mut self, cc: &FloatCC) -> FloatCC { 862 cc.complement() 863 } 864 865 fn floatcc_unordered(&mut self, cc: &FloatCC) -> bool { 866 match *cc { 867 FloatCC::Unordered 868 | FloatCC::UnorderedOrEqual 869 | FloatCC::UnorderedOrLessThan 870 | FloatCC::UnorderedOrLessThanOrEqual 871 | FloatCC::UnorderedOrGreaterThan 872 | FloatCC::UnorderedOrGreaterThanOrEqual => true, 873 _ => false, 874 } 875 } 876 877 #[inline] 878 fn unpack_value_array_2(&mut self, arr: &ValueArray2) -> (Value, Value) { 879 let [a, b] = *arr; 880 (a, b) 881 } 882 883 #[inline] 884 fn pack_value_array_2(&mut self, a: Value, b: Value) -> ValueArray2 { 885 [a, b] 886 } 887 888 #[inline] 889 fn unpack_value_array_3(&mut self, arr: &ValueArray3) -> (Value, Value, Value) { 890 let [a, b, c] = *arr; 891 (a, b, c) 892 } 893 894 #[inline] 895 fn pack_value_array_3(&mut self, a: Value, b: Value, c: Value) -> ValueArray3 { 896 [a, b, c] 897 } 898 899 #[inline] 900 fn unpack_block_array_2(&mut self, arr: &BlockArray2) -> (BlockCall, BlockCall) { 901 let [a, b] = *arr; 902 (a, b) 903 } 904 905 #[inline] 906 fn pack_block_array_2(&mut self, a: BlockCall, b: BlockCall) -> BlockArray2 { 907 [a, b] 908 } 909 910 fn u128_as_u64(&mut self, val: u128) -> Option<u64> { 911 u64::try_from(val).ok() 912 } 913 914 fn u64_as_u32(&mut self, val: u64) -> Option<u32> { 915 u32::try_from(val).ok() 916 } 917 918 fn u32_as_u16(&mut self, val: u32) -> Option<u16> { 919 val.try_into().ok() 920 } 921 922 fn i32_as_i8(&mut self, val: i32) -> Option<i8> { 923 val.try_into().ok() 924 } 925 926 fn u8_as_i8(&mut self, val: u8) -> i8 { 927 val as i8 928 } 929 930 fn u64_as_u8(&mut self, val: u64) -> u8 { 931 val as u8 932 } 933 934 fn u64_as_u16(&mut self, val: u64) -> u16 { 935 val as u16 936 } 937 938 fn u64_as_u16_extractor(&mut self, val: u64) -> Option<u16> { 939 Some(val as u16) 940 } 941 942 fn u8_try_from_u64(&mut self, val: u64) -> Option<u8> { 943 u8::try_from(val).ok() 944 } 945 946 fn u8_try_from_u16(&mut self, val: u16) -> Option<u8> { 947 u8::try_from(val).ok() 948 } 949 950 fn u8_try_from_i32(&mut self, val: i32) -> Option<u8> { 951 u8::try_from(val).ok() 952 } 953 954 fn i32_try_from_i64(&mut self, val: i64) -> Option<i32> { 955 i32::try_from(val).ok() 956 } 957 958 fn u64_try_from_i64(&mut self, val: i64) -> Option<u64> { 959 u64::try_from(val).ok() 960 } 961 962 fn u16_try_from_i32(&mut self, val: i32) -> Option<u16> { 963 u16::try_from(val).ok() 964 } 965 966 fn u16_try_from_u64(&mut self, val: u64) -> Option<u16> { 967 u16::try_from(val).ok() 968 } 969 970 fn u32_try_from_u64(&mut self, val: u64) -> Option<u32> { 971 u32::try_from(val).ok() 972 } 973 974 fn i8_try_from_i32(&mut self, val: i32) -> Option<i8> { 975 i8::try_from(val).ok() 976 } 977 978 fn i8_try_from_i64(&mut self, val: i64) -> Option<i8> { 979 i8::try_from(val).ok() 980 } 981 982 fn i8_try_from_u64(&mut self, val: u64) -> Option<i8> { 983 i8::try_from(val).ok() 984 } 985 986 fn i8_as_u8(&mut self, val: i8) -> u8 { 987 val as u8 988 } 989 990 fn i16_as_u16(&mut self, val: i16) -> u16 { 991 val as u16 992 } 993 994 fn i16_try_from_i32(&mut self, val: i32) -> Option<i16> { 995 i16::try_from(val).ok() 996 } 997 998 fn i16_try_from_u64(&mut self, val: u64) -> Option<i16> { 999 i16::try_from(val).ok() 1000 } 1001 1002 fn i32_try_from_u64(&mut self, val: u64) -> Option<i32> { 1003 i32::try_from(val).ok() 1004 } 1005 1006 fn u128_replicated_u64(&mut self, val: u128) -> Option<u64> { 1007 let low64 = val as u64 as u128; 1008 if (low64 | (low64 << 64)) == val { 1009 Some(low64 as u64) 1010 } else { 1011 None 1012 } 1013 } 1014 1015 fn u64_replicated_u32(&mut self, val: u64) -> Option<u64> { 1016 let low32 = val as u32 as u64; 1017 if (low32 | (low32 << 32)) == val { 1018 Some(low32) 1019 } else { 1020 None 1021 } 1022 } 1023 1024 fn u32_replicated_u16(&mut self, val: u64) -> Option<u64> { 1025 let val = val as u32; 1026 let low16 = val as u16 as u32; 1027 if (low16 | (low16 << 16)) == val { 1028 Some(low16.into()) 1029 } else { 1030 None 1031 } 1032 } 1033 1034 fn u16_replicated_u8(&mut self, val: u64) -> Option<u8> { 1035 let val = val as u16; 1036 let low8 = val as u8 as u16; 1037 if (low8 | (low8 << 8)) == val { 1038 Some(low8 as u8) 1039 } else { 1040 None 1041 } 1042 } 1043 1044 fn u128_low_bits(&mut self, val: u128) -> u64 { 1045 val as u64 1046 } 1047 1048 fn u128_high_bits(&mut self, val: u128) -> u64 { 1049 (val >> 64) as u64 1050 } 1051 1052 fn f16_min(&mut self, a: Ieee16, b: Ieee16) -> Option<Ieee16> { 1053 a.minimum(b).non_nan() 1054 } 1055 1056 fn f16_max(&mut self, a: Ieee16, b: Ieee16) -> Option<Ieee16> { 1057 a.maximum(b).non_nan() 1058 } 1059 1060 fn f16_neg(&mut self, n: Ieee16) -> Ieee16 { 1061 -n 1062 } 1063 1064 fn f16_abs(&mut self, n: Ieee16) -> Ieee16 { 1065 n.abs() 1066 } 1067 1068 fn f16_copysign(&mut self, a: Ieee16, b: Ieee16) -> Ieee16 { 1069 a.copysign(b) 1070 } 1071 1072 fn f32_add(&mut self, lhs: Ieee32, rhs: Ieee32) -> Option<Ieee32> { 1073 (lhs + rhs).non_nan() 1074 } 1075 1076 fn f32_sub(&mut self, lhs: Ieee32, rhs: Ieee32) -> Option<Ieee32> { 1077 (lhs - rhs).non_nan() 1078 } 1079 1080 fn f32_mul(&mut self, lhs: Ieee32, rhs: Ieee32) -> Option<Ieee32> { 1081 (lhs * rhs).non_nan() 1082 } 1083 1084 fn f32_div(&mut self, lhs: Ieee32, rhs: Ieee32) -> Option<Ieee32> { 1085 (lhs / rhs).non_nan() 1086 } 1087 1088 fn f32_sqrt(&mut self, n: Ieee32) -> Option<Ieee32> { 1089 n.sqrt().non_nan() 1090 } 1091 1092 fn f32_ceil(&mut self, n: Ieee32) -> Option<Ieee32> { 1093 n.ceil().non_nan() 1094 } 1095 1096 fn f32_floor(&mut self, n: Ieee32) -> Option<Ieee32> { 1097 n.floor().non_nan() 1098 } 1099 1100 fn f32_trunc(&mut self, n: Ieee32) -> Option<Ieee32> { 1101 n.trunc().non_nan() 1102 } 1103 1104 fn f32_nearest(&mut self, n: Ieee32) -> Option<Ieee32> { 1105 n.round_ties_even().non_nan() 1106 } 1107 1108 fn f32_min(&mut self, a: Ieee32, b: Ieee32) -> Option<Ieee32> { 1109 a.minimum(b).non_nan() 1110 } 1111 1112 fn f32_max(&mut self, a: Ieee32, b: Ieee32) -> Option<Ieee32> { 1113 a.maximum(b).non_nan() 1114 } 1115 1116 fn f32_neg(&mut self, n: Ieee32) -> Ieee32 { 1117 -n 1118 } 1119 1120 fn f32_abs(&mut self, n: Ieee32) -> Ieee32 { 1121 n.abs() 1122 } 1123 1124 fn f32_copysign(&mut self, a: Ieee32, b: Ieee32) -> Ieee32 { 1125 a.copysign(b) 1126 } 1127 1128 fn f64_add(&mut self, lhs: Ieee64, rhs: Ieee64) -> Option<Ieee64> { 1129 (lhs + rhs).non_nan() 1130 } 1131 1132 fn f64_sub(&mut self, lhs: Ieee64, rhs: Ieee64) -> Option<Ieee64> { 1133 (lhs - rhs).non_nan() 1134 } 1135 1136 fn f64_mul(&mut self, lhs: Ieee64, rhs: Ieee64) -> Option<Ieee64> { 1137 (lhs * rhs).non_nan() 1138 } 1139 1140 fn f64_div(&mut self, lhs: Ieee64, rhs: Ieee64) -> Option<Ieee64> { 1141 (lhs / rhs).non_nan() 1142 } 1143 1144 fn f64_sqrt(&mut self, n: Ieee64) -> Option<Ieee64> { 1145 n.sqrt().non_nan() 1146 } 1147 1148 fn f64_ceil(&mut self, n: Ieee64) -> Option<Ieee64> { 1149 n.ceil().non_nan() 1150 } 1151 1152 fn f64_floor(&mut self, n: Ieee64) -> Option<Ieee64> { 1153 n.floor().non_nan() 1154 } 1155 1156 fn f64_trunc(&mut self, n: Ieee64) -> Option<Ieee64> { 1157 n.trunc().non_nan() 1158 } 1159 1160 fn f64_nearest(&mut self, n: Ieee64) -> Option<Ieee64> { 1161 n.round_ties_even().non_nan() 1162 } 1163 1164 fn f64_min(&mut self, a: Ieee64, b: Ieee64) -> Option<Ieee64> { 1165 a.minimum(b).non_nan() 1166 } 1167 1168 fn f64_max(&mut self, a: Ieee64, b: Ieee64) -> Option<Ieee64> { 1169 a.maximum(b).non_nan() 1170 } 1171 1172 fn f64_neg(&mut self, n: Ieee64) -> Ieee64 { 1173 -n 1174 } 1175 1176 fn f64_abs(&mut self, n: Ieee64) -> Ieee64 { 1177 n.abs() 1178 } 1179 1180 fn f64_copysign(&mut self, a: Ieee64, b: Ieee64) -> Ieee64 { 1181 a.copysign(b) 1182 } 1183 1184 fn f128_min(&mut self, a: Ieee128, b: Ieee128) -> Option<Ieee128> { 1185 a.minimum(b).non_nan() 1186 } 1187 1188 fn f128_max(&mut self, a: Ieee128, b: Ieee128) -> Option<Ieee128> { 1189 a.maximum(b).non_nan() 1190 } 1191 1192 fn f128_neg(&mut self, n: Ieee128) -> Ieee128 { 1193 -n 1194 } 1195 1196 fn f128_abs(&mut self, n: Ieee128) -> Ieee128 { 1197 n.abs() 1198 } 1199 1200 fn f128_copysign(&mut self, a: Ieee128, b: Ieee128) -> Ieee128 { 1201 a.copysign(b) 1202 } 1203 1204 #[inline] 1205 fn def_inst(&mut self, val: Value) -> Option<Inst> { 1206 self.dfg().value_def(val).inst() 1207 } 1208 }; 1209 } 1210