Skip to content

Commit 158b9bd

Browse files
jamienicolVecvec
authored andcommitted
[naga msl-out hlsl-out] Ensure wrapper functions for integer division and modulo avoid using minimum value literals
As we know that minimum value integer literals can cause problems for some compilers. (See gfx-rs#7437) Make the code which generates these functions call msl::Writer::put_literal() and hlsl::Writer::write_literal() respectively to output the minimum value integer literals instead of just writing them directly, ensuring we only have to handle this workaround in a single location (per backend).
1 parent 10c04c9 commit 158b9bd

File tree

8 files changed

+61
-22
lines changed

8 files changed

+61
-22
lines changed

naga/src/back/hlsl/help.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,8 +1283,16 @@ impl<W: Write> super::Writer<'_, W> {
12831283
let level = crate::back::Level(1);
12841284
match scalar.kind {
12851285
ScalarKind::Sint => {
1286-
let min = -1i64 << (scalar.width as u32 * 8 - 1);
1287-
writeln!(self.out, "{level}return lhs / (((lhs == {min} & rhs == -1) | (rhs == 0)) ? 1 : rhs);")?
1286+
let min_val = match scalar.width {
1287+
4 => crate::Literal::I32(i32::MIN),
1288+
8 => crate::Literal::I64(i64::MIN),
1289+
_ => {
1290+
return Err(super::Error::UnsupportedScalar(scalar));
1291+
}
1292+
};
1293+
write!(self.out, "{level}return lhs / (((lhs == ")?;
1294+
self.write_literal(min_val)?;
1295+
writeln!(self.out, " & rhs == -1) | (rhs == 0)) ? 1 : rhs);")?
12881296
}
12891297
ScalarKind::Uint => {
12901298
writeln!(self.out, "{level}return lhs / (rhs == 0u ? 1u : rhs);")?
@@ -1339,10 +1347,18 @@ impl<W: Write> super::Writer<'_, W> {
13391347
let level = crate::back::Level(1);
13401348
match scalar.kind {
13411349
ScalarKind::Sint => {
1342-
let min = -1i64 << (scalar.width as u32 * 8 - 1);
1350+
let min_val = match scalar.width {
1351+
4 => crate::Literal::I32(i32::MIN),
1352+
8 => crate::Literal::I64(i64::MIN),
1353+
_ => {
1354+
return Err(super::Error::UnsupportedScalar(scalar));
1355+
}
1356+
};
13431357
write!(self.out, "{level}")?;
13441358
self.write_value_type(module, right_ty)?;
1345-
writeln!(self.out, " divisor = ((lhs == {min} & rhs == -1) | (rhs == 0)) ? 1 : rhs;")?;
1359+
write!(self.out, " divisor = ((lhs == ")?;
1360+
self.write_literal(min_val)?;
1361+
writeln!(self.out, " & rhs == -1) | (rhs == 0)) ? 1 : rhs;")?;
13461362
writeln!(
13471363
self.out,
13481364
"{level}return lhs - (lhs / divisor) * divisor;"

naga/src/back/msl/writer.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5346,8 +5346,21 @@ template <typename A>
53465346
let level = back::Level(1);
53475347
match scalar.kind {
53485348
crate::ScalarKind::Sint => {
5349-
let min = -1i64 << (scalar.width as u32 * 8 - 1);
5350-
writeln!(self.out, "{level}return lhs / metal::select(rhs, 1, (lhs == {min} & rhs == -1) | (rhs == 0));")?
5349+
let min_val = match scalar.width {
5350+
4 => crate::Literal::I32(i32::MIN),
5351+
8 => crate::Literal::I64(i64::MIN),
5352+
_ => {
5353+
return Err(Error::GenericValidation(format!(
5354+
"Unexpected width for scalar {scalar:?}"
5355+
)));
5356+
}
5357+
};
5358+
write!(
5359+
self.out,
5360+
"{level}return lhs / metal::select(rhs, 1, (lhs == "
5361+
)?;
5362+
self.put_literal(min_val)?;
5363+
writeln!(self.out, " & rhs == -1) | (rhs == 0));")?
53515364
}
53525365
crate::ScalarKind::Uint => writeln!(
53535366
self.out,
@@ -5415,8 +5428,18 @@ template <typename A>
54155428
let level = back::Level(1);
54165429
match scalar.kind {
54175430
crate::ScalarKind::Sint => {
5418-
let min = -1i64 << (scalar.width as u32 * 8 - 1);
5419-
writeln!(self.out, "{level}{rhs_type_name} divisor = metal::select(rhs, 1, (lhs == {min} & rhs == -1) | (rhs == 0));")?;
5431+
let min_val = match scalar.width {
5432+
4 => crate::Literal::I32(i32::MIN),
5433+
8 => crate::Literal::I64(i64::MIN),
5434+
_ => {
5435+
return Err(Error::GenericValidation(format!(
5436+
"Unexpected width for scalar {scalar:?}"
5437+
)));
5438+
}
5439+
};
5440+
write!(self.out, "{level}{rhs_type_name} divisor = metal::select(rhs, 1, (lhs == ")?;
5441+
self.put_literal(min_val)?;
5442+
writeln!(self.out, " & rhs == -1) | (rhs == 0));")?;
54205443
writeln!(
54215444
self.out,
54225445
"{level}return lhs - (lhs / divisor) * divisor;"

naga/tests/out/hlsl/wgsl-image.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Texture2DArray<float> image_2d_array_depth : register(t3, space1);
2525
TextureCube<float> image_cube_depth : register(t4, space1);
2626

2727
int2 naga_mod(int2 lhs, int2 rhs) {
28-
int2 divisor = ((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs;
28+
int2 divisor = ((lhs == int(-2147483647 - 1) & rhs == -1) | (rhs == 0)) ? 1 : rhs;
2929
return lhs - (lhs / divisor) * divisor;
3030
}
3131

naga/tests/out/hlsl/wgsl-operators.hlsl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ float4 builtins()
1717
}
1818

1919
int4 naga_mod(int4 lhs, int4 rhs) {
20-
int4 divisor = ((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs;
20+
int4 divisor = ((lhs == int(-2147483647 - 1) & rhs == -1) | (rhs == 0)) ? 1 : rhs;
2121
return lhs - (lhs / divisor) * divisor;
2222
}
2323

@@ -66,23 +66,23 @@ int2 naga_neg(int2 val) {
6666
}
6767

6868
int naga_div(int lhs, int rhs) {
69-
return lhs / (((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs);
69+
return lhs / (((lhs == int(-2147483647 - 1) & rhs == -1) | (rhs == 0)) ? 1 : rhs);
7070
}
7171

7272
uint naga_div(uint lhs, uint rhs) {
7373
return lhs / (rhs == 0u ? 1u : rhs);
7474
}
7575

7676
int2 naga_div(int2 lhs, int2 rhs) {
77-
return lhs / (((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs);
77+
return lhs / (((lhs == int(-2147483647 - 1) & rhs == -1) | (rhs == 0)) ? 1 : rhs);
7878
}
7979

8080
uint3 naga_div(uint3 lhs, uint3 rhs) {
8181
return lhs / (rhs == 0u ? 1u : rhs);
8282
}
8383

8484
int naga_mod(int lhs, int rhs) {
85-
int divisor = ((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs;
85+
int divisor = ((lhs == int(-2147483647 - 1) & rhs == -1) | (rhs == 0)) ? 1 : rhs;
8686
return lhs - (lhs / divisor) * divisor;
8787
}
8888

@@ -91,7 +91,7 @@ uint naga_mod(uint lhs, uint rhs) {
9191
}
9292

9393
int2 naga_mod(int2 lhs, int2 rhs) {
94-
int2 divisor = ((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs;
94+
int2 divisor = ((lhs == int(-2147483647 - 1) & rhs == -1) | (rhs == 0)) ? 1 : rhs;
9595
return lhs - (lhs / divisor) * divisor;
9696
}
9797

naga/tests/out/hlsl/wgsl-skybox.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ struct FragmentInput_fs_main {
3333
};
3434

3535
int naga_div(int lhs, int rhs) {
36-
return lhs / (((lhs == -2147483648 & rhs == -1) | (rhs == 0)) ? 1 : rhs);
36+
return lhs / (((lhs == int(-2147483647 - 1) & rhs == -1) | (rhs == 0)) ? 1 : rhs);
3737
}
3838

3939
VertexOutput ConstructVertexOutput(float4 arg0, float3 arg1) {

naga/tests/out/msl/wgsl-image.msl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using metal::uint;
66

77
metal::int2 naga_mod(metal::int2 lhs, metal::int2 rhs) {
8-
metal::int2 divisor = metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0));
8+
metal::int2 divisor = metal::select(rhs, 1, (lhs == (-2147483647 - 1) & rhs == -1) | (rhs == 0));
99
return lhs - (lhs / divisor) * divisor;
1010
}
1111

naga/tests/out/msl/wgsl-operators.msl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ metal::float4 builtins(
2323
}
2424

2525
metal::int4 naga_mod(metal::int4 lhs, metal::int4 rhs) {
26-
metal::int4 divisor = metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0));
26+
metal::int4 divisor = metal::select(rhs, 1, (lhs == (-2147483647 - 1) & rhs == -1) | (rhs == 0));
2727
return lhs - (lhs / divisor) * divisor;
2828
}
2929

@@ -74,23 +74,23 @@ metal::int2 naga_neg(metal::int2 val) {
7474
}
7575

7676
int naga_div(int lhs, int rhs) {
77-
return lhs / metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0));
77+
return lhs / metal::select(rhs, 1, (lhs == (-2147483647 - 1) & rhs == -1) | (rhs == 0));
7878
}
7979

8080
uint naga_div(uint lhs, uint rhs) {
8181
return lhs / metal::select(rhs, 1u, rhs == 0u);
8282
}
8383

8484
metal::int2 naga_div(metal::int2 lhs, metal::int2 rhs) {
85-
return lhs / metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0));
85+
return lhs / metal::select(rhs, 1, (lhs == (-2147483647 - 1) & rhs == -1) | (rhs == 0));
8686
}
8787

8888
metal::uint3 naga_div(metal::uint3 lhs, metal::uint3 rhs) {
8989
return lhs / metal::select(rhs, 1u, rhs == 0u);
9090
}
9191

9292
int naga_mod(int lhs, int rhs) {
93-
int divisor = metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0));
93+
int divisor = metal::select(rhs, 1, (lhs == (-2147483647 - 1) & rhs == -1) | (rhs == 0));
9494
return lhs - (lhs / divisor) * divisor;
9595
}
9696

@@ -99,7 +99,7 @@ uint naga_mod(uint lhs, uint rhs) {
9999
}
100100

101101
metal::int2 naga_mod(metal::int2 lhs, metal::int2 rhs) {
102-
metal::int2 divisor = metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0));
102+
metal::int2 divisor = metal::select(rhs, 1, (lhs == (-2147483647 - 1) & rhs == -1) | (rhs == 0));
103103
return lhs - (lhs / divisor) * divisor;
104104
}
105105

naga/tests/out/msl/wgsl-skybox.msl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ struct Data {
1313
metal::float4x4 view;
1414
};
1515
int naga_div(int lhs, int rhs) {
16-
return lhs / metal::select(rhs, 1, (lhs == -2147483648 & rhs == -1) | (rhs == 0));
16+
return lhs / metal::select(rhs, 1, (lhs == (-2147483647 - 1) & rhs == -1) | (rhs == 0));
1717
}
1818

1919

0 commit comments

Comments
 (0)