@@ -19,7 +19,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
19
19
use rustc_middle:: ty:: { self , Ty } ;
20
20
use rustc_middle:: { bug, span_bug} ;
21
21
use rustc_span:: { sym, symbol:: kw, Span , Symbol } ;
22
- use rustc_target:: abi:: { self , HasDataLayout , Primitive } ;
22
+ use rustc_target:: abi:: { self , Align , HasDataLayout , Primitive } ;
23
23
use rustc_target:: spec:: { HasTargetSpec , PanicStrategy } ;
24
24
25
25
use std:: cmp:: Ordering ;
@@ -1056,16 +1056,13 @@ fn generic_simd_intrinsic(
1056
1056
1057
1057
if name == sym:: simd_bitmask {
1058
1058
// 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.
1064
1064
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 ) ;
1069
1066
1070
1067
// Integer vector <i{in_bitwidth} x in_len>:
1071
1068
let ( i_xn, in_elem_bitwidth) = match in_elem. kind ( ) {
@@ -1095,8 +1092,34 @@ fn generic_simd_intrinsic(
1095
1092
let i1xn = bx. trunc ( i_xn_msb, bx. type_vector ( bx. type_i1 ( ) , in_len) ) ;
1096
1093
// Bitcast <i1 x N> to iN:
1097
1094
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
+ }
1100
1123
}
1101
1124
1102
1125
fn simd_simple_float_intrinsic (
0 commit comments