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>
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index aa14cc1..db40ef3 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -364,6 +364,8 @@
   }
 
   out << "(";
+  TINT_DEFER(out << ")");
+
   if (!EmitExpression(out, expr->lhs())) {
     return false;
   }
@@ -425,6 +427,19 @@
       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 @@
     return false;
   }
 
-  out << ")";
   return true;
 }
 
diff --git a/src/writer/hlsl/generator_impl_binary_test.cc b/src/writer/hlsl/generator_impl_binary_test.cc
index 435ce1d..78d4632 100644
--- a/src/writer/hlsl/generator_impl_binary_test.cc
+++ b/src/writer/hlsl/generator_impl_binary_test.cc
@@ -551,6 +551,32 @@
 )");
 }
 
+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
diff --git a/test/bug/tint/1083.wgsl.expected.hlsl b/test/bug/tint/1083.wgsl.expected.hlsl
index 30e2a72..182701b 100644
--- a/test/bug/tint/1083.wgsl.expected.hlsl
+++ b/test/bug/tint/1083.wgsl.expected.hlsl
@@ -5,5 +5,5 @@
   const int c = (1 / 0);
   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
 
diff --git a/test/vk-gl-cts/graphicsfuzz/cov-loop-increment-or-divide-by-loop-index/0-opt.spvasm.expected.hlsl b/test/vk-gl-cts/graphicsfuzz/cov-loop-increment-or-divide-by-loop-index/0-opt.spvasm.expected.hlsl
index 72454e8..b82d8ee 100644
--- a/test/vk-gl-cts/graphicsfuzz/cov-loop-increment-or-divide-by-loop-index/0-opt.spvasm.expected.hlsl
+++ b/test/vk-gl-cts/graphicsfuzz/cov-loop-increment-or-divide-by-loop-index/0-opt.spvasm.expected.hlsl
@@ -53,6 +53,6 @@
   const tint_symbol tint_symbol_3 = {tint_symbol_1.x_GLF_color_1};
   return tint_symbol_3;
 }
-C:\src\tint\test\Shader@0x0000021F05CF11C0(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): error X4010: Unsigned integer divide by zero
+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.
 
diff --git a/test/vk-gl-cts/graphicsfuzz/cov-loop-increment-or-divide-by-loop-index/0-opt.wgsl.expected.hlsl b/test/vk-gl-cts/graphicsfuzz/cov-loop-increment-or-divide-by-loop-index/0-opt.wgsl.expected.hlsl
index 6ed529d..c98ef25 100644
--- a/test/vk-gl-cts/graphicsfuzz/cov-loop-increment-or-divide-by-loop-index/0-opt.wgsl.expected.hlsl
+++ b/test/vk-gl-cts/graphicsfuzz/cov-loop-increment-or-divide-by-loop-index/0-opt.wgsl.expected.hlsl
@@ -53,6 +53,6 @@
   const tint_symbol tint_symbol_3 = {tint_symbol_1.x_GLF_color_1};
   return tint_symbol_3;
 }
-C:\src\tint\test\Shader@0x00000199CF77C330(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): error X4010: Unsigned integer divide by zero
+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.
 
diff --git a/test/vk-gl-cts/graphicsfuzz/cov-modulo-zero-never-executed/0-opt.spvasm.expected.hlsl b/test/vk-gl-cts/graphicsfuzz/cov-modulo-zero-never-executed/0-opt.spvasm.expected.hlsl
index ada7447..0109ec6 100644
--- a/test/vk-gl-cts/graphicsfuzz/cov-modulo-zero-never-executed/0-opt.spvasm.expected.hlsl
+++ b/test/vk-gl-cts/graphicsfuzz/cov-modulo-zero-never-executed/0-opt.spvasm.expected.hlsl
@@ -63,5 +63,5 @@
   const tint_symbol_2 tint_symbol_7 = {tint_symbol_3.x_GLF_color_1};
   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
 
diff --git a/test/vk-gl-cts/graphicsfuzz/cov-modulo-zero-never-executed/0-opt.wgsl.expected.hlsl b/test/vk-gl-cts/graphicsfuzz/cov-modulo-zero-never-executed/0-opt.wgsl.expected.hlsl
index bd2158c..3d86b59 100644
--- a/test/vk-gl-cts/graphicsfuzz/cov-modulo-zero-never-executed/0-opt.wgsl.expected.hlsl
+++ b/test/vk-gl-cts/graphicsfuzz/cov-modulo-zero-never-executed/0-opt.wgsl.expected.hlsl
@@ -63,5 +63,5 @@
   const tint_symbol_2 tint_symbol_7 = {tint_symbol_3.x_GLF_color_1};
   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