@@ -15,7 +15,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
1515use rustc_codegen_ssa:: traits:: * ;
1616use rustc_hir as hir;
1717use rustc_middle:: ty:: layout:: { FnAbiOf , HasTyCtxt , LayoutOf } ;
18- use rustc_middle:: ty:: { self , Ty } ;
18+ use rustc_middle:: ty:: { self , GenericArgsRef , Ty } ;
1919use rustc_middle:: { bug, span_bug} ;
2020use rustc_span:: { sym, symbol:: kw, Span , Symbol } ;
2121use rustc_target:: abi:: { self , Align , HasDataLayout , Primitive } ;
@@ -376,7 +376,9 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
376376 }
377377
378378 _ if name. as_str ( ) . starts_with ( "simd_" ) => {
379- match generic_simd_intrinsic ( self , name, callee_ty, args, ret_ty, llret_ty, span) {
379+ match generic_simd_intrinsic (
380+ self , name, callee_ty, fn_args, args, ret_ty, llret_ty, span,
381+ ) {
380382 Ok ( llval) => llval,
381383 Err ( ( ) ) => return ,
382384 }
@@ -911,6 +913,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
911913 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
912914 name : Symbol ,
913915 callee_ty : Ty < ' tcx > ,
916+ fn_args : GenericArgsRef < ' tcx > ,
914917 args : & [ OperandRef < ' tcx , & ' ll Value > ] ,
915918 ret_ty : Ty < ' tcx > ,
916919 llret_ty : & ' ll Type ,
@@ -1030,6 +1033,56 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
10301033 ) ) ;
10311034 }
10321035
1036+ if name == sym:: simd_shuffle_generic {
1037+ let idx = fn_args[ 2 ]
1038+ . expect_const ( )
1039+ . eval ( tcx, ty:: ParamEnv :: reveal_all ( ) , Some ( span) )
1040+ . unwrap ( )
1041+ . unwrap_branch ( ) ;
1042+ let n = idx. len ( ) as u64 ;
1043+
1044+ require_simd ! ( ret_ty, InvalidMonomorphization :: SimdReturn { span, name, ty: ret_ty } ) ;
1045+ let ( out_len, out_ty) = ret_ty. simd_size_and_type ( bx. tcx ( ) ) ;
1046+ require ! (
1047+ out_len == n,
1048+ InvalidMonomorphization :: ReturnLength { span, name, in_len: n, ret_ty, out_len }
1049+ ) ;
1050+ require ! (
1051+ in_elem == out_ty,
1052+ InvalidMonomorphization :: ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty }
1053+ ) ;
1054+
1055+ let total_len = in_len * 2 ;
1056+
1057+ let indices: Option < Vec < _ > > = idx
1058+ . iter ( )
1059+ . enumerate ( )
1060+ . map ( |( arg_idx, val) | {
1061+ let idx = val. unwrap_leaf ( ) . try_to_i32 ( ) . unwrap ( ) ;
1062+ if idx >= i32:: try_from ( total_len) . unwrap ( ) {
1063+ bx. sess ( ) . emit_err ( InvalidMonomorphization :: ShuffleIndexOutOfBounds {
1064+ span,
1065+ name,
1066+ arg_idx : arg_idx as u64 ,
1067+ total_len : total_len. into ( ) ,
1068+ } ) ;
1069+ None
1070+ } else {
1071+ Some ( bx. const_i32 ( idx) )
1072+ }
1073+ } )
1074+ . collect ( ) ;
1075+ let Some ( indices) = indices else {
1076+ return Ok ( bx. const_null ( llret_ty) ) ;
1077+ } ;
1078+
1079+ return Ok ( bx. shuffle_vector (
1080+ args[ 0 ] . immediate ( ) ,
1081+ args[ 1 ] . immediate ( ) ,
1082+ bx. const_vector ( & indices) ,
1083+ ) ) ;
1084+ }
1085+
10331086 if name == sym:: simd_shuffle {
10341087 // Make sure this is actually an array, since typeck only checks the length-suffixed
10351088 // version of this intrinsic.
0 commit comments