[spirv-reader][ir] Support more binary operators

Add support for more of the SPIR-V instructions which convert to binary
operators. This includes:

 * OpFDiv
 * OpSDiv
 * OpUDiv
 * OpIMul
 * OpFRem
 * OpUMod
 * OpSMod
 * OpSRem
 * OpFSub
 * OpISub
 * OpVectorTimesScalar
 * OpMatrixTimesScalar
 * OpVectorTimesMatrix
 * OpMatrixTimesVector
 * OpMatrixTimesMatrix

Bug: 42250952
Change-Id: I58f187578a85569afd4e9bd5ad9eb262e4bf6099
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/220499
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/spirv/reader/parser/binary_test.cc b/src/tint/lang/spirv/reader/parser/binary_test.cc
index bf5d71a..dfe3c6d 100644
--- a/src/tint/lang/spirv/reader/parser/binary_test.cc
+++ b/src/tint/lang/spirv/reader/parser/binary_test.cc
@@ -112,6 +112,28 @@
                                  "%5:vec4<f32> = add %3, %4",
                              },
 
+                             // OpFSub
+                             BinaryCase{
+                                 "f16",
+                                 "OpFSub",
+                                 "%5:f16 = sub %3, %4",
+                             },
+                             BinaryCase{
+                                 "f32",
+                                 "OpFSub",
+                                 "%5:f32 = sub %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec3h",
+                                 "OpFSub",
+                                 "%5:vec3<f16> = sub %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec4f",
+                                 "OpFSub",
+                                 "%5:vec4<f32> = sub %3, %4",
+                             },
+
                              // OpFMul
                              BinaryCase{
                                  "f16",
@@ -134,6 +156,50 @@
                                  "%5:vec4<f32> = mul %3, %4",
                              },
 
+                             // OpFDiv
+                             BinaryCase{
+                                 "f16",
+                                 "OpFDiv",
+                                 "%5:f16 = div %3, %4",
+                             },
+                             BinaryCase{
+                                 "f32",
+                                 "OpFDiv",
+                                 "%5:f32 = div %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec3h",
+                                 "OpFDiv",
+                                 "%5:vec3<f16> = div %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec4f",
+                                 "OpFDiv",
+                                 "%5:vec4<f32> = div %3, %4",
+                             },
+
+                             // OpFRem
+                             BinaryCase{
+                                 "f16",
+                                 "OpFRem",
+                                 "%5:f16 = mod %3, %4",
+                             },
+                             BinaryCase{
+                                 "f32",
+                                 "OpFRem",
+                                 "%5:f32 = mod %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec3h",
+                                 "OpFRem",
+                                 "%5:vec3<f16> = mod %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec4f",
+                                 "OpFRem",
+                                 "%5:vec4<f32> = mod %3, %4",
+                             },
+
                              // OpIAdd
                              BinaryCase{
                                  "i32",
@@ -154,8 +220,283 @@
                                  "vec4u",
                                  "OpIAdd",
                                  "%5:vec4<u32> = add %3, %4",
+                             },
+
+                             // OpISub
+                             BinaryCase{
+                                 "i32",
+                                 "OpISub",
+                                 "%5:i32 = sub %3, %4",
+                             },
+                             BinaryCase{
+                                 "u32",
+                                 "OpISub",
+                                 "%5:u32 = sub %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec3i",
+                                 "OpISub",
+                                 "%5:vec3<i32> = sub %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec4u",
+                                 "OpISub",
+                                 "%5:vec4<u32> = sub %3, %4",
+                             },
+
+                             // OpIMul
+                             BinaryCase{
+                                 "i32",
+                                 "OpIMul",
+                                 "%5:i32 = mul %3, %4",
+                             },
+                             BinaryCase{
+                                 "u32",
+                                 "OpIMul",
+                                 "%5:u32 = mul %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec3i",
+                                 "OpIMul",
+                                 "%5:vec3<i32> = mul %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec4u",
+                                 "OpIMul",
+                                 "%5:vec4<u32> = mul %3, %4",
+                             },
+
+                             // OpSDiv
+                             BinaryCase{
+                                 "i32",
+                                 "OpSDiv",
+                                 "%5:i32 = div %3, %4",
+                             },
+                             BinaryCase{
+                                 "u32",
+                                 "OpSDiv",
+                                 "%5:u32 = div %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec3i",
+                                 "OpSDiv",
+                                 "%5:vec3<i32> = div %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec4u",
+                                 "OpSDiv",
+                                 "%5:vec4<u32> = div %3, %4",
+                             },
+
+                             // OpSMod
+                             BinaryCase{
+                                 "i32",
+                                 "OpSMod",
+                                 "%5:i32 = mod %3, %4",
+                             },
+                             BinaryCase{
+                                 "u32",
+                                 "OpSMod",
+                                 "%5:u32 = mod %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec3i",
+                                 "OpSMod",
+                                 "%5:vec3<i32> = mod %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec4u",
+                                 "OpSMod",
+                                 "%5:vec4<u32> = mod %3, %4",
+                             },
+
+                             // OpSRem
+                             BinaryCase{
+                                 "i32",
+                                 "OpSRem",
+                                 "%5:i32 = mod %3, %4",
+                             },
+                             BinaryCase{
+                                 "u32",
+                                 "OpSRem",
+                                 "%5:u32 = mod %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec3i",
+                                 "OpSRem",
+                                 "%5:vec3<i32> = mod %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec4u",
+                                 "OpSRem",
+                                 "%5:vec4<u32> = mod %3, %4",
+                             },
+
+                             // OpUDiv
+                             BinaryCase{
+                                 "u32",
+                                 "OpUDiv",
+                                 "%5:u32 = div %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec4u",
+                                 "OpUDiv",
+                                 "%5:vec4<u32> = div %3, %4",
+                             },
+
+                             // OpUMod
+                             BinaryCase{
+                                 "u32",
+                                 "OpUMod",
+                                 "%5:u32 = mod %3, %4",
+                             },
+                             BinaryCase{
+                                 "vec4u",
+                                 "OpUMod",
+                                 "%5:vec4<u32> = mod %3, %4",
                              }),
                          PrintBuiltinCase);
 
+struct VectorMatTimesCase {
+    std::string lhs_type;
+    std::string rhs_type;
+    std::string res_type;
+    std::string spirv_opcode;
+    std::string ir;
+};
+std::string PrintVectorMatTimesCase(testing::TestParamInfo<VectorMatTimesCase> bc) {
+    return bc.param.spirv_opcode + "_" + bc.param.lhs_type + "_" + bc.param.rhs_type;
+}
+
+using VectorScalarTest = SpirvParserTestWithParam<VectorMatTimesCase>;
+
+TEST_P(VectorScalarTest, All) {
+    auto params = GetParam();
+    EXPECT_IR(R"(
+               OpCapability Shader
+               OpCapability Float16
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+       %void = OpTypeVoid
+        %f16 = OpTypeFloat 16
+        %f32 = OpTypeFloat 32
+      %vec3h = OpTypeVector %f16 3
+      %vec3f = OpTypeVector %f32 3
+    %mat3x3f = OpTypeMatrix %vec3f 3
+    %mat3x3h = OpTypeMatrix %vec3h 3
+    %ep_type = OpTypeFunction %void
+    %fn_type = OpTypeFunction %)" +
+                  params.res_type + " %" + params.lhs_type + " %" + params.rhs_type + R"(
+       %main = OpFunction %void None %ep_type
+ %main_start = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+        %foo = OpFunction %)" +
+                  params.res_type + " " + R"( None %fn_type
+        %lhs = OpFunctionParameter %)" +
+                  params.lhs_type + " " + R"(
+        %rhs = OpFunctionParameter %)" +
+                  params.rhs_type + " " + R"(
+  %foo_start = OpLabel
+     %result = )" +
+                  params.spirv_opcode + R"( %)" + params.res_type + " " + R"( %lhs %rhs
+               OpReturnValue %result
+               OpFunctionEnd
+)",
+              R"(
+  $B2: {
+    )" + params.ir +
+                  R"(
+    ret %5
+  }
+)");
+}
+
+INSTANTIATE_TEST_SUITE_P(SpirvParser,
+                         VectorScalarTest,
+                         testing::Values(
+                             // OpVectorTimesScalar
+                             VectorMatTimesCase{
+                                 "vec3h",
+                                 "f16",
+                                 "vec3h",
+                                 "OpVectorTimesScalar",
+                                 "%5:vec3<f16> = mul %3, %4",
+                             },
+                             VectorMatTimesCase{
+                                 "vec3f",
+                                 "f32",
+                                 "vec3f",
+                                 "OpVectorTimesScalar",
+                                 "%5:vec3<f32> = mul %3, %4",
+                             },
+
+                             // OpMatrixTimesScalar
+                             VectorMatTimesCase{
+                                 "mat3x3h",
+                                 "f16",
+                                 "mat3x3h",
+                                 "OpMatrixTimesScalar",
+                                 "%5:mat3x3<f16> = mul %3, %4",
+                             },
+                             VectorMatTimesCase{
+                                 "mat3x3f",
+                                 "f32",
+                                 "mat3x3f",
+                                 "OpMatrixTimesScalar",
+                                 "%5:mat3x3<f32> = mul %3, %4",
+                             },
+
+                             // OpMatrixTimesVector
+                             VectorMatTimesCase{
+                                 "mat3x3h",
+                                 "vec3h",
+                                 "vec3h",
+                                 "OpMatrixTimesVector",
+                                 "%5:vec3<f16> = mul %3, %4",
+                             },
+                             VectorMatTimesCase{
+                                 "mat3x3f",
+                                 "vec3f",
+                                 "vec3f",
+                                 "OpMatrixTimesVector",
+                                 "%5:vec3<f32> = mul %3, %4",
+                             },
+
+                             // OpVectorTimesMatrix
+                             VectorMatTimesCase{
+                                 "vec3h",
+                                 "mat3x3h",
+                                 "vec3h",
+                                 "OpVectorTimesMatrix",
+                                 "%5:vec3<f16> = mul %3, %4",
+                             },
+                             VectorMatTimesCase{
+                                 "vec3f",
+                                 "mat3x3f",
+                                 "vec3f",
+                                 "OpVectorTimesMatrix",
+                                 "%5:vec3<f32> = mul %3, %4",
+                             },
+
+                             // OpMatrixTimesMatrix
+                             VectorMatTimesCase{
+                                 "mat3x3h",
+                                 "mat3x3h",
+                                 "mat3x3h",
+                                 "OpMatrixTimesMatrix",
+                                 "%5:mat3x3<f16> = mul %3, %4",
+                             },
+                             VectorMatTimesCase{
+                                 "mat3x3f",
+                                 "mat3x3f",
+                                 "mat3x3f",
+                                 "OpMatrixTimesMatrix",
+                                 "%5:mat3x3<f32> = mul %3, %4",
+                             }),
+                         PrintVectorMatTimesCase);
+
 }  // namespace
 }  // namespace tint::spirv::reader
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc
index 20cbd4d..327566c 100644
--- a/src/tint/lang/spirv/reader/parser/parser.cc
+++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -528,17 +528,36 @@
                     EmitCompositeExtract(inst);
                     break;
                 case spv::Op::OpFAdd:
+                case spv::Op::OpIAdd:
                     EmitBinary(inst, core::BinaryOp::kAdd);
                     break;
+                case spv::Op::OpFDiv:
+                case spv::Op::OpSDiv:
+                case spv::Op::OpUDiv:
+                    EmitBinary(inst, core::BinaryOp::kDivide);
+                    break;
                 case spv::Op::OpFMul:
+                case spv::Op::OpIMul:
+                case spv::Op::OpVectorTimesScalar:
+                case spv::Op::OpMatrixTimesScalar:
+                case spv::Op::OpVectorTimesMatrix:
+                case spv::Op::OpMatrixTimesVector:
+                case spv::Op::OpMatrixTimesMatrix:
                     EmitBinary(inst, core::BinaryOp::kMultiply);
                     break;
+                case spv::Op::OpFRem:
+                case spv::Op::OpUMod:
+                case spv::Op::OpSMod:
+                case spv::Op::OpSRem:
+                    EmitBinary(inst, core::BinaryOp::kModulo);
+                    break;
+                case spv::Op::OpFSub:
+                case spv::Op::OpISub:
+                    EmitBinary(inst, core::BinaryOp::kSubtract);
+                    break;
                 case spv::Op::OpFunctionCall:
                     EmitFunctionCall(inst);
                     break;
-                case spv::Op::OpIAdd:
-                    EmitBinary(inst, core::BinaryOp::kAdd);
-                    break;
                 case spv::Op::OpLoad:
                     Emit(b_.Load(Value(inst.GetSingleWordOperand(2))), inst.result_id());
                     break;