Fuzzers: Avoid passing target backend as parameter

Changes various fuzz targets so that the target back-end language (HLSL,
MSL, SPIR-V or WGSL) is no longer passed as a command line argument, but
instead baked into the fuzzer's binary. This avoids a problem whereby a
ClusterFuzz bug reproducer does not use the required back-end command
line argument.

Change-Id: I64402a23391ca0f24c9d1ffd2aa2f218cc7106b1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/63163
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: Alastair Donaldson <afdx@google.com>
diff --git a/fuzzers/BUILD.gn b/fuzzers/BUILD.gn
index 2e36b52..911c8f6 100644
--- a/fuzzers/BUILD.gn
+++ b/fuzzers/BUILD.gn
@@ -32,7 +32,7 @@
     outputs = [ fuzzer_corpus_wgsl_dir ]
   }
 
-  tint_ast_fuzzer_common_libfuzzer_options = [
+  tint_ast_fuzzer_libfuzzer_options = [
     "cross_over=0",
     "max_len=1000000",
     "mutate_depth=1",
@@ -40,7 +40,7 @@
     "tint_mutation_batch_size=5",
   ]
 
-  tint_regex_fuzzer_common_libfuzzer_options = [
+  tint_regex_fuzzer_libfuzzer_options = [
     "cross_over=0",
     "max_len=100000",
     "mutate_depth=1",
@@ -96,19 +96,17 @@
     }
 
     fuzzer_test("tint_ast_wgsl_writer_fuzzer") {
-      sources = []
+      sources = [ "tint_ast_fuzzer/tint_ast_wgsl_writer_fuzzer.cc" ]
       deps = [ "tint_ast_fuzzer:tint_ast_fuzzer" ]
-      libfuzzer_options = tint_ast_fuzzer_common_libfuzzer_options +
-                          [ "tint_fuzzing_target=wgsl" ]
+      libfuzzer_options = tint_ast_fuzzer_libfuzzer_options
       seed_corpus = fuzzer_corpus_wgsl_dir
       seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
     }
 
     fuzzer_test("tint_regex_wgsl_writer_fuzzer") {
-      sources = []
+      sources = [ "tint_regex_fuzzer/tint_regex_wgsl_writer_fuzzer.cc" ]
       deps = [ "tint_regex_fuzzer:tint_regex_fuzzer" ]
-      libfuzzer_options = tint_regex_fuzzer_common_libfuzzer_options +
-                          [ "tint_fuzzing_target=wgsl" ]
+      libfuzzer_options = tint_regex_fuzzer_libfuzzer_options
       seed_corpus = fuzzer_corpus_wgsl_dir
       seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
     }
@@ -132,10 +130,9 @@
     }
 
     fuzzer_test("tint_ast_spv_writer_fuzzer") {
-      sources = []
+      sources = [ "tint_ast_fuzzer/tint_ast_spv_writer_fuzzer.cc" ]
       deps = [ "tint_ast_fuzzer:tint_ast_fuzzer" ]
-      libfuzzer_options = tint_ast_fuzzer_common_libfuzzer_options +
-                          [ "tint_fuzzing_target=spv" ]
+      libfuzzer_options = tint_ast_fuzzer_libfuzzer_options
       seed_corpus = fuzzer_corpus_wgsl_dir
       seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
     }
@@ -165,10 +162,9 @@
     }
 
     fuzzer_test("tint_regex_spv_writer_fuzzer") {
-      sources = []
+      sources = [ "tint_regex_fuzzer/tint_regex_spv_writer_fuzzer.cc" ]
       deps = [ "tint_regex_fuzzer:tint_regex_fuzzer" ]
-      libfuzzer_options = tint_regex_fuzzer_common_libfuzzer_options +
-                          [ "tint_fuzzing_target=spv" ]
+      libfuzzer_options = tint_regex_fuzzer_libfuzzer_options
       seed_corpus = fuzzer_corpus_wgsl_dir
       seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
     }
@@ -216,19 +212,17 @@
 
   if (tint_build_wgsl_reader && tint_build_hlsl_writer) {
     fuzzer_test("tint_ast_hlsl_writer_fuzzer") {
-      sources = []
+      sources = [ "tint_ast_fuzzer/tint_ast_hlsl_writer_fuzzer.cc" ]
       deps = [ "tint_ast_fuzzer:tint_ast_fuzzer" ]
-      libfuzzer_options = tint_ast_fuzzer_common_libfuzzer_options +
-                          [ "tint_fuzzing_target=hlsl" ]
+      libfuzzer_options = tint_ast_fuzzer_libfuzzer_options
       seed_corpus = fuzzer_corpus_wgsl_dir
       seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
     }
 
     fuzzer_test("tint_regex_hlsl_writer_fuzzer") {
-      sources = []
+      sources = [ "tint_regex_fuzzer/tint_regex_hlsl_writer_fuzzer.cc" ]
       deps = [ "tint_regex_fuzzer:tint_regex_fuzzer" ]
-      libfuzzer_options = tint_regex_fuzzer_common_libfuzzer_options +
-                          [ "tint_fuzzing_target=hlsl" ]
+      libfuzzer_options = tint_regex_fuzzer_libfuzzer_options
       seed_corpus = fuzzer_corpus_wgsl_dir
       seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
     }
@@ -244,19 +238,17 @@
 
   if (tint_build_wgsl_reader && tint_build_msl_writer) {
     fuzzer_test("tint_ast_msl_writer_fuzzer") {
-      sources = []
+      sources = [ "tint_ast_fuzzer/tint_ast_msl_writer_fuzzer.cc" ]
       deps = [ "tint_ast_fuzzer:tint_ast_fuzzer" ]
-      libfuzzer_options = tint_ast_fuzzer_common_libfuzzer_options +
-                          [ "tint_fuzzing_target=msl" ]
+      libfuzzer_options = tint_ast_fuzzer_libfuzzer_options
       seed_corpus = fuzzer_corpus_wgsl_dir
       seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
     }
 
     fuzzer_test("tint_regex_msl_writer_fuzzer") {
-      sources = []
+      sources = [ "tint_regex_fuzzer/tint_regex_msl_writer_fuzzer.cc" ]
       deps = [ "tint_regex_fuzzer:tint_regex_fuzzer" ]
-      libfuzzer_options = tint_regex_fuzzer_common_libfuzzer_options +
-                          [ "tint_fuzzing_target=msl" ]
+      libfuzzer_options = tint_regex_fuzzer_libfuzzer_options
       seed_corpus = fuzzer_corpus_wgsl_dir
       seed_corpus_deps = [ ":tint_generate_wgsl_corpus" ]
     }
diff --git a/fuzzers/tint_ast_fuzzer/BUILD.gn b/fuzzers/tint_ast_fuzzer/BUILD.gn
index e021f3e..888aca5 100644
--- a/fuzzers/tint_ast_fuzzer/BUILD.gn
+++ b/fuzzers/tint_ast_fuzzer/BUILD.gn
@@ -56,6 +56,7 @@
       "mutator.h",
       "node_id_map.cc",
       "node_id_map.h",
+      "override_cli_params.h",
       "probability_context.cc",
       "probability_context.h",
       "protobufs/tint_ast_fuzzer.h",
diff --git a/fuzzers/tint_ast_fuzzer/CMakeLists.txt b/fuzzers/tint_ast_fuzzer/CMakeLists.txt
index bc23dbc..854b08d 100644
--- a/fuzzers/tint_ast_fuzzer/CMakeLists.txt
+++ b/fuzzers/tint_ast_fuzzer/CMakeLists.txt
@@ -12,6 +12,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+function(add_tint_ast_fuzzer NAME)
+  add_executable(${NAME} ${NAME}.cc ${AST_FUZZER_SOURCES})
+  target_link_libraries(${NAME} libtint-fuzz libtint_ast_fuzzer)
+  tint_default_compile_options(${NAME})
+  target_compile_definitions(${NAME} PRIVATE CUSTOM_MUTATOR)
+  target_include_directories(${NAME} PRIVATE ${CMAKE_BINARY_DIR})
+endfunction()
+
 set(PROTOBUF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/protobufs/tint_ast_fuzzer.proto)
 
 file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/protobufs)
@@ -64,17 +72,20 @@
         cli.cc
         cli.h
         fuzzer.cc
+        override_cli_params.h
         ../tint_common_fuzzer.cc
         ../tint_common_fuzzer.h)
 
 set_source_files_properties(fuzzer.cc PROPERTIES COMPILE_FLAGS -Wno-missing-prototypes)
 
-# Add libfuzzer target.
-add_executable(tint_ast_fuzzer ${AST_FUZZER_SOURCES})
-target_link_libraries(tint_ast_fuzzer libtint-fuzz libtint_ast_fuzzer)
-tint_default_compile_options(tint_ast_fuzzer)
-target_compile_definitions(tint_ast_fuzzer PRIVATE CUSTOM_MUTATOR)
-target_include_directories(tint_ast_fuzzer PRIVATE ${CMAKE_BINARY_DIR})
+# Add libfuzzer targets.
+# Targets back-ends according to command line arguments.
+add_tint_ast_fuzzer(tint_ast_fuzzer)
+# Targets back-ends individually.
+add_tint_ast_fuzzer(tint_ast_hlsl_writer_fuzzer)
+add_tint_ast_fuzzer(tint_ast_msl_writer_fuzzer)
+add_tint_ast_fuzzer(tint_ast_spv_writer_fuzzer)
+add_tint_ast_fuzzer(tint_ast_wgsl_writer_fuzzer)
 
 # Add tests.
 if (${TINT_BUILD_TESTS})
diff --git a/fuzzers/tint_ast_fuzzer/fuzzer.cc b/fuzzers/tint_ast_fuzzer/fuzzer.cc
index 9407f82..dcee8dd 100644
--- a/fuzzers/tint_ast_fuzzer/fuzzer.cc
+++ b/fuzzers/tint_ast_fuzzer/fuzzer.cc
@@ -18,6 +18,7 @@
 #include "fuzzers/tint_ast_fuzzer/cli.h"
 #include "fuzzers/tint_ast_fuzzer/mt_rng.h"
 #include "fuzzers/tint_ast_fuzzer/mutator.h"
+#include "fuzzers/tint_ast_fuzzer/override_cli_params.h"
 #include "fuzzers/tint_common_fuzzer.h"
 
 #include "src/reader/wgsl/parser.h"
@@ -34,6 +35,9 @@
   // Parse CLI parameters. `ParseCliParams` will call `exit` if some parameter
   // is invalid.
   cli_params = ParseCliParams(argc, *argv);
+  // For some fuzz targets it is desirable to force the values of certain CLI
+  // parameters after parsing.
+  OverrideCliParams(cli_params);
   return 0;
 }
 
diff --git a/fuzzers/tint_ast_fuzzer/override_cli_params.h b/fuzzers/tint_ast_fuzzer/override_cli_params.h
new file mode 100644
index 0000000..ff7569c
--- /dev/null
+++ b/fuzzers/tint_ast_fuzzer/override_cli_params.h
@@ -0,0 +1,36 @@
+// Copyright 2021 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.
+
+#ifndef FUZZERS_TINT_AST_FUZZER_OVERRIDE_CLI_PARAMS_H_
+#define FUZZERS_TINT_AST_FUZZER_OVERRIDE_CLI_PARAMS_H_
+
+#include "fuzzers/tint_ast_fuzzer/cli.h"
+
+namespace tint {
+namespace fuzzers {
+namespace ast_fuzzer {
+
+/// @brief Allows CLI parameters to be overridden.
+///
+/// This function allows fuzz targets to override particular CLI parameters,
+/// for example forcing a particular back-end to be targeted.
+///
+/// @param cli_params - the parsed CLI parameters to be updated.
+void OverrideCliParams(CliParams& cli_params);
+
+}  // namespace ast_fuzzer
+}  // namespace fuzzers
+}  // namespace tint
+
+#endif  // FUZZERS_TINT_AST_FUZZER_OVERRIDE_CLI_PARAMS_H_
diff --git a/fuzzers/tint_ast_fuzzer/tint_ast_fuzzer.cc b/fuzzers/tint_ast_fuzzer/tint_ast_fuzzer.cc
new file mode 100644
index 0000000..1ce867a
--- /dev/null
+++ b/fuzzers/tint_ast_fuzzer/tint_ast_fuzzer.cc
@@ -0,0 +1,28 @@
+// Copyright 2021 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 "fuzzers/tint_ast_fuzzer/cli.h"
+#include "fuzzers/tint_ast_fuzzer/override_cli_params.h"
+
+namespace tint {
+namespace fuzzers {
+namespace ast_fuzzer {
+
+void OverrideCliParams(CliParams& /*unused*/) {
+  // Leave the CLI parameters unchanged.
+}
+
+}  // namespace ast_fuzzer
+}  // namespace fuzzers
+}  // namespace tint
diff --git a/fuzzers/tint_ast_fuzzer/tint_ast_hlsl_writer_fuzzer.cc b/fuzzers/tint_ast_fuzzer/tint_ast_hlsl_writer_fuzzer.cc
new file mode 100644
index 0000000..6e802dc
--- /dev/null
+++ b/fuzzers/tint_ast_fuzzer/tint_ast_hlsl_writer_fuzzer.cc
@@ -0,0 +1,33 @@
+// Copyright 2021 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 <cassert>
+
+#include "fuzzers/tint_ast_fuzzer/cli.h"
+#include "fuzzers/tint_ast_fuzzer/override_cli_params.h"
+
+namespace tint {
+namespace fuzzers {
+namespace ast_fuzzer {
+
+void OverrideCliParams(CliParams& cli_params) {
+  assert(cli_params.fuzzing_target == FuzzingTarget::kAll &&
+         "The fuzzing target should not have been set by a CLI parameter: it "
+         "should have its default value.");
+  cli_params.fuzzing_target = FuzzingTarget::kHlsl;
+}
+
+}  // namespace ast_fuzzer
+}  // namespace fuzzers
+}  // namespace tint
diff --git a/fuzzers/tint_ast_fuzzer/tint_ast_msl_writer_fuzzer.cc b/fuzzers/tint_ast_fuzzer/tint_ast_msl_writer_fuzzer.cc
new file mode 100644
index 0000000..6af93e7
--- /dev/null
+++ b/fuzzers/tint_ast_fuzzer/tint_ast_msl_writer_fuzzer.cc
@@ -0,0 +1,33 @@
+// Copyright 2021 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 <cassert>
+
+#include "fuzzers/tint_ast_fuzzer/cli.h"
+#include "fuzzers/tint_ast_fuzzer/override_cli_params.h"
+
+namespace tint {
+namespace fuzzers {
+namespace ast_fuzzer {
+
+void OverrideCliParams(CliParams& cli_params) {
+  assert(cli_params.fuzzing_target == FuzzingTarget::kAll &&
+         "The fuzzing target should not have been set by a CLI parameter: it "
+         "should have its default value.");
+  cli_params.fuzzing_target = FuzzingTarget::kMsl;
+}
+
+}  // namespace ast_fuzzer
+}  // namespace fuzzers
+}  // namespace tint
diff --git a/fuzzers/tint_ast_fuzzer/tint_ast_spv_writer_fuzzer.cc b/fuzzers/tint_ast_fuzzer/tint_ast_spv_writer_fuzzer.cc
new file mode 100644
index 0000000..0e37231
--- /dev/null
+++ b/fuzzers/tint_ast_fuzzer/tint_ast_spv_writer_fuzzer.cc
@@ -0,0 +1,33 @@
+// Copyright 2021 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 <cassert>
+
+#include "fuzzers/tint_ast_fuzzer/cli.h"
+#include "fuzzers/tint_ast_fuzzer/override_cli_params.h"
+
+namespace tint {
+namespace fuzzers {
+namespace ast_fuzzer {
+
+void OverrideCliParams(CliParams& cli_params) {
+  assert(cli_params.fuzzing_target == FuzzingTarget::kAll &&
+         "The fuzzing target should not have been set by a CLI parameter: it "
+         "should have its default value.");
+  cli_params.fuzzing_target = FuzzingTarget::kSpv;
+}
+
+}  // namespace ast_fuzzer
+}  // namespace fuzzers
+}  // namespace tint
diff --git a/fuzzers/tint_ast_fuzzer/tint_ast_wgsl_writer_fuzzer.cc b/fuzzers/tint_ast_fuzzer/tint_ast_wgsl_writer_fuzzer.cc
new file mode 100644
index 0000000..03eccae
--- /dev/null
+++ b/fuzzers/tint_ast_fuzzer/tint_ast_wgsl_writer_fuzzer.cc
@@ -0,0 +1,33 @@
+// Copyright 2021 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 <cassert>
+
+#include "fuzzers/tint_ast_fuzzer/cli.h"
+#include "fuzzers/tint_ast_fuzzer/override_cli_params.h"
+
+namespace tint {
+namespace fuzzers {
+namespace ast_fuzzer {
+
+void OverrideCliParams(CliParams& cli_params) {
+  assert(cli_params.fuzzing_target == FuzzingTarget::kAll &&
+         "The fuzzing target should not have been set by a CLI parameter: it "
+         "should have its default value.");
+  cli_params.fuzzing_target = FuzzingTarget::kWgsl;
+}
+
+}  // namespace ast_fuzzer
+}  // namespace fuzzers
+}  // namespace tint
diff --git a/fuzzers/tint_regex_fuzzer/BUILD.gn b/fuzzers/tint_regex_fuzzer/BUILD.gn
index 1ebb545..7b898a9 100644
--- a/fuzzers/tint_regex_fuzzer/BUILD.gn
+++ b/fuzzers/tint_regex_fuzzer/BUILD.gn
@@ -28,6 +28,7 @@
       "cli.cc",
       "cli.h",
       "fuzzer.cc",
+      "override_cli_params.h",
       "wgsl_mutator.cc",
       "wgsl_mutator.h",
     ]
diff --git a/fuzzers/tint_regex_fuzzer/CMakeLists.txt b/fuzzers/tint_regex_fuzzer/CMakeLists.txt
index 3aedb55..d4ae7c1 100644
--- a/fuzzers/tint_regex_fuzzer/CMakeLists.txt
+++ b/fuzzers/tint_regex_fuzzer/CMakeLists.txt
@@ -12,6 +12,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+function(add_tint_regex_fuzzer NAME)
+  add_executable(${NAME} ${NAME}.cc ${REGEX_FUZZER_SOURCES})
+  target_link_libraries(${NAME} libtint-fuzz libtint_regex_fuzzer)
+  tint_default_compile_options(${NAME})
+  target_compile_definitions(${NAME} PRIVATE CUSTOM_MUTATOR)
+  target_include_directories(${NAME} PRIVATE ${CMAKE_BINARY_DIR})
+endfunction()
+
 set(LIBTINT_REGEX_FUZZER_SOURCES
         util.h
         wgsl_mutator.cc
@@ -25,16 +33,20 @@
         cli.cc
         cli.h
         fuzzer.cc
+        override_cli_params.h
         ../tint_common_fuzzer.cc
         ../tint_common_fuzzer.h)
 
-# Add libfuzzer target.
-add_executable(tint_regex_fuzzer ${REGEX_FUZZER_SOURCES})
-target_compile_options(tint_regex_fuzzer PRIVATE
-        -Wno-missing-prototypes)
-target_link_libraries(tint_regex_fuzzer libtint-fuzz libtint_regex_fuzzer)
-tint_default_compile_options(tint_regex_fuzzer)
-target_compile_definitions(tint_regex_fuzzer PUBLIC CUSTOM_MUTATOR)
+set_source_files_properties(fuzzer.cc PROPERTIES COMPILE_FLAGS -Wno-missing-prototypes)
+
+# Add libfuzzer targets.
+# Targets back-ends according to command line arguments.
+add_tint_regex_fuzzer(tint_regex_fuzzer)
+# Targets back-ends individually.
+add_tint_regex_fuzzer(tint_regex_hlsl_writer_fuzzer)
+add_tint_regex_fuzzer(tint_regex_msl_writer_fuzzer)
+add_tint_regex_fuzzer(tint_regex_spv_writer_fuzzer)
+add_tint_regex_fuzzer(tint_regex_wgsl_writer_fuzzer)
 
 # Add tests.
 if (${TINT_BUILD_TESTS})
diff --git a/fuzzers/tint_regex_fuzzer/fuzzer.cc b/fuzzers/tint_regex_fuzzer/fuzzer.cc
index e16028a..5c527c3 100644
--- a/fuzzers/tint_regex_fuzzer/fuzzer.cc
+++ b/fuzzers/tint_regex_fuzzer/fuzzer.cc
@@ -18,6 +18,7 @@
 
 #include "fuzzers/tint_common_fuzzer.h"
 #include "fuzzers/tint_regex_fuzzer/cli.h"
+#include "fuzzers/tint_regex_fuzzer/override_cli_params.h"
 #include "fuzzers/tint_regex_fuzzer/util.h"
 #include "fuzzers/tint_regex_fuzzer/wgsl_mutator.h"
 
@@ -44,6 +45,9 @@
   // Parse CLI parameters. `ParseCliParams` will call `exit` if some parameter
   // is invalid.
   cli_params = ParseCliParams(argc, *argv);
+  // For some fuzz targets it is desirable to force the values of certain CLI
+  // parameters after parsing.
+  OverrideCliParams(cli_params);
   return 0;
 }
 
diff --git a/fuzzers/tint_regex_fuzzer/override_cli_params.h b/fuzzers/tint_regex_fuzzer/override_cli_params.h
new file mode 100644
index 0000000..f5025fc
--- /dev/null
+++ b/fuzzers/tint_regex_fuzzer/override_cli_params.h
@@ -0,0 +1,36 @@
+// Copyright 2021 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.
+
+#ifndef FUZZERS_TINT_REGEX_FUZZER_OVERRIDE_CLI_PARAMS_H_
+#define FUZZERS_TINT_REGEX_FUZZER_OVERRIDE_CLI_PARAMS_H_
+
+#include "fuzzers/tint_regex_fuzzer/cli.h"
+
+namespace tint {
+namespace fuzzers {
+namespace regex_fuzzer {
+
+/// @brief Allows CLI parameters to be overridden.
+///
+/// This function allows fuzz targets to override particular CLI parameters,
+/// for example forcing a particular back-end to be targeted.
+///
+/// @param cli_params - the parsed CLI parameters to be updated.
+void OverrideCliParams(CliParams& cli_params);
+
+}  // namespace regex_fuzzer
+}  // namespace fuzzers
+}  // namespace tint
+
+#endif  // FUZZERS_TINT_REGEX_FUZZER_OVERRIDE_CLI_PARAMS_H_
diff --git a/fuzzers/tint_regex_fuzzer/tint_regex_fuzzer.cc b/fuzzers/tint_regex_fuzzer/tint_regex_fuzzer.cc
new file mode 100644
index 0000000..1714393
--- /dev/null
+++ b/fuzzers/tint_regex_fuzzer/tint_regex_fuzzer.cc
@@ -0,0 +1,28 @@
+// Copyright 2021 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 "fuzzers/tint_regex_fuzzer/cli.h"
+#include "fuzzers/tint_regex_fuzzer/override_cli_params.h"
+
+namespace tint {
+namespace fuzzers {
+namespace regex_fuzzer {
+
+void OverrideCliParams(CliParams& /*unused*/) {
+  // Leave the CLI parameters unchanged.
+}
+
+}  // namespace regex_fuzzer
+}  // namespace fuzzers
+}  // namespace tint
diff --git a/fuzzers/tint_regex_fuzzer/tint_regex_hlsl_writer_fuzzer.cc b/fuzzers/tint_regex_fuzzer/tint_regex_hlsl_writer_fuzzer.cc
new file mode 100644
index 0000000..54a78c5
--- /dev/null
+++ b/fuzzers/tint_regex_fuzzer/tint_regex_hlsl_writer_fuzzer.cc
@@ -0,0 +1,33 @@
+// Copyright 2021 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 <cassert>
+
+#include "fuzzers/tint_regex_fuzzer/cli.h"
+#include "fuzzers/tint_regex_fuzzer/override_cli_params.h"
+
+namespace tint {
+namespace fuzzers {
+namespace regex_fuzzer {
+
+void OverrideCliParams(CliParams& cli_params) {
+  assert(cli_params.fuzzing_target == FuzzingTarget::kAll &&
+         "The fuzzing target should not have been set by a CLI parameter: it "
+         "should have its default value.");
+  cli_params.fuzzing_target = FuzzingTarget::kHlsl;
+}
+
+}  // namespace regex_fuzzer
+}  // namespace fuzzers
+}  // namespace tint
diff --git a/fuzzers/tint_regex_fuzzer/tint_regex_msl_writer_fuzzer.cc b/fuzzers/tint_regex_fuzzer/tint_regex_msl_writer_fuzzer.cc
new file mode 100644
index 0000000..0d059a7
--- /dev/null
+++ b/fuzzers/tint_regex_fuzzer/tint_regex_msl_writer_fuzzer.cc
@@ -0,0 +1,33 @@
+// Copyright 2021 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 <cassert>
+
+#include "fuzzers/tint_regex_fuzzer/cli.h"
+#include "fuzzers/tint_regex_fuzzer/override_cli_params.h"
+
+namespace tint {
+namespace fuzzers {
+namespace regex_fuzzer {
+
+void OverrideCliParams(CliParams& cli_params) {
+  assert(cli_params.fuzzing_target == FuzzingTarget::kAll &&
+         "The fuzzing target should not have been set by a CLI parameter: it "
+         "should have its default value.");
+  cli_params.fuzzing_target = FuzzingTarget::kMsl;
+}
+
+}  // namespace regex_fuzzer
+}  // namespace fuzzers
+}  // namespace tint
diff --git a/fuzzers/tint_regex_fuzzer/tint_regex_spv_writer_fuzzer.cc b/fuzzers/tint_regex_fuzzer/tint_regex_spv_writer_fuzzer.cc
new file mode 100644
index 0000000..34a4ee3
--- /dev/null
+++ b/fuzzers/tint_regex_fuzzer/tint_regex_spv_writer_fuzzer.cc
@@ -0,0 +1,33 @@
+// Copyright 2021 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 <cassert>
+
+#include "fuzzers/tint_regex_fuzzer/cli.h"
+#include "fuzzers/tint_regex_fuzzer/override_cli_params.h"
+
+namespace tint {
+namespace fuzzers {
+namespace regex_fuzzer {
+
+void OverrideCliParams(CliParams& cli_params) {
+  assert(cli_params.fuzzing_target == FuzzingTarget::kAll &&
+         "The fuzzing target should not have been set by a CLI parameter: it "
+         "should have its default value.");
+  cli_params.fuzzing_target = FuzzingTarget::kSpv;
+}
+
+}  // namespace regex_fuzzer
+}  // namespace fuzzers
+}  // namespace tint
diff --git a/fuzzers/tint_regex_fuzzer/tint_regex_wgsl_writer_fuzzer.cc b/fuzzers/tint_regex_fuzzer/tint_regex_wgsl_writer_fuzzer.cc
new file mode 100644
index 0000000..4de33b6
--- /dev/null
+++ b/fuzzers/tint_regex_fuzzer/tint_regex_wgsl_writer_fuzzer.cc
@@ -0,0 +1,33 @@
+// Copyright 2021 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 <cassert>
+
+#include "fuzzers/tint_regex_fuzzer/cli.h"
+#include "fuzzers/tint_regex_fuzzer/override_cli_params.h"
+
+namespace tint {
+namespace fuzzers {
+namespace regex_fuzzer {
+
+void OverrideCliParams(CliParams& cli_params) {
+  assert(cli_params.fuzzing_target == FuzzingTarget::kAll &&
+         "The fuzzing target should not have been set by a CLI parameter: it "
+         "should have its default value.");
+  cli_params.fuzzing_target = FuzzingTarget::kWgsl;
+}
+
+}  // namespace regex_fuzzer
+}  // namespace fuzzers
+}  // namespace tint