Browse Source

Updated spirv-tools.

Бранимир Караџић 5 years ago
parent
commit
6a0b5b5b5c
100 changed files with 1186 additions and 804 deletions
  1. 1 1
      3rdparty/spirv-tools/include/generated/build-version.inc
  2. 4 0
      3rdparty/spirv-tools/source/fuzz/CMakeLists.txt
  3. 9 4
      3rdparty/spirv-tools/source/fuzz/force_render_red.cpp
  4. 2 1
      3rdparty/spirv-tools/source/fuzz/force_render_red.h
  5. 90 80
      3rdparty/spirv-tools/source/fuzz/fuzzer.cpp
  6. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer.h
  7. 54 22
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass.cpp
  8. 25 18
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass.h
  9. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.cpp
  10. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.h
  11. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.cpp
  12. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.h
  13. 6 4
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.cpp
  14. 2 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.h
  15. 8 6
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.cpp
  16. 2 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.h
  17. 6 4
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.cpp
  18. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.h
  19. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
  20. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_equation_instructions.h
  21. 11 7
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.cpp
  22. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.h
  23. 24 23
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.cpp
  24. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.h
  25. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.cpp
  26. 2 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.h
  27. 24 23
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.cpp
  28. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.h
  29. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp
  30. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_no_contraction_decorations.h
  31. 10 5
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.cpp
  32. 2 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.h
  33. 26 18
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_useful_constructs.cpp
  34. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_useful_constructs.h
  35. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
  36. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_function_controls.h
  37. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
  38. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_loop_controls.h
  39. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
  40. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h
  41. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
  42. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_selection_controls.h
  43. 17 9
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
  44. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.h
  45. 103 93
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_construct_composites.cpp
  46. 15 14
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_construct_composites.h
  47. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_copy_objects.cpp
  48. 2 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_copy_objects.h
  49. 21 3
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.cpp
  50. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.h
  51. 8 5
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_merge_blocks.cpp
  52. 2 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_merge_blocks.h
  53. 22 13
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
  54. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_obfuscate_constants.h
  55. 6 4
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_outline_functions.cpp
  56. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_outline_functions.h
  57. 6 4
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_blocks.cpp
  58. 2 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_blocks.h
  59. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_function_parameters.cpp
  60. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_function_parameters.h
  61. 6 4
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_split_blocks.cpp
  62. 2 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_split_blocks.h
  63. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp
  64. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_swap_commutable_operands.h
  65. 3 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
  66. 1 1
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h
  67. 9 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp
  68. 7 2
      3rdparty/spirv-tools/source/fuzz/fuzzer_util.h
  69. 13 0
      3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto
  70. 21 12
      3rdparty/spirv-tools/source/fuzz/replayer.cpp
  71. 2 1
      3rdparty/spirv-tools/source/fuzz/replayer.h
  72. 22 13
      3rdparty/spirv-tools/source/fuzz/shrinker.cpp
  73. 2 2
      3rdparty/spirv-tools/source/fuzz/shrinker.h
  74. 6 2
      3rdparty/spirv-tools/source/fuzz/transformation.cpp
  75. 15 12
      3rdparty/spirv-tools/source/fuzz/transformation.h
  76. 29 27
      3rdparty/spirv-tools/source/fuzz/transformation_access_chain.cpp
  77. 11 8
      3rdparty/spirv-tools/source/fuzz/transformation_access_chain.h
  78. 10 9
      3rdparty/spirv-tools/source/fuzz/transformation_add_constant_boolean.cpp
  79. 6 4
      3rdparty/spirv-tools/source/fuzz/transformation_add_constant_boolean.h
  80. 12 12
      3rdparty/spirv-tools/source/fuzz/transformation_add_constant_composite.cpp
  81. 6 4
      3rdparty/spirv-tools/source/fuzz/transformation_add_constant_composite.h
  82. 66 0
      3rdparty/spirv-tools/source/fuzz/transformation_add_constant_null.cpp
  83. 54 0
      3rdparty/spirv-tools/source/fuzz/transformation_add_constant_null.h
  84. 10 10
      3rdparty/spirv-tools/source/fuzz/transformation_add_constant_scalar.cpp
  85. 6 4
      3rdparty/spirv-tools/source/fuzz/transformation_add_constant_scalar.h
  86. 22 20
      3rdparty/spirv-tools/source/fuzz/transformation_add_dead_block.cpp
  87. 6 4
      3rdparty/spirv-tools/source/fuzz/transformation_add_dead_block.h
  88. 27 24
      3rdparty/spirv-tools/source/fuzz/transformation_add_dead_break.cpp
  89. 8 6
      3rdparty/spirv-tools/source/fuzz/transformation_add_dead_break.h
  90. 29 24
      3rdparty/spirv-tools/source/fuzz/transformation_add_dead_continue.cpp
  91. 7 5
      3rdparty/spirv-tools/source/fuzz/transformation_add_dead_continue.h
  92. 108 97
      3rdparty/spirv-tools/source/fuzz/transformation_add_function.cpp
  93. 22 19
      3rdparty/spirv-tools/source/fuzz/transformation_add_function.h
  94. 9 9
      3rdparty/spirv-tools/source/fuzz/transformation_add_global_undef.cpp
  95. 6 4
      3rdparty/spirv-tools/source/fuzz/transformation_add_global_undef.h
  96. 18 16
      3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.cpp
  97. 9 7
      3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.h
  98. 13 12
      3rdparty/spirv-tools/source/fuzz/transformation_add_local_variable.cpp
  99. 8 6
      3rdparty/spirv-tools/source/fuzz/transformation_add_local_variable.h
  100. 5 6
      3rdparty/spirv-tools/source/fuzz/transformation_add_no_contraction_decoration.cpp

+ 1 - 1
3rdparty/spirv-tools/include/generated/build-version.inc

@@ -1 +1 @@
-"v2020.3-dev", "SPIRV-Tools v2020.3-dev eff6f130119f3e6acbf81f8432c0912296d4dfdb"
+"v2020.3-dev", "SPIRV-Tools v2020.3-dev 9522e65f0f430a45a29053e2aeec768c2dbca075"

+ 4 - 0
3rdparty/spirv-tools/source/fuzz/CMakeLists.txt

@@ -79,6 +79,7 @@ if(SPIRV_BUILD_FUZZER)
         transformation_access_chain.h
         transformation_add_constant_boolean.h
         transformation_add_constant_composite.h
+        transformation_add_constant_null.h
         transformation_add_constant_scalar.h
         transformation_add_dead_block.h
         transformation_add_dead_break.h
@@ -99,6 +100,7 @@ if(SPIRV_BUILD_FUZZER)
         transformation_add_type_vector.h
         transformation_composite_construct.h
         transformation_composite_extract.h
+        transformation_context.h
         transformation_copy_object.h
         transformation_equation_instruction.h
         transformation_function_call.h
@@ -170,6 +172,7 @@ if(SPIRV_BUILD_FUZZER)
         transformation_access_chain.cpp
         transformation_add_constant_boolean.cpp
         transformation_add_constant_composite.cpp
+        transformation_add_constant_null.cpp
         transformation_add_constant_scalar.cpp
         transformation_add_dead_block.cpp
         transformation_add_dead_break.cpp
@@ -190,6 +193,7 @@ if(SPIRV_BUILD_FUZZER)
         transformation_add_type_vector.cpp
         transformation_composite_construct.cpp
         transformation_composite_extract.cpp
+        transformation_context.cpp
         transformation_copy_object.cpp
         transformation_equation_instruction.cpp
         transformation_function_call.cpp

+ 9 - 4
3rdparty/spirv-tools/source/fuzz/force_render_red.cpp

@@ -17,6 +17,7 @@
 #include "source/fuzz/fact_manager.h"
 #include "source/fuzz/instruction_descriptor.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/fuzz/transformation_replace_constant_with_uniform.h"
 #include "source/fuzz/uniform_buffer_element_descriptor.h"
 #include "source/opt/build_module.h"
@@ -159,7 +160,8 @@ MakeConstantUniformReplacement(opt::IRContext* ir_context,
 }  // namespace
 
 bool ForceRenderRed(
-    const spv_target_env& target_env, const std::vector<uint32_t>& binary_in,
+    const spv_target_env& target_env, spv_validator_options validator_options,
+    const std::vector<uint32_t>& binary_in,
     const spvtools::fuzz::protobufs::FactSequence& initial_facts,
     std::vector<uint32_t>* binary_out) {
   auto message_consumer = spvtools::utils::CLIMessageConsumer;
@@ -171,7 +173,7 @@ bool ForceRenderRed(
   }
 
   // Initial binary should be valid.
-  if (!tools.Validate(&binary_in[0], binary_in.size())) {
+  if (!tools.Validate(&binary_in[0], binary_in.size(), validator_options)) {
     message_consumer(SPV_MSG_ERROR, nullptr, {},
                      "Initial binary is invalid; stopping.");
     return false;
@@ -187,6 +189,8 @@ bool ForceRenderRed(
   for (auto& fact : initial_facts.fact()) {
     fact_manager.AddFact(fact, ir_context.get());
   }
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto entry_point_function =
       FindFragmentShaderEntryPoint(ir_context.get(), message_consumer);
@@ -355,8 +359,9 @@ bool ForceRenderRed(
     for (auto& replacement : {first_greater_then_operand_replacement.get(),
                               second_greater_then_operand_replacement.get()}) {
       if (replacement) {
-        assert(replacement->IsApplicable(ir_context.get(), fact_manager));
-        replacement->Apply(ir_context.get(), &fact_manager);
+        assert(replacement->IsApplicable(ir_context.get(),
+                                         transformation_context));
+        replacement->Apply(ir_context.get(), &transformation_context);
       }
     }
   }

+ 2 - 1
3rdparty/spirv-tools/source/fuzz/force_render_red.h

@@ -38,7 +38,8 @@ namespace fuzz {
 // instead become: 'u > v', where 'u' and 'v' are pieces of uniform data for
 // which it is known that 'u < v' holds.
 bool ForceRenderRed(
-    const spv_target_env& target_env, const std::vector<uint32_t>& binary_in,
+    const spv_target_env& target_env, spv_validator_options validator_options,
+    const std::vector<uint32_t>& binary_in,
     const spvtools::fuzz::protobufs::FactSequence& initial_facts,
     std::vector<uint32_t>* binary_out);
 

+ 90 - 80
3rdparty/spirv-tools/source/fuzz/fuzzer.cpp

@@ -51,6 +51,7 @@
 #include "source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/pseudo_random_generator.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/build_module.h"
 #include "source/spirv_fuzzer_options.h"
 #include "source/util/make_unique.h"
@@ -66,19 +67,19 @@ const uint32_t kTransformationLimit = 500;
 const uint32_t kChanceOfApplyingAnotherPass = 85;
 
 // A convenience method to add a fuzzer pass to |passes| with probability 0.5.
-// All fuzzer passes take |ir_context|, |fact_manager|, |fuzzer_context| and
-// |transformation_sequence_out| as parameters.  Extra arguments can be provided
-// via |extra_args|.
+// All fuzzer passes take |ir_context|, |transformation_context|,
+// |fuzzer_context| and |transformation_sequence_out| as parameters.  Extra
+// arguments can be provided via |extra_args|.
 template <typename T, typename... Args>
 void MaybeAddPass(
     std::vector<std::unique_ptr<FuzzerPass>>* passes,
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformation_sequence_out,
     Args&&... extra_args) {
   if (fuzzer_context->ChooseEven()) {
-    passes->push_back(MakeUnique<T>(ir_context, fact_manager, fuzzer_context,
-                                    transformation_sequence_out,
+    passes->push_back(MakeUnique<T>(ir_context, transformation_context,
+                                    fuzzer_context, transformation_sequence_out,
                                     std::forward<Args>(extra_args)...));
   }
 }
@@ -86,26 +87,31 @@ void MaybeAddPass(
 }  // namespace
 
 struct Fuzzer::Impl {
-  explicit Impl(spv_target_env env, uint32_t random_seed,
-                bool validate_after_each_pass)
+  Impl(spv_target_env env, uint32_t random_seed, bool validate_after_each_pass,
+       spv_validator_options options)
       : target_env(env),
         seed(random_seed),
-        validate_after_each_fuzzer_pass(validate_after_each_pass) {}
+        validate_after_each_fuzzer_pass(validate_after_each_pass),
+        validator_options(options) {}
 
   bool ApplyPassAndCheckValidity(FuzzerPass* pass,
                                  const opt::IRContext& ir_context,
                                  const spvtools::SpirvTools& tools) const;
 
   const spv_target_env target_env;       // Target environment.
+  MessageConsumer consumer;              // Message consumer.
   const uint32_t seed;                   // Seed for random number generator.
   bool validate_after_each_fuzzer_pass;  // Determines whether the validator
-  // should be invoked after every fuzzer pass.
-  MessageConsumer consumer;  // Message consumer.
+                                         // should be invoked after every fuzzer
+                                         // pass.
+  spv_validator_options validator_options;  // Options to control validation.
 };
 
 Fuzzer::Fuzzer(spv_target_env env, uint32_t seed,
-               bool validate_after_each_fuzzer_pass)
-    : impl_(MakeUnique<Impl>(env, seed, validate_after_each_fuzzer_pass)) {}
+               bool validate_after_each_fuzzer_pass,
+               spv_validator_options validator_options)
+    : impl_(MakeUnique<Impl>(env, seed, validate_after_each_fuzzer_pass,
+                             validator_options)) {}
 
 Fuzzer::~Fuzzer() = default;
 
@@ -120,7 +126,8 @@ bool Fuzzer::Impl::ApplyPassAndCheckValidity(
   if (validate_after_each_fuzzer_pass) {
     std::vector<uint32_t> binary_to_validate;
     ir_context.module()->ToBinary(&binary_to_validate, false);
-    if (!tools.Validate(&binary_to_validate[0], binary_to_validate.size())) {
+    if (!tools.Validate(&binary_to_validate[0], binary_to_validate.size(),
+                        validator_options)) {
       consumer(SPV_MSG_INFO, nullptr, {},
                "Binary became invalid during fuzzing (set a breakpoint to "
                "inspect); stopping.");
@@ -149,7 +156,8 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
   }
 
   // Initial binary should be valid.
-  if (!tools.Validate(&binary_in[0], binary_in.size())) {
+  if (!tools.Validate(&binary_in[0], binary_in.size(),
+                      impl_->validator_options)) {
     impl_->consumer(SPV_MSG_ERROR, nullptr, {},
                     "Initial binary is invalid; stopping.");
     return Fuzzer::FuzzerResultStatus::kInitialBinaryInvalid;
@@ -175,11 +183,13 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
 
   FactManager fact_manager;
   fact_manager.AddFacts(impl_->consumer, initial_facts, ir_context.get());
+  TransformationContext transformation_context(&fact_manager,
+                                               impl_->validator_options);
 
   // Add some essential ingredients to the module if they are not already
   // present, such as boolean constants.
   FuzzerPassAddUsefulConstructs add_useful_constructs(
-      ir_context.get(), &fact_manager, &fuzzer_context,
+      ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
   if (!impl_->ApplyPassAndCheckValidity(&add_useful_constructs, *ir_context,
                                         tools)) {
@@ -189,69 +199,69 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
   // Apply some semantics-preserving passes.
   std::vector<std::unique_ptr<FuzzerPass>> passes;
   while (passes.empty()) {
-    MaybeAddPass<FuzzerPassAddAccessChains>(&passes, ir_context.get(),
-                                            &fact_manager, &fuzzer_context,
-                                            transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddCompositeTypes>(&passes, ir_context.get(),
-                                              &fact_manager, &fuzzer_context,
-                                              transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddDeadBlocks>(&passes, ir_context.get(),
-                                          &fact_manager, &fuzzer_context,
-                                          transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddDeadBreaks>(&passes, ir_context.get(),
-                                          &fact_manager, &fuzzer_context,
-                                          transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddDeadContinues>(&passes, ir_context.get(),
-                                             &fact_manager, &fuzzer_context,
-                                             transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddAccessChains>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddCompositeTypes>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddDeadBlocks>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddDeadBreaks>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddDeadContinues>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
     MaybeAddPass<FuzzerPassAddEquationInstructions>(
-        &passes, ir_context.get(), &fact_manager, &fuzzer_context,
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
         transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddFunctionCalls>(&passes, ir_context.get(),
-                                             &fact_manager, &fuzzer_context,
-                                             transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddGlobalVariables>(&passes, ir_context.get(),
-                                               &fact_manager, &fuzzer_context,
-                                               transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddLoads>(&passes, ir_context.get(), &fact_manager,
-                                     &fuzzer_context,
+    MaybeAddPass<FuzzerPassAddFunctionCalls>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddGlobalVariables>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddLoads>(&passes, ir_context.get(),
+                                     &transformation_context, &fuzzer_context,
                                      transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddLocalVariables>(&passes, ir_context.get(),
-                                              &fact_manager, &fuzzer_context,
-                                              transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddStores>(&passes, ir_context.get(), &fact_manager,
-                                      &fuzzer_context,
+    MaybeAddPass<FuzzerPassAddLocalVariables>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddStores>(&passes, ir_context.get(),
+                                      &transformation_context, &fuzzer_context,
                                       transformation_sequence_out);
-    MaybeAddPass<FuzzerPassApplyIdSynonyms>(&passes, ir_context.get(),
-                                            &fact_manager, &fuzzer_context,
-                                            transformation_sequence_out);
-    MaybeAddPass<FuzzerPassConstructComposites>(&passes, ir_context.get(),
-                                                &fact_manager, &fuzzer_context,
-                                                transformation_sequence_out);
-    MaybeAddPass<FuzzerPassCopyObjects>(&passes, ir_context.get(),
-                                        &fact_manager, &fuzzer_context,
-                                        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassApplyIdSynonyms>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassConstructComposites>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassCopyObjects>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
     MaybeAddPass<FuzzerPassDonateModules>(
-        &passes, ir_context.get(), &fact_manager, &fuzzer_context,
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
         transformation_sequence_out, donor_suppliers);
-    MaybeAddPass<FuzzerPassMergeBlocks>(&passes, ir_context.get(),
-                                        &fact_manager, &fuzzer_context,
-                                        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassObfuscateConstants>(&passes, ir_context.get(),
-                                               &fact_manager, &fuzzer_context,
-                                               transformation_sequence_out);
-    MaybeAddPass<FuzzerPassOutlineFunctions>(&passes, ir_context.get(),
-                                             &fact_manager, &fuzzer_context,
-                                             transformation_sequence_out);
-    MaybeAddPass<FuzzerPassPermuteBlocks>(&passes, ir_context.get(),
-                                          &fact_manager, &fuzzer_context,
-                                          transformation_sequence_out);
+    MaybeAddPass<FuzzerPassMergeBlocks>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassObfuscateConstants>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassOutlineFunctions>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassPermuteBlocks>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
     MaybeAddPass<FuzzerPassPermuteFunctionParameters>(
-        &passes, ir_context.get(), &fact_manager, &fuzzer_context,
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassSplitBlocks>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
         transformation_sequence_out);
-    MaybeAddPass<FuzzerPassSplitBlocks>(&passes, ir_context.get(),
-                                        &fact_manager, &fuzzer_context,
-                                        transformation_sequence_out);
   }
 
   bool is_first = true;
@@ -272,25 +282,25 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
   // as they do not unlock other passes.
   std::vector<std::unique_ptr<FuzzerPass>> final_passes;
   MaybeAddPass<FuzzerPassAdjustFunctionControls>(
-      &final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
+      transformation_sequence_out);
+  MaybeAddPass<FuzzerPassAdjustLoopControls>(
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
-  MaybeAddPass<FuzzerPassAdjustLoopControls>(&final_passes, ir_context.get(),
-                                             &fact_manager, &fuzzer_context,
-                                             transformation_sequence_out);
   MaybeAddPass<FuzzerPassAdjustMemoryOperandsMasks>(
-      &final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
   MaybeAddPass<FuzzerPassAdjustSelectionControls>(
-      &final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
   MaybeAddPass<FuzzerPassAddNoContractionDecorations>(
-      &final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
   MaybeAddPass<FuzzerPassSwapCommutableOperands>(
-      &final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
   MaybeAddPass<FuzzerPassToggleAccessChainInstruction>(
-      &final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
   for (auto& pass : final_passes) {
     if (!impl_->ApplyPassAndCheckValidity(pass.get(), *ir_context, tools)) {

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer.h

@@ -41,8 +41,9 @@ class Fuzzer {
   // seed for pseudo-random number generation.
   // |validate_after_each_fuzzer_pass| controls whether the validator will be
   // invoked after every fuzzer pass is applied.
-  explicit Fuzzer(spv_target_env env, uint32_t seed,
-                  bool validate_after_each_fuzzer_pass);
+  Fuzzer(spv_target_env env, uint32_t seed,
+         bool validate_after_each_fuzzer_pass,
+         spv_validator_options validator_options);
 
   // Disables copy/move constructor/assignment operations.
   Fuzzer(const Fuzzer&) = delete;

+ 54 - 22
3rdparty/spirv-tools/source/fuzz/fuzzer_pass.cpp

@@ -14,6 +14,8 @@
 
 #include "source/fuzz/fuzzer_pass.h"
 
+#include <set>
+
 #include "source/fuzz/fuzzer_util.h"
 #include "source/fuzz/instruction_descriptor.h"
 #include "source/fuzz/transformation_add_constant_boolean.h"
@@ -31,11 +33,12 @@
 namespace spvtools {
 namespace fuzz {
 
-FuzzerPass::FuzzerPass(opt::IRContext* ir_context, FactManager* fact_manager,
+FuzzerPass::FuzzerPass(opt::IRContext* ir_context,
+                       TransformationContext* transformation_context,
                        FuzzerContext* fuzzer_context,
                        protobufs::TransformationSequence* transformations)
     : ir_context_(ir_context),
-      fact_manager_(fact_manager),
+      transformation_context_(transformation_context),
       fuzzer_context_(fuzzer_context),
       transformations_(transformations) {}
 
@@ -328,43 +331,72 @@ uint32_t FuzzerPass::FindOrCreateGlobalUndef(uint32_t type_id) {
 }
 
 std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
-FuzzerPass::GetAvailableBaseTypesAndPointers(
+FuzzerPass::GetAvailableBasicTypesAndPointers(
     SpvStorageClass storage_class) const {
-  // Records all of the base types available in the module.
-  std::vector<uint32_t> base_types;
+  // Records all of the basic types available in the module.
+  std::set<uint32_t> basic_types;
 
-  // For each base type, records all the associated pointer types that target
-  // that base type and that have |storage_class| as their storage class.
-  std::map<uint32_t, std::vector<uint32_t>> base_type_to_pointers;
+  // For each basic type, records all the associated pointer types that target
+  // the basic type and that have |storage_class| as their storage class.
+  std::map<uint32_t, std::vector<uint32_t>> basic_type_to_pointers;
 
   for (auto& inst : GetIRContext()->types_values()) {
+    // For each basic type that we come across, record type, and the fact that
+    // we cannot yet have seen any pointers that use the basic type as its
+    // pointee type.
+    //
+    // For pointer types with basic pointee types, associate the pointer type
+    // with the basic type.
     switch (inst.opcode()) {
-      case SpvOpTypeArray:
       case SpvOpTypeBool:
       case SpvOpTypeFloat:
       case SpvOpTypeInt:
       case SpvOpTypeMatrix:
-      case SpvOpTypeStruct:
       case SpvOpTypeVector:
-        // These types are suitable as pointer base types.  Record the type,
-        // and the fact that we cannot yet have seen any pointers that use this
-        // as its base type.
-        base_types.push_back(inst.result_id());
-        base_type_to_pointers.insert({inst.result_id(), {}});
+        // These are all basic types.
+        basic_types.insert(inst.result_id());
+        basic_type_to_pointers.insert({inst.result_id(), {}});
+        break;
+      case SpvOpTypeArray:
+        // An array type is basic if its base type is basic.
+        if (basic_types.count(inst.GetSingleWordInOperand(0))) {
+          basic_types.insert(inst.result_id());
+          basic_type_to_pointers.insert({inst.result_id(), {}});
+        }
         break;
-      case SpvOpTypePointer:
-        if (inst.GetSingleWordInOperand(0) == storage_class) {
-          // The pointer has the desired storage class, so we are interested in
-          // it.  Associate it with its base type.
-          base_type_to_pointers.at(inst.GetSingleWordInOperand(1))
-              .push_back(inst.result_id());
+      case SpvOpTypeStruct: {
+        // A struct type is basic if all of its members are basic.
+        bool all_members_are_basic_types = true;
+        for (uint32_t i = 0; i < inst.NumInOperands(); i++) {
+          if (!basic_types.count(inst.GetSingleWordInOperand(i))) {
+            all_members_are_basic_types = false;
+            break;
+          }
+        }
+        if (all_members_are_basic_types) {
+          basic_types.insert(inst.result_id());
+          basic_type_to_pointers.insert({inst.result_id(), {}});
         }
         break;
+      }
+      case SpvOpTypePointer: {
+        // We are interested in the pointer if its pointee type is basic and it
+        // has the right storage class.
+        auto pointee_type = inst.GetSingleWordInOperand(1);
+        if (inst.GetSingleWordInOperand(0) == storage_class &&
+            basic_types.count(pointee_type)) {
+          // The pointer has the desired storage class, and its pointee type is
+          // a basic type, so we are interested in it.  Associate it with its
+          // basic type.
+          basic_type_to_pointers.at(pointee_type).push_back(inst.result_id());
+        }
+        break;
+      }
       default:
         break;
     }
   }
-  return {base_types, base_type_to_pointers};
+  return {{basic_types.begin(), basic_types.end()}, basic_type_to_pointers};
 }
 
 uint32_t FuzzerPass::FindOrCreateZeroConstant(

+ 25 - 18
3rdparty/spirv-tools/source/fuzz/fuzzer_pass.h

@@ -18,9 +18,9 @@
 #include <functional>
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/fuzzer_context.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -29,22 +29,25 @@ namespace fuzz {
 // Interface for applying a pass of transformations to a module.
 class FuzzerPass {
  public:
-  FuzzerPass(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPass(opt::IRContext* ir_context,
+             TransformationContext* transformation_context,
              FuzzerContext* fuzzer_context,
              protobufs::TransformationSequence* transformations);
 
   virtual ~FuzzerPass();
 
   // Applies the pass to the module |ir_context_|, assuming and updating
-  // facts from |fact_manager_|, and using |fuzzer_context_| to guide the
-  // process.  Appends to |transformations_| all transformations that were
-  // applied during the pass.
+  // information from |transformation_context_|, and using |fuzzer_context_| to
+  // guide the process.  Appends to |transformations_| all transformations that
+  // were applied during the pass.
   virtual void Apply() = 0;
 
  protected:
   opt::IRContext* GetIRContext() const { return ir_context_; }
 
-  FactManager* GetFactManager() const { return fact_manager_; }
+  TransformationContext* GetTransformationContext() const {
+    return transformation_context_;
+  }
 
   FuzzerContext* GetFuzzerContext() const { return fuzzer_context_; }
 
@@ -93,9 +96,10 @@ class FuzzerPass {
   // by construction, and adding it to the sequence of applied transformations.
   template <typename TransformationType>
   void ApplyTransformation(const TransformationType& transformation) {
-    assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()) &&
+    assert(transformation.IsApplicable(GetIRContext(),
+                                       *GetTransformationContext()) &&
            "Transformation should be applicable by construction.");
-    transformation.Apply(GetIRContext(), GetFactManager());
+    transformation.Apply(GetIRContext(), GetTransformationContext());
     *GetTransformations()->add_transformation() = transformation.ToMessage();
   }
 
@@ -165,18 +169,21 @@ class FuzzerPass {
   // If no such instruction exists, a transformation is applied to add it.
   uint32_t FindOrCreateGlobalUndef(uint32_t type_id);
 
-  // Yields a pair, (base_type_ids, base_type_ids_to_pointers), such that:
-  // - base_type_ids captures every scalar or composite type declared in the
-  //   module (i.e., all int, bool, float, vector, matrix, struct and array
-  //   types
-  // - base_type_ids_to_pointers maps every such base type to the sequence
+  // Define a *basic type* to be an integer, boolean or floating-point type,
+  // or a matrix, vector, struct or fixed-size array built from basic types.  In
+  // particular, a basic type cannot contain an opaque type (such as an image),
+  // or a runtime-sized array.
+  //
+  // Yields a pair, (basic_type_ids, basic_type_ids_to_pointers), such that:
+  // - basic_type_ids captures every basic type declared in the module.
+  // - basic_type_ids_to_pointers maps every such basic type to the sequence
   //   of all pointer types that have storage class |storage_class| and the
-  //   given base type as their pointee type.  The sequence may be empty for
-  //   some base types if no pointers to those types are defined for the given
+  //   given basic type as their pointee type.  The sequence may be empty for
+  //   some basic types if no pointers to those types are defined for the given
   //   storage class, and the sequence will have multiple elements if there are
-  //   repeated pointer declarations for the same base type and storage class.
+  //   repeated pointer declarations for the same basic type and storage class.
   std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
-  GetAvailableBaseTypesAndPointers(SpvStorageClass storage_class) const;
+  GetAvailableBasicTypesAndPointers(SpvStorageClass storage_class) const;
 
   // Given a type id, |scalar_or_composite_type_id|, which must correspond to
   // some scalar or composite type, returns the result id of an instruction
@@ -230,7 +237,7 @@ class FuzzerPass {
       const std::vector<uint32_t>& constant_ids);
 
   opt::IRContext* ir_context_;
-  FactManager* fact_manager_;
+  TransformationContext* transformation_context_;
   FuzzerContext* fuzzer_context_;
   protobufs::TransformationSequence* transformations_;
 };

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.cpp

@@ -21,10 +21,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddAccessChains::FuzzerPassAddAccessChains(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddAccessChains::~FuzzerPassAddAccessChains() = default;
 

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.h

@@ -26,7 +26,7 @@ namespace fuzz {
 class FuzzerPassAddAccessChains : public FuzzerPass {
  public:
   FuzzerPassAddAccessChains(opt::IRContext* ir_context,
-                            FactManager* fact_manager,
+                            TransformationContext* transformation_context,
                             FuzzerContext* fuzzer_context,
                             protobufs::TransformationSequence* transformations);
 

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.cpp

@@ -22,10 +22,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddCompositeTypes::FuzzerPassAddCompositeTypes(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddCompositeTypes::~FuzzerPassAddCompositeTypes() = default;
 

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.h

@@ -25,7 +25,7 @@ namespace fuzz {
 class FuzzerPassAddCompositeTypes : public FuzzerPass {
  public:
   FuzzerPassAddCompositeTypes(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 6 - 4
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.cpp

@@ -21,10 +21,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddDeadBlocks::FuzzerPassAddDeadBlocks(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddDeadBlocks::~FuzzerPassAddDeadBlocks() = default;
 
@@ -53,8 +54,9 @@ void FuzzerPassAddDeadBlocks::Apply() {
   }
   // Apply all those transformations that are in fact applicable.
   for (auto& transformation : candidate_transformations) {
-    if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
-      transformation.Apply(GetIRContext(), GetFactManager());
+    if (transformation.IsApplicable(GetIRContext(),
+                                    *GetTransformationContext())) {
+      transformation.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = transformation.ToMessage();
     }
   }

+ 2 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.h

@@ -24,7 +24,8 @@ namespace fuzz {
 // passes can then manipulate such blocks.
 class FuzzerPassAddDeadBlocks : public FuzzerPass {
  public:
-  FuzzerPassAddDeadBlocks(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassAddDeadBlocks(opt::IRContext* ir_context,
+                          TransformationContext* transformation_context,
                           FuzzerContext* fuzzer_context,
                           protobufs::TransformationSequence* transformations);
 

+ 8 - 6
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.cpp

@@ -21,10 +21,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddDeadBreaks::FuzzerPassAddDeadBreaks(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddDeadBreaks::~FuzzerPassAddDeadBreaks() = default;
 
@@ -79,8 +80,8 @@ void FuzzerPassAddDeadBreaks::Apply() {
         auto candidate_transformation = TransformationAddDeadBreak(
             block.id(), merge_block->id(), GetFuzzerContext()->ChooseEven(),
             std::move(phi_ids));
-        if (candidate_transformation.IsApplicable(GetIRContext(),
-                                                  *GetFactManager())) {
+        if (candidate_transformation.IsApplicable(
+                GetIRContext(), *GetTransformationContext())) {
           // Only consider a transformation as a candidate if it is applicable.
           candidate_transformations.push_back(
               std::move(candidate_transformation));
@@ -109,10 +110,11 @@ void FuzzerPassAddDeadBreaks::Apply() {
     candidate_transformations.erase(candidate_transformations.begin() + index);
     // Probabilistically decide whether to try to apply it vs. ignore it, in the
     // case that it is applicable.
-    if (transformation.IsApplicable(GetIRContext(), *GetFactManager()) &&
+    if (transformation.IsApplicable(GetIRContext(),
+                                    *GetTransformationContext()) &&
         GetFuzzerContext()->ChoosePercentage(
             GetFuzzerContext()->GetChanceOfAddingDeadBreak())) {
-      transformation.Apply(GetIRContext(), GetFactManager());
+      transformation.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = transformation.ToMessage();
     }
   }

+ 2 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.h

@@ -23,7 +23,8 @@ namespace fuzz {
 // A fuzzer pass for adding dead break edges to the module.
 class FuzzerPassAddDeadBreaks : public FuzzerPass {
  public:
-  FuzzerPassAddDeadBreaks(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassAddDeadBreaks(opt::IRContext* ir_context,
+                          TransformationContext* transformation_context,
                           FuzzerContext* fuzzer_context,
                           protobufs::TransformationSequence* transformations);
 

+ 6 - 4
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.cpp

@@ -21,10 +21,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddDeadContinues::FuzzerPassAddDeadContinues(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddDeadContinues::~FuzzerPassAddDeadContinues() = default;
 
@@ -75,10 +76,11 @@ void FuzzerPassAddDeadContinues::Apply() {
       // Probabilistically decide whether to apply the transformation in the
       // case that it is applicable.
       if (candidate_transformation.IsApplicable(GetIRContext(),
-                                                *GetFactManager()) &&
+                                                *GetTransformationContext()) &&
           GetFuzzerContext()->ChoosePercentage(
               GetFuzzerContext()->GetChanceOfAddingDeadContinue())) {
-        candidate_transformation.Apply(GetIRContext(), GetFactManager());
+        candidate_transformation.Apply(GetIRContext(),
+                                       GetTransformationContext());
         *GetTransformations()->add_transformation() =
             candidate_transformation.ToMessage();
       }

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.h

@@ -24,7 +24,7 @@ namespace fuzz {
 class FuzzerPassAddDeadContinues : public FuzzerPass {
  public:
   FuzzerPassAddDeadContinues(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_equation_instructions.cpp

@@ -23,10 +23,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddEquationInstructions::FuzzerPassAddEquationInstructions(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddEquationInstructions::~FuzzerPassAddEquationInstructions() =
     default;

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_equation_instructions.h

@@ -27,7 +27,7 @@ namespace fuzz {
 class FuzzerPassAddEquationInstructions : public FuzzerPass {
  public:
   FuzzerPassAddEquationInstructions(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 11 - 7
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.cpp

@@ -24,10 +24,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddFunctionCalls::FuzzerPassAddFunctionCalls(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddFunctionCalls::~FuzzerPassAddFunctionCalls() = default;
 
@@ -74,8 +75,9 @@ void FuzzerPassAddFunctionCalls::Apply() {
         while (!candidate_functions.empty()) {
           opt::Function* candidate_function =
               GetFuzzerContext()->RemoveAtRandomIndex(&candidate_functions);
-          if (!GetFactManager()->BlockIsDead(block->id()) &&
-              !GetFactManager()->FunctionIsLivesafe(
+          if (!GetTransformationContext()->GetFactManager()->BlockIsDead(
+                  block->id()) &&
+              !GetTransformationContext()->GetFactManager()->FunctionIsLivesafe(
                   candidate_function->result_id())) {
             // Unless in a dead block, only livesafe functions can be invoked
             continue;
@@ -132,9 +134,11 @@ FuzzerPassAddFunctionCalls::GetAvailableInstructionsSuitableForActualParameters(
                 default:
                   return false;
               }
-              if (!GetFactManager()->BlockIsDead(block->id()) &&
-                  !GetFactManager()->PointeeValueIsIrrelevant(
-                      inst->result_id())) {
+              if (!GetTransformationContext()->GetFactManager()->BlockIsDead(
+                      block->id()) &&
+                  !GetTransformationContext()
+                       ->GetFactManager()
+                       ->PointeeValueIsIrrelevant(inst->result_id())) {
                 // We can only pass a pointer as an actual parameter
                 // if the pointee value for the pointer is irrelevant,
                 // or if the block from which we would make the

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.h

@@ -25,7 +25,7 @@ namespace fuzz {
 class FuzzerPassAddFunctionCalls : public FuzzerPass {
  public:
   FuzzerPassAddFunctionCalls(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 24 - 23
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.cpp

@@ -21,53 +21,54 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddGlobalVariables::FuzzerPassAddGlobalVariables(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddGlobalVariables::~FuzzerPassAddGlobalVariables() = default;
 
 void FuzzerPassAddGlobalVariables::Apply() {
-  auto base_type_ids_and_pointers =
-      GetAvailableBaseTypesAndPointers(SpvStorageClassPrivate);
+  auto basic_type_ids_and_pointers =
+      GetAvailableBasicTypesAndPointers(SpvStorageClassPrivate);
 
-  // These are the base types that are available to this fuzzer pass.
-  auto& base_types = base_type_ids_and_pointers.first;
+  // These are the basic types that are available to this fuzzer pass.
+  auto& basic_types = basic_type_ids_and_pointers.first;
 
-  // These are the pointers to those base types that are *initially* available
+  // These are the pointers to those basic types that are *initially* available
   // to the fuzzer pass.  The fuzzer pass might add pointer types in cases where
-  // none are available for a given base type.
-  auto& base_type_to_pointers = base_type_ids_and_pointers.second;
+  // none are available for a given basic type.
+  auto& basic_type_to_pointers = basic_type_ids_and_pointers.second;
 
   // Probabilistically keep adding global variables.
   while (GetFuzzerContext()->ChoosePercentage(
       GetFuzzerContext()->GetChanceOfAddingGlobalVariable())) {
-    // Choose a random base type; the new variable's type will be a pointer to
-    // this base type.
-    uint32_t base_type =
-        base_types[GetFuzzerContext()->RandomIndex(base_types)];
+    // Choose a random basic type; the new variable's type will be a pointer to
+    // this basic type.
+    uint32_t basic_type =
+        basic_types[GetFuzzerContext()->RandomIndex(basic_types)];
     uint32_t pointer_type_id;
-    std::vector<uint32_t>& available_pointers_to_base_type =
-        base_type_to_pointers.at(base_type);
-    // Determine whether there is at least one pointer to this base type.
-    if (available_pointers_to_base_type.empty()) {
+    std::vector<uint32_t>& available_pointers_to_basic_type =
+        basic_type_to_pointers.at(basic_type);
+    // Determine whether there is at least one pointer to this basic type.
+    if (available_pointers_to_basic_type.empty()) {
       // There is not.  Make one, to use here, and add it to the available
-      // pointers for the base type so that future variables can potentially
+      // pointers for the basic type so that future variables can potentially
       // use it.
       pointer_type_id = GetFuzzerContext()->GetFreshId();
-      available_pointers_to_base_type.push_back(pointer_type_id);
+      available_pointers_to_basic_type.push_back(pointer_type_id);
       ApplyTransformation(TransformationAddTypePointer(
-          pointer_type_id, SpvStorageClassPrivate, base_type));
+          pointer_type_id, SpvStorageClassPrivate, basic_type));
     } else {
       // There is - grab one.
       pointer_type_id =
-          available_pointers_to_base_type[GetFuzzerContext()->RandomIndex(
-              available_pointers_to_base_type)];
+          available_pointers_to_basic_type[GetFuzzerContext()->RandomIndex(
+              available_pointers_to_basic_type)];
     }
     ApplyTransformation(TransformationAddGlobalVariable(
         GetFuzzerContext()->GetFreshId(), pointer_type_id,
-        FindOrCreateZeroConstant(base_type), true));
+        FindOrCreateZeroConstant(basic_type), true));
   }
 }
 

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.h

@@ -25,7 +25,7 @@ namespace fuzz {
 class FuzzerPassAddGlobalVariables : public FuzzerPass {
  public:
   FuzzerPassAddGlobalVariables(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.cpp

@@ -21,10 +21,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddLoads::FuzzerPassAddLoads(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddLoads::~FuzzerPassAddLoads() = default;
 

+ 2 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.h

@@ -23,7 +23,8 @@ namespace fuzz {
 // Fuzzer pass that adds stores, at random, from pointers in the module.
 class FuzzerPassAddLoads : public FuzzerPass {
  public:
-  FuzzerPassAddLoads(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassAddLoads(opt::IRContext* ir_context,
+                     TransformationContext* transformation_context,
                      FuzzerContext* fuzzer_context,
                      protobufs::TransformationSequence* transformations);
 

+ 24 - 23
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.cpp

@@ -22,55 +22,56 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddLocalVariables::FuzzerPassAddLocalVariables(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddLocalVariables::~FuzzerPassAddLocalVariables() = default;
 
 void FuzzerPassAddLocalVariables::Apply() {
-  auto base_type_ids_and_pointers =
-      GetAvailableBaseTypesAndPointers(SpvStorageClassFunction);
+  auto basic_type_ids_and_pointers =
+      GetAvailableBasicTypesAndPointers(SpvStorageClassFunction);
 
-  // These are the base types that are available to this fuzzer pass.
-  auto& base_types = base_type_ids_and_pointers.first;
+  // These are the basic types that are available to this fuzzer pass.
+  auto& basic_types = basic_type_ids_and_pointers.first;
 
-  // These are the pointers to those base types that are *initially* available
+  // These are the pointers to those basic types that are *initially* available
   // to the fuzzer pass.  The fuzzer pass might add pointer types in cases where
-  // none are available for a given base type.
-  auto& base_type_to_pointers = base_type_ids_and_pointers.second;
+  // none are available for a given basic type.
+  auto& basic_type_to_pointers = basic_type_ids_and_pointers.second;
 
   // Consider every function in the module.
   for (auto& function : *GetIRContext()->module()) {
     // Probabilistically keep adding random variables to this function.
     while (GetFuzzerContext()->ChoosePercentage(
         GetFuzzerContext()->GetChanceOfAddingLocalVariable())) {
-      // Choose a random base type; the new variable's type will be a pointer to
-      // this base type.
-      uint32_t base_type =
-          base_types[GetFuzzerContext()->RandomIndex(base_types)];
+      // Choose a random basic type; the new variable's type will be a pointer
+      // to this basic type.
+      uint32_t basic_type =
+          basic_types[GetFuzzerContext()->RandomIndex(basic_types)];
       uint32_t pointer_type;
-      std::vector<uint32_t>& available_pointers_to_base_type =
-          base_type_to_pointers.at(base_type);
-      // Determine whether there is at least one pointer to this base type.
-      if (available_pointers_to_base_type.empty()) {
+      std::vector<uint32_t>& available_pointers_to_basic_type =
+          basic_type_to_pointers.at(basic_type);
+      // Determine whether there is at least one pointer to this basic type.
+      if (available_pointers_to_basic_type.empty()) {
         // There is not.  Make one, to use here, and add it to the available
-        // pointers for the base type so that future variables can potentially
+        // pointers for the basic type so that future variables can potentially
         // use it.
         pointer_type = GetFuzzerContext()->GetFreshId();
         ApplyTransformation(TransformationAddTypePointer(
-            pointer_type, SpvStorageClassFunction, base_type));
-        available_pointers_to_base_type.push_back(pointer_type);
+            pointer_type, SpvStorageClassFunction, basic_type));
+        available_pointers_to_basic_type.push_back(pointer_type);
       } else {
         // There is - grab one.
         pointer_type =
-            available_pointers_to_base_type[GetFuzzerContext()->RandomIndex(
-                available_pointers_to_base_type)];
+            available_pointers_to_basic_type[GetFuzzerContext()->RandomIndex(
+                available_pointers_to_basic_type)];
       }
       ApplyTransformation(TransformationAddLocalVariable(
           GetFuzzerContext()->GetFreshId(), pointer_type, function.result_id(),
-          FindOrCreateZeroConstant(base_type), true));
+          FindOrCreateZeroConstant(basic_type), true));
     }
   }
 }

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.h

@@ -25,7 +25,7 @@ namespace fuzz {
 class FuzzerPassAddLocalVariables : public FuzzerPass {
  public:
   FuzzerPassAddLocalVariables(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp

@@ -20,10 +20,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddNoContractionDecorations::FuzzerPassAddNoContractionDecorations(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddNoContractionDecorations::
     ~FuzzerPassAddNoContractionDecorations() = default;

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_no_contraction_decorations.h

@@ -24,7 +24,7 @@ namespace fuzz {
 class FuzzerPassAddNoContractionDecorations : public FuzzerPass {
  public:
   FuzzerPassAddNoContractionDecorations(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 10 - 5
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.cpp

@@ -21,10 +21,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddStores::FuzzerPassAddStores(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddStores::~FuzzerPassAddStores() = default;
 
@@ -82,9 +83,13 @@ void FuzzerPassAddStores::Apply() {
                     default:
                       break;
                   }
-                  return GetFactManager()->BlockIsDead(block->id()) ||
-                         GetFactManager()->PointeeValueIsIrrelevant(
-                             instruction->result_id());
+                  return GetTransformationContext()
+                             ->GetFactManager()
+                             ->BlockIsDead(block->id()) ||
+                         GetTransformationContext()
+                             ->GetFactManager()
+                             ->PointeeValueIsIrrelevant(
+                                 instruction->result_id());
                 });
 
         // At this point, |relevant_pointers| contains all the pointers we might

+ 2 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.h

@@ -25,7 +25,8 @@ namespace fuzz {
 // are known not to affect the module's overall behaviour.
 class FuzzerPassAddStores : public FuzzerPass {
  public:
-  FuzzerPassAddStores(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassAddStores(opt::IRContext* ir_context,
+                      TransformationContext* transformation_context,
                       FuzzerContext* fuzzer_context,
                       protobufs::TransformationSequence* transformations);
 

+ 26 - 18
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_useful_constructs.cpp

@@ -25,10 +25,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAddUsefulConstructs::FuzzerPassAddUsefulConstructs(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddUsefulConstructs::~FuzzerPassAddUsefulConstructs() = default;
 
@@ -49,9 +50,10 @@ void FuzzerPassAddUsefulConstructs::MaybeAddIntConstant(
     TransformationAddConstantScalar add_constant_int =
         TransformationAddConstantScalar(GetFuzzerContext()->GetFreshId(),
                                         int_type_id, data);
-    assert(add_constant_int.IsApplicable(GetIRContext(), *GetFactManager()) &&
+    assert(add_constant_int.IsApplicable(GetIRContext(),
+                                         *GetTransformationContext()) &&
            "Should be applicable by construction.");
-    add_constant_int.Apply(GetIRContext(), GetFactManager());
+    add_constant_int.Apply(GetIRContext(), GetTransformationContext());
     *GetTransformations()->add_transformation() = add_constant_int.ToMessage();
   }
 }
@@ -75,9 +77,10 @@ void FuzzerPassAddUsefulConstructs::MaybeAddFloatConstant(
     TransformationAddConstantScalar add_constant_float =
         TransformationAddConstantScalar(GetFuzzerContext()->GetFreshId(),
                                         float_type_id, data);
-    assert(add_constant_float.IsApplicable(GetIRContext(), *GetFactManager()) &&
+    assert(add_constant_float.IsApplicable(GetIRContext(),
+                                           *GetTransformationContext()) &&
            "Should be applicable by construction.");
-    add_constant_float.Apply(GetIRContext(), GetFactManager());
+    add_constant_float.Apply(GetIRContext(), GetTransformationContext());
     *GetTransformations()->add_transformation() =
         add_constant_float.ToMessage();
   }
@@ -90,9 +93,10 @@ void FuzzerPassAddUsefulConstructs::Apply() {
     if (!GetIRContext()->get_type_mgr()->GetId(&temp_bool_type)) {
       auto add_type_boolean =
           TransformationAddTypeBoolean(GetFuzzerContext()->GetFreshId());
-      assert(add_type_boolean.IsApplicable(GetIRContext(), *GetFactManager()) &&
+      assert(add_type_boolean.IsApplicable(GetIRContext(),
+                                           *GetTransformationContext()) &&
              "Should be applicable by construction.");
-      add_type_boolean.Apply(GetIRContext(), GetFactManager());
+      add_type_boolean.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() =
           add_type_boolean.ToMessage();
     }
@@ -105,9 +109,10 @@ void FuzzerPassAddUsefulConstructs::Apply() {
       if (!GetIRContext()->get_type_mgr()->GetId(&temp_int_type)) {
         TransformationAddTypeInt add_type_int = TransformationAddTypeInt(
             GetFuzzerContext()->GetFreshId(), 32, is_signed);
-        assert(add_type_int.IsApplicable(GetIRContext(), *GetFactManager()) &&
+        assert(add_type_int.IsApplicable(GetIRContext(),
+                                         *GetTransformationContext()) &&
                "Should be applicable by construction.");
-        add_type_int.Apply(GetIRContext(), GetFactManager());
+        add_type_int.Apply(GetIRContext(), GetTransformationContext());
         *GetTransformations()->add_transformation() = add_type_int.ToMessage();
       }
     }
@@ -119,9 +124,10 @@ void FuzzerPassAddUsefulConstructs::Apply() {
     if (!GetIRContext()->get_type_mgr()->GetId(&temp_float_type)) {
       TransformationAddTypeFloat add_type_float =
           TransformationAddTypeFloat(GetFuzzerContext()->GetFreshId(), 32);
-      assert(add_type_float.IsApplicable(GetIRContext(), *GetFactManager()) &&
+      assert(add_type_float.IsApplicable(GetIRContext(),
+                                         *GetTransformationContext()) &&
              "Should be applicable by construction.");
-      add_type_float.Apply(GetIRContext(), GetFactManager());
+      add_type_float.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = add_type_float.ToMessage();
     }
   }
@@ -139,9 +145,9 @@ void FuzzerPassAddUsefulConstructs::Apply() {
       TransformationAddConstantBoolean add_constant_boolean(
           GetFuzzerContext()->GetFreshId(), boolean_value);
       assert(add_constant_boolean.IsApplicable(GetIRContext(),
-                                               *GetFactManager()) &&
+                                               *GetTransformationContext()) &&
              "Should be applicable by construction.");
-      add_constant_boolean.Apply(GetIRContext(), GetFactManager());
+      add_constant_boolean.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() =
           add_constant_boolean.ToMessage();
     }
@@ -168,8 +174,9 @@ void FuzzerPassAddUsefulConstructs::Apply() {
   //   of the element
   // - a signed integer constant for each index required to access the element
   // - a constant for the constant value itself
-  for (auto& fact_and_type_id :
-       GetFactManager()->GetConstantUniformFactsAndTypes()) {
+  for (auto& fact_and_type_id : GetTransformationContext()
+                                    ->GetFactManager()
+                                    ->GetConstantUniformFactsAndTypes()) {
     uint32_t element_type_id = fact_and_type_id.second;
     assert(element_type_id);
     auto element_type =
@@ -183,9 +190,10 @@ void FuzzerPassAddUsefulConstructs::Apply() {
       auto add_pointer =
           TransformationAddTypePointer(GetFuzzerContext()->GetFreshId(),
                                        SpvStorageClassUniform, element_type_id);
-      assert(add_pointer.IsApplicable(GetIRContext(), *GetFactManager()) &&
+      assert(add_pointer.IsApplicable(GetIRContext(),
+                                      *GetTransformationContext()) &&
              "Should be applicable by construction.");
-      add_pointer.Apply(GetIRContext(), GetFactManager());
+      add_pointer.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = add_pointer.ToMessage();
     }
     std::vector<uint32_t> words;

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_useful_constructs.h

@@ -25,7 +25,7 @@ namespace fuzz {
 class FuzzerPassAddUsefulConstructs : public FuzzerPass {
  public:
   FuzzerPassAddUsefulConstructs(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_function_controls.cpp

@@ -20,10 +20,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAdjustFunctionControls::FuzzerPassAdjustFunctionControls(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAdjustFunctionControls::~FuzzerPassAdjustFunctionControls() = default;
 

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_function_controls.h

@@ -24,7 +24,7 @@ namespace fuzz {
 class FuzzerPassAdjustFunctionControls : public FuzzerPass {
  public:
   FuzzerPassAdjustFunctionControls(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp

@@ -20,10 +20,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAdjustLoopControls::FuzzerPassAdjustLoopControls(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAdjustLoopControls::~FuzzerPassAdjustLoopControls() = default;
 

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_loop_controls.h

@@ -24,7 +24,7 @@ namespace fuzz {
 class FuzzerPassAdjustLoopControls : public FuzzerPass {
  public:
   FuzzerPassAdjustLoopControls(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp

@@ -21,10 +21,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAdjustMemoryOperandsMasks::FuzzerPassAdjustMemoryOperandsMasks(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAdjustMemoryOperandsMasks::~FuzzerPassAdjustMemoryOperandsMasks() =
     default;

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h

@@ -25,7 +25,7 @@ namespace fuzz {
 class FuzzerPassAdjustMemoryOperandsMasks : public FuzzerPass {
  public:
   FuzzerPassAdjustMemoryOperandsMasks(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp

@@ -20,10 +20,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassAdjustSelectionControls::FuzzerPassAdjustSelectionControls(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAdjustSelectionControls::~FuzzerPassAdjustSelectionControls() =
     default;

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_selection_controls.h

@@ -24,7 +24,7 @@ namespace fuzz {
 class FuzzerPassAdjustSelectionControls : public FuzzerPass {
  public:
   FuzzerPassAdjustSelectionControls(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 17 - 9
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp

@@ -25,26 +25,33 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassApplyIdSynonyms::FuzzerPassApplyIdSynonyms(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassApplyIdSynonyms::~FuzzerPassApplyIdSynonyms() = default;
 
 void FuzzerPassApplyIdSynonyms::Apply() {
   for (auto id_with_known_synonyms :
-       GetFactManager()->GetIdsForWhichSynonymsAreKnown(GetIRContext())) {
-    // Gather up all uses of |id_with_known_synonym|, and then subsequently
-    // iterate over these uses.  We use this separation because, when
-    // considering a given use, we might apply a transformation that will
+       GetTransformationContext()
+           ->GetFactManager()
+           ->GetIdsForWhichSynonymsAreKnown(GetIRContext())) {
+    // Gather up all uses of |id_with_known_synonym| as a regular id, and
+    // subsequently iterate over these uses.  We use this separation because,
+    // when considering a given use, we might apply a transformation that will
     // invalidate the def-use manager.
     std::vector<std::pair<opt::Instruction*, uint32_t>> uses;
     GetIRContext()->get_def_use_mgr()->ForEachUse(
         id_with_known_synonyms,
         [&uses](opt::Instruction* use_inst, uint32_t use_index) -> void {
-          uses.emplace_back(
-              std::pair<opt::Instruction*, uint32_t>(use_inst, use_index));
+          // We only gather up regular id uses; e.g. we do not include a use of
+          // the id as the scope for an atomic operation.
+          if (use_inst->GetOperand(use_index).type == SPV_OPERAND_TYPE_ID) {
+            uses.emplace_back(
+                std::pair<opt::Instruction*, uint32_t>(use_inst, use_index));
+          }
         });
 
     for (auto& use : uses) {
@@ -70,7 +77,8 @@ void FuzzerPassApplyIdSynonyms::Apply() {
       }
 
       std::vector<const protobufs::DataDescriptor*> synonyms_to_try;
-      for (auto& data_descriptor : GetFactManager()->GetSynonymsForId(
+      for (auto& data_descriptor :
+           GetTransformationContext()->GetFactManager()->GetSynonymsForId(
                id_with_known_synonyms, GetIRContext())) {
         protobufs::DataDescriptor descriptor_for_this_id =
             MakeDataDescriptor(id_with_known_synonyms, {});

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.h

@@ -27,7 +27,7 @@ namespace fuzz {
 class FuzzerPassApplyIdSynonyms : public FuzzerPass {
  public:
   FuzzerPassApplyIdSynonyms(opt::IRContext* ir_context,
-                            FactManager* fact_manager,
+                            TransformationContext* transformation_context,
                             FuzzerContext* fuzzer_context,
                             protobufs::TransformationSequence* transformations);
 

+ 103 - 93
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_construct_composites.cpp

@@ -25,10 +25,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassConstructComposites::FuzzerPassConstructComposites(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassConstructComposites::~FuzzerPassConstructComposites() = default;
 
@@ -87,7 +88,7 @@ void FuzzerPassConstructComposites::Apply() {
         // for constructing a composite of that type.  Otherwise these variables
         // will remain 0 and null respectively.
         uint32_t chosen_composite_type = 0;
-        std::unique_ptr<std::vector<uint32_t>> constructor_arguments = nullptr;
+        std::vector<uint32_t> constructor_arguments;
 
         // Initially, all composite type ids are available for us to try.  Keep
         // trying until we run out of options.
@@ -95,35 +96,38 @@ void FuzzerPassConstructComposites::Apply() {
         while (!composites_to_try_constructing.empty()) {
           // Remove a composite type from the composite types left for us to
           // try.
-          auto index =
-              GetFuzzerContext()->RandomIndex(composites_to_try_constructing);
           auto next_composite_to_try_constructing =
-              composites_to_try_constructing[index];
-          composites_to_try_constructing.erase(
-              composites_to_try_constructing.begin() + index);
+              GetFuzzerContext()->RemoveAtRandomIndex(
+                  &composites_to_try_constructing);
 
           // Now try to construct a composite of this type, using an appropriate
           // helper method depending on the kind of composite type.
-          auto composite_type = GetIRContext()->get_type_mgr()->GetType(
+          auto composite_type_inst = GetIRContext()->get_def_use_mgr()->GetDef(
               next_composite_to_try_constructing);
-          if (auto array_type = composite_type->AsArray()) {
-            constructor_arguments = TryConstructingArrayComposite(
-                *array_type, type_id_to_available_instructions);
-          } else if (auto matrix_type = composite_type->AsMatrix()) {
-            constructor_arguments = TryConstructingMatrixComposite(
-                *matrix_type, type_id_to_available_instructions);
-          } else if (auto struct_type = composite_type->AsStruct()) {
-            constructor_arguments = TryConstructingStructComposite(
-                *struct_type, type_id_to_available_instructions);
-          } else {
-            auto vector_type = composite_type->AsVector();
-            assert(vector_type &&
-                   "The space of possible composite types should be covered by "
-                   "the above cases.");
-            constructor_arguments = TryConstructingVectorComposite(
-                *vector_type, type_id_to_available_instructions);
+          switch (composite_type_inst->opcode()) {
+            case SpvOpTypeArray:
+              constructor_arguments = FindComponentsToConstructArray(
+                  *composite_type_inst, type_id_to_available_instructions);
+              break;
+            case SpvOpTypeMatrix:
+              constructor_arguments = FindComponentsToConstructMatrix(
+                  *composite_type_inst, type_id_to_available_instructions);
+              break;
+            case SpvOpTypeStruct:
+              constructor_arguments = FindComponentsToConstructStruct(
+                  *composite_type_inst, type_id_to_available_instructions);
+              break;
+            case SpvOpTypeVector:
+              constructor_arguments = FindComponentsToConstructVector(
+                  *composite_type_inst, type_id_to_available_instructions);
+              break;
+            default:
+              assert(false &&
+                     "The space of possible composite types should be covered "
+                     "by the above cases.");
+              break;
           }
-          if (constructor_arguments != nullptr) {
+          if (!constructor_arguments.empty()) {
             // We succeeded!  Note the composite type we finally settled on, and
             // exit from the loop.
             chosen_composite_type = next_composite_to_try_constructing;
@@ -134,20 +138,15 @@ void FuzzerPassConstructComposites::Apply() {
         if (!chosen_composite_type) {
           // We did not manage to make a composite; return 0 to indicate that no
           // instructions were added.
-          assert(constructor_arguments == nullptr);
+          assert(constructor_arguments.empty());
           return;
         }
-        assert(constructor_arguments != nullptr);
+        assert(!constructor_arguments.empty());
 
         // Make and apply a transformation.
-        TransformationCompositeConstruct transformation(
-            chosen_composite_type, *constructor_arguments,
-            instruction_descriptor, GetFuzzerContext()->GetFreshId());
-        assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()) &&
-               "This transformation should be applicable by construction.");
-        transformation.Apply(GetIRContext(), GetFactManager());
-        *GetTransformations()->add_transformation() =
-            transformation.ToMessage();
+        ApplyTransformation(TransformationCompositeConstruct(
+            chosen_composite_type, constructor_arguments,
+            instruction_descriptor, GetFuzzerContext()->GetFreshId()));
       });
 }
 
@@ -160,20 +159,15 @@ void FuzzerPassConstructComposites::RecordAvailableInstruction(
   type_id_to_available_instructions->at(inst->type_id()).push_back(inst);
 }
 
-std::unique_ptr<std::vector<uint32_t>>
-FuzzerPassConstructComposites::TryConstructingArrayComposite(
-    const opt::analysis::Array& array_type,
+std::vector<uint32_t>
+FuzzerPassConstructComposites::FindComponentsToConstructArray(
+    const opt::Instruction& array_type_instruction,
     const TypeIdToInstructions& type_id_to_available_instructions) {
-  // At present we assume arrays have a constant size.
-  assert(array_type.length_info().words.size() == 2);
-  assert(array_type.length_info().words[0] ==
-         opt::analysis::Array::LengthInfo::kConstant);
-
-  auto result = MakeUnique<std::vector<uint32_t>>();
+  assert(array_type_instruction.opcode() == SpvOpTypeArray &&
+         "Precondition: instruction must be an array type.");
 
   // Get the element type for the array.
-  auto element_type_id =
-      GetIRContext()->get_type_mgr()->GetId(array_type.element_type());
+  auto element_type_id = array_type_instruction.GetSingleWordInOperand(0);
 
   // Get all instructions at our disposal that compute something of this element
   // type.
@@ -184,26 +178,34 @@ FuzzerPassConstructComposites::TryConstructingArrayComposite(
     // If there are not any instructions available that compute the element type
     // of the array then we are not in a position to construct a composite with
     // this array type.
-    return nullptr;
+    return {};
   }
-  for (uint32_t index = 0; index < array_type.length_info().words[1]; index++) {
-    result->push_back(available_instructions
-                          ->second[GetFuzzerContext()->RandomIndex(
-                              available_instructions->second)]
-                          ->result_id());
+
+  uint32_t array_length =
+      GetIRContext()
+          ->get_def_use_mgr()
+          ->GetDef(array_type_instruction.GetSingleWordInOperand(1))
+          ->GetSingleWordInOperand(0);
+
+  std::vector<uint32_t> result;
+  for (uint32_t index = 0; index < array_length; index++) {
+    result.push_back(available_instructions
+                         ->second[GetFuzzerContext()->RandomIndex(
+                             available_instructions->second)]
+                         ->result_id());
   }
   return result;
 }
 
-std::unique_ptr<std::vector<uint32_t>>
-FuzzerPassConstructComposites::TryConstructingMatrixComposite(
-    const opt::analysis::Matrix& matrix_type,
+std::vector<uint32_t>
+FuzzerPassConstructComposites::FindComponentsToConstructMatrix(
+    const opt::Instruction& matrix_type_instruction,
     const TypeIdToInstructions& type_id_to_available_instructions) {
-  auto result = MakeUnique<std::vector<uint32_t>>();
+  assert(matrix_type_instruction.opcode() == SpvOpTypeMatrix &&
+         "Precondition: instruction must be a matrix type.");
 
   // Get the element type for the matrix.
-  auto element_type_id =
-      GetIRContext()->get_type_mgr()->GetId(matrix_type.element_type());
+  auto element_type_id = matrix_type_instruction.GetSingleWordInOperand(0);
 
   // Get all instructions at our disposal that compute something of this element
   // type.
@@ -214,25 +216,32 @@ FuzzerPassConstructComposites::TryConstructingMatrixComposite(
     // If there are not any instructions available that compute the element type
     // of the matrix then we are not in a position to construct a composite with
     // this matrix type.
-    return nullptr;
+    return {};
   }
-  for (uint32_t index = 0; index < matrix_type.element_count(); index++) {
-    result->push_back(available_instructions
-                          ->second[GetFuzzerContext()->RandomIndex(
-                              available_instructions->second)]
-                          ->result_id());
+  std::vector<uint32_t> result;
+  for (uint32_t index = 0;
+       index < matrix_type_instruction.GetSingleWordInOperand(1); index++) {
+    result.push_back(available_instructions
+                         ->second[GetFuzzerContext()->RandomIndex(
+                             available_instructions->second)]
+                         ->result_id());
   }
   return result;
 }
 
-std::unique_ptr<std::vector<uint32_t>>
-FuzzerPassConstructComposites::TryConstructingStructComposite(
-    const opt::analysis::Struct& struct_type,
+std::vector<uint32_t>
+FuzzerPassConstructComposites::FindComponentsToConstructStruct(
+    const opt::Instruction& struct_type_instruction,
     const TypeIdToInstructions& type_id_to_available_instructions) {
-  auto result = MakeUnique<std::vector<uint32_t>>();
+  assert(struct_type_instruction.opcode() == SpvOpTypeStruct &&
+         "Precondition: instruction must be a struct type.");
+  std::vector<uint32_t> result;
   // Consider the type of each field of the struct.
-  for (auto element_type : struct_type.element_types()) {
-    auto element_type_id = GetIRContext()->get_type_mgr()->GetId(element_type);
+  for (uint32_t in_operand_index = 0;
+       in_operand_index < struct_type_instruction.NumInOperands();
+       in_operand_index++) {
+    auto element_type_id =
+        struct_type_instruction.GetSingleWordInOperand(in_operand_index);
     // Find the instructions at our disposal that compute something of the field
     // type.
     auto available_instructions =
@@ -240,24 +249,28 @@ FuzzerPassConstructComposites::TryConstructingStructComposite(
     if (available_instructions == type_id_to_available_instructions.cend()) {
       // If there are no such instructions, we cannot construct a composite of
       // this struct type.
-      return nullptr;
+      return {};
     }
-    result->push_back(available_instructions
-                          ->second[GetFuzzerContext()->RandomIndex(
-                              available_instructions->second)]
-                          ->result_id());
+    result.push_back(available_instructions
+                         ->second[GetFuzzerContext()->RandomIndex(
+                             available_instructions->second)]
+                         ->result_id());
   }
   return result;
 }
 
-std::unique_ptr<std::vector<uint32_t>>
-FuzzerPassConstructComposites::TryConstructingVectorComposite(
-    const opt::analysis::Vector& vector_type,
+std::vector<uint32_t>
+FuzzerPassConstructComposites::FindComponentsToConstructVector(
+    const opt::Instruction& vector_type_instruction,
     const TypeIdToInstructions& type_id_to_available_instructions) {
+  assert(vector_type_instruction.opcode() == SpvOpTypeVector &&
+         "Precondition: instruction must be a vector type.");
+
   // Get details of the type underlying the vector, and the width of the vector,
   // for convenience.
-  auto element_type = vector_type.element_type();
-  auto element_count = vector_type.element_count();
+  auto element_type_id = vector_type_instruction.GetSingleWordInOperand(0);
+  auto element_type = GetIRContext()->get_type_mgr()->GetType(element_type_id);
+  auto element_count = vector_type_instruction.GetSingleWordInOperand(1);
 
   // Collect a mapping, from type id to width, for scalar/vector types that are
   // smaller in width than |vector_type|, but that have the same underlying
@@ -268,14 +281,12 @@ FuzzerPassConstructComposites::TryConstructingVectorComposite(
   std::map<uint32_t, uint32_t> smaller_vector_type_id_to_width;
   // Add the underlying type.  This id must exist, in order for |vector_type| to
   // exist.
-  auto scalar_type_id = GetIRContext()->get_type_mgr()->GetId(element_type);
-  smaller_vector_type_id_to_width[scalar_type_id] = 1;
+  smaller_vector_type_id_to_width[element_type_id] = 1;
 
   // Now add every vector type with width at least 2, and less than the width of
   // |vector_type|.
   for (uint32_t width = 2; width < element_count; width++) {
-    opt::analysis::Vector smaller_vector_type(vector_type.element_type(),
-                                              width);
+    opt::analysis::Vector smaller_vector_type(element_type, width);
     auto smaller_vector_type_id =
         GetIRContext()->get_type_mgr()->GetId(&smaller_vector_type);
     // We might find that there is no declared type of this smaller width.
@@ -302,12 +313,11 @@ FuzzerPassConstructComposites::TryConstructingVectorComposite(
   // order at this stage.
   std::vector<opt::Instruction*> instructions_to_use;
 
-  while (vector_slots_used < vector_type.element_count()) {
+  while (vector_slots_used < element_count) {
     std::vector<opt::Instruction*> instructions_to_choose_from;
     for (auto& entry : smaller_vector_type_id_to_width) {
       if (entry.second >
-          std::min(vector_type.element_count() - 1,
-                   vector_type.element_count() - vector_slots_used)) {
+          std::min(element_count - 1, element_count - vector_slots_used)) {
         continue;
       }
       auto available_instructions =
@@ -326,7 +336,7 @@ FuzzerPassConstructComposites::TryConstructingVectorComposite(
       // another manner, so we could opt to retry a few times here, but it is
       // simpler to just give up on the basis that this will not happen
       // frequently.
-      return nullptr;
+      return {};
     }
     auto instruction_to_use =
         instructions_to_choose_from[GetFuzzerContext()->RandomIndex(
@@ -345,16 +355,16 @@ FuzzerPassConstructComposites::TryConstructingVectorComposite(
       vector_slots_used += 1;
     }
   }
-  assert(vector_slots_used == vector_type.element_count());
+  assert(vector_slots_used == element_count);
 
-  auto result = MakeUnique<std::vector<uint32_t>>();
+  std::vector<uint32_t> result;
   std::vector<uint32_t> operands;
   while (!instructions_to_use.empty()) {
     auto index = GetFuzzerContext()->RandomIndex(instructions_to_use);
-    result->push_back(instructions_to_use[index]->result_id());
+    result.push_back(instructions_to_use[index]->result_id());
     instructions_to_use.erase(instructions_to_use.begin() + index);
   }
-  assert(result->size() > 1);
+  assert(result.size() > 1);
   return result;
 }
 

+ 15 - 14
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_construct_composites.h

@@ -27,7 +27,7 @@ namespace fuzz {
 class FuzzerPassConstructComposites : public FuzzerPass {
  public:
   FuzzerPassConstructComposites(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
@@ -49,27 +49,28 @@ class FuzzerPassConstructComposites : public FuzzerPass {
       opt::Instruction* inst,
       TypeIdToInstructions* type_id_to_available_instructions);
 
+  // Requires that |array_type_instruction| has opcode OpTypeArray.
   // Attempts to find suitable instruction result ids from the values of
   // |type_id_to_available_instructions| that would allow a composite of type
-  // |array_type| to be constructed.  Returns said ids if they can be found.
-  // Returns |nullptr| otherwise.
-  std::unique_ptr<std::vector<uint32_t>> TryConstructingArrayComposite(
-      const opt::analysis::Array& array_type,
+  // |array_type_instruction| to be constructed.  Returns said ids if they can
+  // be found and an empty vector otherwise.
+  std::vector<uint32_t> FindComponentsToConstructArray(
+      const opt::Instruction& array_type_instruction,
       const TypeIdToInstructions& type_id_to_available_instructions);
 
-  // Similar to TryConstructingArrayComposite, but for matrices.
-  std::unique_ptr<std::vector<uint32_t>> TryConstructingMatrixComposite(
-      const opt::analysis::Matrix& matrix_type,
+  // Similar to FindComponentsToConstructArray, but for matrices.
+  std::vector<uint32_t> FindComponentsToConstructMatrix(
+      const opt::Instruction& matrix_type_instruction,
       const TypeIdToInstructions& type_id_to_available_instructions);
 
-  // Similar to TryConstructingArrayComposite, but for structs.
-  std::unique_ptr<std::vector<uint32_t>> TryConstructingStructComposite(
-      const opt::analysis::Struct& struct_type,
+  // Similar to FindComponentsToConstructArray, but for structs.
+  std::vector<uint32_t> FindComponentsToConstructStruct(
+      const opt::Instruction& struct_type_instruction,
       const TypeIdToInstructions& type_id_to_available_instructions);
 
-  // Similar to TryConstructingArrayComposite, but for vectors.
-  std::unique_ptr<std::vector<uint32_t>> TryConstructingVectorComposite(
-      const opt::analysis::Vector& vector_type,
+  // Similar to FindComponentsToConstructArray, but for vectors.
+  std::vector<uint32_t> FindComponentsToConstructVector(
+      const opt::Instruction& vector_type_instruction,
       const TypeIdToInstructions& type_id_to_available_instructions);
 };
 

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_copy_objects.cpp

@@ -21,10 +21,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassCopyObjects::FuzzerPassCopyObjects(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassCopyObjects::~FuzzerPassCopyObjects() = default;
 

+ 2 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_copy_objects.h

@@ -23,7 +23,8 @@ namespace fuzz {
 // A fuzzer pass for adding adding copies of objects to the module.
 class FuzzerPassCopyObjects : public FuzzerPass {
  public:
-  FuzzerPassCopyObjects(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassCopyObjects(opt::IRContext* ir_context,
+                        TransformationContext* transformation_context,
                         FuzzerContext* fuzzer_context,
                         protobufs::TransformationSequence* transformations);
 

+ 21 - 3
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.cpp

@@ -22,6 +22,7 @@
 #include "source/fuzz/instruction_message.h"
 #include "source/fuzz/transformation_add_constant_boolean.h"
 #include "source/fuzz/transformation_add_constant_composite.h"
+#include "source/fuzz/transformation_add_constant_null.h"
 #include "source/fuzz/transformation_add_constant_scalar.h"
 #include "source/fuzz/transformation_add_function.h"
 #include "source/fuzz/transformation_add_global_undef.h"
@@ -40,11 +41,12 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassDonateModules::FuzzerPassDonateModules(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations,
     const std::vector<fuzzerutil::ModuleSupplier>& donor_suppliers)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations),
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations),
       donor_suppliers_(donor_suppliers) {}
 
 FuzzerPassDonateModules::~FuzzerPassDonateModules() = default;
@@ -62,7 +64,9 @@ void FuzzerPassDonateModules::Apply() {
     std::unique_ptr<opt::IRContext> donor_ir_context = donor_suppliers_.at(
         GetFuzzerContext()->RandomIndex(donor_suppliers_))();
     assert(donor_ir_context != nullptr && "Supplying of donor failed");
-    assert(fuzzerutil::IsValid(donor_ir_context.get()) &&
+    assert(fuzzerutil::IsValid(
+               donor_ir_context.get(),
+               GetTransformationContext()->GetValidatorOptions()) &&
            "The donor module must be valid");
     // Donate the supplied module.
     //
@@ -391,6 +395,20 @@ void FuzzerPassDonateModules::HandleTypesAndValues(
             original_id_to_donated_id->at(type_or_value.type_id()),
             constituent_ids));
       } break;
+      case SpvOpConstantNull: {
+        if (!original_id_to_donated_id->count(type_or_value.type_id())) {
+          // We did not donate the type associated with this null constant, so
+          // we cannot donate the null constant.
+          continue;
+        }
+
+        // It is fine to have multiple OpConstantNull instructions of the same
+        // type, so we just add this to the recipient module.
+        new_result_id = GetFuzzerContext()->GetFreshId();
+        ApplyTransformation(TransformationAddConstantNull(
+            new_result_id,
+            original_id_to_donated_id->at(type_or_value.type_id())));
+      } break;
       case SpvOpVariable: {
         // This is a global variable that could have one of various storage
         // classes.  However, we change all global variable pointer storage

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.h

@@ -28,7 +28,7 @@ namespace fuzz {
 class FuzzerPassDonateModules : public FuzzerPass {
  public:
   FuzzerPassDonateModules(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations,
       const std::vector<fuzzerutil::ModuleSupplier>& donor_suppliers);

+ 8 - 5
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_merge_blocks.cpp

@@ -22,10 +22,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassMergeBlocks::FuzzerPassMergeBlocks(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassMergeBlocks::~FuzzerPassMergeBlocks() = default;
 
@@ -44,7 +45,8 @@ void FuzzerPassMergeBlocks::Apply() {
       // For other blocks, we add a transformation to merge the block into its
       // predecessor if that transformation would be applicable.
       TransformationMergeBlocks transformation(block.id());
-      if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
+      if (transformation.IsApplicable(GetIRContext(),
+                                      *GetTransformationContext())) {
         potential_transformations.push_back(transformation);
       }
     }
@@ -54,8 +56,9 @@ void FuzzerPassMergeBlocks::Apply() {
     uint32_t index = GetFuzzerContext()->RandomIndex(potential_transformations);
     auto transformation = potential_transformations.at(index);
     potential_transformations.erase(potential_transformations.begin() + index);
-    if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
-      transformation.Apply(GetIRContext(), GetFactManager());
+    if (transformation.IsApplicable(GetIRContext(),
+                                    *GetTransformationContext())) {
+      transformation.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = transformation.ToMessage();
     }
   }

+ 2 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_merge_blocks.h

@@ -23,7 +23,8 @@ namespace fuzz {
 // A fuzzer pass for merging blocks in the module.
 class FuzzerPassMergeBlocks : public FuzzerPass {
  public:
-  FuzzerPassMergeBlocks(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassMergeBlocks(opt::IRContext* ir_context,
+                        TransformationContext* transformation_context,
                         FuzzerContext* fuzzer_context,
                         protobufs::TransformationSequence* transformations);
 

+ 22 - 13
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_obfuscate_constants.cpp

@@ -25,10 +25,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassObfuscateConstants::FuzzerPassObfuscateConstants(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassObfuscateConstants::~FuzzerPassObfuscateConstants() = default;
 
@@ -83,12 +84,13 @@ void FuzzerPassObfuscateConstants::ObfuscateBoolConstantViaConstantPair(
       bool_constant_use, lhs_id, rhs_id, comparison_opcode,
       GetFuzzerContext()->GetFreshId());
   // The transformation should be applicable by construction.
-  assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()));
+  assert(
+      transformation.IsApplicable(GetIRContext(), *GetTransformationContext()));
 
   // Applying this transformation yields a pointer to the new instruction that
   // computes the result of the binary expression.
-  auto binary_operator_instruction =
-      transformation.ApplyWithResult(GetIRContext(), GetFactManager());
+  auto binary_operator_instruction = transformation.ApplyWithResult(
+      GetIRContext(), GetTransformationContext());
 
   // Add this transformation to the sequence of transformations that have been
   // applied.
@@ -245,7 +247,9 @@ void FuzzerPassObfuscateConstants::ObfuscateBoolConstant(
   // with uniforms of the same value.
 
   auto available_types_with_uniforms =
-      GetFactManager()->GetTypesForWhichUniformValuesAreKnown();
+      GetTransformationContext()
+          ->GetFactManager()
+          ->GetTypesForWhichUniformValuesAreKnown();
   if (available_types_with_uniforms.empty()) {
     // Do not try to obfuscate if we do not have access to any uniform
     // elements with known values.
@@ -254,9 +258,10 @@ void FuzzerPassObfuscateConstants::ObfuscateBoolConstant(
   auto chosen_type_id =
       available_types_with_uniforms[GetFuzzerContext()->RandomIndex(
           available_types_with_uniforms)];
-  auto available_constants =
-      GetFactManager()->GetConstantsAvailableFromUniformsForType(
-          GetIRContext(), chosen_type_id);
+  auto available_constants = GetTransformationContext()
+                                 ->GetFactManager()
+                                 ->GetConstantsAvailableFromUniformsForType(
+                                     GetIRContext(), chosen_type_id);
   if (available_constants.size() == 1) {
     // TODO(afd): for now we only obfuscate a boolean if there are at least
     //  two constants available from uniforms, so that we can do a
@@ -308,8 +313,11 @@ void FuzzerPassObfuscateConstants::ObfuscateScalarConstant(
 
   // Check whether we know that any uniforms are guaranteed to be equal to the
   // scalar constant associated with |constant_use|.
-  auto uniform_descriptors = GetFactManager()->GetUniformDescriptorsForConstant(
-      GetIRContext(), constant_use.id_of_interest());
+  auto uniform_descriptors =
+      GetTransformationContext()
+          ->GetFactManager()
+          ->GetUniformDescriptorsForConstant(GetIRContext(),
+                                             constant_use.id_of_interest());
   if (uniform_descriptors.empty()) {
     // No relevant uniforms, so do not obfuscate.
     return;
@@ -324,8 +332,9 @@ void FuzzerPassObfuscateConstants::ObfuscateScalarConstant(
       constant_use, uniform_descriptor, GetFuzzerContext()->GetFreshId(),
       GetFuzzerContext()->GetFreshId());
   // Transformation should be applicable by construction.
-  assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()));
-  transformation.Apply(GetIRContext(), GetFactManager());
+  assert(
+      transformation.IsApplicable(GetIRContext(), *GetTransformationContext()));
+  transformation.Apply(GetIRContext(), GetTransformationContext());
   *GetTransformations()->add_transformation() = transformation.ToMessage();
 }
 

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_obfuscate_constants.h

@@ -28,7 +28,7 @@ namespace fuzz {
 class FuzzerPassObfuscateConstants : public FuzzerPass {
  public:
   FuzzerPassObfuscateConstants(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 6 - 4
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_outline_functions.cpp

@@ -23,10 +23,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassOutlineFunctions::FuzzerPassOutlineFunctions(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassOutlineFunctions::~FuzzerPassOutlineFunctions() = default;
 
@@ -88,8 +89,9 @@ void FuzzerPassOutlineFunctions::Apply() {
         /*new_callee_result_id*/ GetFuzzerContext()->GetFreshId(),
         /*input_id_to_fresh_id*/ std::move(input_id_to_fresh_id),
         /*output_id_to_fresh_id*/ std::move(output_id_to_fresh_id));
-    if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
-      transformation.Apply(GetIRContext(), GetFactManager());
+    if (transformation.IsApplicable(GetIRContext(),
+                                    *GetTransformationContext())) {
+      transformation.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = transformation.ToMessage();
     }
   }

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_outline_functions.h

@@ -25,7 +25,7 @@ namespace fuzz {
 class FuzzerPassOutlineFunctions : public FuzzerPass {
  public:
   FuzzerPassOutlineFunctions(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 6 - 4
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_blocks.cpp

@@ -20,10 +20,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassPermuteBlocks::FuzzerPassPermuteBlocks(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassPermuteBlocks::~FuzzerPassPermuteBlocks() = default;
 
@@ -66,8 +67,9 @@ void FuzzerPassPermuteBlocks::Apply() {
       // down indefinitely.
       while (true) {
         TransformationMoveBlockDown transformation(*id);
-        if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
-          transformation.Apply(GetIRContext(), GetFactManager());
+        if (transformation.IsApplicable(GetIRContext(),
+                                        *GetTransformationContext())) {
+          transformation.Apply(GetIRContext(), GetTransformationContext());
           *GetTransformations()->add_transformation() =
               transformation.ToMessage();
         } else {

+ 2 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_blocks.h

@@ -24,7 +24,8 @@ namespace fuzz {
 // manner.
 class FuzzerPassPermuteBlocks : public FuzzerPass {
  public:
-  FuzzerPassPermuteBlocks(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassPermuteBlocks(opt::IRContext* ir_context,
+                          TransformationContext* transformation_context,
                           FuzzerContext* fuzzer_context,
                           protobufs::TransformationSequence* transformations);
 

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_function_parameters.cpp

@@ -25,10 +25,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassPermuteFunctionParameters::FuzzerPassPermuteFunctionParameters(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassPermuteFunctionParameters::~FuzzerPassPermuteFunctionParameters() =
     default;

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_permute_function_parameters.h

@@ -30,7 +30,7 @@ namespace fuzz {
 class FuzzerPassPermuteFunctionParameters : public FuzzerPass {
  public:
   FuzzerPassPermuteFunctionParameters(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 6 - 4
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_split_blocks.cpp

@@ -23,10 +23,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassSplitBlocks::FuzzerPassSplitBlocks(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassSplitBlocks::~FuzzerPassSplitBlocks() = default;
 
@@ -95,8 +96,9 @@ void FuzzerPassSplitBlocks::Apply() {
     // If the position we have chosen turns out to be a valid place to split
     // the block, we apply the split. Otherwise the block just doesn't get
     // split.
-    if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
-      transformation.Apply(GetIRContext(), GetFactManager());
+    if (transformation.IsApplicable(GetIRContext(),
+                                    *GetTransformationContext())) {
+      transformation.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = transformation.ToMessage();
     }
   }

+ 2 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_split_blocks.h

@@ -24,7 +24,8 @@ namespace fuzz {
 // can be very useful for giving other passes a chance to apply.
 class FuzzerPassSplitBlocks : public FuzzerPass {
  public:
-  FuzzerPassSplitBlocks(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassSplitBlocks(opt::IRContext* ir_context,
+                        TransformationContext* transformation_context,
                         FuzzerContext* fuzzer_context,
                         protobufs::TransformationSequence* transformations);
 

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp

@@ -22,10 +22,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassSwapCommutableOperands::FuzzerPassSwapCommutableOperands(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassSwapCommutableOperands::~FuzzerPassSwapCommutableOperands() = default;
 

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_swap_commutable_operands.h

@@ -26,7 +26,7 @@ namespace fuzz {
 class FuzzerPassSwapCommutableOperands : public FuzzerPass {
  public:
   FuzzerPassSwapCommutableOperands(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp

@@ -22,10 +22,11 @@ namespace spvtools {
 namespace fuzz {
 
 FuzzerPassToggleAccessChainInstruction::FuzzerPassToggleAccessChainInstruction(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassToggleAccessChainInstruction::
     ~FuzzerPassToggleAccessChainInstruction() = default;

+ 1 - 1
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h

@@ -25,7 +25,7 @@ namespace fuzz {
 class FuzzerPassToggleAccessChainInstruction : public FuzzerPass {
  public:
   FuzzerPassToggleAccessChainInstruction(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 

+ 9 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp

@@ -329,11 +329,11 @@ uint32_t GetArraySize(const opt::Instruction& array_type_instruction,
   return array_length_constant->GetU32();
 }
 
-bool IsValid(opt::IRContext* context) {
+bool IsValid(opt::IRContext* context, spv_validator_options validator_options) {
   std::vector<uint32_t> binary;
   context->module()->ToBinary(&binary, false);
   SpirvTools tools(context->grammar().target_env());
-  return tools.Validate(binary);
+  return tools.Validate(binary.data(), binary.size(), validator_options);
 }
 
 std::unique_ptr<opt::IRContext> CloneIRContext(opt::IRContext* context) {
@@ -537,6 +537,13 @@ uint32_t MaybeGetPointerType(opt::IRContext* context, uint32_t pointee_type_id,
   return 0;
 }
 
+bool IsNullConstantSupported(const opt::analysis::Type& type) {
+  return type.AsBool() || type.AsInteger() || type.AsFloat() ||
+         type.AsMatrix() || type.AsVector() || type.AsArray() ||
+         type.AsStruct() || type.AsPointer() || type.AsEvent() ||
+         type.AsDeviceEvent() || type.AsReserveId() || type.AsQueue();
+}
+
 }  // namespace fuzzerutil
 
 }  // namespace fuzz

+ 7 - 2
3rdparty/spirv-tools/source/fuzz/fuzzer_util.h

@@ -132,8 +132,9 @@ uint32_t GetNumberOfStructMembers(
 uint32_t GetArraySize(const opt::Instruction& array_type_instruction,
                       opt::IRContext* context);
 
-// Returns true if and only if |context| is valid, according to the validator.
-bool IsValid(opt::IRContext* context);
+// Returns true if and only if |context| is valid, according to the validator
+// instantiated with |validator_options|.
+bool IsValid(opt::IRContext* context, spv_validator_options validator_options);
 
 // Returns a clone of |context|, by writing |context| to a binary and then
 // parsing it again.
@@ -209,6 +210,10 @@ SpvStorageClass GetStorageClassFromPointerType(opt::IRContext* context,
 uint32_t MaybeGetPointerType(opt::IRContext* context, uint32_t pointee_type_id,
                              SpvStorageClass storage_class);
 
+// Returns true if and only if |type| is one of the types for which it is legal
+// to have an OpConstantNull value.
+bool IsNullConstantSupported(const opt::analysis::Type& type);
+
 }  // namespace fuzzerutil
 
 }  // namespace fuzz

+ 13 - 0
3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto

@@ -372,6 +372,7 @@ message Transformation {
     TransformationSwapCommutableOperands swap_commutable_operands = 41;
     TransformationPermuteFunctionParameters permute_function_parameters = 42;
     TransformationToggleAccessChainInstruction toggle_access_chain_instruction = 43;
+    TransformationAddConstantNull add_constant_null = 44;
     // Add additional option using the next available number.
   }
 }
@@ -422,6 +423,18 @@ message TransformationAddConstantComposite {
 
 }
 
+message TransformationAddConstantNull {
+
+  // Adds a null constant.
+
+  // Id for the constant
+  uint32 fresh_id = 1;
+
+  // Type of the constant
+  uint32 type_id = 2;
+
+}
+
 message TransformationAddConstantScalar {
 
   // Adds a constant of the given scalar type.

+ 21 - 12
3rdparty/spirv-tools/source/fuzz/replayer.cpp

@@ -26,6 +26,7 @@
 #include "source/fuzz/transformation_add_type_float.h"
 #include "source/fuzz/transformation_add_type_int.h"
 #include "source/fuzz/transformation_add_type_pointer.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/fuzz/transformation_move_block_down.h"
 #include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h"
 #include "source/fuzz/transformation_replace_constant_with_uniform.h"
@@ -37,18 +38,22 @@ namespace spvtools {
 namespace fuzz {
 
 struct Replayer::Impl {
-  explicit Impl(spv_target_env env, bool validate)
-      : target_env(env), validate_during_replay(validate) {}
-
-  const spv_target_env target_env;  // Target environment.
-  MessageConsumer consumer;         // Message consumer.
+  Impl(spv_target_env env, bool validate, spv_validator_options options)
+      : target_env(env),
+        validate_during_replay(validate),
+        validator_options(options) {}
 
+  const spv_target_env target_env;    // Target environment.
+  MessageConsumer consumer;           // Message consumer.
   const bool validate_during_replay;  // Controls whether the validator should
                                       // be run after every replay step.
+  spv_validator_options validator_options;  // Options to control
+                                            // validation
 };
 
-Replayer::Replayer(spv_target_env env, bool validate_during_replay)
-    : impl_(MakeUnique<Impl>(env, validate_during_replay)) {}
+Replayer::Replayer(spv_target_env env, bool validate_during_replay,
+                   spv_validator_options validator_options)
+    : impl_(MakeUnique<Impl>(env, validate_during_replay, validator_options)) {}
 
 Replayer::~Replayer() = default;
 
@@ -74,7 +79,8 @@ Replayer::ReplayerResultStatus Replayer::Run(
   }
 
   // Initial binary should be valid.
-  if (!tools.Validate(&binary_in[0], binary_in.size())) {
+  if (!tools.Validate(&binary_in[0], binary_in.size(),
+                      impl_->validator_options)) {
     impl_->consumer(SPV_MSG_INFO, nullptr, {},
                     "Initial binary is invalid; stopping.");
     return Replayer::ReplayerResultStatus::kInitialBinaryInvalid;
@@ -94,16 +100,19 @@ Replayer::ReplayerResultStatus Replayer::Run(
 
   FactManager fact_manager;
   fact_manager.AddFacts(impl_->consumer, initial_facts, ir_context.get());
+  TransformationContext transformation_context(&fact_manager,
+                                               impl_->validator_options);
 
   // Consider the transformation proto messages in turn.
   for (auto& message : transformation_sequence_in.transformation()) {
     auto transformation = Transformation::FromMessage(message);
 
     // Check whether the transformation can be applied.
-    if (transformation->IsApplicable(ir_context.get(), fact_manager)) {
+    if (transformation->IsApplicable(ir_context.get(),
+                                     transformation_context)) {
       // The transformation is applicable, so apply it, and copy it to the
       // sequence of transformations that were applied.
-      transformation->Apply(ir_context.get(), &fact_manager);
+      transformation->Apply(ir_context.get(), &transformation_context);
       *transformation_sequence_out->add_transformation() = message;
 
       if (impl_->validate_during_replay) {
@@ -111,8 +120,8 @@ Replayer::ReplayerResultStatus Replayer::Run(
         ir_context->module()->ToBinary(&binary_to_validate, false);
 
         // Check whether the latest transformation led to a valid binary.
-        if (!tools.Validate(&binary_to_validate[0],
-                            binary_to_validate.size())) {
+        if (!tools.Validate(&binary_to_validate[0], binary_to_validate.size(),
+                            impl_->validator_options)) {
           impl_->consumer(SPV_MSG_INFO, nullptr, {},
                           "Binary became invalid during replay (set a "
                           "breakpoint to inspect); stopping.");

+ 2 - 1
3rdparty/spirv-tools/source/fuzz/replayer.h

@@ -37,7 +37,8 @@ class Replayer {
   };
 
   // Constructs a replayer from the given target environment.
-  explicit Replayer(spv_target_env env, bool validate_during_replay);
+  Replayer(spv_target_env env, bool validate_during_replay,
+           spv_validator_options validator_options);
 
   // Disables copy/move constructor/assignment operations.
   Replayer(const Replayer&) = delete;

+ 22 - 13
3rdparty/spirv-tools/source/fuzz/shrinker.cpp

@@ -60,20 +60,27 @@ protobufs::TransformationSequence RemoveChunk(
 }  // namespace
 
 struct Shrinker::Impl {
-  explicit Impl(spv_target_env env, uint32_t limit, bool validate)
-      : target_env(env), step_limit(limit), validate_during_replay(validate) {}
-
-  const spv_target_env target_env;    // Target environment.
-  MessageConsumer consumer;           // Message consumer.
-  const uint32_t step_limit;          // Step limit for reductions.
-  const bool validate_during_replay;  // Determines whether to check for
-                                      // validity during the replaying of
-                                      // transformations.
+  Impl(spv_target_env env, uint32_t limit, bool validate,
+       spv_validator_options options)
+      : target_env(env),
+        step_limit(limit),
+        validate_during_replay(validate),
+        validator_options(options) {}
+
+  const spv_target_env target_env;          // Target environment.
+  MessageConsumer consumer;                 // Message consumer.
+  const uint32_t step_limit;                // Step limit for reductions.
+  const bool validate_during_replay;        // Determines whether to check for
+                                            // validity during the replaying of
+                                            // transformations.
+  spv_validator_options validator_options;  // Options to control validation.
 };
 
 Shrinker::Shrinker(spv_target_env env, uint32_t step_limit,
-                   bool validate_during_replay)
-    : impl_(MakeUnique<Impl>(env, step_limit, validate_during_replay)) {}
+                   bool validate_during_replay,
+                   spv_validator_options validator_options)
+    : impl_(MakeUnique<Impl>(env, step_limit, validate_during_replay,
+                             validator_options)) {}
 
 Shrinker::~Shrinker() = default;
 
@@ -113,7 +120,8 @@ Shrinker::ShrinkerResultStatus Shrinker::Run(
   // succeeds, (b) get the binary that results from running these
   // transformations, and (c) get the subsequence of the initial transformations
   // that actually apply (in principle this could be a strict subsequence).
-  if (Replayer(impl_->target_env, impl_->validate_during_replay)
+  if (Replayer(impl_->target_env, impl_->validate_during_replay,
+               impl_->validator_options)
           .Run(binary_in, initial_facts, transformation_sequence_in,
                &current_best_binary, &current_best_transformations) !=
       Replayer::ReplayerResultStatus::kComplete) {
@@ -184,7 +192,8 @@ Shrinker::ShrinkerResultStatus Shrinker::Run(
       // transformations inapplicable.
       std::vector<uint32_t> next_binary;
       protobufs::TransformationSequence next_transformation_sequence;
-      if (Replayer(impl_->target_env, false)
+      if (Replayer(impl_->target_env, impl_->validate_during_replay,
+                   impl_->validator_options)
               .Run(binary_in, initial_facts, transformations_with_chunk_removed,
                    &next_binary, &next_transformation_sequence) !=
           Replayer::ReplayerResultStatus::kComplete) {

+ 2 - 2
3rdparty/spirv-tools/source/fuzz/shrinker.h

@@ -50,8 +50,8 @@ class Shrinker {
       const std::vector<uint32_t>& binary, uint32_t counter)>;
 
   // Constructs a shrinker from the given target environment.
-  Shrinker(spv_target_env env, uint32_t step_limit,
-           bool validate_during_replay);
+  Shrinker(spv_target_env env, uint32_t step_limit, bool validate_during_replay,
+           spv_validator_options validator_options);
 
   // Disables copy/move constructor/assignment operations.
   Shrinker(const Shrinker&) = delete;

+ 6 - 2
3rdparty/spirv-tools/source/fuzz/transformation.cpp

@@ -20,6 +20,7 @@
 #include "source/fuzz/transformation_access_chain.h"
 #include "source/fuzz/transformation_add_constant_boolean.h"
 #include "source/fuzz/transformation_add_constant_composite.h"
+#include "source/fuzz/transformation_add_constant_null.h"
 #include "source/fuzz/transformation_add_constant_scalar.h"
 #include "source/fuzz/transformation_add_dead_block.h"
 #include "source/fuzz/transformation_add_dead_break.h"
@@ -78,6 +79,9 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
     case protobufs::Transformation::TransformationCase::kAddConstantComposite:
       return MakeUnique<TransformationAddConstantComposite>(
           message.add_constant_composite());
+    case protobufs::Transformation::TransformationCase::kAddConstantNull:
+      return MakeUnique<TransformationAddConstantNull>(
+          message.add_constant_null());
     case protobufs::Transformation::TransformationCase::kAddConstantScalar:
       return MakeUnique<TransformationAddConstantScalar>(
           message.add_constant_scalar());
@@ -195,9 +199,9 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
 }
 
 bool Transformation::CheckIdIsFreshAndNotUsedByThisTransformation(
-    uint32_t id, opt::IRContext* context,
+    uint32_t id, opt::IRContext* ir_context,
     std::set<uint32_t>* ids_used_by_this_transformation) {
-  if (!fuzzerutil::IsFreshId(context, id)) {
+  if (!fuzzerutil::IsFreshId(ir_context, id)) {
     return false;
   }
   if (ids_used_by_this_transformation->count(id) != 0) {

+ 15 - 12
3rdparty/spirv-tools/source/fuzz/transformation.h

@@ -17,8 +17,8 @@
 
 #include <memory>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -60,19 +60,22 @@ class Transformation {
  public:
   // A precondition that determines whether the transformation can be cleanly
   // applied in a semantics-preserving manner to the SPIR-V module given by
-  // |context|, in the presence of facts captured by |fact_manager|.
+  // |ir_context|, in the presence of facts and other contextual information
+  // captured by |transformation_context|.
+  //
   // Preconditions for individual transformations must be documented in the
-  // associated header file using precise English. The fact manager is used to
-  // provide access to facts about the module that are known to be true, on
+  // associated header file using precise English. The transformation context
+  // provides access to facts about the module that are known to be true, on
   // which the precondition may depend.
-  virtual bool IsApplicable(opt::IRContext* context,
-                            const FactManager& fact_manager) const = 0;
+  virtual bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const = 0;
 
-  // Requires that IsApplicable(context, fact_manager) holds.  Applies the
-  // transformation, mutating |context| and possibly updating |fact_manager|
-  // with new facts established by the transformation.
-  virtual void Apply(opt::IRContext* context,
-                     FactManager* fact_manager) const = 0;
+  // Requires that IsApplicable(ir_context, *transformation_context) holds.
+  // Applies the transformation, mutating |ir_context| and possibly updating
+  // |transformation_context| with new facts established by the transformation.
+  virtual void Apply(opt::IRContext* ir_context,
+                     TransformationContext* transformation_context) const = 0;
 
   // Turns the transformation into a protobuf message for serialization.
   virtual protobufs::Transformation ToMessage() const = 0;
@@ -90,7 +93,7 @@ class Transformation {
   // checking id freshness for a transformation that uses many ids, all of which
   // must be distinct.
   static bool CheckIdIsFreshAndNotUsedByThisTransformation(
-      uint32_t id, opt::IRContext* context,
+      uint32_t id, opt::IRContext* ir_context,
       std::set<uint32_t>* ids_used_by_this_transformation);
 };
 

+ 29 - 27
3rdparty/spirv-tools/source/fuzz/transformation_access_chain.cpp

@@ -40,19 +40,18 @@ TransformationAccessChain::TransformationAccessChain(
 }
 
 bool TransformationAccessChain::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The result id must be fresh
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // The pointer id must exist and have a type.
-  auto pointer = context->get_def_use_mgr()->GetDef(message_.pointer_id());
+  auto pointer = ir_context->get_def_use_mgr()->GetDef(message_.pointer_id());
   if (!pointer || !pointer->type_id()) {
     return false;
   }
   // The type must indeed be a pointer
-  auto pointer_type = context->get_def_use_mgr()->GetDef(pointer->type_id());
+  auto pointer_type = ir_context->get_def_use_mgr()->GetDef(pointer->type_id());
   if (pointer_type->opcode() != SpvOpTypePointer) {
     return false;
   }
@@ -60,7 +59,7 @@ bool TransformationAccessChain::IsApplicable(
   // The described instruction to insert before must exist and be a suitable
   // point where an OpAccessChain instruction could be inserted.
   auto instruction_to_insert_before =
-      FindInstruction(message_.instruction_to_insert_before(), context);
+      FindInstruction(message_.instruction_to_insert_before(), ir_context);
   if (!instruction_to_insert_before) {
     return false;
   }
@@ -86,7 +85,7 @@ bool TransformationAccessChain::IsApplicable(
   // The pointer on which the access chain is to be based needs to be available
   // (according to dominance rules) at the insertion point.
   if (!fuzzerutil::IdIsAvailableBeforeInstruction(
-          context, instruction_to_insert_before, message_.pointer_id())) {
+          ir_context, instruction_to_insert_before, message_.pointer_id())) {
     return false;
   }
 
@@ -104,7 +103,7 @@ bool TransformationAccessChain::IsApplicable(
     // integer.  Otherwise, the integer with which the id is associated is the
     // second component.
     std::pair<bool, uint32_t> maybe_index_value =
-        GetIndexValue(context, index_id);
+        GetIndexValue(ir_context, index_id);
     if (!maybe_index_value.first) {
       // There was no integer: this index is no good.
       return false;
@@ -113,7 +112,7 @@ bool TransformationAccessChain::IsApplicable(
     // type is not a composite or the index is out of bounds, and the id of
     // the next type otherwise.
     subobject_type_id = fuzzerutil::WalkOneCompositeTypeIndex(
-        context, subobject_type_id, maybe_index_value.second);
+        ir_context, subobject_type_id, maybe_index_value.second);
     if (!subobject_type_id) {
       // Either the type was not a composite (so that too many indices were
       // provided), or the index was out of bounds.
@@ -128,13 +127,14 @@ bool TransformationAccessChain::IsApplicable(
   // We do not use the type manager to look up this type, due to problems
   // associated with pointers to isomorphic structs being regarded as the same.
   return fuzzerutil::MaybeGetPointerType(
-             context, subobject_type_id,
+             ir_context, subobject_type_id,
              static_cast<SpvStorageClass>(
                  pointer_type->GetSingleWordInOperand(0))) != 0;
 }
 
 void TransformationAccessChain::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   // The operands to the access chain are the pointer followed by the indices.
   // The result type of the access chain is determined by where the indices
   // lead.  We thus push the pointer to a sequence of operands, and then follow
@@ -148,8 +148,8 @@ void TransformationAccessChain::Apply(
   operands.push_back({SPV_OPERAND_TYPE_ID, {message_.pointer_id()}});
 
   // Start walking the indices, starting with the pointer's base type.
-  auto pointer_type = context->get_def_use_mgr()->GetDef(
-      context->get_def_use_mgr()->GetDef(message_.pointer_id())->type_id());
+  auto pointer_type = ir_context->get_def_use_mgr()->GetDef(
+      ir_context->get_def_use_mgr()->GetDef(message_.pointer_id())->type_id());
   uint32_t subobject_type_id = pointer_type->GetSingleWordInOperand(1);
 
   // Go through the index ids in turn.
@@ -157,33 +157,35 @@ void TransformationAccessChain::Apply(
     // Add the index id to the operands.
     operands.push_back({SPV_OPERAND_TYPE_ID, {index_id}});
     // Get the integer value associated with the index id.
-    uint32_t index_value = GetIndexValue(context, index_id).second;
+    uint32_t index_value = GetIndexValue(ir_context, index_id).second;
     // Walk to the next type in the composite object using this index.
     subobject_type_id = fuzzerutil::WalkOneCompositeTypeIndex(
-        context, subobject_type_id, index_value);
+        ir_context, subobject_type_id, index_value);
   }
   // The access chain's result type is a pointer to the composite component that
   // was reached after following all indices.  The storage class is that of the
   // original pointer.
   uint32_t result_type = fuzzerutil::MaybeGetPointerType(
-      context, subobject_type_id,
+      ir_context, subobject_type_id,
       static_cast<SpvStorageClass>(pointer_type->GetSingleWordInOperand(0)));
 
   // Add the access chain instruction to the module, and update the module's id
   // bound.
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
-  FindInstruction(message_.instruction_to_insert_before(), context)
-      ->InsertBefore(
-          MakeUnique<opt::Instruction>(context, SpvOpAccessChain, result_type,
-                                       message_.fresh_id(), operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+  FindInstruction(message_.instruction_to_insert_before(), ir_context)
+      ->InsertBefore(MakeUnique<opt::Instruction>(
+          ir_context, SpvOpAccessChain, result_type, message_.fresh_id(),
+          operands));
 
   // Conservatively invalidate all analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 
   // If the base pointer's pointee value was irrelevant, the same is true of the
   // pointee value of the result of this access chain.
-  if (fact_manager->PointeeValueIsIrrelevant(message_.pointer_id())) {
-    fact_manager->AddFactValueOfPointeeIsIrrelevant(message_.fresh_id());
+  if (transformation_context->GetFactManager()->PointeeValueIsIrrelevant(
+          message_.pointer_id())) {
+    transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+        message_.fresh_id());
   }
 }
 
@@ -194,8 +196,8 @@ protobufs::Transformation TransformationAccessChain::ToMessage() const {
 }
 
 std::pair<bool, uint32_t> TransformationAccessChain::GetIndexValue(
-    opt::IRContext* context, uint32_t index_id) const {
-  auto index_instruction = context->get_def_use_mgr()->GetDef(index_id);
+    opt::IRContext* ir_context, uint32_t index_id) const {
+  auto index_instruction = ir_context->get_def_use_mgr()->GetDef(index_id);
   if (!index_instruction || !spvOpcodeIsConstant(index_instruction->opcode())) {
     // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3179) We could
     //  allow non-constant indices when looking up non-structs, using clamping
@@ -203,7 +205,7 @@ std::pair<bool, uint32_t> TransformationAccessChain::GetIndexValue(
     return {false, 0};
   }
   auto index_type =
-      context->get_def_use_mgr()->GetDef(index_instruction->type_id());
+      ir_context->get_def_use_mgr()->GetDef(index_instruction->type_id());
   if (index_type->opcode() != SpvOpTypeInt ||
       index_type->GetSingleWordInOperand(0) != 32) {
     return {false, 0};

+ 11 - 8
3rdparty/spirv-tools/source/fuzz/transformation_access_chain.h

@@ -17,9 +17,9 @@
 
 #include <utility>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -47,8 +47,9 @@ class TransformationAccessChain : public Transformation {
   // - If type t is the final type reached by walking these indices, the module
   //   must include an instruction "OpTypePointer SC %t" where SC is the storage
   //   class associated with |message_.pointer_id|
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an instruction of the form:
   //   |message_.fresh_id| = OpAccessChain %ptr |message_.index_id|
@@ -57,10 +58,12 @@ class TransformationAccessChain : public Transformation {
   // the indices in |message_.index_id|, and with the same storage class as
   // |message_.pointer_id|.
   //
-  // If |fact_manager| reports that |message_.pointer_id| has an irrelevant
-  // pointee value, then the fact that |message_.fresh_id| (the result of the
-  // access chain) also has an irrelevant pointee value is also recorded.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  // If the fact manager in |transformation_context| reports that
+  // |message_.pointer_id| has an irrelevant pointee value, then the fact that
+  // |message_.fresh_id| (the result of the access chain) also has an irrelevant
+  // pointee value is also recorded.
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
@@ -68,7 +71,7 @@ class TransformationAccessChain : public Transformation {
   // Returns {false, 0} if |index_id| does not correspond to a 32-bit integer
   // constant.  Otherwise, returns {true, value}, where value is the value of
   // the 32-bit integer constant to which |index_id| corresponds.
-  std::pair<bool, uint32_t> GetIndexValue(opt::IRContext* context,
+  std::pair<bool, uint32_t> GetIndexValue(opt::IRContext* ir_context,
                                           uint32_t index_id) const;
 
   protobufs::TransformationAccessChain message_;

+ 10 - 9
3rdparty/spirv-tools/source/fuzz/transformation_add_constant_boolean.cpp

@@ -31,27 +31,28 @@ TransformationAddConstantBoolean::TransformationAddConstantBoolean(
 }
 
 bool TransformationAddConstantBoolean::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   opt::analysis::Bool bool_type;
-  if (!context->get_type_mgr()->GetId(&bool_type)) {
+  if (!ir_context->get_type_mgr()->GetId(&bool_type)) {
     // No OpTypeBool is present.
     return false;
   }
-  return fuzzerutil::IsFreshId(context, message_.fresh_id());
+  return fuzzerutil::IsFreshId(ir_context, message_.fresh_id());
 }
 
-void TransformationAddConstantBoolean::Apply(opt::IRContext* context,
-                                             FactManager* /*unused*/) const {
+void TransformationAddConstantBoolean::Apply(
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::analysis::Bool bool_type;
   // Add the boolean constant to the module, ensuring the module's id bound is
   // high enough.
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
-  context->module()->AddGlobalValue(
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+  ir_context->module()->AddGlobalValue(
       message_.is_true() ? SpvOpConstantTrue : SpvOpConstantFalse,
-      message_.fresh_id(), context->get_type_mgr()->GetId(&bool_type));
+      message_.fresh_id(), ir_context->get_type_mgr()->GetId(&bool_type));
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddConstantBoolean::ToMessage() const {

+ 6 - 4
3rdparty/spirv-tools/source/fuzz/transformation_add_constant_boolean.h

@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_BOOLEAN_CONSTANT_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_BOOLEAN_CONSTANT_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -32,12 +32,14 @@ class TransformationAddConstantBoolean : public Transformation {
 
   // - |message_.fresh_id| must not be used by the module.
   // - The module must already contain OpTypeBool.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // - Adds OpConstantTrue (OpConstantFalse) to the module with id
   //   |message_.fresh_id| if |message_.is_true| holds (does not hold).
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 

+ 12 - 12
3rdparty/spirv-tools/source/fuzz/transformation_add_constant_composite.cpp

@@ -37,15 +37,14 @@ TransformationAddConstantComposite::TransformationAddConstantComposite(
 }
 
 bool TransformationAddConstantComposite::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // Check that the given id is fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // Check that the composite type id is an instruction id.
   auto composite_type_instruction =
-      context->get_def_use_mgr()->GetDef(message_.type_id());
+      ir_context->get_def_use_mgr()->GetDef(message_.type_id());
   if (!composite_type_instruction) {
     return false;
   }
@@ -56,7 +55,7 @@ bool TransformationAddConstantComposite::IsApplicable(
     case SpvOpTypeArray:
       for (uint32_t index = 0;
            index <
-           fuzzerutil::GetArraySize(*composite_type_instruction, context);
+           fuzzerutil::GetArraySize(*composite_type_instruction, ir_context);
            index++) {
         constituent_type_ids.push_back(
             composite_type_instruction->GetSingleWordInOperand(0));
@@ -93,7 +92,7 @@ bool TransformationAddConstantComposite::IsApplicable(
   // corresponding constituent type.
   for (uint32_t index = 0; index < constituent_type_ids.size(); index++) {
     auto constituent_instruction =
-        context->get_def_use_mgr()->GetDef(message_.constituent_id(index));
+        ir_context->get_def_use_mgr()->GetDef(message_.constituent_id(index));
     if (!constituent_instruction) {
       return false;
     }
@@ -105,18 +104,19 @@ bool TransformationAddConstantComposite::IsApplicable(
 }
 
 void TransformationAddConstantComposite::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList in_operands;
   for (auto constituent_id : message_.constituent_id()) {
     in_operands.push_back({SPV_OPERAND_TYPE_ID, {constituent_id}});
   }
-  context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context, SpvOpConstantComposite, message_.type_id(), message_.fresh_id(),
-      in_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpConstantComposite, message_.type_id(),
+      message_.fresh_id(), in_operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddConstantComposite::ToMessage()

+ 6 - 4
3rdparty/spirv-tools/source/fuzz/transformation_add_constant_composite.h

@@ -17,9 +17,9 @@
 
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -38,13 +38,15 @@ class TransformationAddConstantComposite : public Transformation {
   // - |message_.type_id| must be the id of a composite type
   // - |message_.constituent_id| must refer to ids that match the constituent
   //   types of this composite type
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpConstantComposite instruction defining a constant of type
   // |message_.type_id|, using |message_.constituent_id| as constituents, with
   // result id |message_.fresh_id|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 

+ 66 - 0
3rdparty/spirv-tools/source/fuzz/transformation_add_constant_null.cpp

@@ -0,0 +1,66 @@
+// Copyright (c) 2020 Google LLC
+//
+// 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 "source/fuzz/transformation_add_constant_null.h"
+
+#include "source/fuzz/fuzzer_util.h"
+
+namespace spvtools {
+namespace fuzz {
+
+TransformationAddConstantNull::TransformationAddConstantNull(
+    const spvtools::fuzz::protobufs::TransformationAddConstantNull& message)
+    : message_(message) {}
+
+TransformationAddConstantNull::TransformationAddConstantNull(uint32_t fresh_id,
+                                                             uint32_t type_id) {
+  message_.set_fresh_id(fresh_id);
+  message_.set_type_id(type_id);
+}
+
+bool TransformationAddConstantNull::IsApplicable(
+    opt::IRContext* context, const TransformationContext& /*unused*/) const {
+  // A fresh id is required.
+  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+    return false;
+  }
+  auto type = context->get_type_mgr()->GetType(message_.type_id());
+  // The type must exist.
+  if (!type) {
+    return false;
+  }
+  // The type must be one of the types for which null constants are allowed,
+  // according to the SPIR-V spec.
+  return fuzzerutil::IsNullConstantSupported(*type);
+}
+
+void TransformationAddConstantNull::Apply(
+    opt::IRContext* context, TransformationContext* /*unused*/) const {
+  context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+      context, SpvOpConstantNull, message_.type_id(), message_.fresh_id(),
+      opt::Instruction::OperandList()));
+  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  // We have added an instruction to the module, so need to be careful about the
+  // validity of existing analyses.
+  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+}
+
+protobufs::Transformation TransformationAddConstantNull::ToMessage() const {
+  protobufs::Transformation result;
+  *result.mutable_add_constant_null() = message_;
+  return result;
+}
+
+}  // namespace fuzz
+}  // namespace spvtools

+ 54 - 0
3rdparty/spirv-tools/source/fuzz/transformation_add_constant_null.h

@@ -0,0 +1,54 @@
+// Copyright (c) 2020 Google LLC
+//
+// 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 SOURCE_FUZZ_TRANSFORMATION_ADD_CONSTANT_NULL_H_
+#define SOURCE_FUZZ_TRANSFORMATION_ADD_CONSTANT_NULL_H_
+
+#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
+#include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
+#include "source/opt/ir_context.h"
+
+namespace spvtools {
+namespace fuzz {
+
+class TransformationAddConstantNull : public Transformation {
+ public:
+  explicit TransformationAddConstantNull(
+      const protobufs::TransformationAddConstantNull& message);
+
+  TransformationAddConstantNull(uint32_t fresh_id, uint32_t type_id);
+
+  // - |message_.fresh_id| must be fresh
+  // - |message_.type_id| must be the id of a type for which it is acceptable
+  //   to create a null constant
+  bool IsApplicable(
+      opt::IRContext* context,
+      const TransformationContext& transformation_context) const override;
+
+  // Adds an OpConstantNull instruction to the module, with |message_.type_id|
+  // as its type.  The instruction has result id |message_.fresh_id|.
+  void Apply(opt::IRContext* context,
+             TransformationContext* transformation_context) const override;
+
+  protobufs::Transformation ToMessage() const override;
+
+ private:
+  protobufs::TransformationAddConstantNull message_;
+};
+
+}  // namespace fuzz
+}  // namespace spvtools
+
+#endif  // SOURCE_FUZZ_TRANSFORMATION_ADD_CONSTANT_NULL_H_

+ 10 - 10
3rdparty/spirv-tools/source/fuzz/transformation_add_constant_scalar.cpp

@@ -33,14 +33,13 @@ TransformationAddConstantScalar::TransformationAddConstantScalar(
 }
 
 bool TransformationAddConstantScalar::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The id needs to be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // The type id for the scalar must exist and be a type.
-  auto type = context->get_type_mgr()->GetType(message_.type_id());
+  auto type = ir_context->get_type_mgr()->GetType(message_.type_id());
   if (!type) {
     return false;
   }
@@ -61,20 +60,21 @@ bool TransformationAddConstantScalar::IsApplicable(
 }
 
 void TransformationAddConstantScalar::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList operand_list;
   for (auto word : message_.word()) {
     operand_list.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER, {word}});
   }
-  context->module()->AddGlobalValue(
-      MakeUnique<opt::Instruction>(context, SpvOpConstant, message_.type_id(),
-                                   message_.fresh_id(), operand_list));
+  ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpConstant, message_.type_id(), message_.fresh_id(),
+      operand_list));
 
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
 
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddConstantScalar::ToMessage() const {

+ 6 - 4
3rdparty/spirv-tools/source/fuzz/transformation_add_constant_scalar.h

@@ -17,9 +17,9 @@
 
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -37,11 +37,13 @@ class TransformationAddConstantScalar : public Transformation {
   // - |message_.type_id| must be the id of a floating-point or integer type
   // - The size of |message_.word| must be compatible with the width of this
   //   type
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds a new OpConstant instruction with the given type and words.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 

+ 22 - 20
3rdparty/spirv-tools/source/fuzz/transformation_add_dead_block.cpp

@@ -32,16 +32,15 @@ TransformationAddDeadBlock::TransformationAddDeadBlock(uint32_t fresh_id,
 }
 
 bool TransformationAddDeadBlock::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The new block's id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
 
   // First, we check that a constant with the same value as
   // |message_.condition_value| is present.
-  if (!fuzzerutil::MaybeGetBoolConstantId(context,
+  if (!fuzzerutil::MaybeGetBoolConstantId(ir_context,
                                           message_.condition_value())) {
     // The required constant is not present, so the transformation cannot be
     // applied.
@@ -50,7 +49,7 @@ bool TransformationAddDeadBlock::IsApplicable(
 
   // The existing block must indeed exist.
   auto existing_block =
-      fuzzerutil::MaybeFindBlock(context, message_.existing_block());
+      fuzzerutil::MaybeFindBlock(ir_context, message_.existing_block());
   if (!existing_block) {
     return false;
   }
@@ -68,13 +67,13 @@ bool TransformationAddDeadBlock::IsApplicable(
   // Its successor must not be a merge block nor continue target.
   auto successor_block_id =
       existing_block->terminator()->GetSingleWordInOperand(0);
-  if (fuzzerutil::IsMergeOrContinue(context, successor_block_id)) {
+  if (fuzzerutil::IsMergeOrContinue(ir_context, successor_block_id)) {
     return false;
   }
 
   // The successor must not be a loop header (i.e., |message_.existing_block|
   // must not be a back-edge block.
-  if (context->cfg()->block(successor_block_id)->IsLoopHeader()) {
+  if (ir_context->cfg()->block(successor_block_id)->IsLoopHeader()) {
     return false;
   }
 
@@ -82,34 +81,36 @@ bool TransformationAddDeadBlock::IsApplicable(
 }
 
 void TransformationAddDeadBlock::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   // Update the module id bound so that it is at least the id of the new block.
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
 
   // Get the existing block and its successor.
-  auto existing_block = context->cfg()->block(message_.existing_block());
+  auto existing_block = ir_context->cfg()->block(message_.existing_block());
   auto successor_block_id =
       existing_block->terminator()->GetSingleWordInOperand(0);
 
   // Get the id of the boolean value that will be used as the branch condition.
-  auto bool_id =
-      fuzzerutil::MaybeGetBoolConstantId(context, message_.condition_value());
+  auto bool_id = fuzzerutil::MaybeGetBoolConstantId(ir_context,
+                                                    message_.condition_value());
 
   // Make a new block that unconditionally branches to the original successor
   // block.
   auto enclosing_function = existing_block->GetParent();
-  std::unique_ptr<opt::BasicBlock> new_block = MakeUnique<opt::BasicBlock>(
-      MakeUnique<opt::Instruction>(context, SpvOpLabel, 0, message_.fresh_id(),
-                                   opt::Instruction::OperandList()));
+  std::unique_ptr<opt::BasicBlock> new_block =
+      MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
+          ir_context, SpvOpLabel, 0, message_.fresh_id(),
+          opt::Instruction::OperandList()));
   new_block->AddInstruction(MakeUnique<opt::Instruction>(
-      context, SpvOpBranch, 0, 0,
+      ir_context, SpvOpBranch, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {successor_block_id}}})));
 
   // Turn the original block into a selection merge, with its original successor
   // as the merge block.
   existing_block->terminator()->InsertBefore(MakeUnique<opt::Instruction>(
-      context, SpvOpSelectionMerge, 0, 0,
+      ir_context, SpvOpSelectionMerge, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {successor_block_id}},
            {SPV_OPERAND_TYPE_SELECTION_CONTROL,
@@ -135,7 +136,8 @@ void TransformationAddDeadBlock::Apply(
                                             existing_block);
 
   // Record the fact that the new block is dead.
-  fact_manager->AddFactBlockIsDead(message_.fresh_id());
+  transformation_context->GetFactManager()->AddFactBlockIsDead(
+      message_.fresh_id());
 
   // Fix up OpPhi instructions in the successor block, so that the values they
   // yield when control has transferred from the new block are the same as if
@@ -143,7 +145,7 @@ void TransformationAddDeadBlock::Apply(
   // to be valid since |message_.existing_block| dominates the new block by
   // construction.  Other transformations can change these phi operands to more
   // interesting values.
-  context->cfg()
+  ir_context->cfg()
       ->block(successor_block_id)
       ->ForEachPhiInst([this](opt::Instruction* phi_inst) {
         // Copy the operand that provides the phi value for the first of any
@@ -156,7 +158,7 @@ void TransformationAddDeadBlock::Apply(
 
   // Do not rely on any existing analysis results since the control flow graph
   // of the module has changed.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddDeadBlock::ToMessage() const {

+ 6 - 4
3rdparty/spirv-tools/source/fuzz/transformation_add_dead_block.h

@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_DEAD_BLOCK_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_DEAD_BLOCK_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -41,15 +41,17 @@ class TransformationAddDeadBlock : public Transformation {
   // - |message_.existing_block| must not be a back-edge block, since in this
   //   case the newly-added block would lead to another back-edge to the
   //   associated loop header
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Changes the OpBranch from |message_.existing_block| to its successor 's'
   // to an OpBranchConditional to either 's' or a new block,
   // |message_.fresh_id|, which itself unconditionally branches to 's'.  The
   // conditional branch uses |message.condition_value| as its condition, and is
   // arranged so that control will pass to 's' at runtime.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 

+ 27 - 24
3rdparty/spirv-tools/source/fuzz/transformation_add_dead_break.cpp

@@ -14,8 +14,8 @@
 
 #include "source/fuzz/transformation_add_dead_break.h"
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/fuzzer_util.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/basic_block.h"
 #include "source/opt/ir_context.h"
 #include "source/opt/struct_cfg_analysis.h"
@@ -39,7 +39,7 @@ TransformationAddDeadBreak::TransformationAddDeadBreak(
 }
 
 bool TransformationAddDeadBreak::AddingBreakRespectsStructuredControlFlow(
-    opt::IRContext* context, opt::BasicBlock* bb_from) const {
+    opt::IRContext* ir_context, opt::BasicBlock* bb_from) const {
   // Look at the structured control flow associated with |from_block| and
   // check whether it is contained in an appropriate construct with merge id
   // |to_block| such that a break from |from_block| to |to_block| is legal.
@@ -70,7 +70,7 @@ bool TransformationAddDeadBreak::AddingBreakRespectsStructuredControlFlow(
   // structured control flow construct.
 
   auto containing_construct =
-      context->GetStructuredCFGAnalysis()->ContainingConstruct(
+      ir_context->GetStructuredCFGAnalysis()->ContainingConstruct(
           message_.from_block());
   if (!containing_construct) {
     // |from_block| is not in a construct from which we can break.
@@ -79,7 +79,7 @@ bool TransformationAddDeadBreak::AddingBreakRespectsStructuredControlFlow(
 
   // Consider case (2)
   if (message_.to_block() ==
-      context->cfg()->block(containing_construct)->MergeBlockId()) {
+      ir_context->cfg()->block(containing_construct)->MergeBlockId()) {
     // This looks like an instance of case (2).
     // However, the structured CFG analysis regards the continue construct of a
     // loop as part of the loop, but it is not legal to jump from a loop's
@@ -90,28 +90,29 @@ bool TransformationAddDeadBreak::AddingBreakRespectsStructuredControlFlow(
     //  currently allow a dead break from a back edge block, but we could and
     //  ultimately should.
     return !fuzzerutil::BlockIsInLoopContinueConstruct(
-        context, message_.from_block(), containing_construct);
+        ir_context, message_.from_block(), containing_construct);
   }
 
   // Case (3) holds if and only if |to_block| is the merge block for this
   // innermost loop that contains |from_block|
   auto containing_loop_header =
-      context->GetStructuredCFGAnalysis()->ContainingLoop(
+      ir_context->GetStructuredCFGAnalysis()->ContainingLoop(
           message_.from_block());
   if (containing_loop_header &&
       message_.to_block() ==
-          context->cfg()->block(containing_loop_header)->MergeBlockId()) {
+          ir_context->cfg()->block(containing_loop_header)->MergeBlockId()) {
     return !fuzzerutil::BlockIsInLoopContinueConstruct(
-        context, message_.from_block(), containing_loop_header);
+        ir_context, message_.from_block(), containing_loop_header);
   }
   return false;
 }
 
 bool TransformationAddDeadBreak::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
+    opt::IRContext* ir_context,
+    const TransformationContext& transformation_context) const {
   // First, we check that a constant with the same value as
   // |message_.break_condition_value| is present.
-  if (!fuzzerutil::MaybeGetBoolConstantId(context,
+  if (!fuzzerutil::MaybeGetBoolConstantId(ir_context,
                                           message_.break_condition_value())) {
     // The required constant is not present, so the transformation cannot be
     // applied.
@@ -121,17 +122,17 @@ bool TransformationAddDeadBreak::IsApplicable(
   // Check that |message_.from_block| and |message_.to_block| really are block
   // ids
   opt::BasicBlock* bb_from =
-      fuzzerutil::MaybeFindBlock(context, message_.from_block());
+      fuzzerutil::MaybeFindBlock(ir_context, message_.from_block());
   if (bb_from == nullptr) {
     return false;
   }
   opt::BasicBlock* bb_to =
-      fuzzerutil::MaybeFindBlock(context, message_.to_block());
+      fuzzerutil::MaybeFindBlock(ir_context, message_.to_block());
   if (bb_to == nullptr) {
     return false;
   }
 
-  if (!fuzzerutil::BlockIsReachableInItsFunction(context, bb_to)) {
+  if (!fuzzerutil::BlockIsReachableInItsFunction(ir_context, bb_to)) {
     // If the target of the break is unreachable, we conservatively do not
     // allow adding a dead break, to avoid the compilations that arise due to
     // the lack of sensible dominance information for unreachable blocks.
@@ -157,14 +158,14 @@ bool TransformationAddDeadBreak::IsApplicable(
       "The id of the block we found should match the target id for the break.");
 
   // Check whether the data passed to extend OpPhi instructions is appropriate.
-  if (!fuzzerutil::PhiIdsOkForNewEdge(context, bb_from, bb_to,
+  if (!fuzzerutil::PhiIdsOkForNewEdge(ir_context, bb_from, bb_to,
                                       message_.phi_id())) {
     return false;
   }
 
   // Check that adding the break would respect the rules of structured
   // control flow.
-  if (!AddingBreakRespectsStructuredControlFlow(context, bb_from)) {
+  if (!AddingBreakRespectsStructuredControlFlow(ir_context, bb_from)) {
     return false;
   }
 
@@ -177,16 +178,18 @@ bool TransformationAddDeadBreak::IsApplicable(
   // being places on the validator.  This should be revisited if we are sure
   // the validator is complete with respect to checking structured control flow
   // rules.
-  auto cloned_context = fuzzerutil::CloneIRContext(context);
+  auto cloned_context = fuzzerutil::CloneIRContext(ir_context);
   ApplyImpl(cloned_context.get());
-  return fuzzerutil::IsValid(cloned_context.get());
+  return fuzzerutil::IsValid(cloned_context.get(),
+                             transformation_context.GetValidatorOptions());
 }
 
-void TransformationAddDeadBreak::Apply(opt::IRContext* context,
-                                       FactManager* /*unused*/) const {
-  ApplyImpl(context);
+void TransformationAddDeadBreak::Apply(
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
+  ApplyImpl(ir_context);
   // Invalidate all analyses
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddDeadBreak::ToMessage() const {
@@ -196,10 +199,10 @@ protobufs::Transformation TransformationAddDeadBreak::ToMessage() const {
 }
 
 void TransformationAddDeadBreak::ApplyImpl(
-    spvtools::opt::IRContext* context) const {
+    spvtools::opt::IRContext* ir_context) const {
   fuzzerutil::AddUnreachableEdgeAndUpdateOpPhis(
-      context, context->cfg()->block(message_.from_block()),
-      context->cfg()->block(message_.to_block()),
+      ir_context, ir_context->cfg()->block(message_.from_block()),
+      ir_context->cfg()->block(message_.to_block()),
       message_.break_condition_value(), message_.phi_id());
 }
 

+ 8 - 6
3rdparty/spirv-tools/source/fuzz/transformation_add_dead_break.h

@@ -17,9 +17,9 @@
 
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -50,21 +50,23 @@ class TransformationAddDeadBreak : public Transformation {
   //   maintain validity of the module.
   //   In particular, the new branch must not lead to violations of the rule
   //   that a use must be dominated by its definition.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Replaces the terminator of a with a conditional branch to b or c.
   // The boolean constant associated with |message_.break_condition_value| is
   // used as the condition, and the order of b and c is arranged such that
   // control is guaranteed to jump to c.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
  private:
   // Returns true if and only if adding an edge from |bb_from| to
   // |message_.to_block| respects structured control flow.
-  bool AddingBreakRespectsStructuredControlFlow(opt::IRContext* context,
+  bool AddingBreakRespectsStructuredControlFlow(opt::IRContext* ir_context,
                                                 opt::BasicBlock* bb_from) const;
 
   // Used by 'Apply' to actually apply the transformation to the module of
@@ -73,7 +75,7 @@ class TransformationAddDeadBreak : public Transformation {
   // module.  This is only invoked by 'IsApplicable' after certain basic
   // applicability checks have been made, ensuring that the invocation of this
   // method is legal.
-  void ApplyImpl(opt::IRContext* context) const;
+  void ApplyImpl(opt::IRContext* ir_context) const;
 
   protobufs::TransformationAddDeadBreak message_;
 };

+ 29 - 24
3rdparty/spirv-tools/source/fuzz/transformation_add_dead_continue.cpp

@@ -34,11 +34,12 @@ TransformationAddDeadContinue::TransformationAddDeadContinue(
 }
 
 bool TransformationAddDeadContinue::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
+    opt::IRContext* ir_context,
+    const TransformationContext& transformation_context) const {
   // First, we check that a constant with the same value as
   // |message_.continue_condition_value| is present.
   if (!fuzzerutil::MaybeGetBoolConstantId(
-          context, message_.continue_condition_value())) {
+          ir_context, message_.continue_condition_value())) {
     // The required constant is not present, so the transformation cannot be
     // applied.
     return false;
@@ -46,7 +47,7 @@ bool TransformationAddDeadContinue::IsApplicable(
 
   // Check that |message_.from_block| really is a block id.
   opt::BasicBlock* bb_from =
-      fuzzerutil::MaybeFindBlock(context, message_.from_block());
+      fuzzerutil::MaybeFindBlock(ir_context, message_.from_block());
   if (bb_from == nullptr) {
     return false;
   }
@@ -68,31 +69,33 @@ bool TransformationAddDeadContinue::IsApplicable(
   // Because the structured CFG analysis does not regard a loop header as part
   // of the loop it heads, we check first whether bb_from is a loop header
   // before using the structured CFG analysis.
-  auto loop_header = bb_from->IsLoopHeader()
-                         ? message_.from_block()
-                         : context->GetStructuredCFGAnalysis()->ContainingLoop(
-                               message_.from_block());
+  auto loop_header =
+      bb_from->IsLoopHeader()
+          ? message_.from_block()
+          : ir_context->GetStructuredCFGAnalysis()->ContainingLoop(
+                message_.from_block());
   if (!loop_header) {
     return false;
   }
 
-  auto continue_block = context->cfg()->block(loop_header)->ContinueBlockId();
+  auto continue_block =
+      ir_context->cfg()->block(loop_header)->ContinueBlockId();
 
   if (!fuzzerutil::BlockIsReachableInItsFunction(
-          context, context->cfg()->block(continue_block))) {
+          ir_context, ir_context->cfg()->block(continue_block))) {
     // If the loop's continue block is unreachable, we conservatively do not
     // allow adding a dead continue, to avoid the compilations that arise due to
     // the lack of sensible dominance information for unreachable blocks.
     return false;
   }
 
-  if (fuzzerutil::BlockIsInLoopContinueConstruct(context, message_.from_block(),
-                                                 loop_header)) {
+  if (fuzzerutil::BlockIsInLoopContinueConstruct(
+          ir_context, message_.from_block(), loop_header)) {
     // We cannot jump to the continue target from the continue construct.
     return false;
   }
 
-  if (context->GetStructuredCFGAnalysis()->IsMergeBlock(continue_block)) {
+  if (ir_context->GetStructuredCFGAnalysis()->IsMergeBlock(continue_block)) {
     // A branch straight to the continue target that is also a merge block might
     // break the property that a construct header must dominate its merge block
     // (if the merge block is reachable).
@@ -100,8 +103,8 @@ bool TransformationAddDeadContinue::IsApplicable(
   }
 
   // Check whether the data passed to extend OpPhi instructions is appropriate.
-  if (!fuzzerutil::PhiIdsOkForNewEdge(context, bb_from,
-                                      context->cfg()->block(continue_block),
+  if (!fuzzerutil::PhiIdsOkForNewEdge(ir_context, bb_from,
+                                      ir_context->cfg()->block(continue_block),
                                       message_.phi_id())) {
     return false;
   }
@@ -115,16 +118,18 @@ bool TransformationAddDeadContinue::IsApplicable(
   // being placed on the validator.  This should be revisited if we are sure
   // the validator is complete with respect to checking structured control flow
   // rules.
-  auto cloned_context = fuzzerutil::CloneIRContext(context);
+  auto cloned_context = fuzzerutil::CloneIRContext(ir_context);
   ApplyImpl(cloned_context.get());
-  return fuzzerutil::IsValid(cloned_context.get());
+  return fuzzerutil::IsValid(cloned_context.get(),
+                             transformation_context.GetValidatorOptions());
 }
 
-void TransformationAddDeadContinue::Apply(opt::IRContext* context,
-                                          FactManager* /*unused*/) const {
-  ApplyImpl(context);
+void TransformationAddDeadContinue::Apply(
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
+  ApplyImpl(ir_context);
   // Invalidate all analyses
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddDeadContinue::ToMessage() const {
@@ -134,16 +139,16 @@ protobufs::Transformation TransformationAddDeadContinue::ToMessage() const {
 }
 
 void TransformationAddDeadContinue::ApplyImpl(
-    spvtools::opt::IRContext* context) const {
-  auto bb_from = context->cfg()->block(message_.from_block());
+    spvtools::opt::IRContext* ir_context) const {
+  auto bb_from = ir_context->cfg()->block(message_.from_block());
   auto continue_block =
       bb_from->IsLoopHeader()
           ? bb_from->ContinueBlockId()
-          : context->GetStructuredCFGAnalysis()->LoopContinueBlock(
+          : ir_context->GetStructuredCFGAnalysis()->LoopContinueBlock(
                 message_.from_block());
   assert(continue_block && "message_.from_block must be in a loop.");
   fuzzerutil::AddUnreachableEdgeAndUpdateOpPhis(
-      context, bb_from, context->cfg()->block(continue_block),
+      ir_context, bb_from, ir_context->cfg()->block(continue_block),
       message_.continue_condition_value(), message_.phi_id());
 }
 

+ 7 - 5
3rdparty/spirv-tools/source/fuzz/transformation_add_dead_continue.h

@@ -17,9 +17,9 @@
 
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -52,14 +52,16 @@ class TransformationAddDeadContinue : public Transformation {
   //   In particular, adding an edge from somewhere in the loop to the continue
   //   target must not prevent uses of ids in the continue target from being
   //   dominated by the definitions of those ids.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Replaces the terminator of a with a conditional branch to b or c.
   // The boolean constant associated with |message_.continue_condition_value| is
   // used as the condition, and the order of b and c is arranged such that
   // control is guaranteed to jump to c.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
@@ -70,7 +72,7 @@ class TransformationAddDeadContinue : public Transformation {
   // module.  This is only invoked by 'IsApplicable' after certain basic
   // applicability checks have been made, ensuring that the invocation of this
   // method is legal.
-  void ApplyImpl(opt::IRContext* context) const;
+  void ApplyImpl(opt::IRContext* ir_context) const;
 
   protobufs::TransformationAddDeadContinue message_;
 };

+ 108 - 97
3rdparty/spirv-tools/source/fuzz/transformation_add_function.cpp

@@ -56,8 +56,8 @@ TransformationAddFunction::TransformationAddFunction(
 }
 
 bool TransformationAddFunction::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& fact_manager) const {
+    opt::IRContext* ir_context,
+    const TransformationContext& transformation_context) const {
   // This transformation may use a lot of ids, all of which need to be fresh
   // and distinct.  This set tracks them.
   std::set<uint32_t> ids_used_by_this_transformation;
@@ -66,7 +66,7 @@ bool TransformationAddFunction::IsApplicable(
   for (auto& instruction : message_.instruction()) {
     if (instruction.result_id()) {
       if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-              instruction.result_id(), context,
+              instruction.result_id(), ir_context,
               &ids_used_by_this_transformation)) {
         return false;
       }
@@ -77,28 +77,28 @@ bool TransformationAddFunction::IsApplicable(
     // Ensure that all ids provided for making the function livesafe are fresh
     // and distinct.
     if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-            message_.loop_limiter_variable_id(), context,
+            message_.loop_limiter_variable_id(), ir_context,
             &ids_used_by_this_transformation)) {
       return false;
     }
     for (auto& loop_limiter_info : message_.loop_limiter_info()) {
       if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-              loop_limiter_info.load_id(), context,
+              loop_limiter_info.load_id(), ir_context,
               &ids_used_by_this_transformation)) {
         return false;
       }
       if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-              loop_limiter_info.increment_id(), context,
+              loop_limiter_info.increment_id(), ir_context,
               &ids_used_by_this_transformation)) {
         return false;
       }
       if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-              loop_limiter_info.compare_id(), context,
+              loop_limiter_info.compare_id(), ir_context,
               &ids_used_by_this_transformation)) {
         return false;
       }
       if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-              loop_limiter_info.logical_op_id(), context,
+              loop_limiter_info.logical_op_id(), ir_context,
               &ids_used_by_this_transformation)) {
         return false;
       }
@@ -107,11 +107,11 @@ bool TransformationAddFunction::IsApplicable(
          message_.access_chain_clamping_info()) {
       for (auto& pair : access_chain_clamping_info.compare_and_select_ids()) {
         if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-                pair.first(), context, &ids_used_by_this_transformation)) {
+                pair.first(), ir_context, &ids_used_by_this_transformation)) {
           return false;
         }
         if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-                pair.second(), context, &ids_used_by_this_transformation)) {
+                pair.second(), ir_context, &ids_used_by_this_transformation)) {
           return false;
         }
       }
@@ -123,8 +123,8 @@ bool TransformationAddFunction::IsApplicable(
   // is taken here.
 
   // We first clone the current module, so that we can try adding the new
-  // function without risking wrecking |context|.
-  auto cloned_module = fuzzerutil::CloneIRContext(context);
+  // function without risking wrecking |ir_context|.
+  auto cloned_module = fuzzerutil::CloneIRContext(ir_context);
 
   // We try to add a function to the cloned module, which may fail if
   // |message_.instruction| is not sufficiently well-formed.
@@ -134,12 +134,14 @@ bool TransformationAddFunction::IsApplicable(
 
   // Check whether the cloned module is still valid after adding the function.
   // If it is not, the transformation is not applicable.
-  if (!fuzzerutil::IsValid(cloned_module.get())) {
+  if (!fuzzerutil::IsValid(cloned_module.get(),
+                           transformation_context.GetValidatorOptions())) {
     return false;
   }
 
   if (message_.is_livesafe()) {
-    if (!TryToMakeFunctionLivesafe(cloned_module.get(), fact_manager)) {
+    if (!TryToMakeFunctionLivesafe(cloned_module.get(),
+                                   transformation_context)) {
       return false;
     }
     // After making the function livesafe, we check validity of the module
@@ -148,7 +150,8 @@ bool TransformationAddFunction::IsApplicable(
     // has the potential to make the module invalid when it was otherwise valid.
     // It is simpler to rely on the validator to guard against this than to
     // consider all scenarios when making a function livesafe.
-    if (!fuzzerutil::IsValid(cloned_module.get())) {
+    if (!fuzzerutil::IsValid(cloned_module.get(),
+                             transformation_context.GetValidatorOptions())) {
       return false;
     }
   }
@@ -156,10 +159,11 @@ bool TransformationAddFunction::IsApplicable(
 }
 
 void TransformationAddFunction::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   // Add the function to the module.  As the transformation is applicable, this
   // should succeed.
-  bool success = TryToAddFunction(context);
+  bool success = TryToAddFunction(ir_context);
   assert(success && "The function should be successfully added.");
   (void)(success);  // Keep release builds happy (otherwise they may complain
                     // that |success| is not used).
@@ -172,16 +176,16 @@ void TransformationAddFunction::Apply(
   for (auto& instruction : message_.instruction()) {
     switch (instruction.opcode()) {
       case SpvOpFunctionParameter:
-        if (context->get_def_use_mgr()
+        if (ir_context->get_def_use_mgr()
                 ->GetDef(instruction.result_type_id())
                 ->opcode() == SpvOpTypePointer) {
-          fact_manager->AddFactValueOfPointeeIsIrrelevant(
-              instruction.result_id());
+          transformation_context->GetFactManager()
+              ->AddFactValueOfPointeeIsIrrelevant(instruction.result_id());
         }
         break;
       case SpvOpVariable:
-        fact_manager->AddFactValueOfPointeeIsIrrelevant(
-            instruction.result_id());
+        transformation_context->GetFactManager()
+            ->AddFactValueOfPointeeIsIrrelevant(instruction.result_id());
         break;
       default:
         break;
@@ -190,7 +194,7 @@ void TransformationAddFunction::Apply(
 
   if (message_.is_livesafe()) {
     // Make the function livesafe, which also should succeed.
-    success = TryToMakeFunctionLivesafe(context, *fact_manager);
+    success = TryToMakeFunctionLivesafe(ir_context, *transformation_context);
     assert(success && "It should be possible to make the function livesafe.");
     (void)(success);  // Keep release builds happy.
 
@@ -198,17 +202,18 @@ void TransformationAddFunction::Apply(
     assert(message_.instruction(0).opcode() == SpvOpFunction &&
            "The first instruction of an 'add function' transformation must be "
            "OpFunction.");
-    fact_manager->AddFactFunctionIsLivesafe(
+    transformation_context->GetFactManager()->AddFactFunctionIsLivesafe(
         message_.instruction(0).result_id());
   } else {
     // Inform the fact manager that all blocks in the function are dead.
     for (auto& inst : message_.instruction()) {
       if (inst.opcode() == SpvOpLabel) {
-        fact_manager->AddFactBlockIsDead(inst.result_id());
+        transformation_context->GetFactManager()->AddFactBlockIsDead(
+            inst.result_id());
       }
     }
   }
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddFunction::ToMessage() const {
@@ -218,9 +223,9 @@ protobufs::Transformation TransformationAddFunction::ToMessage() const {
 }
 
 bool TransformationAddFunction::TryToAddFunction(
-    opt::IRContext* context) const {
+    opt::IRContext* ir_context) const {
   // This function returns false if |message_.instruction| was not well-formed
-  // enough to actually create a function and add it to |context|.
+  // enough to actually create a function and add it to |ir_context|.
 
   // A function must have at least some instructions.
   if (message_.instruction().empty()) {
@@ -235,7 +240,7 @@ bool TransformationAddFunction::TryToAddFunction(
 
   // Make a function, headed by the OpFunction instruction.
   std::unique_ptr<opt::Function> new_function = MakeUnique<opt::Function>(
-      InstructionFromMessage(context, function_begin));
+      InstructionFromMessage(ir_context, function_begin));
 
   // Keeps track of which instruction protobuf message we are currently
   // considering.
@@ -249,7 +254,7 @@ bool TransformationAddFunction::TryToAddFunction(
          message_.instruction(instruction_index).opcode() ==
              SpvOpFunctionParameter) {
     new_function->AddParameter(InstructionFromMessage(
-        context, message_.instruction(instruction_index)));
+        ir_context, message_.instruction(instruction_index)));
     instruction_index++;
   }
 
@@ -270,7 +275,7 @@ bool TransformationAddFunction::TryToAddFunction(
     // as its parent.
     std::unique_ptr<opt::BasicBlock> block =
         MakeUnique<opt::BasicBlock>(InstructionFromMessage(
-            context, message_.instruction(instruction_index)));
+            ir_context, message_.instruction(instruction_index)));
     block->SetParent(new_function.get());
 
     // Consider successive instructions until we hit another label or the end
@@ -281,7 +286,7 @@ bool TransformationAddFunction::TryToAddFunction(
                SpvOpFunctionEnd &&
            message_.instruction(instruction_index).opcode() != SpvOpLabel) {
       block->AddInstruction(InstructionFromMessage(
-          context, message_.instruction(instruction_index)));
+          ir_context, message_.instruction(instruction_index)));
       instruction_index++;
     }
     // Add the block to the new function.
@@ -295,22 +300,23 @@ bool TransformationAddFunction::TryToAddFunction(
   }
   // Set the function's final instruction, add the function to the module and
   // report success.
-  new_function->SetFunctionEnd(
-      InstructionFromMessage(context, message_.instruction(instruction_index)));
-  context->AddFunction(std::move(new_function));
+  new_function->SetFunctionEnd(InstructionFromMessage(
+      ir_context, message_.instruction(instruction_index)));
+  ir_context->AddFunction(std::move(new_function));
 
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 
   return true;
 }
 
 bool TransformationAddFunction::TryToMakeFunctionLivesafe(
-    opt::IRContext* context, const FactManager& fact_manager) const {
+    opt::IRContext* ir_context,
+    const TransformationContext& transformation_context) const {
   assert(message_.is_livesafe() && "Precondition: is_livesafe must hold.");
 
   // Get a pointer to the added function.
   opt::Function* added_function = nullptr;
-  for (auto& function : *context->module()) {
+  for (auto& function : *ir_context->module()) {
     if (function.result_id() == message_.instruction(0).result_id()) {
       added_function = &function;
       break;
@@ -318,7 +324,7 @@ bool TransformationAddFunction::TryToMakeFunctionLivesafe(
   }
   assert(added_function && "The added function should have been found.");
 
-  if (!TryToAddLoopLimiters(context, added_function)) {
+  if (!TryToAddLoopLimiters(ir_context, added_function)) {
     // Adding loop limiters did not work; bail out.
     return false;
   }
@@ -332,20 +338,20 @@ bool TransformationAddFunction::TryToMakeFunctionLivesafe(
       switch (inst.opcode()) {
         case SpvOpKill:
         case SpvOpUnreachable:
-          if (!TryToTurnKillOrUnreachableIntoReturn(context, added_function,
+          if (!TryToTurnKillOrUnreachableIntoReturn(ir_context, added_function,
                                                     &inst)) {
             return false;
           }
           break;
         case SpvOpAccessChain:
         case SpvOpInBoundsAccessChain:
-          if (!TryToClampAccessChainIndices(context, &inst)) {
+          if (!TryToClampAccessChainIndices(ir_context, &inst)) {
             return false;
           }
           break;
         case SpvOpFunctionCall:
           // A livesafe function my only call other livesafe functions.
-          if (!fact_manager.FunctionIsLivesafe(
+          if (!transformation_context.GetFactManager()->FunctionIsLivesafe(
                   inst.GetSingleWordInOperand(0))) {
             return false;
           }
@@ -358,7 +364,7 @@ bool TransformationAddFunction::TryToMakeFunctionLivesafe(
 }
 
 bool TransformationAddFunction::TryToAddLoopLimiters(
-    opt::IRContext* context, opt::Function* added_function) const {
+    opt::IRContext* ir_context, opt::Function* added_function) const {
   // Collect up all the loop headers so that we can subsequently add loop
   // limiting logic.
   std::vector<opt::BasicBlock*> loop_headers;
@@ -377,7 +383,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
   // manipulating a loop limiter.
 
   auto loop_limit_constant_id_instr =
-      context->get_def_use_mgr()->GetDef(message_.loop_limit_constant_id());
+      ir_context->get_def_use_mgr()->GetDef(message_.loop_limit_constant_id());
   if (!loop_limit_constant_id_instr ||
       loop_limit_constant_id_instr->opcode() != SpvOpConstant) {
     // The loop limit constant id instruction must exist and have an
@@ -385,7 +391,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
     return false;
   }
 
-  auto loop_limit_type = context->get_def_use_mgr()->GetDef(
+  auto loop_limit_type = ir_context->get_def_use_mgr()->GetDef(
       loop_limit_constant_id_instr->type_id());
   if (loop_limit_type->opcode() != SpvOpTypeInt ||
       loop_limit_type->GetSingleWordInOperand(0) != 32) {
@@ -397,36 +403,36 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
   // Find the id of the "unsigned int" type.
   opt::analysis::Integer unsigned_int_type(32, false);
   uint32_t unsigned_int_type_id =
-      context->get_type_mgr()->GetId(&unsigned_int_type);
+      ir_context->get_type_mgr()->GetId(&unsigned_int_type);
   if (!unsigned_int_type_id) {
     // Unsigned int is not available; we need this type in order to add loop
     // limiters.
     return false;
   }
   auto registered_unsigned_int_type =
-      context->get_type_mgr()->GetRegisteredType(&unsigned_int_type);
+      ir_context->get_type_mgr()->GetRegisteredType(&unsigned_int_type);
 
   // Look for 0 of type unsigned int.
   opt::analysis::IntConstant zero(registered_unsigned_int_type->AsInteger(),
                                   {0});
-  auto registered_zero = context->get_constant_mgr()->FindConstant(&zero);
+  auto registered_zero = ir_context->get_constant_mgr()->FindConstant(&zero);
   if (!registered_zero) {
     // We need 0 in order to be able to initialize loop limiters.
     return false;
   }
-  uint32_t zero_id = context->get_constant_mgr()
+  uint32_t zero_id = ir_context->get_constant_mgr()
                          ->GetDefiningInstruction(registered_zero)
                          ->result_id();
 
   // Look for 1 of type unsigned int.
   opt::analysis::IntConstant one(registered_unsigned_int_type->AsInteger(),
                                  {1});
-  auto registered_one = context->get_constant_mgr()->FindConstant(&one);
+  auto registered_one = ir_context->get_constant_mgr()->FindConstant(&one);
   if (!registered_one) {
     // We need 1 in order to be able to increment loop limiters.
     return false;
   }
-  uint32_t one_id = context->get_constant_mgr()
+  uint32_t one_id = ir_context->get_constant_mgr()
                         ->GetDefiningInstruction(registered_one)
                         ->result_id();
 
@@ -434,7 +440,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
   opt::analysis::Pointer pointer_to_unsigned_int_type(
       registered_unsigned_int_type, SpvStorageClassFunction);
   uint32_t pointer_to_unsigned_int_type_id =
-      context->get_type_mgr()->GetId(&pointer_to_unsigned_int_type);
+      ir_context->get_type_mgr()->GetId(&pointer_to_unsigned_int_type);
   if (!pointer_to_unsigned_int_type_id) {
     // We need pointer-to-unsigned int in order to declare the loop limiter
     // variable.
@@ -443,7 +449,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
 
   // Look for bool type.
   opt::analysis::Bool bool_type;
-  uint32_t bool_type_id = context->get_type_mgr()->GetId(&bool_type);
+  uint32_t bool_type_id = ir_context->get_type_mgr()->GetId(&bool_type);
   if (!bool_type_id) {
     // We need bool in order to compare the loop limiter's value with the loop
     // limit constant.
@@ -454,22 +460,23 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
   // block, via an instruction of the form:
   //   %loop_limiter_var = SpvOpVariable %ptr_to_uint Function %zero
   added_function->begin()->begin()->InsertBefore(MakeUnique<opt::Instruction>(
-      context, SpvOpVariable, pointer_to_unsigned_int_type_id,
+      ir_context, SpvOpVariable, pointer_to_unsigned_int_type_id,
       message_.loop_limiter_variable_id(),
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}},
            {SPV_OPERAND_TYPE_ID, {zero_id}}})));
   // Update the module's id bound since we have added the loop limiter
   // variable id.
-  fuzzerutil::UpdateModuleIdBound(context, message_.loop_limiter_variable_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context,
+                                  message_.loop_limiter_variable_id());
 
   // Consider each loop in turn.
   for (auto loop_header : loop_headers) {
     // Look for the loop's back-edge block.  This is a predecessor of the loop
     // header that is dominated by the loop header.
     uint32_t back_edge_block_id = 0;
-    for (auto pred : context->cfg()->preds(loop_header->id())) {
-      if (context->GetDominatorAnalysis(added_function)
+    for (auto pred : ir_context->cfg()->preds(loop_header->id())) {
+      if (ir_context->GetDominatorAnalysis(added_function)
               ->Dominates(loop_header->id(), pred)) {
         back_edge_block_id = pred;
         break;
@@ -481,7 +488,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
       // move on from this loop.
       continue;
     }
-    auto back_edge_block = context->cfg()->block(back_edge_block_id);
+    auto back_edge_block = ir_context->cfg()->block(back_edge_block_id);
 
     // Go through the sequence of loop limiter infos and find the one
     // corresponding to this loop.
@@ -579,14 +586,15 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
     // Add a load from the loop limiter variable, of the form:
     //   %t1 = OpLoad %uint32 %loop_limiter
     new_instructions.push_back(MakeUnique<opt::Instruction>(
-        context, SpvOpLoad, unsigned_int_type_id, loop_limiter_info.load_id(),
+        ir_context, SpvOpLoad, unsigned_int_type_id,
+        loop_limiter_info.load_id(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}}})));
 
     // Increment the loaded value:
     //   %t2 = OpIAdd %uint32 %t1 %one
     new_instructions.push_back(MakeUnique<opt::Instruction>(
-        context, SpvOpIAdd, unsigned_int_type_id,
+        ir_context, SpvOpIAdd, unsigned_int_type_id,
         loop_limiter_info.increment_id(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.load_id()}},
@@ -595,7 +603,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
     // Store the incremented value back to the loop limiter variable:
     //   OpStore %loop_limiter %t2
     new_instructions.push_back(MakeUnique<opt::Instruction>(
-        context, SpvOpStore, 0, 0,
+        ir_context, SpvOpStore, 0, 0,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}},
              {SPV_OPERAND_TYPE_ID, {loop_limiter_info.increment_id()}}})));
@@ -605,7 +613,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
     // or
     //   %t3 = OpULessThan %bool %t1 %loop_limit
     new_instructions.push_back(MakeUnique<opt::Instruction>(
-        context,
+        ir_context,
         compare_using_greater_than_equal ? SpvOpUGreaterThanEqual
                                          : SpvOpULessThan,
         bool_type_id, loop_limiter_info.compare_id(),
@@ -615,7 +623,7 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
 
     if (back_edge_block_terminator->opcode() == SpvOpBranchConditional) {
       new_instructions.push_back(MakeUnique<opt::Instruction>(
-          context,
+          ir_context,
           compare_using_greater_than_equal ? SpvOpLogicalOr : SpvOpLogicalAnd,
           bool_type_id, loop_limiter_info.logical_op_id(),
           opt::Instruction::OperandList(
@@ -644,8 +652,9 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
       // Check that, if the merge block starts with OpPhi instructions, suitable
       // ids have been provided to give these instructions a value corresponding
       // to the new incoming edge from the back edge block.
-      auto merge_block = context->cfg()->block(loop_header->MergeBlockId());
-      if (!fuzzerutil::PhiIdsOkForNewEdge(context, back_edge_block, merge_block,
+      auto merge_block = ir_context->cfg()->block(loop_header->MergeBlockId());
+      if (!fuzzerutil::PhiIdsOkForNewEdge(ir_context, back_edge_block,
+                                          merge_block,
                                           loop_limiter_info.phi_id())) {
         return false;
       }
@@ -681,16 +690,18 @@ bool TransformationAddFunction::TryToAddLoopLimiters(
 
     // Update the module's id bound with respect to the various ids that
     // have been used for loop limiter manipulation.
-    fuzzerutil::UpdateModuleIdBound(context, loop_limiter_info.load_id());
-    fuzzerutil::UpdateModuleIdBound(context, loop_limiter_info.increment_id());
-    fuzzerutil::UpdateModuleIdBound(context, loop_limiter_info.compare_id());
-    fuzzerutil::UpdateModuleIdBound(context, loop_limiter_info.logical_op_id());
+    fuzzerutil::UpdateModuleIdBound(ir_context, loop_limiter_info.load_id());
+    fuzzerutil::UpdateModuleIdBound(ir_context,
+                                    loop_limiter_info.increment_id());
+    fuzzerutil::UpdateModuleIdBound(ir_context, loop_limiter_info.compare_id());
+    fuzzerutil::UpdateModuleIdBound(ir_context,
+                                    loop_limiter_info.logical_op_id());
   }
   return true;
 }
 
 bool TransformationAddFunction::TryToTurnKillOrUnreachableIntoReturn(
-    opt::IRContext* context, opt::Function* added_function,
+    opt::IRContext* ir_context, opt::Function* added_function,
     opt::Instruction* kill_or_unreachable_inst) const {
   assert((kill_or_unreachable_inst->opcode() == SpvOpKill ||
           kill_or_unreachable_inst->opcode() == SpvOpUnreachable) &&
@@ -698,7 +709,7 @@ bool TransformationAddFunction::TryToTurnKillOrUnreachableIntoReturn(
 
   // Get the function's return type.
   auto function_return_type_inst =
-      context->get_def_use_mgr()->GetDef(added_function->type_id());
+      ir_context->get_def_use_mgr()->GetDef(added_function->type_id());
 
   if (function_return_type_inst->opcode() == SpvOpTypeVoid) {
     // The function has void return type, so change this instruction to
@@ -712,7 +723,7 @@ bool TransformationAddFunction::TryToTurnKillOrUnreachableIntoReturn(
     // We first check that the id, %id, provided with the transformation
     // specifically to turn OpKill and OpUnreachable instructions into
     // OpReturnValue %id has the same type as the function's return type.
-    if (context->get_def_use_mgr()
+    if (ir_context->get_def_use_mgr()
             ->GetDef(message_.kill_unreachable_return_value_id())
             ->type_id() != function_return_type_inst->result_id()) {
       return false;
@@ -725,7 +736,7 @@ bool TransformationAddFunction::TryToTurnKillOrUnreachableIntoReturn(
 }
 
 bool TransformationAddFunction::TryToClampAccessChainIndices(
-    opt::IRContext* context, opt::Instruction* access_chain_inst) const {
+    opt::IRContext* ir_context, opt::Instruction* access_chain_inst) const {
   assert((access_chain_inst->opcode() == SpvOpAccessChain ||
           access_chain_inst->opcode() == SpvOpInBoundsAccessChain) &&
          "Precondition: instruction must be OpAccessChain or "
@@ -756,14 +767,14 @@ bool TransformationAddFunction::TryToClampAccessChainIndices(
 
   // Walk the access chain, clamping each index to be within bounds if it is
   // not a constant.
-  auto base_object = context->get_def_use_mgr()->GetDef(
+  auto base_object = ir_context->get_def_use_mgr()->GetDef(
       access_chain_inst->GetSingleWordInOperand(0));
   assert(base_object && "The base object must exist.");
   auto pointer_type =
-      context->get_def_use_mgr()->GetDef(base_object->type_id());
+      ir_context->get_def_use_mgr()->GetDef(base_object->type_id());
   assert(pointer_type && pointer_type->opcode() == SpvOpTypePointer &&
          "The base object must have pointer type.");
-  auto should_be_composite_type = context->get_def_use_mgr()->GetDef(
+  auto should_be_composite_type = ir_context->get_def_use_mgr()->GetDef(
       pointer_type->GetSingleWordInOperand(1));
 
   // Consider each index input operand in turn (operand 0 is the base object).
@@ -784,18 +795,18 @@ bool TransformationAddFunction::TryToClampAccessChainIndices(
     // Get the bound for the composite being indexed into; e.g. the number of
     // columns of matrix or the size of an array.
     uint32_t bound =
-        GetBoundForCompositeIndex(context, *should_be_composite_type);
+        GetBoundForCompositeIndex(ir_context, *should_be_composite_type);
 
     // Get the instruction associated with the index and figure out its integer
     // type.
     const uint32_t index_id = access_chain_inst->GetSingleWordInOperand(index);
-    auto index_inst = context->get_def_use_mgr()->GetDef(index_id);
+    auto index_inst = ir_context->get_def_use_mgr()->GetDef(index_id);
     auto index_type_inst =
-        context->get_def_use_mgr()->GetDef(index_inst->type_id());
+        ir_context->get_def_use_mgr()->GetDef(index_inst->type_id());
     assert(index_type_inst->opcode() == SpvOpTypeInt);
     assert(index_type_inst->GetSingleWordInOperand(0) == 32);
     opt::analysis::Integer* index_int_type =
-        context->get_type_mgr()
+        ir_context->get_type_mgr()
             ->GetType(index_type_inst->result_id())
             ->AsInteger();
 
@@ -805,20 +816,20 @@ bool TransformationAddFunction::TryToClampAccessChainIndices(
              "Access chain indices into structures are required to be "
              "constants.");
       opt::analysis::IntConstant bound_minus_one(index_int_type, {bound - 1});
-      if (!context->get_constant_mgr()->FindConstant(&bound_minus_one)) {
+      if (!ir_context->get_constant_mgr()->FindConstant(&bound_minus_one)) {
         // We do not have an integer constant whose value is |bound| -1.
         return false;
       }
 
       opt::analysis::Bool bool_type;
-      uint32_t bool_type_id = context->get_type_mgr()->GetId(&bool_type);
+      uint32_t bool_type_id = ir_context->get_type_mgr()->GetId(&bool_type);
       if (!bool_type_id) {
         // Bool type is not declared; we cannot do a comparison.
         return false;
       }
 
       uint32_t bound_minus_one_id =
-          context->get_constant_mgr()
+          ir_context->get_constant_mgr()
               ->GetDefiningInstruction(&bound_minus_one)
               ->result_id();
 
@@ -832,7 +843,7 @@ bool TransformationAddFunction::TryToClampAccessChainIndices(
       // Compare the index with the bound via an instruction of the form:
       //   %t1 = OpULessThanEqual %bool %index %bound_minus_one
       new_instructions.push_back(MakeUnique<opt::Instruction>(
-          context, SpvOpULessThanEqual, bool_type_id, compare_id,
+          ir_context, SpvOpULessThanEqual, bool_type_id, compare_id,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {index_inst->result_id()}},
                {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}})));
@@ -840,7 +851,7 @@ bool TransformationAddFunction::TryToClampAccessChainIndices(
       // Select the index if in-bounds, otherwise one less than the bound:
       //   %t2 = OpSelect %int_type %t1 %index %bound_minus_one
       new_instructions.push_back(MakeUnique<opt::Instruction>(
-          context, SpvOpSelect, index_type_inst->result_id(), select_id,
+          ir_context, SpvOpSelect, index_type_inst->result_id(), select_id,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {compare_id}},
                {SPV_OPERAND_TYPE_ID, {index_inst->result_id()}},
@@ -851,8 +862,8 @@ bool TransformationAddFunction::TryToClampAccessChainIndices(
 
       // Replace %index with %t2.
       access_chain_inst->SetInOperand(index, {select_id});
-      fuzzerutil::UpdateModuleIdBound(context, compare_id);
-      fuzzerutil::UpdateModuleIdBound(context, select_id);
+      fuzzerutil::UpdateModuleIdBound(ir_context, compare_id);
+      fuzzerutil::UpdateModuleIdBound(ir_context, select_id);
     } else {
       // TODO(afd): At present the SPIR-V spec is not clear on whether
       //  statically out-of-bounds indices mean that a module is invalid (so
@@ -870,16 +881,16 @@ bool TransformationAddFunction::TryToClampAccessChainIndices(
       }
     }
     should_be_composite_type =
-        FollowCompositeIndex(context, *should_be_composite_type, index_id);
+        FollowCompositeIndex(ir_context, *should_be_composite_type, index_id);
   }
   return true;
 }
 
 uint32_t TransformationAddFunction::GetBoundForCompositeIndex(
-    opt::IRContext* context, const opt::Instruction& composite_type_inst) {
+    opt::IRContext* ir_context, const opt::Instruction& composite_type_inst) {
   switch (composite_type_inst.opcode()) {
     case SpvOpTypeArray:
-      return fuzzerutil::GetArraySize(composite_type_inst, context);
+      return fuzzerutil::GetArraySize(composite_type_inst, ir_context);
     case SpvOpTypeMatrix:
     case SpvOpTypeVector:
       return composite_type_inst.GetSingleWordInOperand(1);
@@ -893,7 +904,7 @@ uint32_t TransformationAddFunction::GetBoundForCompositeIndex(
 }
 
 opt::Instruction* TransformationAddFunction::FollowCompositeIndex(
-    opt::IRContext* context, const opt::Instruction& composite_type_inst,
+    opt::IRContext* ir_context, const opt::Instruction& composite_type_inst,
     uint32_t index_id) {
   uint32_t sub_object_type_id;
   switch (composite_type_inst.opcode()) {
@@ -905,12 +916,12 @@ opt::Instruction* TransformationAddFunction::FollowCompositeIndex(
       sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0);
       break;
     case SpvOpTypeStruct: {
-      auto index_inst = context->get_def_use_mgr()->GetDef(index_id);
+      auto index_inst = ir_context->get_def_use_mgr()->GetDef(index_id);
       assert(index_inst->opcode() == SpvOpConstant);
-      assert(
-          context->get_def_use_mgr()->GetDef(index_inst->type_id())->opcode() ==
-          SpvOpTypeInt);
-      assert(context->get_def_use_mgr()
+      assert(ir_context->get_def_use_mgr()
+                 ->GetDef(index_inst->type_id())
+                 ->opcode() == SpvOpTypeInt);
+      assert(ir_context->get_def_use_mgr()
                  ->GetDef(index_inst->type_id())
                  ->GetSingleWordInOperand(0) == 32);
       uint32_t index_value = index_inst->GetSingleWordInOperand(0);
@@ -924,7 +935,7 @@ opt::Instruction* TransformationAddFunction::FollowCompositeIndex(
       break;
   }
   assert(sub_object_type_id && "No sub-object found.");
-  return context->get_def_use_mgr()->GetDef(sub_object_type_id);
+  return ir_context->get_def_use_mgr()->GetDef(sub_object_type_id);
 }
 
 }  // namespace fuzz

+ 22 - 19
3rdparty/spirv-tools/source/fuzz/transformation_add_function.h

@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_FUNCTION_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_FUNCTION_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -47,12 +47,14 @@ class TransformationAddFunction : public Transformation {
   //   ingredients to make the function livesafe, and the function must only
   //   invoke other livesafe functions
   // - Adding the created function to the module must lead to a valid module.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds the function defined by |message_.instruction| to the module, making
   // it livesafe if |message_.is_livesafe| holds.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
@@ -61,26 +63,26 @@ class TransformationAddFunction : public Transformation {
   // an array, the number of components of a vector, or the number of columns of
   // a matrix.
   static uint32_t GetBoundForCompositeIndex(
-      opt::IRContext* context, const opt::Instruction& composite_type_inst);
+      opt::IRContext* ir_context, const opt::Instruction& composite_type_inst);
 
   // Helper method that, given composite type |composite_type_inst|, returns the
   // type of the sub-object at index |index_id|, which is required to be in-
   // bounds.
   static opt::Instruction* FollowCompositeIndex(
-      opt::IRContext* context, const opt::Instruction& composite_type_inst,
+      opt::IRContext* ir_context, const opt::Instruction& composite_type_inst,
       uint32_t index_id);
 
  private:
   // Attempts to create a function from the series of instructions in
-  // |message_.instruction| and add it to |context|.
+  // |message_.instruction| and add it to |ir_context|.
   //
   // Returns false if adding the function is not possible due to the messages
   // not respecting the basic structure of a function, e.g. if there is no
-  // OpFunction instruction or no blocks; in this case |context| is left in an
-  // indeterminate state.
+  // OpFunction instruction or no blocks; in this case |ir_context| is left in
+  // an indeterminate state.
   //
-  // Otherwise returns true.  Whether |context| is valid after addition of the
-  // function depends on the contents of |message_.instruction|.
+  // Otherwise returns true.  Whether |ir_context| is valid after addition of
+  // the function depends on the contents of |message_.instruction|.
   //
   // Intended usage:
   // - Perform a dry run of this method on a clone of a module, and use
@@ -89,30 +91,31 @@ class TransformationAddFunction : public Transformation {
   //   added, or leads to an invalid module.
   // - If the dry run succeeds, run the method on the real module of interest,
   //   to add the function.
-  bool TryToAddFunction(opt::IRContext* context) const;
+  bool TryToAddFunction(opt::IRContext* ir_context) const;
 
   // Should only be called if |message_.is_livesafe| holds.  Attempts to make
   // the function livesafe (see FactFunctionIsLivesafe for a definition).
-  // Returns false if this is not possible, due to |message_| or |context| not
-  // containing sufficient ingredients (such as types and fresh ids) to add
+  // Returns false if this is not possible, due to |message_| or |ir_context|
+  // not containing sufficient ingredients (such as types and fresh ids) to add
   // the instrumentation necessary to make the function livesafe.
-  bool TryToMakeFunctionLivesafe(opt::IRContext* context,
-                                 const FactManager& fact_manager) const;
+  bool TryToMakeFunctionLivesafe(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const;
 
   // A helper for TryToMakeFunctionLivesafe that tries to add loop-limiting
   // logic.
-  bool TryToAddLoopLimiters(opt::IRContext* context,
+  bool TryToAddLoopLimiters(opt::IRContext* ir_context,
                             opt::Function* added_function) const;
 
   // A helper for TryToMakeFunctionLivesafe that tries to replace OpKill and
   // OpUnreachable instructions into return instructions.
   bool TryToTurnKillOrUnreachableIntoReturn(
-      opt::IRContext* context, opt::Function* added_function,
+      opt::IRContext* ir_context, opt::Function* added_function,
       opt::Instruction* kill_or_unreachable_inst) const;
 
   // A helper for TryToMakeFunctionLivesafe that tries to clamp access chain
   // indices so that they are guaranteed to be in-bounds.
-  bool TryToClampAccessChainIndices(opt::IRContext* context,
+  bool TryToClampAccessChainIndices(opt::IRContext* ir_context,
                                     opt::Instruction* access_chain_inst) const;
 
   protobufs::TransformationAddFunction message_;

+ 9 - 9
3rdparty/spirv-tools/source/fuzz/transformation_add_global_undef.cpp

@@ -30,26 +30,26 @@ TransformationAddGlobalUndef::TransformationAddGlobalUndef(uint32_t fresh_id,
 }
 
 bool TransformationAddGlobalUndef::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // A fresh id is required.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
-  auto type = context->get_type_mgr()->GetType(message_.type_id());
+  auto type = ir_context->get_type_mgr()->GetType(message_.type_id());
   // The type must exist, and must not be a function type.
   return type && !type->AsFunction();
 }
 
 void TransformationAddGlobalUndef::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
-  context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context, SpvOpUndef, message_.type_id(), message_.fresh_id(),
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
+  ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpUndef, message_.type_id(), message_.fresh_id(),
       opt::Instruction::OperandList()));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddGlobalUndef::ToMessage() const {

+ 6 - 4
3rdparty/spirv-tools/source/fuzz/transformation_add_global_undef.h

@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_UNDEF_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_UNDEF_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -32,12 +32,14 @@ class TransformationAddGlobalUndef : public Transformation {
 
   // - |message_.fresh_id| must be fresh
   // - |message_.type_id| must be the id of a non-function type
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpUndef instruction to the module, with |message_.type_id| as its
   // type.  The instruction has result id |message_.fresh_id|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 

+ 18 - 16
3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.cpp

@@ -33,14 +33,13 @@ TransformationAddGlobalVariable::TransformationAddGlobalVariable(
 }
 
 bool TransformationAddGlobalVariable::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The result id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // The type id must correspond to a type.
-  auto type = context->get_type_mgr()->GetType(message_.type_id());
+  auto type = ir_context->get_type_mgr()->GetType(message_.type_id());
   if (!type) {
     return false;
   }
@@ -55,7 +54,7 @@ bool TransformationAddGlobalVariable::IsApplicable(
   }
   // The initializer id must be the id of a constant.  Check this with the
   // constant manager.
-  auto constant_id = context->get_constant_mgr()->GetConstantsFromIds(
+  auto constant_id = ir_context->get_constant_mgr()->GetConstantsFromIds(
       {message_.initializer_id()});
   if (constant_id.empty()) {
     return false;
@@ -71,7 +70,8 @@ bool TransformationAddGlobalVariable::IsApplicable(
 }
 
 void TransformationAddGlobalVariable::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   opt::Instruction::OperandList input_operands;
   input_operands.push_back(
       {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassPrivate}});
@@ -79,12 +79,12 @@ void TransformationAddGlobalVariable::Apply(
     input_operands.push_back(
         {SPV_OPERAND_TYPE_ID, {message_.initializer_id()}});
   }
-  context->module()->AddGlobalValue(
-      MakeUnique<opt::Instruction>(context, SpvOpVariable, message_.type_id(),
-                                   message_.fresh_id(), input_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpVariable, message_.type_id(), message_.fresh_id(),
+      input_operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
 
-  if (PrivateGlobalsMustBeDeclaredInEntryPointInterfaces(context)) {
+  if (PrivateGlobalsMustBeDeclaredInEntryPointInterfaces(ir_context)) {
     // Conservatively add this global to the interface of every entry point in
     // the module.  This means that the global is available for other
     // transformations to use.
@@ -94,18 +94,20 @@ void TransformationAddGlobalVariable::Apply(
     //
     // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3111) revisit
     //  this if a more thorough approach to entry point interfaces is taken.
-    for (auto& entry_point : context->module()->entry_points()) {
+    for (auto& entry_point : ir_context->module()->entry_points()) {
       entry_point.AddOperand({SPV_OPERAND_TYPE_ID, {message_.fresh_id()}});
     }
   }
 
   if (message_.value_is_irrelevant()) {
-    fact_manager->AddFactValueOfPointeeIsIrrelevant(message_.fresh_id());
+    transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+        message_.fresh_id());
   }
 
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddGlobalVariable::ToMessage() const {
@@ -116,11 +118,11 @@ protobufs::Transformation TransformationAddGlobalVariable::ToMessage() const {
 
 bool TransformationAddGlobalVariable::
     PrivateGlobalsMustBeDeclaredInEntryPointInterfaces(
-        opt::IRContext* context) {
+        opt::IRContext* ir_context) {
   // TODO(afd): We capture the universal environments for which this requirement
   //  holds.  The check should be refined on demand for other target
   //  environments.
-  switch (context->grammar().target_env()) {
+  switch (ir_context->grammar().target_env()) {
     case SPV_ENV_UNIVERSAL_1_0:
     case SPV_ENV_UNIVERSAL_1_1:
     case SPV_ENV_UNIVERSAL_1_2:

+ 9 - 7
3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.h

@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_VARIABLE_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_VARIABLE_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -37,23 +37,25 @@ class TransformationAddGlobalVariable : public Transformation {
   //   class
   // - |message_.initializer_id| must either be 0 or the id of a constant whose
   //   type is the pointee type of |message_.type_id|
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds a global variable with Private storage class to the module, with type
   // |message_.type_id| and either no initializer or |message_.initializer_id|
   // as an initializer, depending on whether |message_.initializer_id| is 0.
   // The global variable has result id |message_.fresh_id|.
   //
-  // If |message_.value_is_irrelevant| holds, adds a corresponding fact to
-  // |fact_manager|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  // If |message_.value_is_irrelevant| holds, adds a corresponding fact to the
+  // fact manager in |transformation_context|.
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
  private:
   static bool PrivateGlobalsMustBeDeclaredInEntryPointInterfaces(
-      opt::IRContext* context);
+      opt::IRContext* ir_context);
 
   protobufs::TransformationAddGlobalVariable message_;
 };

+ 13 - 12
3rdparty/spirv-tools/source/fuzz/transformation_add_local_variable.cpp

@@ -34,23 +34,22 @@ TransformationAddLocalVariable::TransformationAddLocalVariable(
 }
 
 bool TransformationAddLocalVariable::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The provided id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // The pointer type id must indeed correspond to a pointer, and it must have
   // function storage class.
   auto type_instruction =
-      context->get_def_use_mgr()->GetDef(message_.type_id());
+      ir_context->get_def_use_mgr()->GetDef(message_.type_id());
   if (!type_instruction || type_instruction->opcode() != SpvOpTypePointer ||
       type_instruction->GetSingleWordInOperand(0) != SpvStorageClassFunction) {
     return false;
   }
   // The initializer must...
   auto initializer_instruction =
-      context->get_def_use_mgr()->GetDef(message_.initializer_id());
+      ir_context->get_def_use_mgr()->GetDef(message_.initializer_id());
   // ... exist, ...
   if (!initializer_instruction) {
     return false;
@@ -65,17 +64,18 @@ bool TransformationAddLocalVariable::IsApplicable(
     return false;
   }
   // The function to which the local variable is to be added must exist.
-  return fuzzerutil::FindFunction(context, message_.function_id());
+  return fuzzerutil::FindFunction(ir_context, message_.function_id());
 }
 
 void TransformationAddLocalVariable::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
-  fuzzerutil::FindFunction(context, message_.function_id())
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+  fuzzerutil::FindFunction(ir_context, message_.function_id())
       ->begin()
       ->begin()
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          context, SpvOpVariable, message_.type_id(), message_.fresh_id(),
+          ir_context, SpvOpVariable, message_.type_id(), message_.fresh_id(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_STORAGE_CLASS,
                 {
@@ -83,9 +83,10 @@ void TransformationAddLocalVariable::Apply(
                     SpvStorageClassFunction}},
                {SPV_OPERAND_TYPE_ID, {message_.initializer_id()}}})));
   if (message_.value_is_irrelevant()) {
-    fact_manager->AddFactValueOfPointeeIsIrrelevant(message_.fresh_id());
+    transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+        message_.fresh_id());
   }
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddLocalVariable::ToMessage() const {

+ 8 - 6
3rdparty/spirv-tools/source/fuzz/transformation_add_local_variable.h

@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_LOCAL_VARIABLE_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_LOCAL_VARIABLE_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -38,15 +38,17 @@ class TransformationAddLocalVariable : public Transformation {
   // - |message_.initializer_id| must be the id of a constant with the same
   //   type as the pointer's pointee type
   // - |message_.function_id| must be the id of a function
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an instruction to the start of |message_.function_id|, of the form:
   //   |message_.fresh_id| = OpVariable |message_.type_id| Function
   //                         |message_.initializer_id|
-  // If |message_.value_is_irrelevant| holds, adds a corresponding fact to
-  // |fact_manager|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  // If |message_.value_is_irrelevant| holds, adds a corresponding fact to the
+  // fact manager in |transformation_context|.
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 

+ 5 - 6
3rdparty/spirv-tools/source/fuzz/transformation_add_no_contraction_decoration.cpp

@@ -31,10 +31,9 @@ TransformationAddNoContractionDecoration::
 }
 
 bool TransformationAddNoContractionDecoration::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // |message_.result_id| must be the id of an instruction.
-  auto instr = context->get_def_use_mgr()->GetDef(message_.result_id());
+  auto instr = ir_context->get_def_use_mgr()->GetDef(message_.result_id());
   if (!instr) {
     return false;
   }
@@ -43,10 +42,10 @@ bool TransformationAddNoContractionDecoration::IsApplicable(
 }
 
 void TransformationAddNoContractionDecoration::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   // Add a NoContraction decoration targeting |message_.result_id|.
-  context->get_decoration_mgr()->AddDecoration(message_.result_id(),
-                                               SpvDecorationNoContraction);
+  ir_context->get_decoration_mgr()->AddDecoration(message_.result_id(),
+                                                  SpvDecorationNoContraction);
 }
 
 protobufs::Transformation TransformationAddNoContractionDecoration::ToMessage()

Some files were not shown because too many files changed in this diff