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 << "(";
TINT_DEFER(out << ")");
if (!EmitExpression(out, expr->lhs())) {
return false;
}
@@ -425,6 +427,19 @@ bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) {
break;
case ast::BinaryOp::kDivide:
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;
case ast::BinaryOp::kModulo:
out << "%";
@@ -440,7 +455,6 @@ bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) {
return false;
}
out << ")";
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 hlsl
} // namespace writer