[ir][spirv-writer] Implement shift operations

This implements the mapping to the underlying SPIR-V instructions. The
builtin polyfill transform will take care of sanitizing the shift
operand to deliver WGSL's semantics.

Bug: tint:1906
Change-Id: I99985f38323fc1fa93495902695e4e0a7a6ce357
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/139981
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
Auto-Submit: James Price <jrprice@google.com>
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir.cc b/src/tint/writer/spirv/ir/generator_impl_ir.cc
index c9ef217..f099481 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir.cc
@@ -980,6 +980,19 @@
             break;
         }
 
+        case ir::Binary::Kind::kShiftLeft: {
+            op = spv::Op::OpShiftLeftLogical;
+            break;
+        }
+        case ir::Binary::Kind::kShiftRight: {
+            if (ty->is_signed_integer_scalar_or_vector()) {
+                op = spv::Op::OpShiftRightArithmetic;
+            } else if (ty->is_unsigned_integer_scalar_or_vector()) {
+                op = spv::Op::OpShiftRightLogical;
+            }
+            break;
+        }
+
         case ir::Binary::Kind::kEqual: {
             if (lhs_ty->is_bool_scalar_or_vector()) {
                 op = spv::Op::OpLogicalEqual;
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_binary_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_binary_test.cc
index 2cd7ddf..0e6f9ed 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_binary_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_binary_test.cc
@@ -73,17 +73,23 @@
                     BinaryTestCase{kI32, ir::Binary::Kind::kDivide, "OpSDiv", "int"},
                     BinaryTestCase{kI32, ir::Binary::Kind::kAnd, "OpBitwiseAnd", "int"},
                     BinaryTestCase{kI32, ir::Binary::Kind::kOr, "OpBitwiseOr", "int"},
-                    BinaryTestCase{kI32, ir::Binary::Kind::kXor, "OpBitwiseXor", "int"}));
+                    BinaryTestCase{kI32, ir::Binary::Kind::kXor, "OpBitwiseXor", "int"},
+                    BinaryTestCase{kI32, ir::Binary::Kind::kShiftLeft, "OpShiftLeftLogical", "int"},
+                    BinaryTestCase{kI32, ir::Binary::Kind::kShiftRight, "OpShiftRightArithmetic",
+                                   "int"}));
 INSTANTIATE_TEST_SUITE_P(
     SpvGeneratorImplTest_Binary_U32,
     Arithmetic_Bitwise,
-    testing::Values(BinaryTestCase{kU32, ir::Binary::Kind::kAdd, "OpIAdd", "uint"},
-                    BinaryTestCase{kU32, ir::Binary::Kind::kSubtract, "OpISub", "uint"},
-                    BinaryTestCase{kU32, ir::Binary::Kind::kMultiply, "OpIMul", "uint"},
-                    BinaryTestCase{kU32, ir::Binary::Kind::kDivide, "OpUDiv", "uint"},
-                    BinaryTestCase{kU32, ir::Binary::Kind::kAnd, "OpBitwiseAnd", "uint"},
-                    BinaryTestCase{kU32, ir::Binary::Kind::kOr, "OpBitwiseOr", "uint"},
-                    BinaryTestCase{kU32, ir::Binary::Kind::kXor, "OpBitwiseXor", "uint"}));
+    testing::Values(
+        BinaryTestCase{kU32, ir::Binary::Kind::kAdd, "OpIAdd", "uint"},
+        BinaryTestCase{kU32, ir::Binary::Kind::kSubtract, "OpISub", "uint"},
+        BinaryTestCase{kU32, ir::Binary::Kind::kMultiply, "OpIMul", "uint"},
+        BinaryTestCase{kU32, ir::Binary::Kind::kDivide, "OpUDiv", "uint"},
+        BinaryTestCase{kU32, ir::Binary::Kind::kAnd, "OpBitwiseAnd", "uint"},
+        BinaryTestCase{kU32, ir::Binary::Kind::kOr, "OpBitwiseOr", "uint"},
+        BinaryTestCase{kU32, ir::Binary::Kind::kXor, "OpBitwiseXor", "uint"},
+        BinaryTestCase{kU32, ir::Binary::Kind::kShiftLeft, "OpShiftLeftLogical", "uint"},
+        BinaryTestCase{kU32, ir::Binary::Kind::kShiftRight, "OpShiftRightLogical", "uint"}));
 INSTANTIATE_TEST_SUITE_P(
     SpvGeneratorImplTest_Binary_F32,
     Arithmetic_Bitwise,