@@ -3,7 +3,7 @@ use std::iter;
3
3
use log:: trace;
4
4
5
5
use rustc_apfloat:: { Float , Round } ;
6
- use rustc_middle:: ty:: layout:: { IntegerExt , LayoutOf } ;
6
+ use rustc_middle:: ty:: layout:: { HasParamEnv , IntegerExt , LayoutOf } ;
7
7
use rustc_middle:: { mir, mir:: BinOp , ty, ty:: FloatTy } ;
8
8
use rustc_target:: abi:: { Align , Integer } ;
9
9
@@ -570,8 +570,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
570
570
let no = this. read_immediate ( & this. mplace_index ( & no, i) ?. into ( ) ) ?;
571
571
let dest = this. mplace_index ( & dest, i) ?;
572
572
573
- let mask = simd_element_to_bool ( mask) ?;
574
- let val = if mask { yes } else { no } ;
573
+ let val = if simd_element_to_bool ( mask) ? { yes } else { no } ;
575
574
this. write_immediate ( * val, & dest. into ( ) ) ?;
576
575
}
577
576
}
@@ -614,6 +613,91 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
614
613
this. write_immediate ( val, & dest. into ( ) ) ?;
615
614
}
616
615
}
616
+ "simd_shuffle" => {
617
+ let & [ ref left, ref right, ref index] = check_arg_count ( args) ?;
618
+ let ( left, left_len) = this. operand_to_simd ( left) ?;
619
+ let ( right, right_len) = this. operand_to_simd ( right) ?;
620
+ let ( dest, dest_len) = this. place_to_simd ( dest) ?;
621
+
622
+ // `index` is an array, not a SIMD type
623
+ let ty:: Array ( _, index_len) = index. layout . ty . kind ( ) else {
624
+ bug ! ( "simd_shuffle index argument has non-array type {}" , index. layout. ty)
625
+ } ;
626
+ let index_len = index_len. eval_usize ( * this. tcx , this. param_env ( ) ) ;
627
+
628
+ assert_eq ! ( left_len, right_len) ;
629
+ assert_eq ! ( index_len, dest_len) ;
630
+
631
+ for i in 0 ..dest_len {
632
+ let src_index: u64 = this
633
+ . read_immediate ( & this. operand_index ( & index, i) ?. into ( ) ) ?
634
+ . to_scalar ( ) ?
635
+ . to_u32 ( ) ?
636
+ . into ( ) ;
637
+ let dest = this. mplace_index ( & dest, i) ?;
638
+
639
+ let val = if src_index < left_len {
640
+ this. read_immediate ( & this. mplace_index ( & left, src_index) ?. into ( ) ) ?
641
+ } else if src_index < left_len. checked_add ( right_len) . unwrap ( ) {
642
+ this. read_immediate (
643
+ & this. mplace_index ( & right, src_index - left_len) ?. into ( ) ,
644
+ ) ?
645
+ } else {
646
+ bug ! (
647
+ "simd_shuffle index {} is out of bounds for 2 vectors of size {}" ,
648
+ src_index,
649
+ left_len
650
+ ) ;
651
+ } ;
652
+ this. write_immediate ( * val, & dest. into ( ) ) ?;
653
+ }
654
+ }
655
+ "simd_gather" => {
656
+ let & [ ref passthru, ref ptrs, ref mask] = check_arg_count ( args) ?;
657
+ let ( passthru, passthru_len) = this. operand_to_simd ( passthru) ?;
658
+ let ( ptrs, ptrs_len) = this. operand_to_simd ( ptrs) ?;
659
+ let ( mask, mask_len) = this. operand_to_simd ( mask) ?;
660
+ let ( dest, dest_len) = this. place_to_simd ( dest) ?;
661
+
662
+ assert_eq ! ( dest_len, passthru_len) ;
663
+ assert_eq ! ( dest_len, ptrs_len) ;
664
+ assert_eq ! ( dest_len, mask_len) ;
665
+
666
+ for i in 0 ..dest_len {
667
+ let passthru = this. read_immediate ( & this. mplace_index ( & passthru, i) ?. into ( ) ) ?;
668
+ let ptr = this. read_immediate ( & this. mplace_index ( & ptrs, i) ?. into ( ) ) ?;
669
+ let mask = this. read_immediate ( & this. mplace_index ( & mask, i) ?. into ( ) ) ?;
670
+ let dest = this. mplace_index ( & dest, i) ?;
671
+
672
+ let val = if simd_element_to_bool ( mask) ? {
673
+ let place = this. deref_operand ( & ptr. into ( ) ) ?;
674
+ this. read_immediate ( & place. into ( ) ) ?
675
+ } else {
676
+ passthru
677
+ } ;
678
+ this. write_immediate ( * val, & dest. into ( ) ) ?;
679
+ }
680
+ }
681
+ "simd_scatter" => {
682
+ let & [ ref value, ref ptrs, ref mask] = check_arg_count ( args) ?;
683
+ let ( value, value_len) = this. operand_to_simd ( value) ?;
684
+ let ( ptrs, ptrs_len) = this. operand_to_simd ( ptrs) ?;
685
+ let ( mask, mask_len) = this. operand_to_simd ( mask) ?;
686
+
687
+ assert_eq ! ( ptrs_len, value_len) ;
688
+ assert_eq ! ( ptrs_len, mask_len) ;
689
+
690
+ for i in 0 ..ptrs_len {
691
+ let value = this. read_immediate ( & this. mplace_index ( & value, i) ?. into ( ) ) ?;
692
+ let ptr = this. read_immediate ( & this. mplace_index ( & ptrs, i) ?. into ( ) ) ?;
693
+ let mask = this. read_immediate ( & this. mplace_index ( & mask, i) ?. into ( ) ) ?;
694
+
695
+ if simd_element_to_bool ( mask) ? {
696
+ let place = this. deref_operand ( & ptr. into ( ) ) ?;
697
+ this. write_immediate ( * value, & place. into ( ) ) ?;
698
+ }
699
+ }
700
+ }
617
701
618
702
// Atomic operations
619
703
"atomic_load" => this. atomic_load ( args, dest, AtomicReadOp :: SeqCst ) ?,
0 commit comments