[spirv-writer] Generate kill statements.

This Cl adds preliminary support for generating Kill commands. This may
change in the future if the semantics of kill are set in WGSL to not
match OpKill.

Bug: tint:5
Change-Id: Id466a1b26b37867a26373b93f56d627a0491f47f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/22240
Reviewed-by: David Neto <dneto@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 7c08d05..73f3454 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -688,6 +688,7 @@
     "src/writer/spirv/builder_global_variable_test.cc",
     "src/writer/spirv/builder_ident_expression_test.cc",
     "src/writer/spirv/builder_if_test.cc",
+    "src/writer/spirv/builder_kill_test.cc",
     "src/writer/spirv/builder_literal_test.cc",
     "src/writer/spirv/builder_loop_test.cc",
     "src/writer/spirv/builder_return_test.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 117063b..2c4745a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -425,6 +425,7 @@
     writer/spirv/builder_global_variable_test.cc
     writer/spirv/builder_ident_expression_test.cc
     writer/spirv/builder_if_test.cc
+    writer/spirv/builder_kill_test.cc
     writer/spirv/builder_literal_test.cc
     writer/spirv/builder_loop_test.cc
     writer/spirv/builder_return_test.cc
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index d829a63..084a504 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -251,6 +251,14 @@
   return true;
 }
 
+// TODO(dsinclair): This is generating an OpKill but the semantics of kill
+// haven't been defined for WGSL yet. So, this may need to change.
+// https://github.com/gpuweb/gpuweb/issues/676
+bool Builder::GenerateKillStatement(ast::KillStatement*) {
+  push_function_inst(spv::Op::OpKill, {});
+  return true;
+}
+
 bool Builder::GenerateEntryPoint(ast::EntryPoint* ep) {
   auto name = ep->name();
   if (name.empty()) {
@@ -1405,6 +1413,9 @@
   if (stmt->IsIf()) {
     return GenerateIfStatement(stmt->AsIf());
   }
+  if (stmt->IsKill()) {
+    return GenerateKillStatement(stmt->AsKill());
+  }
   if (stmt->IsLoop()) {
     return GenerateLoopStatement(stmt->AsLoop());
   }
diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h
index 2754b7f..a8433e6 100644
--- a/src/writer/spirv/builder.h
+++ b/src/writer/spirv/builder.h
@@ -194,6 +194,10 @@
   /// @param stmt the statement to generate
   /// @returns true if the statement was successfully generated
   bool GenerateContinueStatement(ast::ContinueStatement* stmt);
+  /// Generates a kill statement
+  /// @param stmt the statement to generate
+  /// @returns true if the statement was successfully generated
+  bool GenerateKillStatement(ast::KillStatement* stmt);
   /// Generates an entry point instruction
   /// @param ep the entry point
   /// @returns true if the instruction was generated, false otherwise
diff --git a/src/writer/spirv/builder_kill_test.cc b/src/writer/spirv/builder_kill_test.cc
new file mode 100644
index 0000000..23437c3
--- /dev/null
+++ b/src/writer/spirv/builder_kill_test.cc
@@ -0,0 +1,43 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "gtest/gtest.h"
+#include "src/ast/kill_statement.h"
+#include "src/context.h"
+#include "src/type_determiner.h"
+#include "src/writer/spirv/builder.h"
+#include "src/writer/spirv/spv_dump.h"
+
+namespace tint {
+namespace writer {
+namespace spirv {
+namespace {
+
+using BuilderTest = testing::Test;
+
+TEST_F(BuilderTest, Kill) {
+  ast::KillStatement expr;
+
+  ast::Module mod;
+  Builder b(&mod);
+  b.push_function(Function{});
+  EXPECT_EQ(b.GenerateKillStatement(&expr), 1u) << b.error();
+  EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(OpKill
+)");
+}
+
+}  // namespace
+}  // namespace spirv
+}  // namespace writer
+}  // namespace tint
\ No newline at end of file