Document safety conditions of simd shifts
This commit is contained in:
parent
28580edab8
commit
267558c5c2
1 changed files with 40 additions and 0 deletions
|
|
@ -2318,6 +2318,24 @@ pub fn u8x16_narrow_i16x8(a: v128, b: v128) -> v128 {
|
|||
#[doc(alias("i8x16.shl"))]
|
||||
#[stable(feature = "wasm_simd", since = "1.54.0")]
|
||||
pub fn i8x16_shl(a: v128, amt: u32) -> v128 {
|
||||
// SAFETY: the safety of this intrinsic relies on the fact that the
|
||||
// shift amount for each lane is less than the number of bits in the input
|
||||
// lane. In this case the input has 8-bit lanes but the shift amount above
|
||||
// is `u32`, so a mask is required to discard all the upper bits of `amt` to
|
||||
// ensure that the safety condition is met.
|
||||
//
|
||||
// Note that this is distinct from the behavior of the native WebAssembly
|
||||
// instruction here where WebAssembly defines this instruction as performing
|
||||
// a mask as well. This is nonetheless required since this must have defined
|
||||
// semantics in LLVM, not just WebAssembly.
|
||||
//
|
||||
// Finally note that this mask operation is not actually emitted into the
|
||||
// final binary itself. LLVM understands that the wasm operation implicitly
|
||||
// masks, so it knows this mask operation is redundant.
|
||||
//
|
||||
// Basically the extra mask here is required as a bridge from the documented
|
||||
// semantics through LLVM back out to WebAssembly. Both ends have the
|
||||
// documented semantics, and the mask is required by LLVM in the middle.
|
||||
unsafe { simd_shl(a.as_i8x16(), simd::i8x16::splat((amt & 0x7) as i8)).v128() }
|
||||
}
|
||||
|
||||
|
|
@ -2335,6 +2353,8 @@ pub use i8x16_shl as u8x16_shl;
|
|||
#[doc(alias("i8x16.shr_s"))]
|
||||
#[stable(feature = "wasm_simd", since = "1.54.0")]
|
||||
pub fn i8x16_shr(a: v128, amt: u32) -> v128 {
|
||||
// SAFETY: see i8x16_shl for more documentation why this is unsafe,
|
||||
// essentially the shift amount must be valid hence the mask.
|
||||
unsafe { simd_shr(a.as_i8x16(), simd::i8x16::splat((amt & 0x7) as i8)).v128() }
|
||||
}
|
||||
|
||||
|
|
@ -2349,6 +2369,8 @@ pub fn i8x16_shr(a: v128, amt: u32) -> v128 {
|
|||
#[doc(alias("i8x16.shr_u"))]
|
||||
#[stable(feature = "wasm_simd", since = "1.54.0")]
|
||||
pub fn u8x16_shr(a: v128, amt: u32) -> v128 {
|
||||
// SAFETY: see i8x16_shl for more documentation why this is unsafe,
|
||||
// essentially the shift amount must be valid hence the mask.
|
||||
unsafe { simd_shr(a.as_u8x16(), simd::u8x16::splat((amt & 0x7) as u8)).v128() }
|
||||
}
|
||||
|
||||
|
|
@ -2686,6 +2708,8 @@ pub use i16x8_extend_high_u8x16 as u16x8_extend_high_u8x16;
|
|||
#[doc(alias("i16x8.shl"))]
|
||||
#[stable(feature = "wasm_simd", since = "1.54.0")]
|
||||
pub fn i16x8_shl(a: v128, amt: u32) -> v128 {
|
||||
// SAFETY: see i8x16_shl for more documentation why this is unsafe,
|
||||
// essentially the shift amount must be valid hence the mask.
|
||||
unsafe { simd_shl(a.as_i16x8(), simd::i16x8::splat((amt & 0xf) as i16)).v128() }
|
||||
}
|
||||
|
||||
|
|
@ -2703,6 +2727,8 @@ pub use i16x8_shl as u16x8_shl;
|
|||
#[doc(alias("i16x8.shr_s"))]
|
||||
#[stable(feature = "wasm_simd", since = "1.54.0")]
|
||||
pub fn i16x8_shr(a: v128, amt: u32) -> v128 {
|
||||
// SAFETY: see i8x16_shl for more documentation why this is unsafe,
|
||||
// essentially the shift amount must be valid hence the mask.
|
||||
unsafe { simd_shr(a.as_i16x8(), simd::i16x8::splat((amt & 0xf) as i16)).v128() }
|
||||
}
|
||||
|
||||
|
|
@ -2717,6 +2743,8 @@ pub fn i16x8_shr(a: v128, amt: u32) -> v128 {
|
|||
#[doc(alias("i16x8.shr_u"))]
|
||||
#[stable(feature = "wasm_simd", since = "1.54.0")]
|
||||
pub fn u16x8_shr(a: v128, amt: u32) -> v128 {
|
||||
// SAFETY: see i8x16_shl for more documentation why this is unsafe,
|
||||
// essentially the shift amount must be valid hence the mask.
|
||||
unsafe { simd_shr(a.as_u16x8(), simd::u16x8::splat((amt & 0xf) as u16)).v128() }
|
||||
}
|
||||
|
||||
|
|
@ -3136,6 +3164,8 @@ pub use i32x4_extend_high_u16x8 as u32x4_extend_high_u16x8;
|
|||
#[doc(alias("i32x4.shl"))]
|
||||
#[stable(feature = "wasm_simd", since = "1.54.0")]
|
||||
pub fn i32x4_shl(a: v128, amt: u32) -> v128 {
|
||||
// SAFETY: see i8x16_shl for more documentation why this is unsafe,
|
||||
// essentially the shift amount must be valid hence the mask.
|
||||
unsafe { simd_shl(a.as_i32x4(), simd::i32x4::splat((amt & 0x1f) as i32)).v128() }
|
||||
}
|
||||
|
||||
|
|
@ -3153,6 +3183,8 @@ pub use i32x4_shl as u32x4_shl;
|
|||
#[doc(alias("i32x4.shr_s"))]
|
||||
#[stable(feature = "wasm_simd", since = "1.54.0")]
|
||||
pub fn i32x4_shr(a: v128, amt: u32) -> v128 {
|
||||
// SAFETY: see i8x16_shl for more documentation why this is unsafe,
|
||||
// essentially the shift amount must be valid hence the mask.
|
||||
unsafe { simd_shr(a.as_i32x4(), simd::i32x4::splat((amt & 0x1f) as i32)).v128() }
|
||||
}
|
||||
|
||||
|
|
@ -3167,6 +3199,8 @@ pub fn i32x4_shr(a: v128, amt: u32) -> v128 {
|
|||
#[doc(alias("i32x4.shr_u"))]
|
||||
#[stable(feature = "wasm_simd", since = "1.54.0")]
|
||||
pub fn u32x4_shr(a: v128, amt: u32) -> v128 {
|
||||
// SAFETY: see i8x16_shl for more documentation why this is unsafe,
|
||||
// essentially the shift amount must be valid hence the mask.
|
||||
unsafe { simd_shr(a.as_u32x4(), simd::u32x4::splat(amt & 0x1f)).v128() }
|
||||
}
|
||||
|
||||
|
|
@ -3502,6 +3536,8 @@ pub use i64x2_extend_high_u32x4 as u64x2_extend_high_u32x4;
|
|||
#[doc(alias("i64x2.shl"))]
|
||||
#[stable(feature = "wasm_simd", since = "1.54.0")]
|
||||
pub fn i64x2_shl(a: v128, amt: u32) -> v128 {
|
||||
// SAFETY: see i8x16_shl for more documentation why this is unsafe,
|
||||
// essentially the shift amount must be valid hence the mask.
|
||||
unsafe { simd_shl(a.as_i64x2(), simd::i64x2::splat((amt & 0x3f) as i64)).v128() }
|
||||
}
|
||||
|
||||
|
|
@ -3519,6 +3555,8 @@ pub use i64x2_shl as u64x2_shl;
|
|||
#[doc(alias("i64x2.shr_s"))]
|
||||
#[stable(feature = "wasm_simd", since = "1.54.0")]
|
||||
pub fn i64x2_shr(a: v128, amt: u32) -> v128 {
|
||||
// SAFETY: see i8x16_shl for more documentation why this is unsafe,
|
||||
// essentially the shift amount must be valid hence the mask.
|
||||
unsafe { simd_shr(a.as_i64x2(), simd::i64x2::splat((amt & 0x3f) as i64)).v128() }
|
||||
}
|
||||
|
||||
|
|
@ -3533,6 +3571,8 @@ pub fn i64x2_shr(a: v128, amt: u32) -> v128 {
|
|||
#[doc(alias("i64x2.shr_u"))]
|
||||
#[stable(feature = "wasm_simd", since = "1.54.0")]
|
||||
pub fn u64x2_shr(a: v128, amt: u32) -> v128 {
|
||||
// SAFETY: see i8x16_shl for more documentation why this is unsafe,
|
||||
// essentially the shift amount must be valid hence the mask.
|
||||
unsafe { simd_shr(a.as_u64x2(), simd::u64x2::splat((amt & 0x3f) as u64)).v128() }
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue