[tint][spirv] Add a SPIR-V writer IR fuzzer.

Change-Id: I0ab8cbe6f6f897674f96bd7bad95416653d95d19
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/162309
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Auto-Submit: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/spirv/writer/BUILD.cmake b/src/tint/lang/spirv/writer/BUILD.cmake
index 6db12a5..bdcb472 100644
--- a/src/tint/lang/spirv/writer/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/BUILD.cmake
@@ -230,10 +230,12 @@
 # Condition: TINT_BUILD_SPV_WRITER
 ################################################################################
 tint_add_target(tint_lang_spirv_writer_fuzz fuzz
+  lang/spirv/writer/writer_fuzz.cc
 )
 
 tint_target_add_dependencies(tint_lang_spirv_writer_fuzz fuzz
   tint_api_common
+  tint_cmd_fuzz_ir_fuzz
   tint_lang_core
   tint_lang_core_constant
   tint_lang_core_ir
@@ -269,6 +271,7 @@
   tint_target_add_dependencies(tint_lang_spirv_writer_fuzz fuzz
     tint_lang_spirv_writer
     tint_lang_spirv_writer_common
+    tint_lang_spirv_writer_helpers
   )
 endif(TINT_BUILD_SPV_WRITER)
 
diff --git a/src/tint/lang/spirv/writer/BUILD.gn b/src/tint/lang/spirv/writer/BUILD.gn
index 968d178..7ed3b89 100644
--- a/src/tint/lang/spirv/writer/BUILD.gn
+++ b/src/tint/lang/spirv/writer/BUILD.gn
@@ -203,9 +203,10 @@
 }
 if (tint_build_spv_writer) {
   tint_fuzz_source_set("fuzz") {
-    sources = []
+    sources = [ "writer_fuzz.cc" ]
     deps = [
       "${tint_src_dir}/api/common",
+      "${tint_src_dir}/cmd/fuzz/ir:fuzz",
       "${tint_src_dir}/lang/core",
       "${tint_src_dir}/lang/core/constant",
       "${tint_src_dir}/lang/core/ir",
@@ -239,6 +240,7 @@
       deps += [
         "${tint_src_dir}/lang/spirv/writer",
         "${tint_src_dir}/lang/spirv/writer/common",
+        "${tint_src_dir}/lang/spirv/writer/helpers",
       ]
     }
 
diff --git a/src/tint/lang/spirv/writer/writer_fuzz.cc b/src/tint/lang/spirv/writer/writer_fuzz.cc
new file mode 100644
index 0000000..ff37ab7
--- /dev/null
+++ b/src/tint/lang/spirv/writer/writer_fuzz.cc
@@ -0,0 +1,53 @@
+// Copyright 2023 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/spirv/writer/writer.h"
+
+#include "src/tint/cmd/fuzz/ir/fuzz.h"
+#include "src/tint/lang/spirv/validate/validate.h"
+#include "src/tint/lang/spirv/writer/helpers/generate_bindings.h"
+
+namespace tint::spirv::writer {
+namespace {
+
+void IRPrinterFuzzer(core::ir::Module& module, Options options) {
+    options.bindings = GenerateBindings(module);
+    auto output = Generate(module, options);
+    if (!output) {
+        return;
+    }
+    auto& spirv = output->spirv;
+    if (auto res = validate::Validate(Slice(spirv.data(), spirv.size())); !res) {
+        TINT_ICE() << "Output of SPIR-V writer failed to validate with SPIR-V Tools\n"
+                   << res.Failure();
+    }
+}
+
+}  // namespace
+}  // namespace tint::spirv::writer
+
+TINT_IR_MODULE_FUZZER(tint::spirv::writer::IRPrinterFuzzer);