@@ -15,7 +15,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
15
15
use rustc_codegen_ssa:: traits:: * ;
16
16
use rustc_hir as hir;
17
17
use rustc_middle:: ty:: layout:: { FnAbiOf , HasTyCtxt , LayoutOf } ;
18
- use rustc_middle:: ty:: { self , Ty } ;
18
+ use rustc_middle:: ty:: { self , GenericArgsRef , Ty } ;
19
19
use rustc_middle:: { bug, span_bug} ;
20
20
use rustc_span:: { sym, symbol:: kw, Span , Symbol } ;
21
21
use rustc_target:: abi:: { self , Align , HasDataLayout , Primitive } ;
@@ -376,7 +376,9 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
376
376
}
377
377
378
378
_ 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
+ ) {
380
382
Ok ( llval) => llval,
381
383
Err ( ( ) ) => return ,
382
384
}
@@ -911,6 +913,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
911
913
bx : & mut Builder < ' _ , ' ll , ' tcx > ,
912
914
name : Symbol ,
913
915
callee_ty : Ty < ' tcx > ,
916
+ fn_args : GenericArgsRef < ' tcx > ,
914
917
args : & [ OperandRef < ' tcx , & ' ll Value > ] ,
915
918
ret_ty : Ty < ' tcx > ,
916
919
llret_ty : & ' ll Type ,
@@ -1030,6 +1033,56 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
1030
1033
) ) ;
1031
1034
}
1032
1035
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
+
1033
1086
if name == sym:: simd_shuffle {
1034
1087
// Make sure this is actually an array, since typeck only checks the length-suffixed
1035
1088
// version of this intrinsic.
0 commit comments