[validator] Move switch functional checks.

Move the functional validation for `Switch` to the functional validator.

Bug: 516717234
Change-Id: I980b74ac93fc51234492d521c949410c0b662a2d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/314535
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/core/ir/functional_validator.cc b/src/tint/lang/core/ir/functional_validator.cc
index 14d2c90..a4dc663 100644
--- a/src/tint/lang/core/ir/functional_validator.cc
+++ b/src/tint/lang/core/ir/functional_validator.cc
@@ -307,6 +307,7 @@
         [&](const Phony*) {},                                              //
         [&](const Store* s) { CheckStore(s); },                            //
         [&](const StoreVectorElement* s) { CheckStoreVectorElement(s); },  //
+        [&](const Switch* s) { CheckSwitch(s); },                          //
         [&](const Terminator* b) { CheckTerminator(b); },                  //
         [&](const Var* var) { CheckVar(var); }
         // TODO(516717234): Add TINT_ICE_ON_NO_MATCH when all instructions covered
@@ -1007,4 +1008,40 @@
     first_continues_.Add(loop, c);
 }
 
+void Functional::CheckSwitch(const Switch* s) {
+    if (s->Condition() && !s->Condition()->Type()->IsIntegerScalar()) {
+        auto* cond_ty = s->Condition() ? s->Condition()->Type() : nullptr;
+        AddError(s, Switch::kConditionOperandOffset)
+            << "condition type " << NameOf(cond_ty) << " must be an integer scalar";
+    }
+
+    bool found_default = false;
+    for (auto& case_ : s->Cases()) {
+        if (case_.selectors.IsEmpty()) {
+            AddError(s) << "case does not have any selectors";
+        }
+        CheckBlock(case_.block);
+
+        for (const auto& sel : case_.selectors) {
+            if (sel.IsDefault()) {
+                if (found_default) {
+                    AddError(s) << "multiple default selectors in switch";
+                }
+                found_default = true;
+            } else if (!sel.val->Type()->IsIntegerScalar()) {
+                AddError(s) << "case selector type " << NameOf(sel.val->Type())
+                            << " must be an integer scalar";
+            } else if (s->Condition() && sel.val->Type() != s->Condition()->Type()) {
+                AddError(s) << "case selector type " << NameOf(sel.val->Type())
+                            << " must match the switch condition type "
+                            << NameOf(s->Condition()->Type());
+            }
+        }
+    }
+
+    if (!found_default) {
+        AddError(s) << "missing default case for switch";
+    }
+}
+
 }  // namespace tint::core::ir::validator
diff --git a/src/tint/lang/core/ir/functional_validator.h b/src/tint/lang/core/ir/functional_validator.h
index 1a6084f..b5891c7 100644
--- a/src/tint/lang/core/ir/functional_validator.h
+++ b/src/tint/lang/core/ir/functional_validator.h
@@ -44,6 +44,7 @@
 #include "src/tint/lang/core/ir/override.h"
 #include "src/tint/lang/core/ir/store.h"
 #include "src/tint/lang/core/ir/store_vector_element.h"
+#include "src/tint/lang/core/ir/switch.h"
 #include "src/tint/lang/core/ir/var.h"
 #include "src/tint/utils/containers/hashmap.h"
 #include "src/tint/utils/diagnostic/diagnostic.h"
@@ -125,6 +126,7 @@
     void CheckOverride(const Override* o);
     void CheckStore(const Store* s);
     void CheckStoreVectorElement(const StoreVectorElement* s);
+    void CheckSwitch(const Switch* s);
     void CheckTerminator(const Terminator* b);
     void CheckVar(const Var* var);
 
diff --git a/src/tint/lang/core/ir/structural_validator.cc b/src/tint/lang/core/ir/structural_validator.cc
index 5adff9a..d6e63f9 100644
--- a/src/tint/lang/core/ir/structural_validator.cc
+++ b/src/tint/lang/core/ir/structural_validator.cc
@@ -3663,44 +3663,13 @@
     CheckResults(s);
     CheckOperands(s, Switch::kNumOperands);
 
-    if (s->Condition() && !s->Condition()->Type()->IsIntegerScalar()) {
-        auto* cond_ty = s->Condition() ? s->Condition()->Type() : nullptr;
-        AddError(s, Switch::kConditionOperandOffset)
-            << "condition type " << NameOf(cond_ty) << " must be an integer scalar";
-    }
-
     tasks_.Push([this] { control_stack_.Pop(); });
 
-    bool found_default = false;
     for (auto& cse : s->Cases()) {
         if (cse.block->Is<core::ir::MultiInBlock>()) {
             AddError(s) << "case block must be a block";
         }
-
-        if (cse.selectors.IsEmpty()) {
-            AddError(s) << "case does not have any selectors";
-        }
-
         QueueBlock(cse.block);
-        for (const auto& sel : cse.selectors) {
-            if (sel.IsDefault()) {
-                if (found_default) {
-                    AddError(s) << "multiple default selectors in switch";
-                }
-                found_default = true;
-            } else if (!sel.val->Type()->IsIntegerScalar()) {
-                AddError(s) << "case selector type " << NameOf(sel.val->Type())
-                            << " must be an integer scalar";
-            } else if (s->Condition() && sel.val->Type() != s->Condition()->Type()) {
-                AddError(s) << "case selector type " << NameOf(sel.val->Type())
-                            << " must match the switch condition type "
-                            << NameOf(s->Condition()->Type());
-            }
-        }
-    }
-
-    if (!found_default) {
-        AddError(s) << "missing default case for switch";
     }
 
     tasks_.Push([this, s] { control_stack_.Push(s); });