[ir] Change base class for terminators.

This CL moves the FunctionTerminator and RootTerminator nodes to be
blocks instead of FlowNodes.

Bug: tint:1718
Change-Id: Iee7830bccd99e4587b95b22b53268d1d2921e82f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/134222
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/ir/debug.cc b/src/tint/ir/debug.cc
index 7e8155df..807e951 100644
--- a/src/tint/ir/debug.cc
+++ b/src/tint/ir/debug.cc
@@ -56,6 +56,9 @@
 
         tint::Switch(
             node,
+            [&](const ir::FunctionTerminator*) {
+                // Already done
+            },
             [&](const ir::Block* b) {
                 if (node_to_name.count(b) == 0) {
                     out << name_for(b) << R"( [label="block"])" << std::endl;
@@ -69,9 +72,6 @@
 
                 out << std::endl;
                 Graph(b->Branch()->To());
-            },
-            [&](const ir::FunctionTerminator*) {
-                // Already done
             });
     };
 
diff --git a/src/tint/ir/disassembler.cc b/src/tint/ir/disassembler.cc
index bc957c9..dd9904f 100644
--- a/src/tint/ir/disassembler.cc
+++ b/src/tint/ir/disassembler.cc
@@ -153,6 +153,15 @@
                 out_ << " -> %fn" << IdOf(f->StartTarget()) << std::endl;
                 walk_list_.push_back(f->StartTarget());
             },
+            [&](const ir::FunctionTerminator* t) {
+                TINT_ASSERT(IR, in_function_);
+                Indent() << "%fn" << IdOf(t) << " = func_terminator" << std::endl << std::endl;
+                in_function_ = false;
+            },
+            [&](const ir::RootTerminator* t) {
+                TINT_ASSERT(IR, !in_function_);
+                Indent() << "%fn" << IdOf(t) << " = root_terminator" << std::endl << std::endl;
+            },
             [&](const ir::Block* b) {
                 // If this block is dead, nothing to do
                 if (!b->HasBranchTarget()) {
@@ -183,15 +192,6 @@
                 }
 
                 walk_list_.push_back(b->Branch()->To());
-            },
-            [&](const ir::FunctionTerminator* t) {
-                TINT_ASSERT(IR, in_function_);
-                Indent() << "%fn" << IdOf(t) << " = func_terminator" << std::endl << std::endl;
-                in_function_ = false;
-            },
-            [&](const ir::RootTerminator* t) {
-                TINT_ASSERT(IR, !in_function_);
-                Indent() << "%fn" << IdOf(t) << " = root_terminator" << std::endl << std::endl;
             });
     }
 }
diff --git a/src/tint/ir/function_terminator.h b/src/tint/ir/function_terminator.h
index 668eab6..42aa01e 100644
--- a/src/tint/ir/function_terminator.h
+++ b/src/tint/ir/function_terminator.h
@@ -15,13 +15,13 @@
 #ifndef SRC_TINT_IR_FUNCTION_TERMINATOR_H_
 #define SRC_TINT_IR_FUNCTION_TERMINATOR_H_
 
-#include "src/tint/ir/flow_node.h"
+#include "src/tint/ir/block.h"
 
 namespace tint::ir {
 
-/// Flow node used as the end of a function. Must only be used as the `end_target` in a function
-/// flow node. There are no instructions and no branches from this node.
-class FunctionTerminator : public utils::Castable<FunctionTerminator, FlowNode> {
+/// Block used as the end of a function. Must only be used as the `end_target` in a function. There
+/// are no instructions in this block.
+class FunctionTerminator : public utils::Castable<FunctionTerminator, Block> {
   public:
     /// Constructor
     FunctionTerminator();
diff --git a/src/tint/ir/root_terminator.h b/src/tint/ir/root_terminator.h
index 361aa6d..4a52b32 100644
--- a/src/tint/ir/root_terminator.h
+++ b/src/tint/ir/root_terminator.h
@@ -15,13 +15,12 @@
 #ifndef SRC_TINT_IR_ROOT_TERMINATOR_H_
 #define SRC_TINT_IR_ROOT_TERMINATOR_H_
 
-#include "src/tint/ir/flow_node.h"
+#include "src/tint/ir/block.h"
 
 namespace tint::ir {
 
-/// Flow node used as the end of a function. Must only be used as the `end_target` in a function
-/// flow node. There are no instructions and no branches from this node.
-class RootTerminator : public utils::Castable<RootTerminator, FlowNode> {
+/// Block used as the end of a root block. There are no instructions in this block.
+class RootTerminator : public utils::Castable<RootTerminator, Block> {
   public:
     /// Constructor
     RootTerminator();
diff --git a/src/tint/ir/to_program.cc b/src/tint/ir/to_program.cc
index 390266d..05b735c 100644
--- a/src/tint/ir/to_program.cc
+++ b/src/tint/ir/to_program.cc
@@ -126,6 +126,8 @@
             Status status = tint::Switch(
                 block,
 
+                [&](const ir::FunctionTerminator*) { return kStop; },
+
                 [&](const ir::Block* blk) {
                     for (auto* inst : blk->Instructions()) {
                         auto stmt = Stmt(inst);
@@ -150,8 +152,6 @@
                     return kStop;
                 },
 
-                [&](const ir::FunctionTerminator*) { return kStop; },
-
                 [&](Default) {
                     UNHANDLED_CASE(block);
                     return kError;
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir.cc b/src/tint/writer/spirv/ir/generator_impl_ir.cc
index 494f78f..f1e3410 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir.cc
@@ -355,7 +355,6 @@
 void GeneratorImplIr::EmitBranch(const ir::Branch* b) {
     Switch(
         b->To(),
-        [&](const ir::Block* blk) { current_function_.push_inst(spv::Op::OpBranch, {Label(blk)}); },
         [&](const ir::FunctionTerminator*) {
             if (!b->Args().IsEmpty()) {
                 TINT_ASSERT(Writer, b->Args().Length() == 1u);
@@ -366,6 +365,7 @@
                 current_function_.push_inst(spv::Op::OpReturn, {});
             }
         },
+        [&](const ir::Block* blk) { current_function_.push_inst(spv::Op::OpBranch, {Label(blk)}); },
         [&](Default) {
             // A block may not have an outward branch (e.g. an unreachable merge
             // block).