@@ -2318,6 +2318,24 @@ pub fn u8x16_narrow_i16x8(a: v128, b: v128) -> v128 {
23182318#[ doc( alias( "i8x16.shl" ) ) ]
23192319#[ stable( feature = "wasm_simd" , since = "1.54.0" ) ]
23202320pub fn i8x16_shl ( a : v128 , amt : u32 ) -> v128 {
2321+ // SAFETY: the safety of this intrinsic relies on the fact that the
2322+ // shift amount for each lane is less than the number of bits in the input
2323+ // lane. In this case the input has 8-bit lanes but the shift amount above
2324+ // is `u32`, so a mask is required to discard all the upper bits of `amt` to
2325+ // ensure that the safety condition is met.
2326+ //
2327+ // Note that this is distinct from the behavior of the native WebAssembly
2328+ // instruction here where WebAssembly defines this instruction as performing
2329+ // a mask as well. This is nonetheless required since this must have defined
2330+ // semantics in LLVM, not just WebAssembly.
2331+ //
2332+ // Finally note that this mask operation is not actually emitted into the
2333+ // final binary itself. LLVM understands that the wasm operation implicitly
2334+ // masks, so it knows this mask operation is redundant.
2335+ //
2336+ // Basically the extra mask here is required as a bridge from the documented
2337+ // semantics through LLVM back out to WebAssembly. Both ends have the
2338+ // documented semantics, and the mask is required by LLVM in the middle.
23212339 unsafe { simd_shl ( a. as_i8x16 ( ) , simd:: i8x16:: splat ( ( amt & 0x7 ) as i8 ) ) . v128 ( ) }
23222340}
23232341
@@ -2335,6 +2353,8 @@ pub use i8x16_shl as u8x16_shl;
23352353#[ doc( alias( "i8x16.shr_s" ) ) ]
23362354#[ stable( feature = "wasm_simd" , since = "1.54.0" ) ]
23372355pub fn i8x16_shr ( a : v128 , amt : u32 ) -> v128 {
2356+ // SAFETY: see i8x16_shl for more documentation why this is unsafe,
2357+ // essentially the shift amount must be valid hence the mask.
23382358 unsafe { simd_shr ( a. as_i8x16 ( ) , simd:: i8x16:: splat ( ( amt & 0x7 ) as i8 ) ) . v128 ( ) }
23392359}
23402360
@@ -2349,6 +2369,8 @@ pub fn i8x16_shr(a: v128, amt: u32) -> v128 {
23492369#[ doc( alias( "i8x16.shr_u" ) ) ]
23502370#[ stable( feature = "wasm_simd" , since = "1.54.0" ) ]
23512371pub fn u8x16_shr ( a : v128 , amt : u32 ) -> v128 {
2372+ // SAFETY: see i8x16_shl for more documentation why this is unsafe,
2373+ // essentially the shift amount must be valid hence the mask.
23522374 unsafe { simd_shr ( a. as_u8x16 ( ) , simd:: u8x16:: splat ( ( amt & 0x7 ) as u8 ) ) . v128 ( ) }
23532375}
23542376
@@ -2686,6 +2708,8 @@ pub use i16x8_extend_high_u8x16 as u16x8_extend_high_u8x16;
26862708#[ doc( alias( "i16x8.shl" ) ) ]
26872709#[ stable( feature = "wasm_simd" , since = "1.54.0" ) ]
26882710pub fn i16x8_shl ( a : v128 , amt : u32 ) -> v128 {
2711+ // SAFETY: see i8x16_shl for more documentation why this is unsafe,
2712+ // essentially the shift amount must be valid hence the mask.
26892713 unsafe { simd_shl ( a. as_i16x8 ( ) , simd:: i16x8:: splat ( ( amt & 0xf ) as i16 ) ) . v128 ( ) }
26902714}
26912715
@@ -2703,6 +2727,8 @@ pub use i16x8_shl as u16x8_shl;
27032727#[ doc( alias( "i16x8.shr_s" ) ) ]
27042728#[ stable( feature = "wasm_simd" , since = "1.54.0" ) ]
27052729pub fn i16x8_shr ( a : v128 , amt : u32 ) -> v128 {
2730+ // SAFETY: see i8x16_shl for more documentation why this is unsafe,
2731+ // essentially the shift amount must be valid hence the mask.
27062732 unsafe { simd_shr ( a. as_i16x8 ( ) , simd:: i16x8:: splat ( ( amt & 0xf ) as i16 ) ) . v128 ( ) }
27072733}
27082734
@@ -2717,6 +2743,8 @@ pub fn i16x8_shr(a: v128, amt: u32) -> v128 {
27172743#[ doc( alias( "i16x8.shr_u" ) ) ]
27182744#[ stable( feature = "wasm_simd" , since = "1.54.0" ) ]
27192745pub fn u16x8_shr ( a : v128 , amt : u32 ) -> v128 {
2746+ // SAFETY: see i8x16_shl for more documentation why this is unsafe,
2747+ // essentially the shift amount must be valid hence the mask.
27202748 unsafe { simd_shr ( a. as_u16x8 ( ) , simd:: u16x8:: splat ( ( amt & 0xf ) as u16 ) ) . v128 ( ) }
27212749}
27222750
@@ -3136,6 +3164,8 @@ pub use i32x4_extend_high_u16x8 as u32x4_extend_high_u16x8;
31363164#[ doc( alias( "i32x4.shl" ) ) ]
31373165#[ stable( feature = "wasm_simd" , since = "1.54.0" ) ]
31383166pub fn i32x4_shl ( a : v128 , amt : u32 ) -> v128 {
3167+ // SAFETY: see i8x16_shl for more documentation why this is unsafe,
3168+ // essentially the shift amount must be valid hence the mask.
31393169 unsafe { simd_shl ( a. as_i32x4 ( ) , simd:: i32x4:: splat ( ( amt & 0x1f ) as i32 ) ) . v128 ( ) }
31403170}
31413171
@@ -3153,6 +3183,8 @@ pub use i32x4_shl as u32x4_shl;
31533183#[ doc( alias( "i32x4.shr_s" ) ) ]
31543184#[ stable( feature = "wasm_simd" , since = "1.54.0" ) ]
31553185pub fn i32x4_shr ( a : v128 , amt : u32 ) -> v128 {
3186+ // SAFETY: see i8x16_shl for more documentation why this is unsafe,
3187+ // essentially the shift amount must be valid hence the mask.
31563188 unsafe { simd_shr ( a. as_i32x4 ( ) , simd:: i32x4:: splat ( ( amt & 0x1f ) as i32 ) ) . v128 ( ) }
31573189}
31583190
@@ -3167,6 +3199,8 @@ pub fn i32x4_shr(a: v128, amt: u32) -> v128 {
31673199#[ doc( alias( "i32x4.shr_u" ) ) ]
31683200#[ stable( feature = "wasm_simd" , since = "1.54.0" ) ]
31693201pub fn u32x4_shr ( a : v128 , amt : u32 ) -> v128 {
3202+ // SAFETY: see i8x16_shl for more documentation why this is unsafe,
3203+ // essentially the shift amount must be valid hence the mask.
31703204 unsafe { simd_shr ( a. as_u32x4 ( ) , simd:: u32x4:: splat ( amt & 0x1f ) ) . v128 ( ) }
31713205}
31723206
@@ -3502,6 +3536,8 @@ pub use i64x2_extend_high_u32x4 as u64x2_extend_high_u32x4;
35023536#[ doc( alias( "i64x2.shl" ) ) ]
35033537#[ stable( feature = "wasm_simd" , since = "1.54.0" ) ]
35043538pub fn i64x2_shl ( a : v128 , amt : u32 ) -> v128 {
3539+ // SAFETY: see i8x16_shl for more documentation why this is unsafe,
3540+ // essentially the shift amount must be valid hence the mask.
35053541 unsafe { simd_shl ( a. as_i64x2 ( ) , simd:: i64x2:: splat ( ( amt & 0x3f ) as i64 ) ) . v128 ( ) }
35063542}
35073543
@@ -3519,6 +3555,8 @@ pub use i64x2_shl as u64x2_shl;
35193555#[ doc( alias( "i64x2.shr_s" ) ) ]
35203556#[ stable( feature = "wasm_simd" , since = "1.54.0" ) ]
35213557pub fn i64x2_shr ( a : v128 , amt : u32 ) -> v128 {
3558+ // SAFETY: see i8x16_shl for more documentation why this is unsafe,
3559+ // essentially the shift amount must be valid hence the mask.
35223560 unsafe { simd_shr ( a. as_i64x2 ( ) , simd:: i64x2:: splat ( ( amt & 0x3f ) as i64 ) ) . v128 ( ) }
35233561}
35243562
@@ -3533,6 +3571,8 @@ pub fn i64x2_shr(a: v128, amt: u32) -> v128 {
35333571#[ doc( alias( "i64x2.shr_u" ) ) ]
35343572#[ stable( feature = "wasm_simd" , since = "1.54.0" ) ]
35353573pub fn u64x2_shr ( a : v128 , amt : u32 ) -> v128 {
3574+ // SAFETY: see i8x16_shl for more documentation why this is unsafe,
3575+ // essentially the shift amount must be valid hence the mask.
35363576 unsafe { simd_shr ( a. as_u64x2 ( ) , simd:: u64x2:: splat ( ( amt & 0x3f ) as u64 ) ) . v128 ( ) }
35373577}
35383578
0 commit comments