Add IR validation for LogicalAnd and LogicalOr.

The `LogicalAnd` and `LogicalOr` binary operators should not appear in
the IR (they should get converted to `if/else` on lowering). Add
validation that they do not appear.

Fixed: 442044018
Change-Id: I19eb7b8ae81f8c7018941f8b76b36376139ff802
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/260437
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index 1f0e65b..1986519 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -3428,6 +3428,15 @@
         return;
     }
 
+    if (b->Op() == core::BinaryOp::kLogicalAnd) {
+        AddError(b) << "logical-and is not valid in the IR";
+        return;
+    }
+    if (b->Op() == core::BinaryOp::kLogicalOr) {
+        AddError(b) << "logical-or is not valid in the IR";
+        return;
+    }
+
     if (b->LHS() && b->RHS()) {
         intrinsic::Context context{b->TableData(), type_mgr_, symbols_};
 
diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc
index 2f777c8..01fd704 100644
--- a/src/tint/lang/core/ir/validator_test.cc
+++ b/src/tint/lang/core/ir/validator_test.cc
@@ -1287,6 +1287,39 @@
 )")) << res.Failure();
 }
 
+TEST_F(IR_ValidatorTest, Binary_LogicalOr) {
+    auto* func = b.Function("foo", ty.void_());
+    b.Append(func->Block(), [&] {
+        b.Binary(core::BinaryOp::kLogicalOr, ty.bool_(), b.Constant(true), b.Constant(true));
+        b.Return(func);
+    });
+
+    auto res = ir::Validate(mod);
+    ASSERT_NE(res, Success);
+    EXPECT_THAT(res.Failure().reason,
+                testing::HasSubstr(R"(:3:5 error: binary: logical-or is not valid in the IR
+    %2:bool = logical-or true, true
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+)")) << res.Failure();
+}
+
+TEST_F(IR_ValidatorTest, Binary_LogicalAnd) {
+    auto* func = b.Function("foo", ty.void_());
+    b.Append(func->Block(), [&] {
+        b.Binary(core::BinaryOp::kLogicalAnd, ty.bool_(), b.Constant(false), b.Constant(false));
+        b.Return(func);
+    });
+
+    auto res = ir::Validate(mod);
+    ASSERT_NE(res, Success);
+    EXPECT_THAT(res.Failure().reason,
+                testing::HasSubstr(R"(:3:5 error: binary: logical-and is not valid in the IR
+    %2:bool = logical-and false, false
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+)")) << res.Failure();
+}
+
 TEST_F(IR_ValidatorTest, Binary_Valid) {
     auto* i32 = ty.i32();
     auto* func = b.Function("foo", ty.void_());