writer/hlsl: Don't emit literal integer divide-by-zeros

FXC errors on these, and they are undefined behavior in WGSL.

Bug: tint:1083
Change-Id: I7643fdc6991f8729f274535b603b761398412398
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/60500
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
Ben Clayton 2021-08-03 17:51:32 +00:00 committed by Tint LUCI CQ
parent 72dad76c21
commit 51750f15d2
7 changed files with 48 additions and 8 deletions

View File

@ -364,6 +364,8 @@ bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) {
} }
out << "("; out << "(";
TINT_DEFER(out << ")");
if (!EmitExpression(out, expr->lhs())) { if (!EmitExpression(out, expr->lhs())) {
return false; return false;
} }
@ -425,6 +427,19 @@ bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) {
break; break;
case ast::BinaryOp::kDivide: case ast::BinaryOp::kDivide:
out << "/"; out << "/";
if (auto val = program_->Sem().Get(expr->rhs())->ConstantValue()) {
// Integer divide by zero is a DXC compile error, and undefined behavior
// in WGSL. Replace the 0 with 1.
if (val.Type()->Is<sem::I32>() && val.Elements()[0].i32 == 0) {
out << " 1";
return true;
}
if (val.Type()->Is<sem::U32>() && val.Elements()[0].u32 == 0u) {
out << " 1u";
return true;
}
}
break; break;
case ast::BinaryOp::kModulo: case ast::BinaryOp::kModulo:
out << "%"; out << "%";
@ -440,7 +455,6 @@ bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) {
return false; return false;
} }
out << ")";
return true; return true;
} }

View File

@ -551,6 +551,32 @@ foo((tint_tmp), (tint_tmp_1), (tint_tmp_2));
)"); )");
} }
TEST_F(HlslGeneratorImplTest_Binary, DivideByLiteralZero_i32) {
Global("a", ty.i32(), ast::StorageClass::kPrivate);
auto* expr = Div("a", 0);
WrapInFunction(expr);
GeneratorImpl& gen = Build();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), R"((a / 1))");
}
TEST_F(HlslGeneratorImplTest_Binary, DivideByLiteralZero_u32) {
Global("a", ty.u32(), ast::StorageClass::kPrivate);
auto* expr = Div("a", 0u);
WrapInFunction(expr);
GeneratorImpl& gen = Build();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), R"((a / 1u))");
}
} // namespace } // namespace
} // namespace hlsl } // namespace hlsl
} // namespace writer } // namespace writer

View File

@ -5,5 +5,5 @@ void f() {
const int c = (1 / 0); const int c = (1 / 0);
return; return;
} }
C:\src\tint\test\Shader@0x000001BC7A7DD8D0(3,18-22): error X4010: Unsigned integer divide by zero O:\src\chrome\src\third_party\dawn\third_party\tint\test\Shader@0x000002477B82F5C0(3,18-22): error X4010: Unsigned integer divide by zero

View File

@ -53,6 +53,6 @@ tint_symbol main() {
const tint_symbol tint_symbol_3 = {tint_symbol_1.x_GLF_color_1}; const tint_symbol tint_symbol_3 = {tint_symbol_1.x_GLF_color_1};
return tint_symbol_3; return tint_symbol_3;
} }
C:\src\tint\test\Shader@0x0000021F05CF11C0(19,14-18): error X4010: Unsigned integer divide by zero O:\src\chrome\src\third_party\dawn\third_party\tint\test\Shader@0x000001481B9B0CA0(19,14-18): error X4010: Unsigned integer divide by zero
C:\src\tint\test\Shader@0x0000021F05CF11C0(19,14-18): warning X3556: integer divides may be much slower, try using uints if possible. O:\src\chrome\src\third_party\dawn\third_party\tint\test\Shader@0x000001481B9B0CA0(19,14-18): warning X3556: integer divides may be much slower, try using uints if possible.

View File

@ -53,6 +53,6 @@ tint_symbol main() {
const tint_symbol tint_symbol_3 = {tint_symbol_1.x_GLF_color_1}; const tint_symbol tint_symbol_3 = {tint_symbol_1.x_GLF_color_1};
return tint_symbol_3; return tint_symbol_3;
} }
C:\src\tint\test\Shader@0x00000199CF77C330(19,14-18): error X4010: Unsigned integer divide by zero O:\src\chrome\src\third_party\dawn\third_party\tint\test\Shader@0x0000029A80398B60(19,14-18): error X4010: Unsigned integer divide by zero
C:\src\tint\test\Shader@0x00000199CF77C330(19,14-18): warning X3556: integer divides may be much slower, try using uints if possible. O:\src\chrome\src\third_party\dawn\third_party\tint\test\Shader@0x0000029A80398B60(19,14-18): warning X3556: integer divides may be much slower, try using uints if possible.

View File

@ -63,5 +63,5 @@ tint_symbol_2 main(tint_symbol_1 tint_symbol) {
const tint_symbol_2 tint_symbol_7 = {tint_symbol_3.x_GLF_color_1}; const tint_symbol_2 tint_symbol_7 = {tint_symbol_3.x_GLF_color_1};
return tint_symbol_7; return tint_symbol_7;
} }
C:\src\tint\test\Shader@0x000002787AC0C3C0(25,16-23): error X4010: Unsigned integer divide by zero O:\src\chrome\src\third_party\dawn\third_party\tint\test\Shader@0x0000028809903F10(25,16-23): error X4010: Unsigned integer divide by zero

View File

@ -63,5 +63,5 @@ tint_symbol_2 main(tint_symbol_1 tint_symbol) {
const tint_symbol_2 tint_symbol_7 = {tint_symbol_3.x_GLF_color_1}; const tint_symbol_2 tint_symbol_7 = {tint_symbol_3.x_GLF_color_1};
return tint_symbol_7; return tint_symbol_7;
} }
C:\src\tint\test\Shader@0x0000020234C8C230(25,16-23): error X4010: Unsigned integer divide by zero O:\src\chrome\src\third_party\dawn\third_party\tint\test\Shader@0x000001EB404C9FC0(25,16-23): error X4010: Unsigned integer divide by zero