tint: Simplify backend Sanitize functions by passing in Options

Reduces the amount of variable duplication and copying we do.

Bug: tint:1495
Change-Id: I7999eadf09dc899361926e01dea715e9edc124c9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/86203
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/tint/writer/hlsl/generator.cc b/src/tint/writer/hlsl/generator.cc
index a24d129..682d371 100644
--- a/src/tint/writer/hlsl/generator.cc
+++ b/src/tint/writer/hlsl/generator.cc
@@ -31,10 +31,7 @@
   Result result;
 
   // Sanitize the program.
-  auto sanitized_result = Sanitize(program, options.root_constant_binding_point,
-                                   options.disable_workgroup_init,
-                                   options.generate_external_texture_bindings,
-                                   options.array_length_from_uniform);
+  auto sanitized_result = Sanitize(program, options);
   if (!sanitized_result.program.IsValid()) {
     result.success = false;
     result.error = sanitized_result.program.Diagnostics().str();
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index 110071f..008f184 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -134,12 +134,7 @@
 SanitizedResult::~SanitizedResult() = default;
 SanitizedResult::SanitizedResult(SanitizedResult&&) = default;
 
-SanitizedResult Sanitize(
-    const Program* in,
-    sem::BindingPoint root_constant_binding_point,
-    bool disable_workgroup_init,
-    bool generate_external_texture_bindings,
-    const ArrayLengthFromUniformOptions& array_length_from_uniform) {
+SanitizedResult Sanitize(const Program* in, const Options& options) {
   transform::Manager manager;
   transform::DataMap data;
 
@@ -158,12 +153,13 @@
   }
 
   // Build the config for the internal ArrayLengthFromUniform transform.
+  auto& array_length_from_uniform = options.array_length_from_uniform;
   transform::ArrayLengthFromUniform::Config array_length_from_uniform_cfg(
       array_length_from_uniform.ubo_binding);
   array_length_from_uniform_cfg.bindpoint_to_size_index =
       array_length_from_uniform.bindpoint_to_size_index;
 
-  if (generate_external_texture_bindings) {
+  if (options.generate_external_texture_bindings) {
     auto new_bindings_map = GenerateExternalTextureBindings(in);
     data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(
         new_bindings_map);
@@ -186,7 +182,7 @@
   manager.Add<transform::FoldTrivialSingleUseLets>();
   manager.Add<transform::LoopToForLoop>();
 
-  if (!disable_workgroup_init) {
+  if (!options.disable_workgroup_init) {
     // ZeroInitWorkgroupMemory must come before CanonicalizeEntryPointIO as
     // ZeroInitWorkgroupMemory may inject new builtin parameters.
     manager.Add<transform::ZeroInitWorkgroupMemory>();
@@ -227,7 +223,7 @@
   data.Add<transform::CanonicalizeEntryPointIO::Config>(
       transform::CanonicalizeEntryPointIO::ShaderStyle::kHlsl);
   data.Add<transform::NumWorkgroupsFromUniform::Config>(
-      root_constant_binding_point);
+      options.root_constant_binding_point);
 
   auto out = manager.Run(in, data);
 
diff --git a/src/tint/writer/hlsl/generator_impl.h b/src/tint/writer/hlsl/generator_impl.h
index 96481c2..4048430 100644
--- a/src/tint/writer/hlsl/generator_impl.h
+++ b/src/tint/writer/hlsl/generator_impl.h
@@ -37,6 +37,7 @@
 #include "src/tint/transform/decompose_memory_access.h"
 #include "src/tint/utils/hash.h"
 #include "src/tint/writer/array_length_from_uniform_options.h"
+#include "src/tint/writer/hlsl/generator.h"
 #include "src/tint/writer/text_generator.h"
 
 // Forward declarations
@@ -66,16 +67,10 @@
 };
 
 /// Sanitize a program in preparation for generating HLSL.
-/// @param root_constant_binding_point the binding point to use for information
-/// that will be passed via root constants
-/// @param disable_workgroup_init `true` to disable workgroup memory zero
+/// @program The program to sanitize
+/// @param options The HLSL generator options.
 /// @returns the sanitized program and any supplementary information
-SanitizedResult Sanitize(
-    const Program* program,
-    sem::BindingPoint root_constant_binding_point = {},
-    bool disable_workgroup_init = false,
-    bool generate_external_texture_bindings = false,
-    const ArrayLengthFromUniformOptions& array_length_from_uniform = {});
+SanitizedResult Sanitize(const Program* program, const Options& options);
 
 /// Implementation class for HLSL generator
 class GeneratorImpl : public TextGenerator {
diff --git a/src/tint/writer/hlsl/test_helper.h b/src/tint/writer/hlsl/test_helper.h
index 2fc800d..a75d725 100644
--- a/src/tint/writer/hlsl/test_helper.h
+++ b/src/tint/writer/hlsl/test_helper.h
@@ -76,11 +76,7 @@
           << formatter.format(program->Diagnostics());
     }();
 
-    auto sanitized_result =
-        Sanitize(program.get(), options.root_constant_binding_point,
-                 options.disable_workgroup_init,
-                 options.generate_external_texture_bindings,
-                 options.array_length_from_uniform);
+    auto sanitized_result = Sanitize(program.get(), options);
     [&]() {
       ASSERT_TRUE(sanitized_result.program.IsValid())
           << formatter.format(sanitized_result.program.Diagnostics());
diff --git a/src/tint/writer/msl/generator.cc b/src/tint/writer/msl/generator.cc
index ecb1b57..ee33006 100644
--- a/src/tint/writer/msl/generator.cc
+++ b/src/tint/writer/msl/generator.cc
@@ -33,11 +33,7 @@
   Result result;
 
   // Sanitize the program.
-  auto sanitized_result = Sanitize(
-      program, options.buffer_size_ubo_index, options.fixed_sample_mask,
-      options.emit_vertex_point_size, options.disable_workgroup_init,
-      options.generate_external_texture_bindings,
-      options.array_length_from_uniform);
+  auto sanitized_result = Sanitize(program, options);
   if (!sanitized_result.program.IsValid()) {
     result.success = false;
     result.error = sanitized_result.program.Diagnostics().str();
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index 9aa48de..349ed1d 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -119,14 +119,7 @@
 SanitizedResult::~SanitizedResult() = default;
 SanitizedResult::SanitizedResult(SanitizedResult&&) = default;
 
-SanitizedResult Sanitize(
-    const Program* in,
-    uint32_t buffer_size_ubo_index,
-    uint32_t fixed_sample_mask,
-    bool emit_vertex_point_size,
-    bool disable_workgroup_init,
-    bool generate_external_texture_bindings,
-    const ArrayLengthFromUniformOptions& array_length_from_uniform) {
+SanitizedResult Sanitize(const Program* in, const Options& options) {
   transform::Manager manager;
   transform::DataMap data;
 
@@ -142,6 +135,7 @@
   }
 
   // Build the config for the internal ArrayLengthFromUniform transform.
+  auto& array_length_from_uniform = options.array_length_from_uniform;
   transform::ArrayLengthFromUniform::Config array_length_from_uniform_cfg(
       array_length_from_uniform.ubo_binding);
   if (!array_length_from_uniform.bindpoint_to_size_index.empty()) {
@@ -152,7 +146,7 @@
     // If the binding map is empty, use the deprecated |buffer_size_ubo_index|
     // and automatically choose indices using the binding numbers.
     array_length_from_uniform_cfg = transform::ArrayLengthFromUniform::Config(
-        sem::BindingPoint{0, buffer_size_ubo_index});
+        sem::BindingPoint{0, options.buffer_size_ubo_index});
     // Use the SSBO binding numbers as the indices for the buffer size lookups.
     for (auto* var : in->AST().GlobalVariables()) {
       auto* global = in->Sem().Get<sem::GlobalVariable>(var);
@@ -165,10 +159,10 @@
 
   // Build the configs for the internal CanonicalizeEntryPointIO transform.
   auto entry_point_io_cfg = transform::CanonicalizeEntryPointIO::Config(
-      transform::CanonicalizeEntryPointIO::ShaderStyle::kMsl, fixed_sample_mask,
-      emit_vertex_point_size);
+      transform::CanonicalizeEntryPointIO::ShaderStyle::kMsl,
+      options.fixed_sample_mask, options.emit_vertex_point_size);
 
-  if (generate_external_texture_bindings) {
+  if (options.generate_external_texture_bindings) {
     auto new_bindings_map = GenerateExternalTextureBindings(in);
     data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(
         new_bindings_map);
@@ -177,7 +171,7 @@
 
   manager.Add<transform::Unshadow>();
 
-  if (!disable_workgroup_init) {
+  if (!options.disable_workgroup_init) {
     // ZeroInitWorkgroupMemory must come before CanonicalizeEntryPointIO as
     // ZeroInitWorkgroupMemory may inject new builtin parameters.
     manager.Add<transform::ZeroInitWorkgroupMemory>();
diff --git a/src/tint/writer/msl/generator_impl.h b/src/tint/writer/msl/generator_impl.h
index f6e2c62..f3cee25 100644
--- a/src/tint/writer/msl/generator_impl.h
+++ b/src/tint/writer/msl/generator_impl.h
@@ -39,6 +39,7 @@
 #include "src/tint/scope_stack.h"
 #include "src/tint/sem/struct.h"
 #include "src/tint/writer/array_length_from_uniform_options.h"
+#include "src/tint/writer/msl/generator.h"
 #include "src/tint/writer/text_generator.h"
 
 // Forward declarations
@@ -70,19 +71,10 @@
 };
 
 /// Sanitize a program in preparation for generating MSL.
-/// @param buffer_size_ubo_index the index to use for the buffer size UBO
-/// @param fixed_sample_mask the fixed sample mask to use for fragment shaders
-/// @param emit_vertex_point_size `true` to emit a vertex point size builtin
-/// @param disable_workgroup_init `true` to disable workgroup memory zero
+/// @program The program to sanitize
+/// @param options The MSL generator options.
 /// @returns the sanitized program and any supplementary information
-SanitizedResult Sanitize(
-    const Program* program,
-    uint32_t buffer_size_ubo_index,
-    uint32_t fixed_sample_mask = 0xFFFFFFFF,
-    bool emit_vertex_point_size = false,
-    bool disable_workgroup_init = false,
-    bool generate_external_texture_bindings = false,
-    const ArrayLengthFromUniformOptions& array_length_from_uniform = {});
+SanitizedResult Sanitize(const Program* program, const Options& options);
 
 /// Implementation class for MSL generator
 class GeneratorImpl : public TextGenerator {
diff --git a/src/tint/writer/msl/test_helper.h b/src/tint/writer/msl/test_helper.h
index 88f1ff5..25fb046 100644
--- a/src/tint/writer/msl/test_helper.h
+++ b/src/tint/writer/msl/test_helper.h
@@ -74,11 +74,7 @@
           << diag::Formatter().format(program->Diagnostics());
     }();
 
-    auto result = Sanitize(
-        program.get(), options.buffer_size_ubo_index, options.fixed_sample_mask,
-        options.emit_vertex_point_size, options.disable_workgroup_init,
-        options.generate_external_texture_bindings,
-        options.array_length_from_uniform);
+    auto result = Sanitize(program.get(), options);
     [&]() {
       ASSERT_TRUE(result.program.IsValid())
           << diag::Formatter().format(result.program.Diagnostics());
diff --git a/src/tint/writer/spirv/builder.cc b/src/tint/writer/spirv/builder.cc
index 97d2d7d..436f977 100644
--- a/src/tint/writer/spirv/builder.cc
+++ b/src/tint/writer/spirv/builder.cc
@@ -255,10 +255,7 @@
 
 }  // namespace
 
-SanitizedResult Sanitize(const Program* in,
-                         bool emit_vertex_point_size,
-                         bool disable_workgroup_init,
-                         bool generate_external_texture_bindings) {
+SanitizedResult Sanitize(const Program* in, const Options& options) {
   transform::Manager manager;
   transform::DataMap data;
 
@@ -275,7 +272,7 @@
     manager.Add<transform::BuiltinPolyfill>();
   }
 
-  if (generate_external_texture_bindings) {
+  if (options.generate_external_texture_bindings) {
     auto new_bindings_map = GenerateExternalTextureBindings(in);
     data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(
         new_bindings_map);
@@ -283,7 +280,10 @@
   manager.Add<transform::MultiplanarExternalTexture>();
 
   manager.Add<transform::Unshadow>();
-  if (!disable_workgroup_init) {
+  bool disable_workgroup_init_in_sanitizer =
+      options.disable_workgroup_init ||
+      options.use_zero_initialize_workgroup_memory_extension;
+  if (!disable_workgroup_init_in_sanitizer) {
     manager.Add<transform::ZeroInitWorkgroupMemory>();
   }
   manager.Add<transform::RemoveUnreachableStatements>();
@@ -303,7 +303,7 @@
   data.Add<transform::CanonicalizeEntryPointIO::Config>(
       transform::CanonicalizeEntryPointIO::Config(
           transform::CanonicalizeEntryPointIO::ShaderStyle::kSpirv, 0xFFFFFFFF,
-          emit_vertex_point_size));
+          options.emit_vertex_point_size));
 
   SanitizedResult result;
   result.program = std::move(manager.Run(in, data).program);
diff --git a/src/tint/writer/spirv/builder.h b/src/tint/writer/spirv/builder.h
index f789683..c36efcc 100644
--- a/src/tint/writer/spirv/builder.h
+++ b/src/tint/writer/spirv/builder.h
@@ -38,6 +38,7 @@
 #include "src/tint/sem/builtin.h"
 #include "src/tint/sem/storage_texture_type.h"
 #include "src/tint/writer/spirv/function.h"
+#include "src/tint/writer/spirv/generator.h"
 #include "src/tint/writer/spirv/scalar_constant.h"
 
 // Forward declarations
@@ -57,13 +58,9 @@
 };
 
 /// Sanitize a program in preparation for generating SPIR-V.
-/// @param emit_vertex_point_size `true` to emit a vertex point size builtin
-/// @param disable_workgroup_init `true` to disable workgroup memory zero
-/// @returns the sanitized program and any supplementary information
-SanitizedResult Sanitize(const Program* program,
-                         bool emit_vertex_point_size = false,
-                         bool disable_workgroup_init = false,
-                         bool generate_external_texture_bindings = false);
+/// @program The program to sanitize
+/// @param options The SPIR-V generator options.
+SanitizedResult Sanitize(const Program* program, const Options& options);
 
 /// Builder class to create SPIR-V instructions from a module.
 class Builder {
diff --git a/src/tint/writer/spirv/builder_entry_point_test.cc b/src/tint/writer/spirv/builder_entry_point_test.cc
index 738aa4b..23c5e67 100644
--- a/src/tint/writer/spirv/builder_entry_point_test.cc
+++ b/src/tint/writer/spirv/builder_entry_point_test.cc
@@ -221,30 +221,32 @@
 
   EXPECT_EQ(DumpBuilder(b), R"(OpCapability Shader
 OpMemoryModel Logical GLSL450
-OpEntryPoint Vertex %22 "vert_main" %1 %5
-OpEntryPoint Fragment %32 "frag_main" %9 %11 %13
-OpExecutionMode %32 OriginUpperLeft
-OpExecutionMode %32 DepthReplacing
+OpEntryPoint Vertex %23 "vert_main" %1 %5 %9
+OpEntryPoint Fragment %34 "frag_main" %10 %12 %14
+OpExecutionMode %34 OriginUpperLeft
+OpExecutionMode %34 DepthReplacing
 OpName %1 "value_1"
 OpName %5 "pos_1"
-OpName %9 "value_2"
-OpName %11 "pos_2"
-OpName %13 "value_3"
-OpName %15 "Interface"
-OpMemberName %15 0 "value"
-OpMemberName %15 1 "pos"
-OpName %16 "vert_main_inner"
-OpName %22 "vert_main"
-OpName %28 "frag_main_inner"
-OpName %29 "inputs"
-OpName %32 "frag_main"
+OpName %9 "vertex_point_size"
+OpName %10 "value_2"
+OpName %12 "pos_2"
+OpName %14 "value_3"
+OpName %16 "Interface"
+OpMemberName %16 0 "value"
+OpMemberName %16 1 "pos"
+OpName %17 "vert_main_inner"
+OpName %23 "vert_main"
+OpName %30 "frag_main_inner"
+OpName %31 "inputs"
+OpName %34 "frag_main"
 OpDecorate %1 Location 1
 OpDecorate %5 BuiltIn Position
-OpDecorate %9 Location 1
-OpDecorate %11 BuiltIn FragCoord
-OpDecorate %13 BuiltIn FragDepth
-OpMemberDecorate %15 0 Offset 0
-OpMemberDecorate %15 1 Offset 16
+OpDecorate %9 BuiltIn PointSize
+OpDecorate %10 Location 1
+OpDecorate %12 BuiltIn FragCoord
+OpDecorate %14 BuiltIn FragDepth
+OpMemberDecorate %16 0 Offset 0
+OpMemberDecorate %16 1 Offset 16
 %3 = OpTypeFloat 32
 %2 = OpTypePointer Output %3
 %4 = OpConstantNull %3
@@ -253,44 +255,47 @@
 %6 = OpTypePointer Output %7
 %8 = OpConstantNull %7
 %5 = OpVariable %6 Output %8
-%10 = OpTypePointer Input %3
-%9 = OpVariable %10 Input
-%12 = OpTypePointer Input %7
-%11 = OpVariable %12 Input
-%13 = OpVariable %2 Output %4
-%15 = OpTypeStruct %3 %7
-%14 = OpTypeFunction %15
-%18 = OpConstant %3 42
-%19 = OpConstantComposite %15 %18 %8
-%21 = OpTypeVoid
-%20 = OpTypeFunction %21
-%27 = OpTypeFunction %3 %15
-%16 = OpFunction %15 None %14
-%17 = OpLabel
-OpReturnValue %19
+%9 = OpVariable %2 Output %4
+%11 = OpTypePointer Input %3
+%10 = OpVariable %11 Input
+%13 = OpTypePointer Input %7
+%12 = OpVariable %13 Input
+%14 = OpVariable %2 Output %4
+%16 = OpTypeStruct %3 %7
+%15 = OpTypeFunction %16
+%19 = OpConstant %3 42
+%20 = OpConstantComposite %16 %19 %8
+%22 = OpTypeVoid
+%21 = OpTypeFunction %22
+%28 = OpConstant %3 1
+%29 = OpTypeFunction %3 %16
+%17 = OpFunction %16 None %15
+%18 = OpLabel
+OpReturnValue %20
 OpFunctionEnd
-%22 = OpFunction %21 None %20
-%23 = OpLabel
-%24 = OpFunctionCall %15 %16
-%25 = OpCompositeExtract %3 %24 0
-OpStore %1 %25
-%26 = OpCompositeExtract %7 %24 1
-OpStore %5 %26
+%23 = OpFunction %22 None %21
+%24 = OpLabel
+%25 = OpFunctionCall %16 %17
+%26 = OpCompositeExtract %3 %25 0
+OpStore %1 %26
+%27 = OpCompositeExtract %7 %25 1
+OpStore %5 %27
+OpStore %9 %28
 OpReturn
 OpFunctionEnd
-%28 = OpFunction %3 None %27
-%29 = OpFunctionParameter %15
-%30 = OpLabel
-%31 = OpCompositeExtract %3 %29 0
-OpReturnValue %31
+%30 = OpFunction %3 None %29
+%31 = OpFunctionParameter %16
+%32 = OpLabel
+%33 = OpCompositeExtract %3 %31 0
+OpReturnValue %33
 OpFunctionEnd
-%32 = OpFunction %21 None %20
-%33 = OpLabel
-%35 = OpLoad %3 %9
-%36 = OpLoad %7 %11
-%37 = OpCompositeConstruct %15 %35 %36
-%34 = OpFunctionCall %3 %28 %37
-OpStore %13 %34
+%34 = OpFunction %22 None %21
+%35 = OpLabel
+%37 = OpLoad %3 %10
+%38 = OpLoad %7 %12
+%39 = OpCompositeConstruct %16 %37 %38
+%36 = OpFunctionCall %3 %30 %39
+OpStore %14 %36
 OpReturn
 OpFunctionEnd
 )");
diff --git a/src/tint/writer/spirv/generator.cc b/src/tint/writer/spirv/generator.cc
index 7d29935..938f8f7 100644
--- a/src/tint/writer/spirv/generator.cc
+++ b/src/tint/writer/spirv/generator.cc
@@ -26,12 +26,7 @@
   Result result;
 
   // Sanitize the program.
-  bool disable_workgroup_init_in_sanitizer =
-      options.disable_workgroup_init ||
-      options.use_zero_initialize_workgroup_memory_extension;
-  auto sanitized_result = Sanitize(program, options.emit_vertex_point_size,
-                                   disable_workgroup_init_in_sanitizer,
-                                   options.generate_external_texture_bindings);
+  auto sanitized_result = Sanitize(program, options);
   if (!sanitized_result.program.IsValid()) {
     result.success = false;
     result.error = sanitized_result.program.Diagnostics().str();
diff --git a/src/tint/writer/spirv/test_helper.h b/src/tint/writer/spirv/test_helper.h
index e80c331..ecf2a21 100644
--- a/src/tint/writer/spirv/test_helper.h
+++ b/src/tint/writer/spirv/test_helper.h
@@ -55,10 +55,11 @@
 
   /// Builds the program, runs the program through the transform::Spirv
   /// sanitizer and returns a spirv::Builder from the sanitized program.
+  /// @param options The SPIR-V generator options.
   /// @note The spirv::Builder is only built once. Multiple calls to Build()
   /// will return the same spirv::Builder without rebuilding.
   /// @return the built spirv::Builder
-  spirv::Builder& SanitizeAndBuild() {
+  spirv::Builder& SanitizeAndBuild(const Options& options = {}) {
     if (spirv_builder) {
       return *spirv_builder;
     }
@@ -71,7 +72,7 @@
       ASSERT_TRUE(program->IsValid())
           << diag::Formatter().format(program->Diagnostics());
     }();
-    auto result = Sanitize(program.get());
+    auto result = Sanitize(program.get(), options);
     [&]() {
       ASSERT_TRUE(result.program.IsValid())
           << diag::Formatter().format(result.program.Diagnostics());