@@ -12,6 +12,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
1212 fn emulate_simd_intrinsic (
1313 & mut self ,
1414 intrinsic_name : & str ,
15+ generic_args : ty:: GenericArgsRef < ' tcx > ,
1516 args : & [ OpTy < ' tcx , Provenance > ] ,
1617 dest : & PlaceTy < ' tcx , Provenance > ,
1718 ) -> InterpResult < ' tcx > {
@@ -490,6 +491,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
490491 this. write_immediate ( val, & dest) ?;
491492 }
492493 }
494+ "shuffle_generic" => {
495+ let [ left, right] = check_arg_count ( args) ?;
496+ let ( left, left_len) = this. operand_to_simd ( left) ?;
497+ let ( right, right_len) = this. operand_to_simd ( right) ?;
498+ let ( dest, dest_len) = this. place_to_simd ( dest) ?;
499+
500+ let index = generic_args[ 2 ] . expect_const ( ) . eval ( * this. tcx , this. param_env ( ) , Some ( this. tcx . span ) ) . unwrap ( ) . unwrap_branch ( ) ;
501+ let index_len = index. len ( ) ;
502+
503+ assert_eq ! ( left_len, right_len) ;
504+ assert_eq ! ( index_len as u64 , dest_len) ;
505+
506+ for i in 0 ..dest_len {
507+ let src_index: u64 = index[ i as usize ] . unwrap_leaf ( )
508+ . try_to_u32 ( ) . unwrap ( )
509+ . into ( ) ;
510+ let dest = this. project_index ( & dest, i) ?;
511+
512+ let val = if src_index < left_len {
513+ this. read_immediate ( & this. project_index ( & left, src_index) ?) ?
514+ } else if src_index < left_len. checked_add ( right_len) . unwrap ( ) {
515+ let right_idx = src_index. checked_sub ( left_len) . unwrap ( ) ;
516+ this. read_immediate ( & this. project_index ( & right, right_idx) ?) ?
517+ } else {
518+ span_bug ! (
519+ this. cur_span( ) ,
520+ "simd_shuffle index {src_index} is out of bounds for 2 vectors of size {left_len}" ,
521+ ) ;
522+ } ;
523+ this. write_immediate ( * val, & dest) ?;
524+ }
525+ }
493526 "shuffle" => {
494527 let [ left, right, index] = check_arg_count ( args) ?;
495528 let ( left, left_len) = this. operand_to_simd ( left) ?;
0 commit comments