Skip to content

Commit bc69ac6

Browse files
committed
support array return types in simb_bitmask
1 parent b3ed052 commit bc69ac6

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

src/shims/intrinsics/simd.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
563563
let (op, op_len) = this.operand_to_simd(op)?;
564564
let bitmask_len = op_len.max(8);
565565

566-
assert!(dest.layout.ty.is_integral());
566+
// Returns either an unsigned integer or array of `u8`.
567+
assert!(
568+
dest.layout.ty.is_integral()
569+
|| matches!(dest.layout.ty.kind(), ty::Array(elemty, _) if elemty == &this.tcx.types.u8)
570+
);
567571
assert!(bitmask_len <= 64);
568572
assert_eq!(bitmask_len, dest.layout.size.bits());
569573
let op_len = u32::try_from(op_len).unwrap();
@@ -577,7 +581,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
577581
.unwrap();
578582
}
579583
}
580-
this.write_int(res, dest)?;
584+
// We have to force the place type to be an int so that we can write `res` into it.
585+
let mut dest = this.force_allocation(dest)?;
586+
dest.layout = this.machine.layouts.uint(dest.layout.size).unwrap();
587+
this.write_int(res, &dest.into())?;
581588
}
582589

583590
name => throw_unsup_format!("unimplemented intrinsic: `simd_{name}`"),

tests/pass/portable-simd.rs

+31
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
#![feature(portable_simd, platform_intrinsics)]
33
use std::simd::*;
44

5+
extern "platform-intrinsic" {
6+
pub(crate) fn simd_bitmask<T, U>(x: T) -> U;
7+
}
8+
59
fn simd_ops_f32() {
610
let a = f32x4::splat(10.0);
711
let b = f32x4::from_array([1.0, 2.0, 3.0, -4.0]);
@@ -208,11 +212,38 @@ fn simd_mask() {
208212
assert_eq!(bitmask, 0b1010001101001001);
209213
assert_eq!(Mask::<i64, 16>::from_bitmask(bitmask), mask);
210214

215+
// Also directly call intrinsic, to test both kinds of return types.
216+
unsafe {
217+
let bitmask1: u16 = simd_bitmask(mask.to_int());
218+
let bitmask2: [u8; 2] = simd_bitmask(mask.to_int());
219+
if cfg!(target_endian = "little") {
220+
assert_eq!(bitmask1, 0b1010001101001001);
221+
assert_eq!(bitmask2, [0b01001001, 0b10100011]);
222+
} else {
223+
assert_eq!(bitmask1, 0b1001001011000101);
224+
assert_eq!(bitmask2, [0b10010010, 0b11000101]);
225+
}
226+
}
227+
228+
// Mask less than 8 bits long, which is a special case (padding with 0s).
211229
let values = [false, false, false, true];
212230
let mask = Mask::<i64, 4>::from_array(values);
213231
let bitmask = mask.to_bitmask();
214232
assert_eq!(bitmask, 0b1000);
215233
assert_eq!(Mask::<i64, 4>::from_bitmask(bitmask), mask);
234+
235+
// Also directly call intrinsic, to test both kinds of return types.
236+
unsafe {
237+
let bitmask1: u8 = simd_bitmask(mask.to_int());
238+
let bitmask2: [u8; 1] = simd_bitmask(mask.to_int());
239+
if cfg!(target_endian = "little") {
240+
assert_eq!(bitmask1, 0b1000);
241+
assert_eq!(bitmask2, [0b1000]);
242+
} else {
243+
assert_eq!(bitmask1, 0b0001);
244+
assert_eq!(bitmask2, [0b0001]);
245+
}
246+
}
216247
}
217248

218249
fn simd_cast() {

0 commit comments

Comments
 (0)