@@ -19,7 +19,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
1919use rustc_middle:: ty:: { self , Ty } ;
2020use rustc_middle:: { bug, span_bug} ;
2121use rustc_span:: { sym, symbol:: kw, Span , Symbol } ;
22- use rustc_target:: abi:: { self , HasDataLayout , Primitive } ;
22+ use rustc_target:: abi:: { self , Align , HasDataLayout , Primitive } ;
2323use rustc_target:: spec:: { HasTargetSpec , PanicStrategy } ;
2424
2525use std:: cmp:: Ordering ;
@@ -1056,16 +1056,13 @@ fn generic_simd_intrinsic(
10561056
10571057 if name == sym:: simd_bitmask {
10581058 // The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a
1059- // vector mask and returns an unsigned integer containing the most
1060- // significant bit (MSB) of each lane.
1061-
1062- // If the vector has less than 8 lanes, a u8 is returned with zeroed
1063- // trailing bits.
1059+ // vector mask and returns the most significant bit (MSB) of each lane in the form
1060+ // of either:
1061+ // * an unsigned integer
1062+ // * an array of `u8`
1063+ // If the vector has less than 8 lanes, a u8 is returned with zeroed trailing bits.
10641064 let expected_int_bits = in_len. max ( 8 ) ;
1065- match ret_ty. kind ( ) {
1066- ty:: Uint ( i) if i. bit_width ( ) == Some ( expected_int_bits) => ( ) ,
1067- _ => return_error ! ( "bitmask `{}`, expected `u{}`" , ret_ty, expected_int_bits) ,
1068- }
1065+ let expected_bytes = expected_int_bits / 8 + ( ( expected_int_bits % 8 > 1 ) as u64 ) ;
10691066
10701067 // Integer vector <i{in_bitwidth} x in_len>:
10711068 let ( i_xn, in_elem_bitwidth) = match in_elem. kind ( ) {
@@ -1095,8 +1092,34 @@ fn generic_simd_intrinsic(
10951092 let i1xn = bx. trunc ( i_xn_msb, bx. type_vector ( bx. type_i1 ( ) , in_len) ) ;
10961093 // Bitcast <i1 x N> to iN:
10971094 let i_ = bx. bitcast ( i1xn, bx. type_ix ( in_len) ) ;
1098- // Zero-extend iN to the bitmask type:
1099- return Ok ( bx. zext ( i_, bx. type_ix ( expected_int_bits) ) ) ;
1095+
1096+ match ret_ty. kind ( ) {
1097+ ty:: Uint ( i) if i. bit_width ( ) == Some ( expected_int_bits) => {
1098+ // Zero-extend iN to the bitmask type:
1099+ return Ok ( bx. zext ( i_, bx. type_ix ( expected_int_bits) ) ) ;
1100+ }
1101+ ty:: Array ( elem, len)
1102+ if matches ! ( elem. kind( ) , ty:: Uint ( ty:: UintTy :: U8 ) )
1103+ && len. try_eval_usize ( bx. tcx , ty:: ParamEnv :: reveal_all ( ) )
1104+ == Some ( expected_bytes) =>
1105+ {
1106+ // Zero-extend iN to the array lengh:
1107+ let ze = bx. zext ( i_, bx. type_ix ( expected_bytes * 8 ) ) ;
1108+
1109+ // Convert the integer to a byte array
1110+ let ptr = bx. alloca ( bx. type_ix ( expected_bytes * 8 ) , Align :: ONE ) ;
1111+ bx. store ( ze, ptr, Align :: ONE ) ;
1112+ let array_ty = bx. type_array ( bx. type_i8 ( ) , expected_bytes) ;
1113+ let ptr = bx. pointercast ( ptr, bx. cx . type_ptr_to ( array_ty) ) ;
1114+ return Ok ( bx. load ( array_ty, ptr, Align :: ONE ) ) ;
1115+ }
1116+ _ => return_error ! (
1117+ "cannot return `{}`, expected `u{}` or `[u8; {}]`" ,
1118+ ret_ty,
1119+ expected_int_bits,
1120+ expected_bytes
1121+ ) ,
1122+ }
11001123 }
11011124
11021125 fn simd_simple_float_intrinsic (
0 commit comments