Skip to content

Commit ab098c6

Browse files
alexcrichtonAmanieu
authored andcommitted
wasm32: Fix undefined behavior with shift intrinsics
This commit fixes an issue where simd shift intrinsic in LLVM are undefined behavior if the shift amount is larger than the bit width of the lane. While in WebAssembly the corresponding instructions are defined as masking out the upper bits we need to represent that explicitly in LLVM IR to ensure that the semantics remain defined. cc #137941
1 parent ec55ab6 commit ab098c6

File tree

1 file changed

+13
-15
lines changed
  • library/stdarch/crates/core_arch/src/wasm32

1 file changed

+13
-15
lines changed

library/stdarch/crates/core_arch/src/wasm32/simd128.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2318,7 +2318,7 @@ pub fn u8x16_narrow_i16x8(a: v128, b: v128) -> v128 {
23182318
#[doc(alias("i8x16.shl"))]
23192319
#[stable(feature = "wasm_simd", since = "1.54.0")]
23202320
pub fn i8x16_shl(a: v128, amt: u32) -> v128 {
2321-
unsafe { simd_shl(a.as_i8x16(), simd::i8x16::splat(amt as i8)).v128() }
2321+
unsafe { simd_shl(a.as_i8x16(), simd::i8x16::splat((amt & 0x7) as i8)).v128() }
23222322
}
23232323

23242324
#[stable(feature = "wasm_simd", since = "1.54.0")]
@@ -2335,7 +2335,7 @@ pub use i8x16_shl as u8x16_shl;
23352335
#[doc(alias("i8x16.shr_s"))]
23362336
#[stable(feature = "wasm_simd", since = "1.54.0")]
23372337
pub fn i8x16_shr(a: v128, amt: u32) -> v128 {
2338-
unsafe { simd_shr(a.as_i8x16(), simd::i8x16::splat(amt as i8)).v128() }
2338+
unsafe { simd_shr(a.as_i8x16(), simd::i8x16::splat((amt & 0x7) as i8)).v128() }
23392339
}
23402340

23412341
/// Shifts each lane to the right by the specified number of bits, shifting in
@@ -2349,7 +2349,7 @@ pub fn i8x16_shr(a: v128, amt: u32) -> v128 {
23492349
#[doc(alias("i8x16.shr_u"))]
23502350
#[stable(feature = "wasm_simd", since = "1.54.0")]
23512351
pub fn u8x16_shr(a: v128, amt: u32) -> v128 {
2352-
unsafe { simd_shr(a.as_u8x16(), simd::u8x16::splat(amt as u8)).v128() }
2352+
unsafe { simd_shr(a.as_u8x16(), simd::u8x16::splat((amt & 0x7) as u8)).v128() }
23532353
}
23542354

23552355
/// Adds two 128-bit vectors as if they were two packed sixteen 8-bit integers.
@@ -2686,7 +2686,7 @@ pub use i16x8_extend_high_u8x16 as u16x8_extend_high_u8x16;
26862686
#[doc(alias("i16x8.shl"))]
26872687
#[stable(feature = "wasm_simd", since = "1.54.0")]
26882688
pub fn i16x8_shl(a: v128, amt: u32) -> v128 {
2689-
unsafe { simd_shl(a.as_i16x8(), simd::i16x8::splat(amt as i16)).v128() }
2689+
unsafe { simd_shl(a.as_i16x8(), simd::i16x8::splat((amt & 0xf) as i16)).v128() }
26902690
}
26912691

26922692
#[stable(feature = "wasm_simd", since = "1.54.0")]
@@ -2703,7 +2703,7 @@ pub use i16x8_shl as u16x8_shl;
27032703
#[doc(alias("i16x8.shr_s"))]
27042704
#[stable(feature = "wasm_simd", since = "1.54.0")]
27052705
pub fn i16x8_shr(a: v128, amt: u32) -> v128 {
2706-
unsafe { simd_shr(a.as_i16x8(), simd::i16x8::splat(amt as i16)).v128() }
2706+
unsafe { simd_shr(a.as_i16x8(), simd::i16x8::splat((amt & 0xf) as i16)).v128() }
27072707
}
27082708

27092709
/// Shifts each lane to the right by the specified number of bits, shifting in
@@ -2717,7 +2717,7 @@ pub fn i16x8_shr(a: v128, amt: u32) -> v128 {
27172717
#[doc(alias("i16x8.shr_u"))]
27182718
#[stable(feature = "wasm_simd", since = "1.54.0")]
27192719
pub fn u16x8_shr(a: v128, amt: u32) -> v128 {
2720-
unsafe { simd_shr(a.as_u16x8(), simd::u16x8::splat(amt as u16)).v128() }
2720+
unsafe { simd_shr(a.as_u16x8(), simd::u16x8::splat((amt & 0xf) as u16)).v128() }
27212721
}
27222722

27232723
/// Adds two 128-bit vectors as if they were two packed eight 16-bit integers.
@@ -3136,7 +3136,7 @@ pub use i32x4_extend_high_u16x8 as u32x4_extend_high_u16x8;
31363136
#[doc(alias("i32x4.shl"))]
31373137
#[stable(feature = "wasm_simd", since = "1.54.0")]
31383138
pub fn i32x4_shl(a: v128, amt: u32) -> v128 {
3139-
unsafe { simd_shl(a.as_i32x4(), simd::i32x4::splat(amt as i32)).v128() }
3139+
unsafe { simd_shl(a.as_i32x4(), simd::i32x4::splat((amt & 0x1f) as i32)).v128() }
31403140
}
31413141

31423142
#[stable(feature = "wasm_simd", since = "1.54.0")]
@@ -3153,7 +3153,7 @@ pub use i32x4_shl as u32x4_shl;
31533153
#[doc(alias("i32x4.shr_s"))]
31543154
#[stable(feature = "wasm_simd", since = "1.54.0")]
31553155
pub fn i32x4_shr(a: v128, amt: u32) -> v128 {
3156-
unsafe { simd_shr(a.as_i32x4(), simd::i32x4::splat(amt as i32)).v128() }
3156+
unsafe { simd_shr(a.as_i32x4(), simd::i32x4::splat((amt & 0x1f) as i32)).v128() }
31573157
}
31583158

31593159
/// Shifts each lane to the right by the specified number of bits, shifting in
@@ -3167,7 +3167,7 @@ pub fn i32x4_shr(a: v128, amt: u32) -> v128 {
31673167
#[doc(alias("i32x4.shr_u"))]
31683168
#[stable(feature = "wasm_simd", since = "1.54.0")]
31693169
pub fn u32x4_shr(a: v128, amt: u32) -> v128 {
3170-
unsafe { simd_shr(a.as_u32x4(), simd::u32x4::splat(amt)).v128() }
3170+
unsafe { simd_shr(a.as_u32x4(), simd::u32x4::splat(amt & 0x1f)).v128() }
31713171
}
31723172

31733173
/// Adds two 128-bit vectors as if they were two packed four 32-bit integers.
@@ -3502,7 +3502,7 @@ pub use i64x2_extend_high_u32x4 as u64x2_extend_high_u32x4;
35023502
#[doc(alias("i64x2.shl"))]
35033503
#[stable(feature = "wasm_simd", since = "1.54.0")]
35043504
pub fn i64x2_shl(a: v128, amt: u32) -> v128 {
3505-
unsafe { simd_shl(a.as_i64x2(), simd::i64x2::splat(amt as i64)).v128() }
3505+
unsafe { simd_shl(a.as_i64x2(), simd::i64x2::splat((amt & 0x3f) as i64)).v128() }
35063506
}
35073507

35083508
#[stable(feature = "wasm_simd", since = "1.54.0")]
@@ -3519,7 +3519,7 @@ pub use i64x2_shl as u64x2_shl;
35193519
#[doc(alias("i64x2.shr_s"))]
35203520
#[stable(feature = "wasm_simd", since = "1.54.0")]
35213521
pub fn i64x2_shr(a: v128, amt: u32) -> v128 {
3522-
unsafe { simd_shr(a.as_i64x2(), simd::i64x2::splat(amt as i64)).v128() }
3522+
unsafe { simd_shr(a.as_i64x2(), simd::i64x2::splat((amt & 0x3f) as i64)).v128() }
35233523
}
35243524

35253525
/// Shifts each lane to the right by the specified number of bits, shifting in
@@ -3533,7 +3533,7 @@ pub fn i64x2_shr(a: v128, amt: u32) -> v128 {
35333533
#[doc(alias("i64x2.shr_u"))]
35343534
#[stable(feature = "wasm_simd", since = "1.54.0")]
35353535
pub fn u64x2_shr(a: v128, amt: u32) -> v128 {
3536-
unsafe { simd_shr(a.as_u64x2(), simd::u64x2::splat(amt as u64)).v128() }
3536+
unsafe { simd_shr(a.as_u64x2(), simd::u64x2::splat((amt & 0x3f) as u64)).v128() }
35373537
}
35383538

35393539
/// Adds two 128-bit vectors as if they were two packed two 64-bit integers.
@@ -4344,9 +4344,7 @@ mod tests {
43444344
};
43454345
assert_eq!(
43464346
bytes,
4347-
[
4348-
-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16
4349-
]
4347+
[-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16]
43504348
);
43514349
}
43524350

0 commit comments

Comments
 (0)