[tint][ir] Simplify ir::Switch case generation

Also remove Case::Block() method, as the field is public.

Change-Id: I76d7d1cc39f6f1248fe626bee0b09f3b8b685b62
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/161006
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/lang/core/ir/builder.cc b/src/tint/lang/core/ir/builder.cc
index f6f94ef..9315f8a4 100644
--- a/src/tint/lang/core/ir/builder.cc
+++ b/src/tint/lang/core/ir/builder.cc
@@ -66,15 +66,25 @@
     return Append(ir.instructions.Create<ir::Loop>(Block(), MultiInBlock(), MultiInBlock()));
 }
 
-Block* Builder::Case(ir::Switch* s, VectorRef<Switch::CaseSelector> selectors) {
+Block* Builder::Case(ir::Switch* s, VectorRef<ir::Constant*> values) {
     auto* block = Block();
-    s->Cases().Push(Switch::Case{std::move(selectors), block});
+
+    Switch::Case c;
+    c.block = block;
+    for (auto* value : values) {
+        c.selectors.Push(Switch::CaseSelector{value});
+    }
+    s->Cases().Push(std::move(c));
     block->SetParent(s);
     return block;
 }
 
-Block* Builder::Case(ir::Switch* s, std::initializer_list<Switch::CaseSelector> selectors) {
-    return Case(s, Vector<Switch::CaseSelector, 4>(selectors));
+Block* Builder::DefaultCase(ir::Switch* s) {
+    return Case(s, Vector<ir::Constant*, 1>{nullptr});
+}
+
+Block* Builder::Case(ir::Switch* s, std::initializer_list<ir::Constant*> selectors) {
+    return Case(s, Vector<ir::Constant*, 4>(selectors));
 }
 
 ir::Discard* Builder::Discard() {
diff --git a/src/tint/lang/core/ir/builder.h b/src/tint/lang/core/ir/builder.h
index e1bdb13..7054822 100644
--- a/src/tint/lang/core/ir/builder.h
+++ b/src/tint/lang/core/ir/builder.h
@@ -268,17 +268,22 @@
         return Append(ir.instructions.Create<ir::Switch>(cond_val));
     }
 
-    /// Creates a case for the switch @p s with the given selectors
+    /// Creates a default case for the switch @p s
     /// @param s the switch to create the case into
-    /// @param selectors the case selectors for the case statement
     /// @returns the start block for the case instruction
-    ir::Block* Case(ir::Switch* s, VectorRef<Switch::CaseSelector> selectors);
+    ir::Block* DefaultCase(ir::Switch* s);
 
     /// Creates a case for the switch @p s with the given selectors
     /// @param s the switch to create the case into
-    /// @param selectors the case selectors for the case statement
+    /// @param values the case selector values for the case statement
     /// @returns the start block for the case instruction
-    ir::Block* Case(ir::Switch* s, std::initializer_list<Switch::CaseSelector> selectors);
+    ir::Block* Case(ir::Switch* s, VectorRef<ir::Constant*> values);
+
+    /// Creates a case for the switch @p s with the given selectors
+    /// @param s the switch to create the case into
+    /// @param values the case selector values for the case statement
+    /// @returns the start block for the case instruction
+    ir::Block* Case(ir::Switch* s, std::initializer_list<ir::Constant*> values);
 
     /// Creates a new ir::Constant
     /// @param val the constant value
diff --git a/src/tint/lang/core/ir/disassembler.cc b/src/tint/lang/core/ir/disassembler.cc
index f266200..6147550 100644
--- a/src/tint/lang/core/ir/disassembler.cc
+++ b/src/tint/lang/core/ir/disassembler.cc
@@ -718,7 +718,7 @@
                 EmitValue(selector.val);
             }
         }
-        out_ << ", %b" << IdOf(c.Block()) << ")";
+        out_ << ", %b" << IdOf(c.block) << ")";
     }
     out_ << "]";
     sm.Store(s);
@@ -728,7 +728,7 @@
 
     for (auto& c : s->Cases()) {
         ScopedIndent si(indent_size_);
-        EmitBlock(c.Block(), "case");
+        EmitBlock(c.block, "case");
     }
 
     Indent();
diff --git a/src/tint/lang/core/ir/switch.cc b/src/tint/lang/core/ir/switch.cc
index 3880fa0..cedf58f 100644
--- a/src/tint/lang/core/ir/switch.cc
+++ b/src/tint/lang/core/ir/switch.cc
@@ -27,6 +27,8 @@
 
 #include "src/tint/lang/core/ir/switch.h"
 
+#include <utility>
+
 #include "src/tint/lang/core/ir/clone_context.h"
 #include "src/tint/lang/core/ir/module.h"
 #include "src/tint/utils/ice/ice.h"
@@ -45,7 +47,7 @@
 
 void Switch::ForeachBlock(const std::function<void(ir::Block*)>& cb) {
     for (auto& c : cases_) {
-        cb(c.Block());
+        cb(c.block);
     }
 }
 
@@ -65,7 +67,7 @@
             auto* new_val = sel.val ? ctx.Clone(sel.val) : nullptr;
             new_case.selectors.Push(Switch::CaseSelector{new_val});
         }
-        new_switch->cases_.Push(new_case);
+        new_switch->cases_.Push(std::move(new_case));
     }
 
     new_switch->SetResults(ctx.Clone(results_));
diff --git a/src/tint/lang/core/ir/switch.h b/src/tint/lang/core/ir/switch.h
index 4ca3965..ddc9f32 100644
--- a/src/tint/lang/core/ir/switch.h
+++ b/src/tint/lang/core/ir/switch.h
@@ -29,6 +29,7 @@
 #define SRC_TINT_LANG_CORE_IR_SWITCH_H_
 
 #include <string>
+#include <utility>
 
 #include "src/tint/lang/core/ir/control_instruction.h"
 
@@ -64,7 +65,7 @@
     /// A case selector
     struct CaseSelector {
         /// @returns true if this is a default selector
-        bool IsDefault() { return val == nullptr; }
+        bool IsDefault() const { return val == nullptr; }
 
         /// The selector value, or nullptr if this is the default selector
         Constant* val = nullptr;
@@ -74,11 +75,9 @@
     struct Case {
         /// The case selector for this node
         Vector<CaseSelector, 4> selectors;
+
         /// The case block.
         ir::Block* block = nullptr;
-
-        /// @returns the case block
-        ir::Block* Block() { return block; }
     };
 
     /// Constructor
diff --git a/src/tint/lang/core/ir/switch_test.cc b/src/tint/lang/core/ir/switch_test.cc
index 8e6f7c8..d2b13d9 100644
--- a/src/tint/lang/core/ir/switch_test.cc
+++ b/src/tint/lang/core/ir/switch_test.cc
@@ -52,15 +52,14 @@
 
 TEST_F(IR_SwitchTest, Parent) {
     auto* switch_ = b.Switch(1_i);
-    b.Case(switch_, {Switch::CaseSelector{nullptr}});
-    EXPECT_THAT(switch_->Cases().Front().Block()->Parent(), switch_);
+    b.DefaultCase(switch_);
+    EXPECT_THAT(switch_->Cases().Front().block->Parent(), switch_);
 }
 
 TEST_F(IR_SwitchTest, Clone) {
     auto* switch_ = b.Switch(1_i);
-    switch_->Cases().Push(
-        Switch::Case{{Switch::CaseSelector{}, Switch::CaseSelector{b.Constant(2_i)}}, b.Block()});
-    switch_->Cases().Push(Switch::Case{{Switch::CaseSelector{b.Constant(3_i)}}, b.Block()});
+    b.Case(switch_, {nullptr, b.Constant(2_i)});
+    b.Case(switch_, {b.Constant(3_i)});
 
     auto* new_switch = clone_ctx.Clone(switch_);
 
@@ -70,7 +69,7 @@
     ASSERT_TRUE(new_cond->Is<core::constant::Scalar<i32>>());
     EXPECT_EQ(1_i, new_cond->As<core::constant::Scalar<i32>>()->ValueAs<i32>());
 
-    auto& cases = new_switch->Cases();
+    auto cases = new_switch->Cases();
     ASSERT_EQ(2u, cases.Length());
 
     {
@@ -102,9 +101,8 @@
     {
         auto* switch_ = b.Switch(1_i);
 
-        auto* blk = b.Block();
+        auto* blk = b.Case(switch_, {b.Constant(3_i)});
         b.Append(blk, [&] { b.ExitSwitch(switch_); });
-        switch_->Cases().Push(Switch::Case{{Switch::CaseSelector{b.Constant(3_i)}}, blk});
         new_switch = clone_ctx.Clone(switch_);
     }
 
@@ -121,9 +119,8 @@
         auto* switch_ = b.Switch(1_i);
         switch_->SetResults(Vector{r0, r1});
 
-        auto* blk = b.Block();
+        auto* blk = b.Case(switch_, Vector{b.Constant(3_i)});
         b.Append(blk, [&] { b.ExitSwitch(switch_, b.Constant(42_i), b.Constant(42_f)); });
-        switch_->Cases().Push(Switch::Case{{Switch::CaseSelector{b.Constant(3_i)}}, blk});
         new_switch = clone_ctx.Clone(switch_);
     }
 
diff --git a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc
index 3546b1e..d0a972e 100644
--- a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc
+++ b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc
@@ -1579,7 +1579,7 @@
         auto* ifelse = b.If(true);
         b.Append(ifelse->True(), [&] {  //
             auto* sw = b.Switch(42_i);
-            auto* def_case = b.Case(sw, Vector{core::ir::Switch::CaseSelector()});
+            auto* def_case = b.DefaultCase(sw);
             b.Append(def_case, [&] {  //
                 auto* loop = b.Loop();
                 b.Append(loop->Body(), [&] {  //
@@ -1703,7 +1703,7 @@
         auto* ifelse = b.If(true);
         b.Append(ifelse->True(), [&] {  //
             auto* sw = b.Switch(42_i);
-            auto* def_case = b.Case(sw, Vector{core::ir::Switch::CaseSelector()});
+            auto* def_case = b.DefaultCase(sw);
             b.Append(def_case, [&] {  //
                 auto* loop = b.Loop();
                 b.Append(loop->Body(), [&] {  //
diff --git a/src/tint/lang/core/ir/traverse_test.cc b/src/tint/lang/core/ir/traverse_test.cc
index 0fc7397..d792c24 100644
--- a/src/tint/lang/core/ir/traverse_test.cc
+++ b/src/tint/lang/core/ir/traverse_test.cc
@@ -71,10 +71,10 @@
         auto* switch_ = b.Switch(1_i);
         expect.Push(switch_);
 
-        auto* case_0 = b.Case(switch_, {Switch::CaseSelector{b.Constant(0_i)}});
+        auto* case_0 = b.Case(switch_, {b.Constant(0_i)});
         b.Append(case_0, [&] { expect.Push(b.Var<function, i32>()); });
 
-        auto* case_1 = b.Case(switch_, {Switch::CaseSelector{b.Constant(1_i)}});
+        auto* case_1 = b.Case(switch_, {b.Constant(1_i)});
         b.Append(case_1, [&] { expect.Push(b.Var<function, i32>()); });
 
         expect.Push(b.Var<function, i32>());
@@ -113,10 +113,10 @@
 
         auto* switch_ = b.Switch(1_i);
 
-        auto* case_0 = b.Case(switch_, {Switch::CaseSelector{b.Constant(0_i)}});
+        auto* case_0 = b.Case(switch_, {b.Constant(0_i)});
         b.Append(case_0, [&] { b.Var<function, i32>(); });
 
-        auto* case_1 = b.Case(switch_, {Switch::CaseSelector{b.Constant(1_i)}});
+        auto* case_1 = b.Case(switch_, {b.Constant(1_i)});
         b.Append(case_1, [&] { b.Var<function, i32>(); });
 
         b.Var<function, i32>();
diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc
index 728d65d..a9e38b4 100644
--- a/src/tint/lang/core/ir/validator_test.cc
+++ b/src/tint/lang/core/ir/validator_test.cc
@@ -1682,7 +1682,7 @@
         b.ExitIf(if_outer);
     });
 
-    auto* c = b.Case(switch_inner, {Switch::CaseSelector{b.Constant(1_i)}});
+    auto* c = b.Case(switch_inner, {b.Constant(1_i)});
     b.Append(c, [&] { b.ExitIf(if_outer); });
 
     b.Append(f->Block(), [&] {
@@ -1779,7 +1779,7 @@
 TEST_F(IR_ValidatorTest, ExitSwitch) {
     auto* switch_ = b.Switch(true);
 
-    auto* def = b.Case(switch_, {Switch::CaseSelector{}});
+    auto* def = b.DefaultCase(switch_);
     def->Append(b.ExitSwitch(switch_));
 
     auto* f = b.Function("my_func", ty.void_());
@@ -1794,7 +1794,7 @@
 TEST_F(IR_ValidatorTest, ExitSwitch_NullSwitch) {
     auto* switch_ = b.Switch(true);
 
-    auto* def = b.Case(switch_, {Switch::CaseSelector{}});
+    auto* def = b.DefaultCase(switch_);
     def->Append(mod.instructions.Create<ExitSwitch>(nullptr));
 
     auto* f = b.Function("my_func", ty.void_());
@@ -1834,7 +1834,7 @@
     auto* r2 = b.InstructionResult(ty.f32());
     switch_->SetResults(Vector{r1, r2});
 
-    auto* def = b.Case(switch_, {Switch::CaseSelector{}});
+    auto* def = b.DefaultCase(switch_);
     def->Append(b.ExitSwitch(switch_, 1_i));
 
     auto* f = b.Function("my_func", ty.void_());
@@ -1878,7 +1878,7 @@
     auto* r2 = b.InstructionResult(ty.f32());
     switch_->SetResults(Vector{r1, r2});
 
-    auto* def = b.Case(switch_, {Switch::CaseSelector{}});
+    auto* def = b.DefaultCase(switch_);
     def->Append(b.ExitSwitch(switch_, 1_i, 2_f, 3_i));
 
     auto* f = b.Function("my_func", ty.void_());
@@ -1922,7 +1922,7 @@
     auto* r2 = b.InstructionResult(ty.f32());
     switch_->SetResults(Vector{r1, r2});
 
-    auto* def = b.Case(switch_, {Switch::CaseSelector{}});
+    auto* def = b.DefaultCase(switch_);
     def->Append(b.ExitSwitch(switch_, 1_i, 2_f));
 
     auto* f = b.Function("my_func", ty.void_());
@@ -1940,7 +1940,7 @@
     auto* r2 = b.InstructionResult(ty.f32());
     switch_->SetResults(Vector{r1, r2});
 
-    auto* def = b.Case(switch_, {Switch::CaseSelector{}});
+    auto* def = b.DefaultCase(switch_);
     def->Append(b.ExitSwitch(switch_, 1_i, 2_i));
 
     auto* f = b.Function("my_func", ty.void_());
@@ -1983,7 +1983,7 @@
 
     auto* f = b.Function("my_func", ty.void_());
 
-    auto* def = b.Case(switch_, {Switch::CaseSelector{}});
+    auto* def = b.DefaultCase(switch_);
     def->Append(b.Return(f));
 
     auto sb = b.Append(f->Block());
@@ -2037,7 +2037,7 @@
 
     auto* f = b.Function("my_func", ty.void_());
 
-    auto* def = b.Case(switch_, {Switch::CaseSelector{}});
+    auto* def = b.DefaultCase(switch_);
     b.Append(def, [&] {
         auto* if_ = b.If(true);
         b.Append(if_->True(), [&] {
@@ -2059,12 +2059,12 @@
 TEST_F(IR_ValidatorTest, ExitSwitch_InvalidJumpOverSwitch) {
     auto* switch_ = b.Switch(true);
 
-    auto* def = b.Case(switch_, {Switch::CaseSelector{}});
+    auto* def = b.DefaultCase(switch_);
     b.Append(def, [&] {
         auto* inner = b.Switch(false);
         b.ExitSwitch(switch_);
 
-        auto* inner_def = b.Case(inner, {Switch::CaseSelector{}});
+        auto* inner_def = b.DefaultCase(inner);
         b.Append(inner_def, [&] { b.ExitSwitch(switch_); });
     });
 
@@ -2112,7 +2112,7 @@
 TEST_F(IR_ValidatorTest, ExitSwitch_InvalidJumpOverLoop) {
     auto* switch_ = b.Switch(true);
 
-    auto* def = b.Case(switch_, {Switch::CaseSelector{}});
+    auto* def = b.DefaultCase(switch_);
     b.Append(def, [&] {
         auto* loop = b.Loop();
         b.Append(loop->Body(), [&] { b.ExitSwitch(switch_); });
@@ -2458,7 +2458,7 @@
         auto* inner = b.Switch(false);
         b.ExitLoop(loop);
 
-        auto* inner_def = b.Case(inner, {Switch::CaseSelector{}});
+        auto* inner_def = b.DefaultCase(inner);
         b.Append(inner_def, [&] { b.ExitLoop(loop); });
     });
 
diff --git a/src/tint/lang/spirv/writer/printer/printer.cc b/src/tint/lang/spirv/writer/printer/printer.cc
index cb2f29e..78bca04 100644
--- a/src/tint/lang/spirv/writer/printer/printer.cc
+++ b/src/tint/lang/spirv/writer/printer/printer.cc
@@ -1885,7 +1885,7 @@
         for (auto& c : swtch->Cases()) {
             for (auto& sel : c.selectors) {
                 if (sel.IsDefault()) {
-                    default_label = Label(c.Block());
+                    default_label = Label(c.block);
                 }
             }
         }
@@ -1894,7 +1894,7 @@
         // Build the operands to the OpSwitch instruction.
         OperandList switch_operands = {Value(swtch->Condition()), default_label};
         for (auto& c : swtch->Cases()) {
-            auto label = Label(c.Block());
+            auto label = Label(c.block);
             for (auto& sel : c.selectors) {
                 if (sel.IsDefault()) {
                     continue;
@@ -1914,7 +1914,7 @@
 
         // Emit the cases.
         for (auto& c : swtch->Cases()) {
-            EmitBlock(c.Block());
+            EmitBlock(c.block);
         }
 
         // Emit the switch merge block.
diff --git a/src/tint/lang/spirv/writer/raise/merge_return_test.cc b/src/tint/lang/spirv/writer/raise/merge_return_test.cc
index 29a5b3f..425f1c0 100644
--- a/src/tint/lang/spirv/writer/raise/merge_return_test.cc
+++ b/src/tint/lang/spirv/writer/raise/merge_return_test.cc
@@ -111,7 +111,7 @@
 
     b.Append(func->Block(), [&] {
         auto* swtch = b.Switch(in);
-        b.Append(b.Case(swtch, {core::ir::Switch::CaseSelector{}}), [&] { b.ExitSwitch(swtch); });
+        b.Append(b.DefaultCase(swtch), [&] { b.ExitSwitch(swtch); });
 
         auto* l = b.Loop();
         b.Append(l->Body(), [&] { b.ExitLoop(l); });
@@ -1649,9 +1649,8 @@
 
     b.Append(func->Block(), [&] {
         auto* sw = b.Switch(cond);
-        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{b.Constant(1_i)}}),
-                 [&] { b.Return(func, 42_i); });
-        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{}}), [&] { b.ExitSwitch(sw); });
+        b.Append(b.Case(sw, {b.Constant(1_i)}), [&] { b.Return(func, 42_i); });
+        b.Append(b.DefaultCase(sw), [&] { b.ExitSwitch(sw); });
 
         b.Return(func, 0_i);
     });
@@ -1716,7 +1715,7 @@
 
     b.Append(func->Block(), [&] {
         auto* sw = b.Switch(cond);
-        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{b.Constant(1_i)}}), [&] {
+        b.Append(b.Case(sw, {b.Constant(1_i)}), [&] {
             auto* ifcond = b.Equal(ty.bool_(), cond, 1_i);
             auto* ifelse = b.If(ifcond);
             b.Append(ifelse->True(), [&] { b.Return(func, 42_i); });
@@ -1726,7 +1725,7 @@
             b.ExitSwitch(sw);
         });
 
-        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{}}), [&] { b.ExitSwitch(sw); });
+        b.Append(b.DefaultCase(sw), [&] { b.ExitSwitch(sw); });
 
         b.Return(func, 0_i);
     });
@@ -1823,13 +1822,10 @@
     b.Append(func->Block(), [&] {
         auto* sw = b.Switch(cond);
         sw->SetResults(b.InstructionResult(ty.i32()));  // NOLINT: false detection of std::tuple
-        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{b.Constant(1_i)}}),
-                 [&] { b.Return(func, 42_i); });
-        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{b.Constant(2_i)}}),
-                 [&] { b.Return(func, 99_i); });
-        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{b.Constant(3_i)}}),
-                 [&] { b.ExitSwitch(sw, 1_i); });
-        b.Append(b.Case(sw, {core::ir::Switch::CaseSelector{}}), [&] { b.ExitSwitch(sw, 0_i); });
+        b.Append(b.Case(sw, {b.Constant(1_i)}), [&] { b.Return(func, 42_i); });
+        b.Append(b.Case(sw, {b.Constant(2_i)}), [&] { b.Return(func, 99_i); });
+        b.Append(b.Case(sw, {b.Constant(3_i)}), [&] { b.ExitSwitch(sw, 1_i); });
+        b.Append(b.DefaultCase(sw), [&] { b.ExitSwitch(sw, 0_i); });
 
         b.Return(func, sw->Result(0));
     });
diff --git a/src/tint/lang/spirv/writer/switch_test.cc b/src/tint/lang/spirv/writer/switch_test.cc
index d00d32e..b91069a 100644
--- a/src/tint/lang/spirv/writer/switch_test.cc
+++ b/src/tint/lang/spirv/writer/switch_test.cc
@@ -37,7 +37,7 @@
     b.Append(func->Block(), [&] {
         auto* swtch = b.Switch(42_i);
 
-        auto* def_case = b.Case(swtch, Vector{core::ir::Switch::CaseSelector()});
+        auto* def_case = b.DefaultCase(swtch);
         b.Append(def_case, [&] {  //
             b.ExitSwitch(swtch);
         });
@@ -63,17 +63,17 @@
     b.Append(func->Block(), [&] {
         auto* swtch = b.Switch(42_i);
 
-        auto* case_a = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)}});
+        auto* case_a = b.Case(swtch, Vector{b.Constant(1_i)});
         b.Append(case_a, [&] {  //
             b.ExitSwitch(swtch);
         });
 
-        auto* case_b = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(swtch, Vector{b.Constant(2_i)});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(swtch);
         });
 
-        auto* def_case = b.Case(swtch, Vector{core::ir::Switch::CaseSelector()});
+        auto* def_case = b.DefaultCase(swtch);
         b.Append(def_case, [&] {  //
             b.ExitSwitch(swtch);
         });
@@ -103,20 +103,17 @@
     b.Append(func->Block(), [&] {
         auto* swtch = b.Switch(42_i);
 
-        auto* case_a = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)},
-                                            core::ir::Switch::CaseSelector{b.Constant(3_i)}});
+        auto* case_a = b.Case(swtch, Vector{b.Constant(1_i), b.Constant(3_i)});
         b.Append(case_a, [&] {  //
             b.ExitSwitch(swtch);
         });
 
-        auto* case_b = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)},
-                                            core::ir::Switch::CaseSelector{b.Constant(4_i)}});
+        auto* case_b = b.Case(swtch, Vector{b.Constant(2_i), b.Constant(4_i)});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(swtch);
         });
 
-        auto* def_case = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(5_i)},
-                                              core::ir::Switch::CaseSelector()});
+        auto* def_case = b.Case(swtch, Vector{b.Constant(5_i), nullptr});
         b.Append(def_case, [&] {  //
             b.ExitSwitch(swtch);
         });
@@ -146,17 +143,17 @@
     b.Append(func->Block(), [&] {
         auto* swtch = b.Switch(42_i);
 
-        auto* case_a = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)}});
+        auto* case_a = b.Case(swtch, Vector{b.Constant(1_i)});
         b.Append(case_a, [&] {  //
             b.Return(func);
         });
 
-        auto* case_b = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(swtch, Vector{b.Constant(2_i)});
         b.Append(case_b, [&] {  //
             b.Return(func);
         });
 
-        auto* def_case = b.Case(swtch, Vector{core::ir::Switch::CaseSelector()});
+        auto* def_case = b.DefaultCase(swtch);
         b.Append(def_case, [&] {  //
             b.Return(func);
         });
@@ -186,7 +183,7 @@
     b.Append(func->Block(), [&] {
         auto* swtch = b.Switch(42_i);
 
-        auto* case_a = b.Case(swtch, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)}});
+        auto* case_a = b.Case(swtch, Vector{b.Constant(1_i)});
         b.Append(case_a, [&] {
             auto* cond_break = b.If(true);
             b.Append(cond_break->True(), [&] {  //
@@ -199,7 +196,7 @@
             b.Return(func);
         });
 
-        auto* def_case = b.Case(swtch, Vector{core::ir::Switch::CaseSelector()});
+        auto* def_case = b.DefaultCase(swtch);
         b.Append(def_case, [&] {  //
             b.ExitSwitch(swtch);
         });
@@ -232,13 +229,12 @@
     b.Append(func->Block(), [&] {
         auto* s = b.Switch(42_i);
         s->SetResults(b.InstructionResult(ty.i32()));
-        auto* case_a = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)},
-                                        core::ir::Switch::CaseSelector{nullptr}});
+        auto* case_a = b.Case(s, Vector{b.Constant(1_i), nullptr});
         b.Append(case_a, [&] {  //
             b.ExitSwitch(s, 10_i);
         });
 
-        auto* case_b = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(s, Vector{b.Constant(2_i)});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(s, 20_i);
         });
@@ -267,13 +263,12 @@
     b.Append(func->Block(), [&] {
         auto* s = b.Switch(42_i);
         s->SetResults(b.InstructionResult(ty.i32()));
-        auto* case_a = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)},
-                                        core::ir::Switch::CaseSelector{nullptr}});
+        auto* case_a = b.Case(s, Vector{b.Constant(1_i), nullptr});
         b.Append(case_a, [&] {  //
             b.Return(func, 10_i);
         });
 
-        auto* case_b = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(s, Vector{b.Constant(2_i)});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(s, 20_i);
         });
@@ -315,13 +310,12 @@
     b.Append(func->Block(), [&] {
         auto* s = b.Switch(42_i);
         s->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
-        auto* case_a = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)},
-                                        core::ir::Switch::CaseSelector{nullptr}});
+        auto* case_a = b.Case(s, Vector{b.Constant(1_i), nullptr});
         b.Append(case_a, [&] {  //
             b.ExitSwitch(s, 10_i, true);
         });
 
-        auto* case_b = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(s, Vector{b.Constant(2_i)});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(s, 20_i, false);
         });
@@ -351,13 +345,12 @@
     b.Append(func->Block(), [&] {
         auto* s = b.Switch(b.Constant(42_i));
         s->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
-        auto* case_a = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)},
-                                        core::ir::Switch::CaseSelector{nullptr}});
+        auto* case_a = b.Case(s, Vector{b.Constant(1_i), nullptr});
         b.Append(case_a, [&] {  //
             b.ExitSwitch(s, 10_i, true);
         });
 
-        auto* case_b = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(s, Vector{b.Constant(2_i)});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(s, 20_i, false);
         });
@@ -387,8 +380,7 @@
     b.Append(func->Block(), [&] {
         auto* s = b.Switch(42_i);
         s->SetResults(b.InstructionResult(ty.i32()));
-        auto* case_a = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)},
-                                        core::ir::Switch::CaseSelector{nullptr}});
+        auto* case_a = b.Case(s, Vector{b.Constant(1_i), nullptr});
         b.Append(case_a, [&] {  //
             auto* inner = b.If(true);
             inner->SetResults(b.InstructionResult(ty.i32()));
@@ -402,7 +394,7 @@
             b.ExitSwitch(s, inner->Result());
         });
 
-        auto* case_b = b.Case(s, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(s, Vector{b.Constant(2_i)});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(s, 20_i);
         });
@@ -439,12 +431,10 @@
     b.Append(func->Block(), [&] {
         auto* outer = b.Switch(42_i);
         outer->SetResults(b.InstructionResult(ty.i32()));
-        auto* case_a = b.Case(outer, Vector{core::ir::Switch::CaseSelector{b.Constant(1_i)},
-                                            core::ir::Switch::CaseSelector{nullptr}});
+        auto* case_a = b.Case(outer, Vector{b.Constant(1_i), nullptr});
         b.Append(case_a, [&] {  //
             auto* inner = b.Switch(42_i);
-            auto* case_inner = b.Case(inner, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)},
-                                                    core::ir::Switch::CaseSelector{nullptr}});
+            auto* case_inner = b.Case(inner, Vector{b.Constant(2_i), nullptr});
             b.Append(case_inner, [&] {  //
                 b.ExitSwitch(inner);
             });
@@ -452,7 +442,7 @@
             b.ExitSwitch(outer, 10_i);
         });
 
-        auto* case_b = b.Case(outer, Vector{core::ir::Switch::CaseSelector{b.Constant(2_i)}});
+        auto* case_b = b.Case(outer, Vector{b.Constant(2_i)});
         b.Append(case_b, [&] {  //
             b.ExitSwitch(outer, 20_i);
         });
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
index 8190dd0..9941893 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
@@ -771,12 +771,12 @@
 
         const auto* sem = program_.Sem().Get(stmt);
         for (const auto* c : sem->Cases()) {
-            Vector<core::ir::Switch::CaseSelector, 4> selectors;
+            Vector<core::ir::Constant*, 4> selectors;
             for (const auto* selector : c->Selectors()) {
                 if (selector->IsDefault()) {
-                    selectors.Push({nullptr});
+                    selectors.Push(nullptr);
                 } else {
-                    selectors.Push({builder_.Constant(selector->Value()->Clone(clone_ctx_))});
+                    selectors.Push(builder_.Constant(selector->Value()->Clone(clone_ctx_)));
                 }
             }
 
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc
index d08dbbf..e69347d 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/inlining_test.cc
@@ -934,7 +934,7 @@
     b.Append(fn->Block(), [&] {
         auto* v = b.Add(ty.i32(), 1_i, 2_i);
         auto* switch_ = b.Switch(3_i);
-        auto* case_ = b.Case(switch_, {core::ir::Switch::CaseSelector{}});
+        auto* case_ = b.DefaultCase(switch_);
         b.Append(case_, [&] { b.Return(fn, v); });
         b.Return(fn, 0_i);
     });
@@ -959,7 +959,7 @@
         auto* v_1 = b.Load(var);
         auto* v_2 = b.Add(ty.i32(), v_1, 2_i);
         auto* switch_ = b.Switch(3_i);
-        auto* case_ = b.Case(switch_, {core::ir::Switch::CaseSelector{}});
+        auto* case_ = b.DefaultCase(switch_);
         b.Append(case_, [&] { b.Return(fn, v_2); });
         b.Return(fn, 0_i);
     });
@@ -983,7 +983,7 @@
     b.Append(fn->Block(), [&] {
         auto* v = b.Add(ty.i32(), 1_i, 2_i);
         auto* switch_ = b.Switch(v);
-        auto* case_ = b.Case(switch_, {core::ir::Switch::CaseSelector{}});
+        auto* case_ = b.DefaultCase(switch_);
         b.Append(case_, [&] { b.Return(fn, 3_i); });
         b.Return(fn, 0_i);
     });
@@ -1007,7 +1007,7 @@
         var->SetInitializer(b.Constant(1_i));
         auto* v_1 = b.Load(var);
         auto* switch_ = b.Switch(v_1);
-        auto* case_ = b.Case(switch_, {core::ir::Switch::CaseSelector{}});
+        auto* case_ = b.DefaultCase(switch_);
         b.Append(case_, [&] { b.Return(fn, 3_i); });
         b.Return(fn, 0_i);
     });
@@ -1032,7 +1032,7 @@
         b.Store(var, 1_i);
         auto* load = b.Load(var);
         auto* switch_ = b.Switch(1_i);
-        auto* case_ = b.Case(switch_, {core::ir::Switch::CaseSelector{}});
+        auto* case_ = b.DefaultCase(switch_);
         b.Append(case_, [&] {
             b.Store(var, 2_i);
             b.ExitSwitch(switch_);
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index 3a6ca12..168d78a 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -476,8 +476,8 @@
 
                 const ast::BlockStatement* body = nullptr;
                 {
-                    TINT_SCOPED_ASSIGNMENT(current_switch_case_, c.Block());
-                    body = Block(c.Block());
+                    TINT_SCOPED_ASSIGNMENT(current_switch_case_, c.block);
+                    body = Block(c.block);
                 }
 
                 auto selectors = tint::Transform(c.selectors,  //
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index 53af431..3de0d4a 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -2206,7 +2206,7 @@
         v->SetInitializer(b.Constant(42_i));
 
         auto s = b.Switch(b.Load(v));
-        b.Append(b.Case(s, {core::ir::Switch::CaseSelector{}}), [&] {
+        b.Append(b.DefaultCase(s), [&] {
             b.Call(ty.void_(), fn_a);
             b.ExitSwitch(s);
         });
@@ -2246,20 +2246,15 @@
         v->SetInitializer(b.Constant(42_i));
 
         auto s = b.Switch(b.Load(v));
-        b.Append(b.Case(s, {core::ir::Switch::CaseSelector{b.Constant(0_i)}}), [&] {
+        b.Append(b.Case(s, {b.Constant(0_i)}), [&] {
             b.Call(ty.void_(), fn_a);
             b.ExitSwitch(s);
         });
-        b.Append(b.Case(s,
-                        {
-                            core::ir::Switch::CaseSelector{b.Constant(1_i)},
-                            core::ir::Switch::CaseSelector{},
-                        }),
-                 [&] {
-                     b.Call(ty.void_(), fn_b);
-                     b.ExitSwitch(s);
-                 });
-        b.Append(b.Case(s, {core::ir::Switch::CaseSelector{b.Constant(2_i)}}), [&] {
+        b.Append(b.Case(s, {b.Constant(1_i), nullptr}), [&] {
+            b.Call(ty.void_(), fn_b);
+            b.ExitSwitch(s);
+        });
+        b.Append(b.Case(s, {b.Constant(2_i)}), [&] {
             b.Call(ty.void_(), fn_c);
             b.ExitSwitch(s);
         });
@@ -2305,16 +2300,9 @@
         v->SetInitializer(b.Constant(42_i));
 
         auto s = b.Switch(b.Load(v));
-        b.Append(b.Case(s, {core::ir::Switch::CaseSelector{b.Constant(0_i)}}),
-                 [&] { b.Return(fn); });
-        b.Append(b.Case(s,
-                        {
-                            core::ir::Switch::CaseSelector{b.Constant(1_i)},
-                            core::ir::Switch::CaseSelector{},
-                        }),
-                 [&] { b.Return(fn); });
-        b.Append(b.Case(s, {core::ir::Switch::CaseSelector{b.Constant(2_i)}}),
-                 [&] { b.Return(fn); });
+        b.Append(b.Case(s, {b.Constant(0_i)}), [&] { b.Return(fn); });
+        b.Append(b.Case(s, {b.Constant(1_i), nullptr}), [&] { b.Return(fn); });
+        b.Append(b.Case(s, {b.Constant(2_i)}), [&] { b.Return(fn); });
 
         b.Call(ty.void_(), fn_a);
         b.Return(fn);
@@ -2361,29 +2349,18 @@
         v2->SetInitializer(b.Constant(24_i));
 
         auto s1 = b.Switch(b.Load(v1));
-        b.Append(b.Case(s1, {core::ir::Switch::CaseSelector{b.Constant(0_i)}}), [&] {
+        b.Append(b.Case(s1, {b.Constant(0_i)}), [&] {
             b.Call(ty.void_(), fn_a);
             b.ExitSwitch(s1);
         });
-        b.Append(b.Case(s1,
-                        {
-                            core::ir::Switch::CaseSelector{b.Constant(1_i)},
-                            core::ir::Switch::CaseSelector{},
-                        }),
-                 [&] {
-                     auto s2 = b.Switch(b.Load(v2));
-                     b.Append(b.Case(s2, {core::ir::Switch::CaseSelector{b.Constant(0_i)}}),
-                              [&] { b.ExitSwitch(s2); });
-                     b.Append(b.Case(s2,
-                                     {
-                                         core::ir::Switch::CaseSelector{b.Constant(1_i)},
-                                         core::ir::Switch::CaseSelector{},
-                                     }),
-                              [&] { b.Return(fn); });
+        b.Append(b.Case(s1, {b.Constant(1_i), nullptr}), [&] {
+            auto s2 = b.Switch(b.Load(v2));
+            b.Append(b.Case(s2, {b.Constant(0_i)}), [&] { b.ExitSwitch(s2); });
+            b.Append(b.Case(s2, {b.Constant(1_i), nullptr}), [&] { b.Return(fn); });
 
-                     b.ExitSwitch(s1);
-                 });
-        b.Append(b.Case(s1, {core::ir::Switch::CaseSelector{b.Constant(2_i)}}), [&] {
+            b.ExitSwitch(s1);
+        });
+        b.Append(b.Case(s1, {b.Constant(2_i)}), [&] {
             b.Call(ty.void_(), fn_c);
             b.ExitSwitch(s1);
         });