Бранимир Караџић 5 лет назад
Родитель
Сommit
765b7b02eb
100 измененных файлов с 1 добавлено и 13406 удалено
  1. 1 1
      3rdparty/spirv-tools/include/generated/build-version.inc
  2. 0 392
      3rdparty/spirv-tools/source/fuzz/CMakeLists.txt
  3. 0 81
      3rdparty/spirv-tools/source/fuzz/call_graph.cpp
  4. 0 62
      3rdparty/spirv-tools/source/fuzz/call_graph.h
  5. 0 30
      3rdparty/spirv-tools/source/fuzz/counter_overflow_id_source.cpp
  6. 0 45
      3rdparty/spirv-tools/source/fuzz/counter_overflow_id_source.h
  7. 0 69
      3rdparty/spirv-tools/source/fuzz/data_descriptor.cpp
  8. 0 48
      3rdparty/spirv-tools/source/fuzz/data_descriptor.h
  9. 0 245
      3rdparty/spirv-tools/source/fuzz/equivalence_relation.h
  10. 0 235
      3rdparty/spirv-tools/source/fuzz/fact_manager/constant_uniform_facts.cpp
  11. 0 90
      3rdparty/spirv-tools/source/fuzz/fact_manager/constant_uniform_facts.h
  12. 0 861
      3rdparty/spirv-tools/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.cpp
  13. 0 156
      3rdparty/spirv-tools/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.h
  14. 0 31
      3rdparty/spirv-tools/source/fuzz/fact_manager/dead_block_facts.cpp
  15. 0 44
      3rdparty/spirv-tools/source/fuzz/fact_manager/dead_block_facts.h
  16. 0 244
      3rdparty/spirv-tools/source/fuzz/fact_manager/fact_manager.cpp
  17. 0 213
      3rdparty/spirv-tools/source/fuzz/fact_manager/fact_manager.h
  18. 0 51
      3rdparty/spirv-tools/source/fuzz/fact_manager/irrelevant_value_facts.cpp
  19. 0 52
      3rdparty/spirv-tools/source/fuzz/fact_manager/irrelevant_value_facts.h
  20. 0 32
      3rdparty/spirv-tools/source/fuzz/fact_manager/livesafe_function_facts.cpp
  21. 0 44
      3rdparty/spirv-tools/source/fuzz/fact_manager/livesafe_function_facts.h
  22. 0 372
      3rdparty/spirv-tools/source/fuzz/force_render_red.cpp
  23. 0 49
      3rdparty/spirv-tools/source/fuzz/force_render_red.h
  24. 0 394
      3rdparty/spirv-tools/source/fuzz/fuzzer.cpp
  25. 0 101
      3rdparty/spirv-tools/source/fuzz/fuzzer.h
  26. 0 320
      3rdparty/spirv-tools/source/fuzz/fuzzer_context.cpp
  27. 0 445
      3rdparty/spirv-tools/source/fuzz/fuzzer_context.h
  28. 0 715
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass.cpp
  29. 0 330
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass.h
  30. 0 192
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.cpp
  31. 0 41
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_access_chains.h
  32. 0 236
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_inserts.cpp
  33. 0 45
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_inserts.h
  34. 0 139
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.cpp
  35. 0 61
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_types.h
  36. 0 82
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_copy_memory.cpp
  37. 0 40
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_copy_memory.h
  38. 0 67
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.cpp
  39. 0 40
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.h
  40. 0 122
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.cpp
  41. 0 39
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.h
  42. 0 89
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.cpp
  43. 0 39
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.h
  44. 0 413
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
  45. 0 80
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_equation_instructions.h
  46. 0 199
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.cpp
  47. 0 50
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.h
  48. 0 95
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.cpp
  49. 0 40
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.h
  50. 0 200
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_image_sample_unused_components.cpp
  51. 0 41
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_image_sample_unused_components.h
  52. 0 96
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.cpp
  53. 0 39
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.h
  54. 0 80
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.cpp
  55. 0 40
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.h
  56. 0 66
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loop_preheaders.cpp
  57. 0 43
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loop_preheaders.h
  58. 0 57
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp
  59. 0 39
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_no_contraction_decorations.h
  60. 0 297
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp
  61. 0 73
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_opphi_synonyms.h
  62. 0 147
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_parameters.cpp
  63. 0 47
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_parameters.h
  64. 0 55
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_relaxed_decorations.cpp
  65. 0 39
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_relaxed_decorations.h
  66. 0 132
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.cpp
  67. 0 41
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.h
  68. 0 127
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_synonyms.cpp
  69. 0 40
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_synonyms.h
  70. 0 145
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp
  71. 0 39
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.h
  72. 0 48
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp
  73. 0 41
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_branch_weights.h
  74. 0 71
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
  75. 0 39
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_function_controls.h
  76. 0 118
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
  77. 0 39
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_loop_controls.h
  78. 0 109
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
  79. 0 40
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h
  80. 0 73
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
  81. 0 39
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_selection_controls.h
  82. 0 192
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
  83. 0 51
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.h
  84. 0 385
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_construct_composites.cpp
  85. 0 80
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_construct_composites.h
  86. 0 83
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_copy_objects.cpp
  87. 0 39
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_copy_objects.h
  88. 0 1258
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.cpp
  89. 0 170
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.h
  90. 0 104
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_inline_functions.cpp
  91. 0 41
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_inline_functions.h
  92. 0 156
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.cpp
  93. 0 51
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.h
  94. 0 116
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_interchange_zero_like_constants.cpp
  95. 0 53
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_interchange_zero_like_constants.h
  96. 0 52
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_invert_comparison_operators.cpp
  97. 0 40
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_invert_comparison_operators.h
  98. 0 71
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp
  99. 0 40
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.h
  100. 0 63
      3rdparty/spirv-tools/source/fuzz/fuzzer_pass_merge_blocks.cpp

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

@@ -1 +1 @@
-"v2020.5", "SPIRV-Tools v2020.5 e272a31e19b278158551bc64142947df09ede4ac"
+"v2020.5", "SPIRV-Tools v2020.5 86402fec24134b6d4103b6ad1e689fb5840f720f"

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

@@ -1,392 +0,0 @@
-# Copyright (c) 2019 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.
-
-if(SPIRV_BUILD_FUZZER)
-
-  file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/protobufs)
-
-  set(PROTOBUF_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/protobufs/spvtoolsfuzz.proto)
-
-  add_custom_command(
-        OUTPUT protobufs/spvtoolsfuzz.pb.cc protobufs/spvtoolsfuzz.pb.h
-        COMMAND protobuf::protoc
-        -I=${CMAKE_CURRENT_SOURCE_DIR}/protobufs
-        --cpp_out=protobufs
-        ${PROTOBUF_SOURCE}
-        DEPENDS ${PROTOBUF_SOURCE}
-        COMMENT "Generate protobuf sources from proto definition file."
-  )
-
-  set(SPIRV_TOOLS_FUZZ_SOURCES
-        call_graph.h
-        counter_overflow_id_source.h
-        data_descriptor.h
-        equivalence_relation.h
-        fact_manager/constant_uniform_facts.h
-        fact_manager/data_synonym_and_id_equation_facts.h
-        fact_manager/dead_block_facts.h
-        fact_manager/fact_manager.h
-        fact_manager/irrelevant_value_facts.h
-        fact_manager/livesafe_function_facts.h
-        force_render_red.h
-        fuzzer.h
-        fuzzer_context.h
-        fuzzer_pass.h
-        fuzzer_pass_add_access_chains.h
-        fuzzer_pass_add_composite_inserts.h
-        fuzzer_pass_add_composite_types.h
-        fuzzer_pass_add_copy_memory.h
-        fuzzer_pass_add_dead_blocks.h
-        fuzzer_pass_add_dead_breaks.h
-        fuzzer_pass_add_dead_continues.h
-        fuzzer_pass_add_equation_instructions.h
-        fuzzer_pass_add_function_calls.h
-        fuzzer_pass_add_global_variables.h
-        fuzzer_pass_add_image_sample_unused_components.h
-        fuzzer_pass_add_synonyms.h
-        fuzzer_pass_add_loads.h
-        fuzzer_pass_add_local_variables.h
-        fuzzer_pass_add_loop_preheaders.h
-        fuzzer_pass_add_no_contraction_decorations.h
-        fuzzer_pass_add_opphi_synonyms.h
-        fuzzer_pass_add_parameters.h
-        fuzzer_pass_add_relaxed_decorations.h
-        fuzzer_pass_add_stores.h
-        fuzzer_pass_add_vector_shuffle_instructions.h
-        fuzzer_pass_adjust_branch_weights.h
-        fuzzer_pass_adjust_function_controls.h
-        fuzzer_pass_adjust_loop_controls.h
-        fuzzer_pass_adjust_memory_operands_masks.h
-        fuzzer_pass_adjust_selection_controls.h
-        fuzzer_pass_apply_id_synonyms.h
-        fuzzer_pass_construct_composites.h
-        fuzzer_pass_copy_objects.h
-        fuzzer_pass_donate_modules.h
-        fuzzer_pass_inline_functions.h
-        fuzzer_pass_invert_comparison_operators.h
-        fuzzer_pass_interchange_signedness_of_integer_operands.h
-        fuzzer_pass_interchange_zero_like_constants.h
-        fuzzer_pass_make_vector_operations_dynamic.h
-        fuzzer_pass_merge_blocks.h
-        fuzzer_pass_obfuscate_constants.h
-        fuzzer_pass_outline_functions.h
-        fuzzer_pass_permute_blocks.h
-        fuzzer_pass_permute_function_parameters.h
-        fuzzer_pass_permute_instructions.h
-        fuzzer_pass_permute_phi_operands.h
-        fuzzer_pass_propagate_instructions_up.h
-        fuzzer_pass_push_ids_through_variables.h
-        fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.h
-        fuzzer_pass_replace_copy_memories_with_loads_stores.h
-        fuzzer_pass_replace_copy_objects_with_stores_loads.h
-        fuzzer_pass_replace_linear_algebra_instructions.h
-        fuzzer_pass_replace_loads_stores_with_copy_memories.h
-        fuzzer_pass_replace_parameter_with_global.h
-        fuzzer_pass_replace_params_with_struct.h
-        fuzzer_pass_split_blocks.h
-        fuzzer_pass_swap_commutable_operands.h
-        fuzzer_pass_swap_conditional_branch_operands.h
-        fuzzer_pass_toggle_access_chain_instruction.h
-        fuzzer_util.h
-        id_use_descriptor.h
-        instruction_descriptor.h
-        instruction_message.h
-        overflow_id_source.h
-        protobufs/spirvfuzz_protobufs.h
-        pseudo_random_generator.h
-        random_generator.h
-        replayer.h
-        shrinker.h
-        transformation.h
-        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_copy_memory.h
-        transformation_add_dead_block.h
-        transformation_add_dead_break.h
-        transformation_add_dead_continue.h
-        transformation_add_function.h
-        transformation_add_global_undef.h
-        transformation_add_global_variable.h
-        transformation_add_image_sample_unused_components.h
-        transformation_add_local_variable.h
-        transformation_add_loop_preheader.h
-        transformation_add_no_contraction_decoration.h
-        transformation_add_opphi_synonym.h
-        transformation_add_parameter.h
-        transformation_add_relaxed_decoration.h
-        transformation_add_spec_constant_op.h
-        transformation_add_synonym.h
-        transformation_add_type_array.h
-        transformation_add_type_boolean.h
-        transformation_add_type_float.h
-        transformation_add_type_function.h
-        transformation_add_type_int.h
-        transformation_add_type_matrix.h
-        transformation_add_type_pointer.h
-        transformation_add_type_struct.h
-        transformation_add_type_vector.h
-        transformation_adjust_branch_weights.h
-        transformation_composite_construct.h
-        transformation_composite_extract.h
-        transformation_composite_insert.h
-        transformation_compute_data_synonym_fact_closure.h
-        transformation_context.h
-        transformation_equation_instruction.h
-        transformation_function_call.h
-        transformation_inline_function.h
-        transformation_invert_comparison_operator.h
-        transformation_load.h
-        transformation_make_vector_operation_dynamic.h
-        transformation_merge_blocks.h
-        transformation_move_block_down.h
-        transformation_move_instruction_down.h
-        transformation_outline_function.h
-        transformation_permute_function_parameters.h
-        transformation_permute_phi_operands.h
-        transformation_propagate_instruction_up.h
-        transformation_push_id_through_variable.h
-        transformation_record_synonymous_constants.h
-        transformation_replace_add_sub_mul_with_carrying_extended.h
-        transformation_replace_boolean_constant_with_constant_binary.h
-        transformation_replace_constant_with_uniform.h
-        transformation_replace_copy_memory_with_load_store.h
-        transformation_replace_copy_object_with_store_load.h
-        transformation_replace_id_with_synonym.h
-        transformation_replace_linear_algebra_instruction.h
-        transformation_replace_load_store_with_copy_memory.h
-        transformation_replace_parameter_with_global.h
-        transformation_replace_params_with_struct.h
-        transformation_set_function_control.h
-        transformation_set_loop_control.h
-        transformation_set_memory_operands_mask.h
-        transformation_set_selection_control.h
-        transformation_split_block.h
-        transformation_store.h
-        transformation_swap_commutable_operands.h
-        transformation_swap_conditional_branch_operands.h
-        transformation_toggle_access_chain_instruction.h
-        transformation_vector_shuffle.h
-        uniform_buffer_element_descriptor.h
-        ${CMAKE_CURRENT_BINARY_DIR}/protobufs/spvtoolsfuzz.pb.h
-
-        call_graph.cpp
-        counter_overflow_id_source.cpp
-        data_descriptor.cpp
-        fact_manager/constant_uniform_facts.cpp
-        fact_manager/data_synonym_and_id_equation_facts.cpp
-        fact_manager/dead_block_facts.cpp
-        fact_manager/fact_manager.cpp
-        fact_manager/irrelevant_value_facts.cpp
-        fact_manager/livesafe_function_facts.cpp
-        force_render_red.cpp
-        fuzzer.cpp
-        fuzzer_context.cpp
-        fuzzer_pass.cpp
-        fuzzer_pass_add_access_chains.cpp
-        fuzzer_pass_add_composite_inserts.cpp
-        fuzzer_pass_add_composite_types.cpp
-        fuzzer_pass_add_copy_memory.cpp
-        fuzzer_pass_add_dead_blocks.cpp
-        fuzzer_pass_add_dead_breaks.cpp
-        fuzzer_pass_add_dead_continues.cpp
-        fuzzer_pass_add_equation_instructions.cpp
-        fuzzer_pass_add_function_calls.cpp
-        fuzzer_pass_add_global_variables.cpp
-        fuzzer_pass_add_image_sample_unused_components.cpp
-        fuzzer_pass_add_synonyms.cpp
-        fuzzer_pass_add_loads.cpp
-        fuzzer_pass_add_local_variables.cpp
-        fuzzer_pass_add_loop_preheaders.cpp
-        fuzzer_pass_add_no_contraction_decorations.cpp
-        fuzzer_pass_add_opphi_synonyms.cpp
-        fuzzer_pass_add_parameters.cpp
-        fuzzer_pass_add_relaxed_decorations.cpp
-        fuzzer_pass_add_stores.cpp
-        fuzzer_pass_add_vector_shuffle_instructions.cpp
-        fuzzer_pass_adjust_branch_weights.cpp
-        fuzzer_pass_adjust_function_controls.cpp
-        fuzzer_pass_adjust_loop_controls.cpp
-        fuzzer_pass_adjust_memory_operands_masks.cpp
-        fuzzer_pass_adjust_selection_controls.cpp
-        fuzzer_pass_apply_id_synonyms.cpp
-        fuzzer_pass_construct_composites.cpp
-        fuzzer_pass_copy_objects.cpp
-        fuzzer_pass_donate_modules.cpp
-        fuzzer_pass_inline_functions.cpp
-        fuzzer_pass_invert_comparison_operators.cpp
-        fuzzer_pass_interchange_signedness_of_integer_operands.cpp
-        fuzzer_pass_interchange_zero_like_constants.cpp
-        fuzzer_pass_make_vector_operations_dynamic.cpp
-        fuzzer_pass_merge_blocks.cpp
-        fuzzer_pass_obfuscate_constants.cpp
-        fuzzer_pass_outline_functions.cpp
-        fuzzer_pass_permute_blocks.cpp
-        fuzzer_pass_permute_function_parameters.cpp
-        fuzzer_pass_permute_instructions.cpp
-        fuzzer_pass_permute_phi_operands.cpp
-        fuzzer_pass_propagate_instructions_up.cpp
-        fuzzer_pass_push_ids_through_variables.cpp
-        fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.cpp
-        fuzzer_pass_replace_copy_memories_with_loads_stores.cpp
-        fuzzer_pass_replace_copy_objects_with_stores_loads.cpp
-        fuzzer_pass_replace_linear_algebra_instructions.cpp
-        fuzzer_pass_replace_loads_stores_with_copy_memories.cpp
-        fuzzer_pass_replace_parameter_with_global.cpp
-        fuzzer_pass_replace_params_with_struct.cpp
-        fuzzer_pass_split_blocks.cpp
-        fuzzer_pass_swap_commutable_operands.cpp
-        fuzzer_pass_swap_conditional_branch_operands.cpp
-        fuzzer_pass_toggle_access_chain_instruction.cpp
-        fuzzer_util.cpp
-        id_use_descriptor.cpp
-        instruction_descriptor.cpp
-        instruction_message.cpp
-        overflow_id_source.cpp
-        pseudo_random_generator.cpp
-        random_generator.cpp
-        replayer.cpp
-        shrinker.cpp
-        transformation.cpp
-        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_copy_memory.cpp
-        transformation_add_dead_block.cpp
-        transformation_add_dead_break.cpp
-        transformation_add_dead_continue.cpp
-        transformation_add_function.cpp
-        transformation_add_global_undef.cpp
-        transformation_add_global_variable.cpp
-        transformation_add_image_sample_unused_components.cpp
-        transformation_add_local_variable.cpp
-        transformation_add_loop_preheader.cpp
-        transformation_add_no_contraction_decoration.cpp
-        transformation_add_opphi_synonym.cpp
-        transformation_add_parameter.cpp
-        transformation_add_relaxed_decoration.cpp
-        transformation_add_spec_constant_op.cpp
-        transformation_add_synonym.cpp
-        transformation_add_type_array.cpp
-        transformation_add_type_boolean.cpp
-        transformation_add_type_float.cpp
-        transformation_add_type_function.cpp
-        transformation_add_type_int.cpp
-        transformation_add_type_matrix.cpp
-        transformation_add_type_pointer.cpp
-        transformation_add_type_struct.cpp
-        transformation_add_type_vector.cpp
-        transformation_adjust_branch_weights.cpp
-        transformation_composite_construct.cpp
-        transformation_composite_extract.cpp
-        transformation_composite_insert.cpp
-        transformation_compute_data_synonym_fact_closure.cpp
-        transformation_context.cpp
-        transformation_equation_instruction.cpp
-        transformation_function_call.cpp
-        transformation_inline_function.cpp
-        transformation_invert_comparison_operator.cpp
-        transformation_load.cpp
-        transformation_make_vector_operation_dynamic.cpp
-        transformation_merge_blocks.cpp
-        transformation_move_block_down.cpp
-        transformation_move_instruction_down.cpp
-        transformation_outline_function.cpp
-        transformation_permute_function_parameters.cpp
-        transformation_permute_phi_operands.cpp
-        transformation_propagate_instruction_up.cpp
-        transformation_push_id_through_variable.cpp
-        transformation_record_synonymous_constants.cpp
-        transformation_replace_add_sub_mul_with_carrying_extended.cpp
-        transformation_replace_boolean_constant_with_constant_binary.cpp
-        transformation_replace_constant_with_uniform.cpp
-        transformation_replace_copy_memory_with_load_store.cpp
-        transformation_replace_copy_object_with_store_load.cpp
-        transformation_replace_id_with_synonym.cpp
-        transformation_replace_linear_algebra_instruction.cpp
-        transformation_replace_load_store_with_copy_memory.cpp
-        transformation_replace_parameter_with_global.cpp
-        transformation_replace_params_with_struct.cpp
-        transformation_set_function_control.cpp
-        transformation_set_loop_control.cpp
-        transformation_set_memory_operands_mask.cpp
-        transformation_set_selection_control.cpp
-        transformation_split_block.cpp
-        transformation_store.cpp
-        transformation_swap_commutable_operands.cpp
-        transformation_swap_conditional_branch_operands.cpp
-        transformation_toggle_access_chain_instruction.cpp
-        transformation_vector_shuffle.cpp
-        uniform_buffer_element_descriptor.cpp
-        ${CMAKE_CURRENT_BINARY_DIR}/protobufs/spvtoolsfuzz.pb.cc
-        )
-
-  if(MSVC AND (NOT ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")))
-    # Enable parallel builds across four cores for this lib
-    add_definitions(/MP4)
-  endif()
-
-  spvtools_pch(SPIRV_TOOLS_FUZZ_SOURCES pch_source_fuzz)
-
-  add_library(SPIRV-Tools-fuzz ${SPIRV_TOOLS_FUZZ_SOURCES})
-
-  spvtools_default_compile_options(SPIRV-Tools-fuzz)
-  target_compile_definitions(SPIRV-Tools-fuzz PUBLIC -DGOOGLE_PROTOBUF_NO_RTTI -DGOOGLE_PROTOBUF_USE_UNALIGNED=0)
-
-  # Compilation of the auto-generated protobuf source file will yield warnings,
-  # which we have no control over and thus wish to ignore.
-  if(${COMPILER_IS_LIKE_GNU})
-    set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/protobufs/spvtoolsfuzz.pb.cc PROPERTIES COMPILE_FLAGS -w)
-  endif()
-  if(MSVC)
-    set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/protobufs/spvtoolsfuzz.pb.cc PROPERTIES COMPILE_FLAGS /w)
-  endif()
-
-  target_include_directories(SPIRV-Tools-fuzz
-		PUBLIC
-			$<BUILD_INTERFACE:${spirv-tools_SOURCE_DIR}/include>
-			$<BUILD_INTERFACE:${SPIRV_HEADER_INCLUDE_DIR}>
-			$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
-        PRIVATE ${spirv-tools_BINARY_DIR}
-        PRIVATE ${CMAKE_BINARY_DIR})
-
-  # The fuzzer reuses a lot of functionality from the SPIRV-Tools library.
-  target_link_libraries(SPIRV-Tools-fuzz
-        PUBLIC ${SPIRV_TOOLS}-static
-        PUBLIC SPIRV-Tools-opt
-        PUBLIC protobuf::libprotobuf)
-
-  set_property(TARGET SPIRV-Tools-fuzz PROPERTY FOLDER "SPIRV-Tools libraries")
-  spvtools_check_symbol_exports(SPIRV-Tools-fuzz)
-
-  if(ENABLE_SPIRV_TOOLS_INSTALL)
-      install(TARGETS SPIRV-Tools-fuzz EXPORT SPIRV-Tools-fuzzTargets
-            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
-      export(EXPORT SPIRV-Tools-fuzzTargets FILE SPIRV-Tools-fuzzTarget.cmake)
-
-      spvtools_config_package_dir(SPIRV-Tools-fuzz PACKAGE_DIR)
-      install(EXPORT SPIRV-Tools-fuzzTargets FILE SPIRV-Tools-fuzzTarget.cmake
-            DESTINATION ${PACKAGE_DIR})
-
-      spvtools_generate_config_file(SPIRV-Tools-fuzz)
-      install(FILES ${CMAKE_BINARY_DIR}/SPIRV-Tools-fuzzConfig.cmake DESTINATION ${PACKAGE_DIR})
-  endif(ENABLE_SPIRV_TOOLS_INSTALL)
-
-endif(SPIRV_BUILD_FUZZER)

+ 0 - 81
3rdparty/spirv-tools/source/fuzz/call_graph.cpp

@@ -1,81 +0,0 @@
-// 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/call_graph.h"
-
-#include <queue>
-
-namespace spvtools {
-namespace fuzz {
-
-CallGraph::CallGraph(opt::IRContext* context) {
-  // Initialize function in-degree and call graph edges to 0 and empty.
-  for (auto& function : *context->module()) {
-    function_in_degree_[function.result_id()] = 0;
-    call_graph_edges_[function.result_id()] = std::set<uint32_t>();
-  }
-
-  // Consider every function.
-  for (auto& function : *context->module()) {
-    // Avoid considering the same callee of this function multiple times by
-    // recording known callees.
-    std::set<uint32_t> known_callees;
-    // Consider every function call instruction in every block.
-    for (auto& block : function) {
-      for (auto& instruction : block) {
-        if (instruction.opcode() != SpvOpFunctionCall) {
-          continue;
-        }
-        // Get the id of the function being called.
-        uint32_t callee = instruction.GetSingleWordInOperand(0);
-        if (known_callees.count(callee)) {
-          // We have already considered a call to this function - ignore it.
-          continue;
-        }
-        // Increase the callee's in-degree and add an edge to the call graph.
-        function_in_degree_[callee]++;
-        call_graph_edges_[function.result_id()].insert(callee);
-        // Mark the callee as 'known'.
-        known_callees.insert(callee);
-      }
-    }
-  }
-}
-
-void CallGraph::PushDirectCallees(uint32_t function_id,
-                                  std::queue<uint32_t>* queue) const {
-  for (auto callee : GetDirectCallees(function_id)) {
-    queue->push(callee);
-  }
-}
-
-std::set<uint32_t> CallGraph::GetIndirectCallees(uint32_t function_id) const {
-  std::set<uint32_t> result;
-  std::queue<uint32_t> queue;
-  PushDirectCallees(function_id, &queue);
-
-  while (!queue.empty()) {
-    auto next = queue.front();
-    queue.pop();
-    if (result.count(next)) {
-      continue;
-    }
-    result.insert(next);
-    PushDirectCallees(next, &queue);
-  }
-  return result;
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 62
3rdparty/spirv-tools/source/fuzz/call_graph.h

@@ -1,62 +0,0 @@
-// 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_CALL_GRAPH_H_
-#define SOURCE_FUZZ_CALL_GRAPH_H_
-
-#include <map>
-#include <set>
-
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Represents the acyclic call graph of a SPIR-V module.
-class CallGraph {
- public:
-  // Creates a call graph corresponding to the given SPIR-V module.
-  explicit CallGraph(opt::IRContext* context);
-
-  // Returns a mapping from each function to its number of distinct callers.
-  const std::map<uint32_t, uint32_t>& GetFunctionInDegree() const {
-    return function_in_degree_;
-  }
-
-  // Returns the ids of the functions that |function_id| directly invokes.
-  const std::set<uint32_t>& GetDirectCallees(uint32_t function_id) const {
-    return call_graph_edges_.at(function_id);
-  }
-
-  // Returns the ids of the functions that |function_id| directly or indirectly
-  // invokes.
-  std::set<uint32_t> GetIndirectCallees(uint32_t function_id) const;
-
- private:
-  // Pushes the direct callees of |function_id| on to |queue|.
-  void PushDirectCallees(uint32_t function_id,
-                         std::queue<uint32_t>* queue) const;
-
-  // Maps each function id to the ids of its immediate callees.
-  std::map<uint32_t, std::set<uint32_t>> call_graph_edges_;
-
-  // For each function id, stores the number of distinct functions that call
-  // the function.
-  std::map<uint32_t, uint32_t> function_in_degree_;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_CALL_GRAPH_H_

+ 0 - 30
3rdparty/spirv-tools/source/fuzz/counter_overflow_id_source.cpp

@@ -1,30 +0,0 @@
-// 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/counter_overflow_id_source.h"
-
-namespace spvtools {
-namespace fuzz {
-
-CounterOverflowIdSource::CounterOverflowIdSource(uint32_t first_available_id)
-    : next_available_id_(first_available_id) {}
-
-bool CounterOverflowIdSource::HasOverflowIds() const { return true; }
-
-uint32_t CounterOverflowIdSource::GetNextOverflowId() {
-  return next_available_id_++;
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 45
3rdparty/spirv-tools/source/fuzz/counter_overflow_id_source.h

@@ -1,45 +0,0 @@
-// 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_COUNTER_OVERFLOW_ID_SOURCE_H_
-#define SOURCE_FUZZ_COUNTER_OVERFLOW_ID_SOURCE_H_
-
-#include "source/fuzz/overflow_id_source.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A source of overflow ids that uses a counter to provide successive ids from
-// a given starting value.
-class CounterOverflowIdSource : public OverflowIdSource {
- public:
-  // |first_available_id| is the starting value for the counter.
-  explicit CounterOverflowIdSource(uint32_t first_available_id);
-
-  // Always returns true.
-  bool HasOverflowIds() const override;
-
-  // Returns the current counter value and increments the counter.
-  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2541) We should
-  //  account for the case where the maximum allowed id is reached.
-  uint32_t GetNextOverflowId() override;
-
- private:
-  uint32_t next_available_id_;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_OVERFLOW_ID_SOURCE_COUNTER_H_

+ 0 - 69
3rdparty/spirv-tools/source/fuzz/data_descriptor.cpp

@@ -1,69 +0,0 @@
-// Copyright (c) 2019 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/data_descriptor.h"
-
-#include <algorithm>
-
-namespace spvtools {
-namespace fuzz {
-
-protobufs::DataDescriptor MakeDataDescriptor(uint32_t object,
-                                             std::vector<uint32_t>&& indices) {
-  protobufs::DataDescriptor result;
-  result.set_object(object);
-  for (auto index : indices) {
-    result.add_index(index);
-  }
-  return result;
-}
-
-size_t DataDescriptorHash::operator()(
-    const protobufs::DataDescriptor* data_descriptor) const {
-  std::u32string hash;
-  hash.push_back(data_descriptor->object());
-  for (auto an_index : data_descriptor->index()) {
-    hash.push_back(an_index);
-  }
-  return std::hash<std::u32string>()(hash);
-}
-
-bool DataDescriptorEquals::operator()(
-    const protobufs::DataDescriptor* first,
-    const protobufs::DataDescriptor* second) const {
-  return first->object() == second->object() &&
-         first->index().size() == second->index().size() &&
-         std::equal(first->index().begin(), first->index().end(),
-                    second->index().begin());
-}
-
-std::ostream& operator<<(std::ostream& out,
-                         const protobufs::DataDescriptor& data_descriptor) {
-  out << data_descriptor.object();
-  out << "[";
-  bool first = true;
-  for (auto index : data_descriptor.index()) {
-    if (first) {
-      first = false;
-    } else {
-      out << ", ";
-    }
-    out << index;
-  }
-  out << "]";
-  return out;
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 48
3rdparty/spirv-tools/source/fuzz/data_descriptor.h

@@ -1,48 +0,0 @@
-// Copyright (c) 2019 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_DATA_DESCRIPTOR_H_
-#define SOURCE_FUZZ_DATA_DESCRIPTOR_H_
-
-#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
-
-#include <ostream>
-#include <vector>
-
-namespace spvtools {
-namespace fuzz {
-
-// Factory method to create a data descriptor message from an object id and a
-// list of indices.
-protobufs::DataDescriptor MakeDataDescriptor(uint32_t object,
-                                             std::vector<uint32_t>&& indices);
-
-// Hash function for data descriptors.
-struct DataDescriptorHash {
-  size_t operator()(const protobufs::DataDescriptor* data_descriptor) const;
-};
-
-// Equality function for data descriptors.
-struct DataDescriptorEquals {
-  bool operator()(const protobufs::DataDescriptor* first,
-                  const protobufs::DataDescriptor* second) const;
-};
-
-std::ostream& operator<<(std::ostream& out,
-                         const protobufs::DataDescriptor& data_descriptor);
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_DATA_DESCRIPTOR_H_

+ 0 - 245
3rdparty/spirv-tools/source/fuzz/equivalence_relation.h

@@ -1,245 +0,0 @@
-// Copyright (c) 2019 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_EQUIVALENCE_RELATION_H_
-#define SOURCE_FUZZ_EQUIVALENCE_RELATION_H_
-
-#include <memory>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include "source/util/make_unique.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A class for representing an equivalence relation on objects of type |T|,
-// which should be a value type.  The type |T| is required to have a copy
-// constructor, and |PointerHashT| and |PointerEqualsT| must be functors
-// providing hashing and equality testing functionality for pointers to objects
-// of type |T|.
-//
-// A disjoint-set (a.k.a. union-find or merge-find) data structure is used to
-// represent the equivalence relation.  Path compression is used.  Union by
-// rank/size is not used.
-//
-// Each disjoint set is represented as a tree, rooted at the representative
-// of the set.
-//
-// Getting the representative of a value simply requires chasing parent pointers
-// from the value until you reach the root.
-//
-// Checking equivalence of two elements requires checking that the
-// representatives are equal.
-//
-// Traversing the tree rooted at a value's representative visits the value's
-// equivalence class.
-//
-// |PointerHashT| and |PointerEqualsT| are used to define *equality* between
-// values, and otherwise are *not* used to define the equivalence relation
-// (except that equal values are equivalent).  The equivalence relation is
-// constructed by repeatedly adding pairs of (typically non-equal) values that
-// are deemed to be equivalent.
-//
-// For example in an equivalence relation on integers, 1 and 5 might be added
-// as equivalent, so that IsEquivalent(1, 5) holds, because they represent
-// IDs in a SPIR-V binary that are known to contain the same value at run time,
-// but clearly 1 != 5.  Since 1 and 1 are equal, IsEquivalent(1, 1) will also
-// hold.
-//
-// Each unique (up to equality) value added to the relation is copied into
-// |owned_values_|, so there is one canonical memory address per unique value.
-// Uniqueness is ensured by storing (and checking) a set of pointers to these
-// values in |value_set_|, which uses |PointerHashT| and |PointerEqualsT|.
-//
-// |parent_| and |children_| encode the equivalence relation, i.e., the trees.
-template <typename T, typename PointerHashT, typename PointerEqualsT>
-class EquivalenceRelation {
- public:
-  // Requires that |value1| and |value2| are already registered in the
-  // equivalence relation.  Merges the equivalence classes associated with
-  // |value1| and |value2|.
-  void MakeEquivalent(const T& value1, const T& value2) {
-    assert(Exists(value1) &&
-           "Precondition: value1 must already be registered.");
-    assert(Exists(value2) &&
-           "Precondition: value2 must already be registered.");
-
-    // Look up canonical pointers to each of the values in the value pool.
-    const T* value1_ptr = *value_set_.find(&value1);
-    const T* value2_ptr = *value_set_.find(&value2);
-
-    // If the values turn out to be identical, they are already in the same
-    // equivalence class so there is nothing to do.
-    if (value1_ptr == value2_ptr) {
-      return;
-    }
-
-    // Find the representative for each value's equivalence class, and if they
-    // are not already in the same class, make one the parent of the other.
-    const T* representative1 = Find(value1_ptr);
-    const T* representative2 = Find(value2_ptr);
-    assert(representative1 && "Representatives should never be null.");
-    assert(representative2 && "Representatives should never be null.");
-    if (representative1 != representative2) {
-      parent_[representative1] = representative2;
-      children_[representative2].push_back(representative1);
-    }
-  }
-
-  // Requires that |value| is not known to the equivalence relation. Registers
-  // it in its own equivalence class and returns a pointer to the equivalence
-  // class representative.
-  const T* Register(const T& value) {
-    assert(!Exists(value));
-
-    // This relies on T having a copy constructor.
-    auto unique_pointer_to_value = MakeUnique<T>(value);
-    auto pointer_to_value = unique_pointer_to_value.get();
-    owned_values_.push_back(std::move(unique_pointer_to_value));
-    value_set_.insert(pointer_to_value);
-
-    // Initially say that the value is its own parent and that it has no
-    // children.
-    assert(pointer_to_value && "Representatives should never be null.");
-    parent_[pointer_to_value] = pointer_to_value;
-    children_[pointer_to_value] = std::vector<const T*>();
-
-    return pointer_to_value;
-  }
-
-  // Returns exactly one representative per equivalence class.
-  std::vector<const T*> GetEquivalenceClassRepresentatives() const {
-    std::vector<const T*> result;
-    for (auto& value : owned_values_) {
-      if (parent_[value.get()] == value.get()) {
-        result.push_back(value.get());
-      }
-    }
-    return result;
-  }
-
-  // Returns pointers to all values in the equivalence class of |value|, which
-  // must already be part of the equivalence relation.
-  std::vector<const T*> GetEquivalenceClass(const T& value) const {
-    assert(Exists(value));
-
-    std::vector<const T*> result;
-
-    // Traverse the tree of values rooted at the representative of the
-    // equivalence class to which |value| belongs, and collect up all the values
-    // that are encountered.  This constitutes the whole equivalence class.
-    std::vector<const T*> stack;
-    stack.push_back(Find(*value_set_.find(&value)));
-    while (!stack.empty()) {
-      const T* item = stack.back();
-      result.push_back(item);
-      stack.pop_back();
-      for (auto child : children_[item]) {
-        stack.push_back(child);
-      }
-    }
-    return result;
-  }
-
-  // Returns true if and only if |value1| and |value2| are in the same
-  // equivalence class.  Both values must already be known to the equivalence
-  // relation.
-  bool IsEquivalent(const T& value1, const T& value2) const {
-    return Find(&value1) == Find(&value2);
-  }
-
-  // Returns all values known to be part of the equivalence relation.
-  std::vector<const T*> GetAllKnownValues() const {
-    std::vector<const T*> result;
-    for (auto& value : owned_values_) {
-      result.push_back(value.get());
-    }
-    return result;
-  }
-
-  // Returns true if and only if |value| is known to be part of the equivalence
-  // relation.
-  bool Exists(const T& value) const {
-    return value_set_.find(&value) != value_set_.end();
-  }
-
-  // Returns the representative of the equivalence class of |value|, which must
-  // already be known to the equivalence relation.  This is the 'Find' operation
-  // in a classic union-find data structure.
-  const T* Find(const T* value) const {
-    assert(Exists(*value));
-
-    // Get the canonical pointer to the value from the value pool.
-    const T* known_value = *value_set_.find(value);
-    assert(parent_[known_value] && "Every known value should have a parent.");
-
-    // Compute the result by chasing parents until we find a value that is its
-    // own parent.
-    const T* result = known_value;
-    while (parent_[result] != result) {
-      result = parent_[result];
-    }
-    assert(result && "Representatives should never be null.");
-
-    // At this point, |result| is the representative of the equivalence class.
-    // Now perform the 'path compression' optimization by doing another pass up
-    // the parent chain, setting the parent of each node to be the
-    // representative, and rewriting children correspondingly.
-    const T* current = known_value;
-    while (parent_[current] != result) {
-      const T* next = parent_[current];
-      parent_[current] = result;
-      children_[result].push_back(current);
-      auto child_iterator =
-          std::find(children_[next].begin(), children_[next].end(), current);
-      assert(child_iterator != children_[next].end() &&
-             "'next' is the parent of 'current', so 'current' should be a "
-             "child of 'next'");
-      children_[next].erase(child_iterator);
-      current = next;
-    }
-    return result;
-  }
-
- private:
-  // Maps every value to a parent.  The representative of an equivalence class
-  // is its own parent.  A value's representative can be found by walking its
-  // chain of ancestors.
-  //
-  // Mutable because the intuitively const method, 'Find', performs path
-  // compression.
-  mutable std::unordered_map<const T*, const T*> parent_;
-
-  // Stores the children of each value.  This allows the equivalence class of
-  // a value to be calculated by traversing all descendents of the class's
-  // representative.
-  //
-  // Mutable because the intuitively const method, 'Find', performs path
-  // compression.
-  mutable std::unordered_map<const T*, std::vector<const T*>> children_;
-
-  // The values known to the equivalence relation are allocated in
-  // |owned_values_|, and |value_pool_| provides (via |PointerHashT| and
-  // |PointerEqualsT|) a means for mapping a value of interest to a pointer
-  // into an equivalent value in |owned_values_|.
-  std::unordered_set<const T*, PointerHashT, PointerEqualsT> value_set_;
-  std::vector<std::unique_ptr<T>> owned_values_;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_EQUIVALENCE_RELATION_H_

+ 0 - 235
3rdparty/spirv-tools/source/fuzz/fact_manager/constant_uniform_facts.cpp

@@ -1,235 +0,0 @@
-// Copyright (c) 2019 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/fact_manager/constant_uniform_facts.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/uniform_buffer_element_descriptor.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace fact_manager {
-
-uint32_t ConstantUniformFacts::GetConstantId(
-    opt::IRContext* context,
-    const protobufs::FactConstantUniform& constant_uniform_fact,
-    uint32_t type_id) {
-  auto type = context->get_type_mgr()->GetType(type_id);
-  assert(type != nullptr && "Unknown type id.");
-  const opt::analysis::Constant* known_constant;
-  if (type->AsInteger()) {
-    opt::analysis::IntConstant candidate_constant(
-        type->AsInteger(), GetConstantWords(constant_uniform_fact));
-    known_constant =
-        context->get_constant_mgr()->FindConstant(&candidate_constant);
-  } else {
-    assert(
-        type->AsFloat() &&
-        "Uniform constant facts are only supported for int and float types.");
-    opt::analysis::FloatConstant candidate_constant(
-        type->AsFloat(), GetConstantWords(constant_uniform_fact));
-    known_constant =
-        context->get_constant_mgr()->FindConstant(&candidate_constant);
-  }
-  if (!known_constant) {
-    return 0;
-  }
-  return context->get_constant_mgr()->FindDeclaredConstant(known_constant,
-                                                           type_id);
-}
-
-std::vector<uint32_t> ConstantUniformFacts::GetConstantWords(
-    const protobufs::FactConstantUniform& constant_uniform_fact) {
-  std::vector<uint32_t> result;
-  for (auto constant_word : constant_uniform_fact.constant_word()) {
-    result.push_back(constant_word);
-  }
-  return result;
-}
-
-bool ConstantUniformFacts::DataMatches(
-    const opt::Instruction& constant_instruction,
-    const protobufs::FactConstantUniform& constant_uniform_fact) {
-  assert(constant_instruction.opcode() == SpvOpConstant);
-  std::vector<uint32_t> data_in_constant;
-  for (uint32_t i = 0; i < constant_instruction.NumInOperands(); i++) {
-    data_in_constant.push_back(constant_instruction.GetSingleWordInOperand(i));
-  }
-  return data_in_constant == GetConstantWords(constant_uniform_fact);
-}
-
-std::vector<uint32_t>
-ConstantUniformFacts::GetConstantsAvailableFromUniformsForType(
-    opt::IRContext* ir_context, uint32_t type_id) const {
-  std::vector<uint32_t> result;
-  std::set<uint32_t> already_seen;
-  for (auto& fact_and_type_id : facts_and_type_ids_) {
-    if (fact_and_type_id.second != type_id) {
-      continue;
-    }
-    if (auto constant_id =
-            GetConstantId(ir_context, fact_and_type_id.first, type_id)) {
-      if (already_seen.find(constant_id) == already_seen.end()) {
-        result.push_back(constant_id);
-        already_seen.insert(constant_id);
-      }
-    }
-  }
-  return result;
-}
-
-std::vector<protobufs::UniformBufferElementDescriptor>
-ConstantUniformFacts::GetUniformDescriptorsForConstant(
-    opt::IRContext* ir_context, uint32_t constant_id) const {
-  std::vector<protobufs::UniformBufferElementDescriptor> result;
-  auto constant_inst = ir_context->get_def_use_mgr()->GetDef(constant_id);
-  assert(constant_inst->opcode() == SpvOpConstant &&
-         "The given id must be that of a constant");
-  auto type_id = constant_inst->type_id();
-  for (auto& fact_and_type_id : facts_and_type_ids_) {
-    if (fact_and_type_id.second != type_id) {
-      continue;
-    }
-    if (DataMatches(*constant_inst, fact_and_type_id.first)) {
-      result.emplace_back(
-          fact_and_type_id.first.uniform_buffer_element_descriptor());
-    }
-  }
-  return result;
-}
-
-uint32_t ConstantUniformFacts::GetConstantFromUniformDescriptor(
-    opt::IRContext* context,
-    const protobufs::UniformBufferElementDescriptor& uniform_descriptor) const {
-  // Consider each fact.
-  for (auto& fact_and_type : facts_and_type_ids_) {
-    // Check whether the uniform descriptor associated with the fact matches
-    // |uniform_descriptor|.
-    if (UniformBufferElementDescriptorEquals()(
-            &uniform_descriptor,
-            &fact_and_type.first.uniform_buffer_element_descriptor())) {
-      return GetConstantId(context, fact_and_type.first, fact_and_type.second);
-    }
-  }
-  // No fact associated with the given uniform descriptor was found.
-  return 0;
-}
-
-std::vector<uint32_t>
-ConstantUniformFacts::GetTypesForWhichUniformValuesAreKnown() const {
-  std::vector<uint32_t> result;
-  for (auto& fact_and_type : facts_and_type_ids_) {
-    if (std::find(result.begin(), result.end(), fact_and_type.second) ==
-        result.end()) {
-      result.push_back(fact_and_type.second);
-    }
-  }
-  return result;
-}
-
-bool ConstantUniformFacts::FloatingPointValueIsSuitable(
-    const protobufs::FactConstantUniform& fact, uint32_t width) {
-  const uint32_t kFloatWidth = 32;
-  const uint32_t kDoubleWidth = 64;
-  if (width != kFloatWidth && width != kDoubleWidth) {
-    // Only 32- and 64-bit floating-point types are handled.
-    return false;
-  }
-  std::vector<uint32_t> words = GetConstantWords(fact);
-  if (width == 32) {
-    float value;
-    memcpy(&value, words.data(), sizeof(float));
-    if (!std::isfinite(value)) {
-      return false;
-    }
-  } else {
-    double value;
-    memcpy(&value, words.data(), sizeof(double));
-    if (!std::isfinite(value)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-bool ConstantUniformFacts::AddFact(const protobufs::FactConstantUniform& fact,
-                                   opt::IRContext* context) {
-  // Try to find a unique instruction that declares a variable such that the
-  // variable is decorated with the descriptor set and binding associated with
-  // the constant uniform fact.
-  opt::Instruction* uniform_variable = FindUniformVariable(
-      fact.uniform_buffer_element_descriptor(), context, true);
-
-  if (!uniform_variable) {
-    return false;
-  }
-
-  assert(SpvOpVariable == uniform_variable->opcode());
-  assert(SpvStorageClassUniform == uniform_variable->GetSingleWordInOperand(0));
-
-  auto should_be_uniform_pointer_type =
-      context->get_type_mgr()->GetType(uniform_variable->type_id());
-  if (!should_be_uniform_pointer_type->AsPointer()) {
-    return false;
-  }
-  if (should_be_uniform_pointer_type->AsPointer()->storage_class() !=
-      SpvStorageClassUniform) {
-    return false;
-  }
-  auto should_be_uniform_pointer_instruction =
-      context->get_def_use_mgr()->GetDef(uniform_variable->type_id());
-  auto composite_type =
-      should_be_uniform_pointer_instruction->GetSingleWordInOperand(1);
-
-  auto final_element_type_id = fuzzerutil::WalkCompositeTypeIndices(
-      context, composite_type,
-      fact.uniform_buffer_element_descriptor().index());
-  if (!final_element_type_id) {
-    return false;
-  }
-  auto final_element_type =
-      context->get_type_mgr()->GetType(final_element_type_id);
-  assert(final_element_type &&
-         "There should be a type corresponding to this id.");
-
-  if (!(final_element_type->AsFloat() || final_element_type->AsInteger())) {
-    return false;
-  }
-  auto width = final_element_type->AsFloat()
-                   ? final_element_type->AsFloat()->width()
-                   : final_element_type->AsInteger()->width();
-
-  if (final_element_type->AsFloat() &&
-      !FloatingPointValueIsSuitable(fact, width)) {
-    return false;
-  }
-
-  auto required_words = (width + 32 - 1) / 32;
-  if (static_cast<uint32_t>(fact.constant_word().size()) != required_words) {
-    return false;
-  }
-  facts_and_type_ids_.emplace_back(
-      std::pair<protobufs::FactConstantUniform, uint32_t>(
-          fact, final_element_type_id));
-  return true;
-}
-
-const std::vector<std::pair<protobufs::FactConstantUniform, uint32_t>>&
-ConstantUniformFacts::GetConstantUniformFactsAndTypes() const {
-  return facts_and_type_ids_;
-}
-
-}  // namespace fact_manager
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 90
3rdparty/spirv-tools/source/fuzz/fact_manager/constant_uniform_facts.h

@@ -1,90 +0,0 @@
-// Copyright (c) 2019 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_FACT_MANAGER_CONSTANT_UNIFORM_FACTS_H_
-#define SOURCE_FUZZ_FACT_MANAGER_CONSTANT_UNIFORM_FACTS_H_
-
-#include <vector>
-
-#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace fact_manager {
-
-// The purpose of this class is to group the fields and data used to represent
-// facts about uniform constants.
-class ConstantUniformFacts {
- public:
-  // See method in FactManager which delegates to this method.
-  bool AddFact(const protobufs::FactConstantUniform& fact,
-               opt::IRContext* context);
-
-  // See method in FactManager which delegates to this method.
-  std::vector<uint32_t> GetConstantsAvailableFromUniformsForType(
-      opt::IRContext* ir_context, uint32_t type_id) const;
-
-  // See method in FactManager which delegates to this method.
-  std::vector<protobufs::UniformBufferElementDescriptor>
-  GetUniformDescriptorsForConstant(opt::IRContext* ir_context,
-                                   uint32_t constant_id) const;
-
-  // See method in FactManager which delegates to this method.
-  uint32_t GetConstantFromUniformDescriptor(
-      opt::IRContext* context,
-      const protobufs::UniformBufferElementDescriptor& uniform_descriptor)
-      const;
-
-  // See method in FactManager which delegates to this method.
-  std::vector<uint32_t> GetTypesForWhichUniformValuesAreKnown() const;
-
-  // See method in FactManager which delegates to this method.
-  const std::vector<std::pair<protobufs::FactConstantUniform, uint32_t>>&
-  GetConstantUniformFactsAndTypes() const;
-
- private:
-  // Returns true if and only if the words associated with
-  // |constant_instruction| exactly match the words for the constant associated
-  // with |constant_uniform_fact|.
-  static bool DataMatches(
-      const opt::Instruction& constant_instruction,
-      const protobufs::FactConstantUniform& constant_uniform_fact);
-
-  // Yields the constant words associated with |constant_uniform_fact|.
-  static std::vector<uint32_t> GetConstantWords(
-      const protobufs::FactConstantUniform& constant_uniform_fact);
-
-  // Yields the id of a constant of type |type_id| whose data matches the
-  // constant data in |constant_uniform_fact|, or 0 if no such constant is
-  // declared.
-  static uint32_t GetConstantId(
-      opt::IRContext* context,
-      const protobufs::FactConstantUniform& constant_uniform_fact,
-      uint32_t type_id);
-
-  // Checks that the width of a floating-point constant is supported, and that
-  // the constant is finite.
-  static bool FloatingPointValueIsSuitable(
-      const protobufs::FactConstantUniform& fact, uint32_t width);
-
-  std::vector<std::pair<protobufs::FactConstantUniform, uint32_t>>
-      facts_and_type_ids_;
-};
-
-}  // namespace fact_manager
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FACT_MANAGER_CONSTANT_UNIFORM_FACTS_H_

+ 0 - 861
3rdparty/spirv-tools/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.cpp

@@ -1,861 +0,0 @@
-// Copyright (c) 2019 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/fact_manager/data_synonym_and_id_equation_facts.h"
-
-#include "source/fuzz/fuzzer_util.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace fact_manager {
-
-size_t DataSynonymAndIdEquationFacts::OperationHash::operator()(
-    const Operation& operation) const {
-  std::u32string hash;
-  hash.push_back(operation.opcode);
-  for (auto operand : operation.operands) {
-    hash.push_back(static_cast<uint32_t>(DataDescriptorHash()(operand)));
-  }
-  return std::hash<std::u32string>()(hash);
-}
-
-bool DataSynonymAndIdEquationFacts::OperationEquals::operator()(
-    const Operation& first, const Operation& second) const {
-  // Equal operations require...
-  //
-  // Equal opcodes.
-  if (first.opcode != second.opcode) {
-    return false;
-  }
-  // Matching operand counts.
-  if (first.operands.size() != second.operands.size()) {
-    return false;
-  }
-  // Equal operands.
-  for (uint32_t i = 0; i < first.operands.size(); i++) {
-    if (!DataDescriptorEquals()(first.operands[i], second.operands[i])) {
-      return false;
-    }
-  }
-  return true;
-}
-
-void DataSynonymAndIdEquationFacts::AddFact(
-    const protobufs::FactDataSynonym& fact, opt::IRContext* context) {
-  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3550)
-  //  Assert that ids are not irrelevant.
-
-  // Add the fact, including all facts relating sub-components of the data
-  // descriptors that are involved.
-  AddDataSynonymFactRecursive(fact.data1(), fact.data2(), context);
-}
-
-void DataSynonymAndIdEquationFacts::AddFact(
-    const protobufs::FactIdEquation& fact, opt::IRContext* context) {
-  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3550)
-  //  Assert that ids are not irrelevant.
-
-  protobufs::DataDescriptor lhs_dd = MakeDataDescriptor(fact.lhs_id(), {});
-
-  // Register the LHS in the equivalence relation if needed.
-  RegisterDataDescriptor(lhs_dd);
-
-  // Get equivalence class representatives for all ids used on the RHS of the
-  // equation.
-  std::vector<const protobufs::DataDescriptor*> rhs_dds;
-  for (auto rhs_id : fact.rhs_id()) {
-    // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3550)
-    //  Assert that ids are not irrelevant.
-
-    // Register a data descriptor based on this id in the equivalence relation
-    // if needed, and then record the equivalence class representative.
-    rhs_dds.push_back(RegisterDataDescriptor(MakeDataDescriptor(rhs_id, {})));
-  }
-
-  // Now add the fact.
-  AddEquationFactRecursive(lhs_dd, static_cast<SpvOp>(fact.opcode()), rhs_dds,
-                           context);
-}
-
-DataSynonymAndIdEquationFacts::OperationSet
-DataSynonymAndIdEquationFacts::GetEquations(
-    const protobufs::DataDescriptor* lhs) const {
-  auto existing = id_equations_.find(lhs);
-  if (existing == id_equations_.end()) {
-    return OperationSet();
-  }
-  return existing->second;
-}
-
-void DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
-    const protobufs::DataDescriptor& lhs_dd, SpvOp opcode,
-    const std::vector<const protobufs::DataDescriptor*>& rhs_dds,
-    opt::IRContext* context) {
-  assert(synonymous_.Exists(lhs_dd) &&
-         "The LHS must be known to the equivalence relation.");
-  for (auto rhs_dd : rhs_dds) {
-    // Keep release compilers happy.
-    (void)(rhs_dd);
-    assert(synonymous_.Exists(*rhs_dd) &&
-           "The RHS operands must be known to the equivalence relation.");
-  }
-
-  auto lhs_dd_representative = synonymous_.Find(&lhs_dd);
-
-  if (id_equations_.count(lhs_dd_representative) == 0) {
-    // We have not seen an equation with this LHS before, so associate the LHS
-    // with an initially empty set.
-    id_equations_.insert({lhs_dd_representative, OperationSet()});
-  }
-
-  {
-    auto existing_equations = id_equations_.find(lhs_dd_representative);
-    assert(existing_equations != id_equations_.end() &&
-           "A set of operations should be present, even if empty.");
-
-    Operation new_operation = {opcode, rhs_dds};
-    if (existing_equations->second.count(new_operation)) {
-      // This equation is known, so there is nothing further to be done.
-      return;
-    }
-    // Add the equation to the set of known equations.
-    existing_equations->second.insert(new_operation);
-  }
-
-  // Now try to work out corollaries implied by the new equation and existing
-  // facts.
-  switch (opcode) {
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-      ComputeConversionDataSynonymFacts(*rhs_dds[0], context);
-      break;
-    case SpvOpBitcast: {
-      assert(DataDescriptorsAreWellFormedAndComparable(context, lhs_dd,
-                                                       *rhs_dds[0]) &&
-             "Operands of OpBitcast equation fact must have compatible types");
-      if (!synonymous_.IsEquivalent(lhs_dd, *rhs_dds[0])) {
-        AddDataSynonymFactRecursive(lhs_dd, *rhs_dds[0], context);
-      }
-    } break;
-    case SpvOpIAdd: {
-      // Equation form: "a = b + c"
-      for (const auto& equation : GetEquations(rhs_dds[0])) {
-        if (equation.opcode == SpvOpISub) {
-          // Equation form: "a = (d - e) + c"
-          if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[1])) {
-            // Equation form: "a = (d - c) + c"
-            // We can thus infer "a = d"
-            AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], context);
-          }
-          if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
-            // Equation form: "a = (c - e) + c"
-            // We can thus infer "a = -e"
-            AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
-                                     {equation.operands[1]}, context);
-          }
-        }
-      }
-      for (const auto& equation : GetEquations(rhs_dds[1])) {
-        if (equation.opcode == SpvOpISub) {
-          // Equation form: "a = b + (d - e)"
-          if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[0])) {
-            // Equation form: "a = b + (d - b)"
-            // We can thus infer "a = d"
-            AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], context);
-          }
-        }
-      }
-      break;
-    }
-    case SpvOpISub: {
-      // Equation form: "a = b - c"
-      for (const auto& equation : GetEquations(rhs_dds[0])) {
-        if (equation.opcode == SpvOpIAdd) {
-          // Equation form: "a = (d + e) - c"
-          if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
-            // Equation form: "a = (c + e) - c"
-            // We can thus infer "a = e"
-            AddDataSynonymFactRecursive(lhs_dd, *equation.operands[1], context);
-          }
-          if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[1])) {
-            // Equation form: "a = (d + c) - c"
-            // We can thus infer "a = d"
-            AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], context);
-          }
-        }
-
-        if (equation.opcode == SpvOpISub) {
-          // Equation form: "a = (d - e) - c"
-          if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
-            // Equation form: "a = (c - e) - c"
-            // We can thus infer "a = -e"
-            AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
-                                     {equation.operands[1]}, context);
-          }
-        }
-      }
-
-      for (const auto& equation : GetEquations(rhs_dds[1])) {
-        if (equation.opcode == SpvOpIAdd) {
-          // Equation form: "a = b - (d + e)"
-          if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[0])) {
-            // Equation form: "a = b - (b + e)"
-            // We can thus infer "a = -e"
-            AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
-                                     {equation.operands[1]}, context);
-          }
-          if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[0])) {
-            // Equation form: "a = b - (d + b)"
-            // We can thus infer "a = -d"
-            AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
-                                     {equation.operands[0]}, context);
-          }
-        }
-        if (equation.opcode == SpvOpISub) {
-          // Equation form: "a = b - (d - e)"
-          if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[0])) {
-            // Equation form: "a = b - (b - e)"
-            // We can thus infer "a = e"
-            AddDataSynonymFactRecursive(lhs_dd, *equation.operands[1], context);
-          }
-        }
-      }
-      break;
-    }
-    case SpvOpLogicalNot:
-    case SpvOpSNegate: {
-      // Equation form: "a = !b" or "a = -b"
-      for (const auto& equation : GetEquations(rhs_dds[0])) {
-        if (equation.opcode == opcode) {
-          // Equation form: "a = !!b" or "a = -(-b)"
-          // We can thus infer "a = b"
-          AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], context);
-        }
-      }
-      break;
-    }
-    default:
-      break;
-  }
-}
-
-void DataSynonymAndIdEquationFacts::AddDataSynonymFactRecursive(
-    const protobufs::DataDescriptor& dd1, const protobufs::DataDescriptor& dd2,
-    opt::IRContext* context) {
-  assert(DataDescriptorsAreWellFormedAndComparable(context, dd1, dd2));
-
-  // Record that the data descriptors provided in the fact are equivalent.
-  MakeEquivalent(dd1, dd2);
-  assert(synonymous_.Find(&dd1) == synonymous_.Find(&dd2) &&
-         "|dd1| and |dd2| must have a single representative");
-
-  // Compute various corollary facts.
-
-  // |dd1| and |dd2| belong to the same equivalence class so it doesn't matter
-  // which one we use here.
-  ComputeConversionDataSynonymFacts(dd1, context);
-
-  ComputeCompositeDataSynonymFacts(dd1, dd2, context);
-}
-
-void DataSynonymAndIdEquationFacts::ComputeConversionDataSynonymFacts(
-    const protobufs::DataDescriptor& dd, opt::IRContext* context) {
-  assert(synonymous_.Exists(dd) &&
-         "|dd| should've been registered in the equivalence relation");
-
-  const auto* representative = synonymous_.Find(&dd);
-  assert(representative &&
-         "Representative can't be null for a registered descriptor");
-
-  const auto* type =
-      context->get_type_mgr()->GetType(fuzzerutil::WalkCompositeTypeIndices(
-          context, fuzzerutil::GetTypeId(context, representative->object()),
-          representative->index()));
-  assert(type && "Data descriptor has invalid type");
-
-  if ((type->AsVector() && type->AsVector()->element_type()->AsInteger()) ||
-      type->AsInteger()) {
-    // If there exist equation facts of the form |%a = opcode %representative|
-    // and |%b = opcode %representative| where |opcode| is either OpConvertSToF
-    // or OpConvertUToF, then |a| and |b| are synonymous.
-    std::vector<const protobufs::DataDescriptor*> convert_s_to_f_lhs;
-    std::vector<const protobufs::DataDescriptor*> convert_u_to_f_lhs;
-
-    for (const auto& fact : id_equations_) {
-      for (const auto& equation : fact.second) {
-        if (synonymous_.IsEquivalent(*equation.operands[0], *representative)) {
-          if (equation.opcode == SpvOpConvertSToF) {
-            convert_s_to_f_lhs.push_back(fact.first);
-          } else if (equation.opcode == SpvOpConvertUToF) {
-            convert_u_to_f_lhs.push_back(fact.first);
-          }
-        }
-      }
-    }
-
-    for (const auto& synonyms :
-         {std::move(convert_s_to_f_lhs), std::move(convert_u_to_f_lhs)}) {
-      for (const auto* synonym_a : synonyms) {
-        for (const auto* synonym_b : synonyms) {
-          if (!synonymous_.IsEquivalent(*synonym_a, *synonym_b) &&
-              DataDescriptorsAreWellFormedAndComparable(context, *synonym_a,
-                                                        *synonym_b)) {
-            // |synonym_a| and |synonym_b| have compatible types - they are
-            // synonymous.
-            AddDataSynonymFactRecursive(*synonym_a, *synonym_b, context);
-          }
-        }
-      }
-    }
-  }
-}
-
-void DataSynonymAndIdEquationFacts::ComputeCompositeDataSynonymFacts(
-    const protobufs::DataDescriptor& dd1, const protobufs::DataDescriptor& dd2,
-    opt::IRContext* context) {
-  // Check whether this is a synonym about composite objects. If it is,
-  // we can recursively add synonym facts about their associated sub-components.
-
-  // Get the type of the object referred to by the first data descriptor in the
-  // synonym fact.
-  uint32_t type_id = fuzzerutil::WalkCompositeTypeIndices(
-      context, context->get_def_use_mgr()->GetDef(dd1.object())->type_id(),
-      dd1.index());
-  auto type = context->get_type_mgr()->GetType(type_id);
-  auto type_instruction = context->get_def_use_mgr()->GetDef(type_id);
-  assert(type != nullptr &&
-         "Invalid data synonym fact: one side has an unknown type.");
-
-  // Check whether the type is composite, recording the number of elements
-  // associated with the composite if so.
-  uint32_t num_composite_elements;
-  if (type->AsArray()) {
-    num_composite_elements =
-        fuzzerutil::GetArraySize(*type_instruction, context);
-  } else if (type->AsMatrix()) {
-    num_composite_elements = type->AsMatrix()->element_count();
-  } else if (type->AsStruct()) {
-    num_composite_elements =
-        fuzzerutil::GetNumberOfStructMembers(*type_instruction);
-  } else if (type->AsVector()) {
-    num_composite_elements = type->AsVector()->element_count();
-  } else {
-    // The type is not a composite, so return.
-    return;
-  }
-
-  // If the fact has the form:
-  //   obj_1[a_1, ..., a_m] == obj_2[b_1, ..., b_n]
-  // then for each composite index i, we add a fact of the form:
-  //   obj_1[a_1, ..., a_m, i] == obj_2[b_1, ..., b_n, i]
-  //
-  // However, to avoid adding a large number of synonym facts e.g. in the case
-  // of arrays, we bound the number of composite elements to which this is
-  // applied.  Nevertheless, we always add a synonym fact for the final
-  // components, as this may be an interesting edge case.
-
-  // The bound on the number of indices of the composite pair to note as being
-  // synonymous.
-  const uint32_t kCompositeElementBound = 10;
-
-  for (uint32_t i = 0; i < num_composite_elements;) {
-    std::vector<uint32_t> extended_indices1 =
-        fuzzerutil::RepeatedFieldToVector(dd1.index());
-    extended_indices1.push_back(i);
-    std::vector<uint32_t> extended_indices2 =
-        fuzzerutil::RepeatedFieldToVector(dd2.index());
-    extended_indices2.push_back(i);
-    AddDataSynonymFactRecursive(
-        MakeDataDescriptor(dd1.object(), std::move(extended_indices1)),
-        MakeDataDescriptor(dd2.object(), std::move(extended_indices2)),
-        context);
-
-    if (i < kCompositeElementBound - 1 || i == num_composite_elements - 1) {
-      // We have not reached the bound yet, or have already skipped ahead to the
-      // last element, so increment the loop counter as standard.
-      i++;
-    } else {
-      // We have reached the bound, so skip ahead to the last element.
-      assert(i == kCompositeElementBound - 1);
-      i = num_composite_elements - 1;
-    }
-  }
-}
-
-void DataSynonymAndIdEquationFacts::ComputeClosureOfFacts(
-    opt::IRContext* context, uint32_t maximum_equivalence_class_size) {
-  // Suppose that obj_1[a_1, ..., a_m] and obj_2[b_1, ..., b_n] are distinct
-  // data descriptors that describe objects of the same composite type, and that
-  // the composite type is comprised of k components.
-  //
-  // For example, if m is a mat4x4 and v a vec4, we might consider:
-  //   m[2]: describes the 2nd column of m, a vec4
-  //   v[]: describes all of v, a vec4
-  //
-  // Suppose that we know, for every 0 <= i < k, that the fact:
-  //   obj_1[a_1, ..., a_m, i] == obj_2[b_1, ..., b_n, i]
-  // holds - i.e. that the children of the two data descriptors are synonymous.
-  //
-  // Then we can conclude that:
-  //   obj_1[a_1, ..., a_m] == obj_2[b_1, ..., b_n]
-  // holds.
-  //
-  // For instance, if we have the facts:
-  //   m[2, 0] == v[0]
-  //   m[2, 1] == v[1]
-  //   m[2, 2] == v[2]
-  //   m[2, 3] == v[3]
-  // then we can conclude that:
-  //   m[2] == v.
-  //
-  // This method repeatedly searches the equivalence relation of data
-  // descriptors, deducing and adding such facts, until a pass over the
-  // relation leads to no further facts being deduced.
-
-  // The method relies on working with pairs of data descriptors, and in
-  // particular being able to hash and compare such pairs.
-
-  using DataDescriptorPair =
-      std::pair<protobufs::DataDescriptor, protobufs::DataDescriptor>;
-
-  struct DataDescriptorPairHash {
-    std::size_t operator()(const DataDescriptorPair& pair) const {
-      return DataDescriptorHash()(&pair.first) ^
-             DataDescriptorHash()(&pair.second);
-    }
-  };
-
-  struct DataDescriptorPairEquals {
-    bool operator()(const DataDescriptorPair& first,
-                    const DataDescriptorPair& second) const {
-      return (DataDescriptorEquals()(&first.first, &second.first) &&
-              DataDescriptorEquals()(&first.second, &second.second)) ||
-             (DataDescriptorEquals()(&first.first, &second.second) &&
-              DataDescriptorEquals()(&first.second, &second.first));
-    }
-  };
-
-  // This map records, for a given pair of composite data descriptors of the
-  // same type, all the indices at which the data descriptors are known to be
-  // synonymous.  A pair is a key to this map only if we have observed that
-  // the pair are synonymous at *some* index, but not at *all* indices.
-  // Once we find that a pair of data descriptors are equivalent at all indices
-  // we record the fact that they are synonymous and remove them from the map.
-  //
-  // Using the m and v example from above, initially the pair (m[2], v) would
-  // not be a key to the map.  If we find that m[2, 2] == v[2] holds, we would
-  // add an entry:
-  //   (m[2], v) -> [false, false, true, false]
-  // to record that they are synonymous at index 2.  If we then find that
-  // m[2, 0] == v[0] holds, we would update this entry to:
-  //   (m[2], v) -> [true, false, true, false]
-  // If we then find that m[2, 3] == v[3] holds, we would update this entry to:
-  //   (m[2], v) -> [true, false, true, true]
-  // Finally, if we then find that m[2, 1] == v[1] holds, which would make the
-  // boolean vector true at every index, we would add the fact:
-  //   m[2] == v
-  // to the equivalence relation and remove (m[2], v) from the map.
-  std::unordered_map<DataDescriptorPair, std::vector<bool>,
-                     DataDescriptorPairHash, DataDescriptorPairEquals>
-      candidate_composite_synonyms;
-
-  // We keep looking for new facts until we perform a complete pass over the
-  // equivalence relation without finding any new facts.
-  while (closure_computation_required_) {
-    // We have not found any new facts yet during this pass; we set this to
-    // 'true' if we do find a new fact.
-    closure_computation_required_ = false;
-
-    // Consider each class in the equivalence relation.
-    for (auto representative :
-         synonymous_.GetEquivalenceClassRepresentatives()) {
-      auto equivalence_class = synonymous_.GetEquivalenceClass(*representative);
-
-      if (equivalence_class.size() > maximum_equivalence_class_size) {
-        // This equivalence class is larger than the maximum size we are willing
-        // to consider, so we skip it.  This potentially leads to missed fact
-        // deductions, but avoids excessive runtime for closure computation.
-        continue;
-      }
-
-      // Consider every data descriptor in the equivalence class.
-      for (auto dd1_it = equivalence_class.begin();
-           dd1_it != equivalence_class.end(); ++dd1_it) {
-        // If this data descriptor has no indices then it does not have the form
-        // obj_1[a_1, ..., a_m, i], so move on.
-        auto dd1 = *dd1_it;
-        if (dd1->index_size() == 0) {
-          continue;
-        }
-
-        // Consider every other data descriptor later in the equivalence class
-        // (due to symmetry, there is no need to compare with previous data
-        // descriptors).
-        auto dd2_it = dd1_it;
-        for (++dd2_it; dd2_it != equivalence_class.end(); ++dd2_it) {
-          auto dd2 = *dd2_it;
-          // If this data descriptor has no indices then it does not have the
-          // form obj_2[b_1, ..., b_n, i], so move on.
-          if (dd2->index_size() == 0) {
-            continue;
-          }
-
-          // At this point we know that:
-          // - |dd1| has the form obj_1[a_1, ..., a_m, i]
-          // - |dd2| has the form obj_2[b_1, ..., b_n, j]
-          assert(dd1->index_size() > 0 && dd2->index_size() > 0 &&
-                 "Control should not reach here if either data descriptor has "
-                 "no indices.");
-
-          // We are only interested if i == j.
-          if (dd1->index(dd1->index_size() - 1) !=
-              dd2->index(dd2->index_size() - 1)) {
-            continue;
-          }
-
-          const uint32_t common_final_index = dd1->index(dd1->index_size() - 1);
-
-          // Make data descriptors |dd1_prefix| and |dd2_prefix| for
-          //   obj_1[a_1, ..., a_m]
-          // and
-          //   obj_2[b_1, ..., b_n]
-          // These are the two data descriptors we might be getting closer to
-          // deducing as being synonymous, due to knowing that they are
-          // synonymous when extended by a particular index.
-          protobufs::DataDescriptor dd1_prefix;
-          dd1_prefix.set_object(dd1->object());
-          for (uint32_t i = 0; i < static_cast<uint32_t>(dd1->index_size() - 1);
-               i++) {
-            dd1_prefix.add_index(dd1->index(i));
-          }
-          protobufs::DataDescriptor dd2_prefix;
-          dd2_prefix.set_object(dd2->object());
-          for (uint32_t i = 0; i < static_cast<uint32_t>(dd2->index_size() - 1);
-               i++) {
-            dd2_prefix.add_index(dd2->index(i));
-          }
-          assert(!DataDescriptorEquals()(&dd1_prefix, &dd2_prefix) &&
-                 "By construction these prefixes should be different.");
-
-          // If we already know that these prefixes are synonymous, move on.
-          if (synonymous_.Exists(dd1_prefix) &&
-              synonymous_.Exists(dd2_prefix) &&
-              synonymous_.IsEquivalent(dd1_prefix, dd2_prefix)) {
-            continue;
-          }
-
-          // Get the type of obj_1
-          auto dd1_root_type_id =
-              context->get_def_use_mgr()->GetDef(dd1->object())->type_id();
-          // Use this type, together with a_1, ..., a_m, to get the type of
-          // obj_1[a_1, ..., a_m].
-          auto dd1_prefix_type = fuzzerutil::WalkCompositeTypeIndices(
-              context, dd1_root_type_id, dd1_prefix.index());
-
-          // Similarly, get the type of obj_2 and use it to get the type of
-          // obj_2[b_1, ..., b_n].
-          auto dd2_root_type_id =
-              context->get_def_use_mgr()->GetDef(dd2->object())->type_id();
-          auto dd2_prefix_type = fuzzerutil::WalkCompositeTypeIndices(
-              context, dd2_root_type_id, dd2_prefix.index());
-
-          // If the types of dd1_prefix and dd2_prefix are not the same, they
-          // cannot be synonymous.
-          if (dd1_prefix_type != dd2_prefix_type) {
-            continue;
-          }
-
-          // At this point, we know we have synonymous data descriptors of the
-          // form:
-          //   obj_1[a_1, ..., a_m, i]
-          //   obj_2[b_1, ..., b_n, i]
-          // with the same last_index i, such that:
-          //   obj_1[a_1, ..., a_m]
-          // and
-          //   obj_2[b_1, ..., b_n]
-          // have the same type.
-
-          // Work out how many components there are in the (common) commposite
-          // type associated with obj_1[a_1, ..., a_m] and obj_2[b_1, ..., b_n].
-          // This depends on whether the composite type is array, matrix, struct
-          // or vector.
-          uint32_t num_components_in_composite;
-          auto composite_type =
-              context->get_type_mgr()->GetType(dd1_prefix_type);
-          auto composite_type_instruction =
-              context->get_def_use_mgr()->GetDef(dd1_prefix_type);
-          if (composite_type->AsArray()) {
-            num_components_in_composite =
-                fuzzerutil::GetArraySize(*composite_type_instruction, context);
-            if (num_components_in_composite == 0) {
-              // This indicates that the array has an unknown size, in which
-              // case we cannot be sure we have matched all of its elements with
-              // synonymous elements of another array.
-              continue;
-            }
-          } else if (composite_type->AsMatrix()) {
-            num_components_in_composite =
-                composite_type->AsMatrix()->element_count();
-          } else if (composite_type->AsStruct()) {
-            num_components_in_composite = fuzzerutil::GetNumberOfStructMembers(
-                *composite_type_instruction);
-          } else {
-            assert(composite_type->AsVector());
-            num_components_in_composite =
-                composite_type->AsVector()->element_count();
-          }
-
-          // We are one step closer to being able to say that |dd1_prefix| and
-          // |dd2_prefix| are synonymous.
-          DataDescriptorPair candidate_composite_synonym(dd1_prefix,
-                                                         dd2_prefix);
-
-          // We look up what we already know about this pair.
-          auto existing_entry =
-              candidate_composite_synonyms.find(candidate_composite_synonym);
-
-          if (existing_entry == candidate_composite_synonyms.end()) {
-            // If this is the first time we have seen the pair, we make a vector
-            // of size |num_components_in_composite| that is 'true' at the
-            // common final index associated with |dd1| and |dd2|, and 'false'
-            // everywhere else, and register this vector as being associated
-            // with the pair.
-            std::vector<bool> entry;
-            for (uint32_t i = 0; i < num_components_in_composite; i++) {
-              entry.push_back(i == common_final_index);
-            }
-            candidate_composite_synonyms[candidate_composite_synonym] = entry;
-            existing_entry =
-                candidate_composite_synonyms.find(candidate_composite_synonym);
-          } else {
-            // We have seen this pair of data descriptors before, and we now
-            // know that they are synonymous at one further index, so we
-            // update the entry to record that.
-            existing_entry->second[common_final_index] = true;
-          }
-          assert(existing_entry != candidate_composite_synonyms.end());
-
-          // Check whether |dd1_prefix| and |dd2_prefix| are now known to match
-          // at every sub-component.
-          bool all_components_match = true;
-          for (uint32_t i = 0; i < num_components_in_composite; i++) {
-            if (!existing_entry->second[i]) {
-              all_components_match = false;
-              break;
-            }
-          }
-          if (all_components_match) {
-            // The two prefixes match on all sub-components, so we know that
-            // they are synonymous.  We add this fact *non-recursively*, as we
-            // have deduced that |dd1_prefix| and |dd2_prefix| are synonymous
-            // by observing that all their sub-components are already
-            // synonymous.
-            assert(DataDescriptorsAreWellFormedAndComparable(
-                context, dd1_prefix, dd2_prefix));
-            MakeEquivalent(dd1_prefix, dd2_prefix);
-            // Now that we know this pair of data descriptors are synonymous,
-            // there is no point recording how close they are to being
-            // synonymous.
-            candidate_composite_synonyms.erase(candidate_composite_synonym);
-          }
-        }
-      }
-    }
-  }
-}
-
-void DataSynonymAndIdEquationFacts::MakeEquivalent(
-    const protobufs::DataDescriptor& dd1,
-    const protobufs::DataDescriptor& dd2) {
-  // Register the data descriptors if they are not already known to the
-  // equivalence relation.
-  RegisterDataDescriptor(dd1);
-  RegisterDataDescriptor(dd2);
-
-  if (synonymous_.IsEquivalent(dd1, dd2)) {
-    // The data descriptors are already known to be equivalent, so there is
-    // nothing to do.
-    return;
-  }
-
-  // We must make the data descriptors equivalent, and also make sure any
-  // equation facts known about their representatives are merged.
-
-  // Record the original equivalence class representatives of the data
-  // descriptors.
-  auto dd1_original_representative = synonymous_.Find(&dd1);
-  auto dd2_original_representative = synonymous_.Find(&dd2);
-
-  // Make the data descriptors equivalent.
-  synonymous_.MakeEquivalent(dd1, dd2);
-  // As we have updated the equivalence relation, we might be able to deduce
-  // more facts by performing a closure computation, so we record that such a
-  // computation is required.
-  closure_computation_required_ = true;
-
-  // At this point, exactly one of |dd1_original_representative| and
-  // |dd2_original_representative| will be the representative of the combined
-  // equivalence class.  We work out which one of them is still the class
-  // representative and which one is no longer the class representative.
-
-  auto still_representative = synonymous_.Find(dd1_original_representative) ==
-                                      dd1_original_representative
-                                  ? dd1_original_representative
-                                  : dd2_original_representative;
-  auto no_longer_representative =
-      still_representative == dd1_original_representative
-          ? dd2_original_representative
-          : dd1_original_representative;
-
-  assert(no_longer_representative != still_representative &&
-         "The current and former representatives cannot be the same.");
-
-  // We now need to add all equations about |no_longer_representative| to the
-  // set of equations known about |still_representative|.
-
-  // Get the equations associated with |no_longer_representative|.
-  auto no_longer_representative_id_equations =
-      id_equations_.find(no_longer_representative);
-  if (no_longer_representative_id_equations != id_equations_.end()) {
-    // There are some equations to transfer.  There might not yet be any
-    // equations about |still_representative|; create an empty set of equations
-    // if this is the case.
-    if (!id_equations_.count(still_representative)) {
-      id_equations_.insert({still_representative, OperationSet()});
-    }
-    auto still_representative_id_equations =
-        id_equations_.find(still_representative);
-    assert(still_representative_id_equations != id_equations_.end() &&
-           "At this point there must be a set of equations.");
-    // Add all the equations known about |no_longer_representative| to the set
-    // of equations known about |still_representative|.
-    still_representative_id_equations->second.insert(
-        no_longer_representative_id_equations->second.begin(),
-        no_longer_representative_id_equations->second.end());
-  }
-  // Delete the no longer-relevant equations about |no_longer_representative|.
-  id_equations_.erase(no_longer_representative);
-}
-
-const protobufs::DataDescriptor*
-DataSynonymAndIdEquationFacts::RegisterDataDescriptor(
-    const protobufs::DataDescriptor& dd) {
-  return synonymous_.Exists(dd) ? synonymous_.Find(&dd)
-                                : synonymous_.Register(dd);
-}
-
-bool DataSynonymAndIdEquationFacts::DataDescriptorsAreWellFormedAndComparable(
-    opt::IRContext* context, const protobufs::DataDescriptor& dd1,
-    const protobufs::DataDescriptor& dd2) {
-  auto end_type_id_1 = fuzzerutil::WalkCompositeTypeIndices(
-      context, context->get_def_use_mgr()->GetDef(dd1.object())->type_id(),
-      dd1.index());
-  auto end_type_id_2 = fuzzerutil::WalkCompositeTypeIndices(
-      context, context->get_def_use_mgr()->GetDef(dd2.object())->type_id(),
-      dd2.index());
-  // The end types of the data descriptors must exist.
-  if (end_type_id_1 == 0 || end_type_id_2 == 0) {
-    return false;
-  }
-  // Neither end type is allowed to be void.
-  if (context->get_def_use_mgr()->GetDef(end_type_id_1)->opcode() ==
-          SpvOpTypeVoid ||
-      context->get_def_use_mgr()->GetDef(end_type_id_2)->opcode() ==
-          SpvOpTypeVoid) {
-    return false;
-  }
-  // If the end types are the same, the data descriptors are comparable.
-  if (end_type_id_1 == end_type_id_2) {
-    return true;
-  }
-  // Otherwise they are only comparable if they are integer scalars or integer
-  // vectors that differ only in signedness.
-
-  // Get both types.
-  const auto* type_a = context->get_type_mgr()->GetType(end_type_id_1);
-  const auto* type_b = context->get_type_mgr()->GetType(end_type_id_2);
-  assert(type_a && type_b && "Data descriptors have invalid type(s)");
-
-  // If both types are numerical or vectors of numerical components, then they
-  // are compatible if they have the same number of components and the same bit
-  // count per component.
-
-  if (type_a->AsVector() && type_b->AsVector()) {
-    const auto* vector_a = type_a->AsVector();
-    const auto* vector_b = type_b->AsVector();
-
-    if (vector_a->element_count() != vector_b->element_count() ||
-        vector_a->element_type()->AsBool() ||
-        vector_b->element_type()->AsBool()) {
-      // The case where both vectors have boolean elements and the same number
-      // of components is handled by the direct equality check earlier.
-      // You can't have multiple identical boolean vector types.
-      return false;
-    }
-
-    type_a = vector_a->element_type();
-    type_b = vector_b->element_type();
-  }
-
-  auto get_bit_count_for_numeric_type =
-      [](const opt::analysis::Type& type) -> uint32_t {
-    if (const auto* integer = type.AsInteger()) {
-      return integer->width();
-    } else if (const auto* floating = type.AsFloat()) {
-      return floating->width();
-    } else {
-      assert(false && "|type| must be a numerical type");
-      return 0;
-    }
-  };
-
-  // Checks that both |type_a| and |type_b| are either numerical or vectors of
-  // numerical components and have the same number of bits.
-  return (type_a->AsInteger() || type_a->AsFloat()) &&
-         (type_b->AsInteger() || type_b->AsFloat()) &&
-         (get_bit_count_for_numeric_type(*type_a) ==
-          get_bit_count_for_numeric_type(*type_b));
-}
-
-std::vector<const protobufs::DataDescriptor*>
-DataSynonymAndIdEquationFacts::GetSynonymsForDataDescriptor(
-    const protobufs::DataDescriptor& data_descriptor) const {
-  if (synonymous_.Exists(data_descriptor)) {
-    return synonymous_.GetEquivalenceClass(data_descriptor);
-  }
-  return {};
-}
-
-std::vector<uint32_t>
-DataSynonymAndIdEquationFacts::GetIdsForWhichSynonymsAreKnown() const {
-  std::vector<uint32_t> result;
-  for (auto& data_descriptor : synonymous_.GetAllKnownValues()) {
-    if (data_descriptor->index().empty()) {
-      result.push_back(data_descriptor->object());
-    }
-  }
-  return result;
-}
-
-bool DataSynonymAndIdEquationFacts::IsSynonymous(
-    const protobufs::DataDescriptor& data_descriptor1,
-    const protobufs::DataDescriptor& data_descriptor2) const {
-  return synonymous_.Exists(data_descriptor1) &&
-         synonymous_.Exists(data_descriptor2) &&
-         synonymous_.IsEquivalent(data_descriptor1, data_descriptor2);
-}
-
-}  // namespace fact_manager
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 156
3rdparty/spirv-tools/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.h

@@ -1,156 +0,0 @@
-// Copyright (c) 2019 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_FACT_MANAGER_DATA_SYNONYM_AND_ID_EQUATION_FACTS_H_
-#define SOURCE_FUZZ_FACT_MANAGER_DATA_SYNONYM_AND_ID_EQUATION_FACTS_H_
-
-#include <unordered_set>
-#include <vector>
-
-#include "source/fuzz/data_descriptor.h"
-#include "source/fuzz/equivalence_relation.h"
-#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace fact_manager {
-
-// The purpose of this class is to group the fields and data used to represent
-// facts about data synonyms and id equations.
-class DataSynonymAndIdEquationFacts {
- public:
-  // See method in FactManager which delegates to this method.
-  void AddFact(const protobufs::FactDataSynonym& fact, opt::IRContext* context);
-
-  // See method in FactManager which delegates to this method.
-  void AddFact(const protobufs::FactIdEquation& fact, opt::IRContext* context);
-
-  // See method in FactManager which delegates to this method.
-  std::vector<const protobufs::DataDescriptor*> GetSynonymsForDataDescriptor(
-      const protobufs::DataDescriptor& data_descriptor) const;
-
-  // See method in FactManager which delegates to this method.
-  std::vector<uint32_t> GetIdsForWhichSynonymsAreKnown() const;
-
-  // See method in FactManager which delegates to this method.
-  bool IsSynonymous(const protobufs::DataDescriptor& data_descriptor1,
-                    const protobufs::DataDescriptor& data_descriptor2) const;
-
-  // See method in FactManager which delegates to this method.
-  void ComputeClosureOfFacts(opt::IRContext* context,
-                             uint32_t maximum_equivalence_class_size);
-
- private:
-  // This helper struct represents the right hand side of an equation as an
-  // operator applied to a number of data descriptor operands.
-  struct Operation {
-    SpvOp opcode;
-    std::vector<const protobufs::DataDescriptor*> operands;
-  };
-
-  // Hashing for operations, to allow deterministic unordered sets.
-  struct OperationHash {
-    size_t operator()(const Operation& operation) const;
-  };
-
-  // Equality for operations, to allow deterministic unordered sets.
-  struct OperationEquals {
-    bool operator()(const Operation& first, const Operation& second) const;
-  };
-
-  using OperationSet =
-      std::unordered_set<Operation, OperationHash, OperationEquals>;
-
-  // Adds the synonym |dd1| = |dd2| to the set of managed facts, and recurses
-  // into sub-components of the data descriptors, if they are composites, to
-  // record that their components are pairwise-synonymous.
-  void AddDataSynonymFactRecursive(const protobufs::DataDescriptor& dd1,
-                                   const protobufs::DataDescriptor& dd2,
-                                   opt::IRContext* context);
-
-  // Computes various corollary facts from the data descriptor |dd| if members
-  // of its equivalence class participate in equation facts with OpConvert*
-  // opcodes. The descriptor should be registered in the equivalence relation.
-  void ComputeConversionDataSynonymFacts(const protobufs::DataDescriptor& dd,
-                                         opt::IRContext* context);
-
-  // Recurses into sub-components of the data descriptors, if they are
-  // composites, to record that their components are pairwise-synonymous.
-  void ComputeCompositeDataSynonymFacts(const protobufs::DataDescriptor& dd1,
-                                        const protobufs::DataDescriptor& dd2,
-                                        opt::IRContext* context);
-
-  // Records the fact that |dd1| and |dd2| are equivalent, and merges the sets
-  // of equations that are known about them.
-  void MakeEquivalent(const protobufs::DataDescriptor& dd1,
-                      const protobufs::DataDescriptor& dd2);
-
-  // Registers a data descriptor in the equivalence relation if it hasn't been
-  // registered yet, and returns its representative.
-  const protobufs::DataDescriptor* RegisterDataDescriptor(
-      const protobufs::DataDescriptor& dd);
-
-  // Returns true if and only if |dd1| and |dd2| are valid data descriptors
-  // whose associated data have compatible types. Two types are compatible if:
-  // - they are the same
-  // - they both are numerical or vectors of numerical components with the same
-  //   number of components and the same bit count per component
-  static bool DataDescriptorsAreWellFormedAndComparable(
-      opt::IRContext* context, const protobufs::DataDescriptor& dd1,
-      const protobufs::DataDescriptor& dd2);
-
-  OperationSet GetEquations(const protobufs::DataDescriptor* lhs) const;
-
-  // Requires that |lhs_dd| and every element of |rhs_dds| is present in the
-  // |synonymous_| equivalence relation, but is not necessarily its own
-  // representative.  Records the fact that the equation
-  // "|lhs_dd| |opcode| |rhs_dds_non_canonical|" holds, and adds any
-  // corollaries, in the form of data synonym or equation facts, that follow
-  // from this and other known facts.
-  void AddEquationFactRecursive(
-      const protobufs::DataDescriptor& lhs_dd, SpvOp opcode,
-      const std::vector<const protobufs::DataDescriptor*>& rhs_dds,
-      opt::IRContext* context);
-
-  // The data descriptors that are known to be synonymous with one another are
-  // captured by this equivalence relation.
-  EquivalenceRelation<protobufs::DataDescriptor, DataDescriptorHash,
-                      DataDescriptorEquals>
-      synonymous_;
-
-  // When a new synonym fact is added, it may be possible to deduce further
-  // synonym facts by computing a closure of all known facts.  However, this is
-  // an expensive operation, so it should be performed sparingly and only there
-  // is some chance of new facts being deduced.  This boolean tracks whether a
-  // closure computation is required - i.e., whether a new fact has been added
-  // since the last time such a computation was performed.
-  bool closure_computation_required_ = false;
-
-  // Represents a set of equations on data descriptors as a map indexed by
-  // left-hand-side, mapping a left-hand-side to a set of operations, each of
-  // which (together with the left-hand-side) defines an equation.
-  //
-  // All data descriptors occurring in equations are required to be present in
-  // the |synonymous_| equivalence relation, and to be their own representatives
-  // in that relation.
-  std::unordered_map<const protobufs::DataDescriptor*, OperationSet>
-      id_equations_;
-};
-
-}  // namespace fact_manager
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FACT_MANAGER_DATA_SYNONYM_AND_ID_EQUATION_FACTS_H_

+ 0 - 31
3rdparty/spirv-tools/source/fuzz/fact_manager/dead_block_facts.cpp

@@ -1,31 +0,0 @@
-// Copyright (c) 2019 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/fact_manager/dead_block_facts.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace fact_manager {
-
-void DeadBlockFacts::AddFact(const protobufs::FactBlockIsDead& fact) {
-  dead_block_ids_.insert(fact.block_id());
-}
-
-bool DeadBlockFacts::BlockIsDead(uint32_t block_id) const {
-  return dead_block_ids_.count(block_id) != 0;
-}
-
-}  // namespace fact_manager
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 44
3rdparty/spirv-tools/source/fuzz/fact_manager/dead_block_facts.h

@@ -1,44 +0,0 @@
-// Copyright (c) 2019 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_FACT_MANAGER_DEAD_BLOCK_FACTS_H_
-#define SOURCE_FUZZ_FACT_MANAGER_DEAD_BLOCK_FACTS_H_
-
-#include <unordered_set>
-
-#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace fact_manager {
-
-// The purpose of this class is to group the fields and data used to represent
-// facts about data blocks.
-class DeadBlockFacts {
- public:
-  // See method in FactManager which delegates to this method.
-  void AddFact(const protobufs::FactBlockIsDead& fact);
-
-  // See method in FactManager which delegates to this method.
-  bool BlockIsDead(uint32_t block_id) const;
-
- private:
-  std::unordered_set<uint32_t> dead_block_ids_;
-};
-
-}  // namespace fact_manager
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FACT_MANAGER_DEAD_BLOCK_FACTS_H_

+ 0 - 244
3rdparty/spirv-tools/source/fuzz/fact_manager/fact_manager.cpp

@@ -1,244 +0,0 @@
-// Copyright (c) 2019 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 "fact_manager.h"
-
-#include <sstream>
-#include <unordered_map>
-
-#include "source/fuzz/uniform_buffer_element_descriptor.h"
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace {
-
-std::string ToString(const protobufs::FactConstantUniform& fact) {
-  std::stringstream stream;
-  stream << "(" << fact.uniform_buffer_element_descriptor().descriptor_set()
-         << ", " << fact.uniform_buffer_element_descriptor().binding() << ")[";
-
-  bool first = true;
-  for (auto index : fact.uniform_buffer_element_descriptor().index()) {
-    if (first) {
-      first = false;
-    } else {
-      stream << ", ";
-    }
-    stream << index;
-  }
-
-  stream << "] == [";
-
-  first = true;
-  for (auto constant_word : fact.constant_word()) {
-    if (first) {
-      first = false;
-    } else {
-      stream << ", ";
-    }
-    stream << constant_word;
-  }
-
-  stream << "]";
-  return stream.str();
-}
-
-std::string ToString(const protobufs::FactDataSynonym& fact) {
-  std::stringstream stream;
-  stream << fact.data1() << " = " << fact.data2();
-  return stream.str();
-}
-
-std::string ToString(const protobufs::FactIdEquation& fact) {
-  std::stringstream stream;
-  stream << fact.lhs_id();
-  stream << " " << static_cast<SpvOp>(fact.opcode());
-  for (auto rhs_id : fact.rhs_id()) {
-    stream << " " << rhs_id;
-  }
-  return stream.str();
-}
-
-std::string ToString(const protobufs::Fact& fact) {
-  switch (fact.fact_case()) {
-    case protobufs::Fact::kConstantUniformFact:
-      return ToString(fact.constant_uniform_fact());
-    case protobufs::Fact::kDataSynonymFact:
-      return ToString(fact.data_synonym_fact());
-    case protobufs::Fact::kIdEquationFact:
-      return ToString(fact.id_equation_fact());
-    default:
-      assert(false && "Stringification not supported for this fact.");
-      return "";
-  }
-}
-
-}  // namespace
-
-void FactManager::AddFacts(const MessageConsumer& message_consumer,
-                           const protobufs::FactSequence& initial_facts,
-                           opt::IRContext* context) {
-  for (auto& fact : initial_facts.fact()) {
-    if (!AddFact(fact, context)) {
-      auto message = "Invalid fact " + ToString(fact) + " ignored.";
-      message_consumer(SPV_MSG_WARNING, nullptr, {}, message.c_str());
-    }
-  }
-}
-
-bool FactManager::AddFact(const fuzz::protobufs::Fact& fact,
-                          opt::IRContext* context) {
-  switch (fact.fact_case()) {
-    case protobufs::Fact::kConstantUniformFact:
-      return constant_uniform_facts_.AddFact(fact.constant_uniform_fact(),
-                                             context);
-    case protobufs::Fact::kDataSynonymFact:
-      data_synonym_and_id_equation_facts_.AddFact(fact.data_synonym_fact(),
-                                                  context);
-      return true;
-    case protobufs::Fact::kBlockIsDeadFact:
-      dead_block_facts_.AddFact(fact.block_is_dead_fact());
-      return true;
-    case protobufs::Fact::kFunctionIsLivesafeFact:
-      livesafe_function_facts_.AddFact(fact.function_is_livesafe_fact());
-      return true;
-    default:
-      assert(false && "Unknown fact type.");
-      return false;
-  }
-}
-
-void FactManager::AddFactDataSynonym(const protobufs::DataDescriptor& data1,
-                                     const protobufs::DataDescriptor& data2,
-                                     opt::IRContext* context) {
-  protobufs::FactDataSynonym fact;
-  *fact.mutable_data1() = data1;
-  *fact.mutable_data2() = data2;
-  data_synonym_and_id_equation_facts_.AddFact(fact, context);
-}
-
-std::vector<uint32_t> FactManager::GetConstantsAvailableFromUniformsForType(
-    opt::IRContext* ir_context, uint32_t type_id) const {
-  return constant_uniform_facts_.GetConstantsAvailableFromUniformsForType(
-      ir_context, type_id);
-}
-
-std::vector<protobufs::UniformBufferElementDescriptor>
-FactManager::GetUniformDescriptorsForConstant(opt::IRContext* ir_context,
-                                              uint32_t constant_id) const {
-  return constant_uniform_facts_.GetUniformDescriptorsForConstant(ir_context,
-                                                                  constant_id);
-}
-
-uint32_t FactManager::GetConstantFromUniformDescriptor(
-    opt::IRContext* context,
-    const protobufs::UniformBufferElementDescriptor& uniform_descriptor) const {
-  return constant_uniform_facts_.GetConstantFromUniformDescriptor(
-      context, uniform_descriptor);
-}
-
-std::vector<uint32_t> FactManager::GetTypesForWhichUniformValuesAreKnown()
-    const {
-  return constant_uniform_facts_.GetTypesForWhichUniformValuesAreKnown();
-}
-
-const std::vector<std::pair<protobufs::FactConstantUniform, uint32_t>>&
-FactManager::GetConstantUniformFactsAndTypes() const {
-  return constant_uniform_facts_.GetConstantUniformFactsAndTypes();
-}
-
-std::vector<uint32_t> FactManager::GetIdsForWhichSynonymsAreKnown() const {
-  return data_synonym_and_id_equation_facts_.GetIdsForWhichSynonymsAreKnown();
-}
-
-std::vector<const protobufs::DataDescriptor*>
-FactManager::GetSynonymsForDataDescriptor(
-    const protobufs::DataDescriptor& data_descriptor) const {
-  return data_synonym_and_id_equation_facts_.GetSynonymsForDataDescriptor(
-      data_descriptor);
-}
-
-std::vector<const protobufs::DataDescriptor*> FactManager::GetSynonymsForId(
-    uint32_t id) const {
-  return GetSynonymsForDataDescriptor(MakeDataDescriptor(id, {}));
-}
-
-bool FactManager::IsSynonymous(
-    const protobufs::DataDescriptor& data_descriptor1,
-    const protobufs::DataDescriptor& data_descriptor2) const {
-  return data_synonym_and_id_equation_facts_.IsSynonymous(data_descriptor1,
-                                                          data_descriptor2);
-}
-
-bool FactManager::BlockIsDead(uint32_t block_id) const {
-  return dead_block_facts_.BlockIsDead(block_id);
-}
-
-void FactManager::AddFactBlockIsDead(uint32_t block_id) {
-  protobufs::FactBlockIsDead fact;
-  fact.set_block_id(block_id);
-  dead_block_facts_.AddFact(fact);
-}
-
-bool FactManager::FunctionIsLivesafe(uint32_t function_id) const {
-  return livesafe_function_facts_.FunctionIsLivesafe(function_id);
-}
-
-void FactManager::AddFactFunctionIsLivesafe(uint32_t function_id) {
-  protobufs::FactFunctionIsLivesafe fact;
-  fact.set_function_id(function_id);
-  livesafe_function_facts_.AddFact(fact);
-}
-
-bool FactManager::PointeeValueIsIrrelevant(uint32_t pointer_id) const {
-  return irrelevant_value_facts_.PointeeValueIsIrrelevant(pointer_id);
-}
-
-bool FactManager::IdIsIrrelevant(uint32_t result_id) const {
-  return irrelevant_value_facts_.IdIsIrrelevant(result_id);
-}
-
-void FactManager::AddFactValueOfPointeeIsIrrelevant(uint32_t pointer_id) {
-  protobufs::FactPointeeValueIsIrrelevant fact;
-  fact.set_pointer_id(pointer_id);
-  irrelevant_value_facts_.AddFact(fact);
-}
-
-void FactManager::AddFactIdIsIrrelevant(uint32_t result_id) {
-  protobufs::FactIdIsIrrelevant fact;
-  fact.set_result_id(result_id);
-  irrelevant_value_facts_.AddFact(fact);
-}
-
-void FactManager::AddFactIdEquation(uint32_t lhs_id, SpvOp opcode,
-                                    const std::vector<uint32_t>& rhs_id,
-                                    opt::IRContext* context) {
-  protobufs::FactIdEquation fact;
-  fact.set_lhs_id(lhs_id);
-  fact.set_opcode(opcode);
-  for (auto an_rhs_id : rhs_id) {
-    fact.add_rhs_id(an_rhs_id);
-  }
-  data_synonym_and_id_equation_facts_.AddFact(fact, context);
-}
-
-void FactManager::ComputeClosureOfFacts(
-    opt::IRContext* ir_context, uint32_t maximum_equivalence_class_size) {
-  data_synonym_and_id_equation_facts_.ComputeClosureOfFacts(
-      ir_context, maximum_equivalence_class_size);
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 213
3rdparty/spirv-tools/source/fuzz/fact_manager/fact_manager.h

@@ -1,213 +0,0 @@
-// Copyright (c) 2019 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_FACT_MANAGER_FACT_MANAGER_H_
-#define SOURCE_FUZZ_FACT_MANAGER_FACT_MANAGER_H_
-
-#include <set>
-#include <utility>
-#include <vector>
-
-#include "source/fuzz/data_descriptor.h"
-#include "source/fuzz/fact_manager/constant_uniform_facts.h"
-#include "source/fuzz/fact_manager/data_synonym_and_id_equation_facts.h"
-#include "source/fuzz/fact_manager/dead_block_facts.h"
-#include "source/fuzz/fact_manager/irrelevant_value_facts.h"
-#include "source/fuzz/fact_manager/livesafe_function_facts.h"
-#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
-#include "source/opt/constants.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Keeps track of facts about the module being transformed on which the fuzzing
-// process can depend. Some initial facts can be provided, for example about
-// guarantees on the values of inputs to SPIR-V entry points. Transformations
-// may then rely on these facts, can add further facts that they establish.
-// Facts are intended to be simple properties that either cannot be deduced from
-// the module (such as properties that are guaranteed to hold for entry point
-// inputs), or that are established by transformations, likely to be useful for
-// future transformations, and not completely trivial to deduce straight from
-// the module.
-class FactManager {
- public:
-  // Adds all the facts from |facts|, checking them for validity with respect to
-  // |context|.  Warnings about invalid facts are communicated via
-  // |message_consumer|; such facts are otherwise ignored.
-  void AddFacts(const MessageConsumer& message_consumer,
-                const protobufs::FactSequence& facts, opt::IRContext* context);
-
-  // Checks the fact for validity with respect to |context|.  Returns false,
-  // with no side effects, if the fact is invalid.  Otherwise adds |fact| to the
-  // fact manager.
-  bool AddFact(const protobufs::Fact& fact, opt::IRContext* context);
-
-  // Record the fact that |data1| and |data2| are synonymous.
-  void AddFactDataSynonym(const protobufs::DataDescriptor& data1,
-                          const protobufs::DataDescriptor& data2,
-                          opt::IRContext* context);
-
-  // Records the fact that |block_id| is dead.
-  void AddFactBlockIsDead(uint32_t block_id);
-
-  // Records the fact that |function_id| is livesafe.
-  void AddFactFunctionIsLivesafe(uint32_t function_id);
-
-  // Records the fact that the value of the pointee associated with |pointer_id|
-  // is irrelevant: it does not affect the observable behaviour of the module.
-  void AddFactValueOfPointeeIsIrrelevant(uint32_t pointer_id);
-
-  // Records a fact that the |result_id| is irrelevant (i.e. it doesn't affect
-  // the semantics of the module)
-  void AddFactIdIsIrrelevant(uint32_t result_id);
-
-  // Records the fact that |lhs_id| is defined by the equation:
-  //
-  //   |lhs_id| = |opcode| |rhs_id[0]| ... |rhs_id[N-1]|
-  //
-  void AddFactIdEquation(uint32_t lhs_id, SpvOp opcode,
-                         const std::vector<uint32_t>& rhs_id,
-                         opt::IRContext* context);
-
-  // Inspects all known facts and adds corollary facts; e.g. if we know that
-  // a.x == b.x and a.y == b.y, where a and b have vec2 type, we can record
-  // that a == b holds.
-  //
-  // This method is expensive, and should only be called (by applying a
-  // transformation) at the start of a fuzzer pass that depends on data
-  // synonym facts, rather than calling it every time a new data synonym fact
-  // is added.
-  //
-  // The parameter |maximum_equivalence_class_size| specifies the size beyond
-  // which equivalence classes should not be mined for new facts, to avoid
-  // excessively-long closure computations.
-  void ComputeClosureOfFacts(opt::IRContext* ir_context,
-                             uint32_t maximum_equivalence_class_size);
-
-  // The fact manager is responsible for managing a few distinct categories of
-  // facts. In principle there could be different fact managers for each kind
-  // of fact, but in practice providing one 'go to' place for facts is
-  // convenient.  To keep some separation, the public methods of the fact
-  // manager should be grouped according to the kind of fact to which they
-  // relate.
-
-  //==============================
-  // Querying facts about uniform constants
-
-  // Provides the distinct type ids for which at least one  "constant ==
-  // uniform element" fact is known.
-  std::vector<uint32_t> GetTypesForWhichUniformValuesAreKnown() const;
-
-  // Provides distinct constant ids with type |type_id| for which at least one
-  // "constant == uniform element" fact is known.  If multiple identically-
-  // valued constants are relevant, only one will appear in the sequence.
-  std::vector<uint32_t> GetConstantsAvailableFromUniformsForType(
-      opt::IRContext* ir_context, uint32_t type_id) const;
-
-  // Provides details of all uniform elements that are known to be equal to the
-  // constant associated with |constant_id| in |ir_context|.
-  std::vector<protobufs::UniformBufferElementDescriptor>
-  GetUniformDescriptorsForConstant(opt::IRContext* ir_context,
-                                   uint32_t constant_id) const;
-
-  // Returns the id of a constant whose value is known to match that of
-  // |uniform_descriptor|, and whose type matches the type of the uniform
-  // element.  If multiple such constant is exist, the one that is returned
-  // is arbitrary.  Returns 0 if no such constant id exists.
-  uint32_t GetConstantFromUniformDescriptor(
-      opt::IRContext* context,
-      const protobufs::UniformBufferElementDescriptor& uniform_descriptor)
-      const;
-
-  // Returns all "constant == uniform element" facts known to the fact
-  // manager, pairing each fact with id of the type that is associated with
-  // both the constant and the uniform element.
-  const std::vector<std::pair<protobufs::FactConstantUniform, uint32_t>>&
-  GetConstantUniformFactsAndTypes() const;
-
-  // End of uniform constant facts
-  //==============================
-
-  //==============================
-  // Querying facts about id synonyms
-
-  // Returns every id for which a fact of the form "this id is synonymous with
-  // this piece of data" is known.
-  std::vector<uint32_t> GetIdsForWhichSynonymsAreKnown() const;
-
-  // Returns the equivalence class of all known synonyms of |id|, or an empty
-  // set if no synonyms are known.
-  std::vector<const protobufs::DataDescriptor*> GetSynonymsForId(
-      uint32_t id) const;
-
-  // Returns the equivalence class of all known synonyms of |data_descriptor|,
-  // or empty if no synonyms are known.
-  std::vector<const protobufs::DataDescriptor*> GetSynonymsForDataDescriptor(
-      const protobufs::DataDescriptor& data_descriptor) const;
-
-  // Returns true if and ony if |data_descriptor1| and |data_descriptor2| are
-  // known to be synonymous.
-  bool IsSynonymous(const protobufs::DataDescriptor& data_descriptor1,
-                    const protobufs::DataDescriptor& data_descriptor2) const;
-
-  // End of id synonym facts
-  //==============================
-
-  //==============================
-  // Querying facts about dead blocks
-
-  // Returns true if and ony if |block_id| is the id of a block known to be
-  // dynamically unreachable.
-  bool BlockIsDead(uint32_t block_id) const;
-
-  // End of dead block facts
-  //==============================
-
-  //==============================
-  // Querying facts about livesafe function
-
-  // Returns true if and ony if |function_id| is the id of a function known
-  // to be livesafe.
-  bool FunctionIsLivesafe(uint32_t function_id) const;
-
-  // End of dead livesafe function facts
-  //==============================
-
-  //==============================
-  // Querying facts about irrelevant values
-
-  // Returns true if and ony if the value of the pointee associated with
-  // |pointer_id| is irrelevant.
-  bool PointeeValueIsIrrelevant(uint32_t pointer_id) const;
-
-  // Returns true iff there exists a fact that the |result_id| is irrelevant.
-  bool IdIsIrrelevant(uint32_t result_id) const;
-
-  // End of irrelevant value facts
-  //==============================
-
- private:
-  // Keep these in alphabetical order.
-  fact_manager::ConstantUniformFacts constant_uniform_facts_;
-  fact_manager::DataSynonymAndIdEquationFacts
-      data_synonym_and_id_equation_facts_;
-  fact_manager::DeadBlockFacts dead_block_facts_;
-  fact_manager::LivesafeFunctionFacts livesafe_function_facts_;
-  fact_manager::IrrelevantValueFacts irrelevant_value_facts_;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FACT_MANAGER_FACT_MANAGER_H_

+ 0 - 51
3rdparty/spirv-tools/source/fuzz/fact_manager/irrelevant_value_facts.cpp

@@ -1,51 +0,0 @@
-// Copyright (c) 2019 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/fact_manager/irrelevant_value_facts.h"
-
-#include "source/fuzz/data_descriptor.h"
-#include "source/fuzz/fuzzer_util.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace fact_manager {
-
-void IrrelevantValueFacts::AddFact(
-    const protobufs::FactPointeeValueIsIrrelevant& fact) {
-  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3550)
-  //  Assert that the id does not participate in DataSynonym facts and is a
-  //  pointer.
-
-  pointers_to_irrelevant_pointees_ids_.insert(fact.pointer_id());
-}
-
-void IrrelevantValueFacts::AddFact(const protobufs::FactIdIsIrrelevant& fact) {
-  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3550)
-  //  Assert that the id does not participate in DataSynonym facts and is not a
-  //  pointer.
-
-  irrelevant_ids_.insert(fact.result_id());
-}
-
-bool IrrelevantValueFacts::PointeeValueIsIrrelevant(uint32_t pointer_id) const {
-  return pointers_to_irrelevant_pointees_ids_.count(pointer_id) != 0;
-}
-
-bool IrrelevantValueFacts::IdIsIrrelevant(uint32_t pointer_id) const {
-  return irrelevant_ids_.count(pointer_id) != 0;
-}
-
-}  // namespace fact_manager
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 52
3rdparty/spirv-tools/source/fuzz/fact_manager/irrelevant_value_facts.h

@@ -1,52 +0,0 @@
-// Copyright (c) 2019 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_FACT_MANAGER_IRRELEVANT_VALUE_FACTS_H_
-#define SOURCE_FUZZ_FACT_MANAGER_IRRELEVANT_VALUE_FACTS_H_
-
-#include <unordered_set>
-
-#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace fact_manager {
-
-// The purpose of this class is to group the fields and data used to represent
-// facts about various irrelevant values in the module.
-class IrrelevantValueFacts {
- public:
-  // See method in FactManager which delegates to this method.
-  void AddFact(const protobufs::FactPointeeValueIsIrrelevant& fact);
-
-  // See method in FactManager which delegates to this method.
-  void AddFact(const protobufs::FactIdIsIrrelevant& fact);
-
-  // See method in FactManager which delegates to this method.
-  bool PointeeValueIsIrrelevant(uint32_t pointer_id) const;
-
-  // See method in FactManager which delegates to this method.
-  bool IdIsIrrelevant(uint32_t pointer_id) const;
-
- private:
-  std::unordered_set<uint32_t> pointers_to_irrelevant_pointees_ids_;
-  std::unordered_set<uint32_t> irrelevant_ids_;
-};
-
-}  // namespace fact_manager
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FACT_MANAGER_IRRELEVANT_VALUE_FACTS_H_

+ 0 - 32
3rdparty/spirv-tools/source/fuzz/fact_manager/livesafe_function_facts.cpp

@@ -1,32 +0,0 @@
-// Copyright (c) 2019 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/fact_manager/livesafe_function_facts.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace fact_manager {
-
-void LivesafeFunctionFacts::AddFact(
-    const protobufs::FactFunctionIsLivesafe& fact) {
-  livesafe_function_ids_.insert(fact.function_id());
-}
-
-bool LivesafeFunctionFacts::FunctionIsLivesafe(uint32_t function_id) const {
-  return livesafe_function_ids_.count(function_id) != 0;
-}
-
-}  // namespace fact_manager
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 44
3rdparty/spirv-tools/source/fuzz/fact_manager/livesafe_function_facts.h

@@ -1,44 +0,0 @@
-// Copyright (c) 2019 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_FACT_MANAGER_LIVESAFE_FUNCTION_FACTS_H_
-#define SOURCE_FUZZ_FACT_MANAGER_LIVESAFE_FUNCTION_FACTS_H_
-
-#include <unordered_set>
-
-#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace fact_manager {
-
-// The purpose of this class is to group the fields and data used to represent
-// facts about livesafe functions.
-class LivesafeFunctionFacts {
- public:
-  // See method in FactManager which delegates to this method.
-  void AddFact(const protobufs::FactFunctionIsLivesafe& fact);
-
-  // See method in FactManager which delegates to this method.
-  bool FunctionIsLivesafe(uint32_t function_id) const;
-
- private:
-  std::unordered_set<uint32_t> livesafe_function_ids_;
-};
-
-}  // namespace fact_manager
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FACT_MANAGER_LIVESAFE_FUNCTION_FACTS_H_

+ 0 - 372
3rdparty/spirv-tools/source/fuzz/force_render_red.cpp

@@ -1,372 +0,0 @@
-// Copyright (c) 2019 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/force_render_red.h"
-
-#include "source/fuzz/fact_manager/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"
-#include "source/opt/ir_context.h"
-#include "source/opt/types.h"
-#include "source/util/make_unique.h"
-#include "tools/util/cli_consumer.h"
-
-namespace spvtools {
-namespace fuzz {
-
-namespace {
-
-// Helper method to find the fragment shader entry point, complaining if there
-// is no shader or if there is no fragment entry point.
-opt::Function* FindFragmentShaderEntryPoint(opt::IRContext* ir_context,
-                                            MessageConsumer message_consumer) {
-  // Check that this is a fragment shader
-  bool found_capability_shader = false;
-  for (auto& capability : ir_context->capabilities()) {
-    assert(capability.opcode() == SpvOpCapability);
-    if (capability.GetSingleWordInOperand(0) == SpvCapabilityShader) {
-      found_capability_shader = true;
-      break;
-    }
-  }
-  if (!found_capability_shader) {
-    message_consumer(
-        SPV_MSG_ERROR, nullptr, {},
-        "Forcing of red rendering requires the Shader capability.");
-    return nullptr;
-  }
-
-  opt::Instruction* fragment_entry_point = nullptr;
-  for (auto& entry_point : ir_context->module()->entry_points()) {
-    if (entry_point.GetSingleWordInOperand(0) == SpvExecutionModelFragment) {
-      fragment_entry_point = &entry_point;
-      break;
-    }
-  }
-  if (fragment_entry_point == nullptr) {
-    message_consumer(SPV_MSG_ERROR, nullptr, {},
-                     "Forcing of red rendering requires an entry point with "
-                     "the Fragment execution model.");
-    return nullptr;
-  }
-
-  for (auto& function : *ir_context->module()) {
-    if (function.result_id() ==
-        fragment_entry_point->GetSingleWordInOperand(1)) {
-      return &function;
-    }
-  }
-  assert(
-      false &&
-      "A valid module must have a function associate with each entry point.");
-  return nullptr;
-}
-
-// Helper method to check that there is a single vec4 output variable and get a
-// pointer to it.
-opt::Instruction* FindVec4OutputVariable(opt::IRContext* ir_context,
-                                         MessageConsumer message_consumer) {
-  opt::Instruction* output_variable = nullptr;
-  for (auto& inst : ir_context->types_values()) {
-    if (inst.opcode() == SpvOpVariable &&
-        inst.GetSingleWordInOperand(0) == SpvStorageClassOutput) {
-      if (output_variable != nullptr) {
-        message_consumer(SPV_MSG_ERROR, nullptr, {},
-                         "Only one output variable can be handled at present; "
-                         "found multiple.");
-        return nullptr;
-      }
-      output_variable = &inst;
-      // Do not break, as we want to check for multiple output variables.
-    }
-  }
-  if (output_variable == nullptr) {
-    message_consumer(SPV_MSG_ERROR, nullptr, {},
-                     "No output variable to which to write red was found.");
-    return nullptr;
-  }
-
-  auto output_variable_base_type = ir_context->get_type_mgr()
-                                       ->GetType(output_variable->type_id())
-                                       ->AsPointer()
-                                       ->pointee_type()
-                                       ->AsVector();
-  if (!output_variable_base_type ||
-      output_variable_base_type->element_count() != 4 ||
-      !output_variable_base_type->element_type()->AsFloat()) {
-    message_consumer(SPV_MSG_ERROR, nullptr, {},
-                     "The output variable must have type vec4.");
-    return nullptr;
-  }
-
-  return output_variable;
-}
-
-// Helper to get the ids of float constants 0.0 and 1.0, creating them if
-// necessary.
-std::pair<uint32_t, uint32_t> FindOrCreateFloatZeroAndOne(
-    opt::IRContext* ir_context, opt::analysis::Float* float_type) {
-  float one = 1.0;
-  uint32_t one_as_uint;
-  memcpy(&one_as_uint, &one, sizeof(float));
-  std::vector<uint32_t> zero_bytes = {0};
-  std::vector<uint32_t> one_bytes = {one_as_uint};
-  auto constant_zero = ir_context->get_constant_mgr()->RegisterConstant(
-      MakeUnique<opt::analysis::FloatConstant>(float_type, zero_bytes));
-  auto constant_one = ir_context->get_constant_mgr()->RegisterConstant(
-      MakeUnique<opt::analysis::FloatConstant>(float_type, one_bytes));
-  auto constant_zero_id = ir_context->get_constant_mgr()
-                              ->GetDefiningInstruction(constant_zero)
-                              ->result_id();
-  auto constant_one_id = ir_context->get_constant_mgr()
-                             ->GetDefiningInstruction(constant_one)
-                             ->result_id();
-  return std::pair<uint32_t, uint32_t>(constant_zero_id, constant_one_id);
-}
-
-std::unique_ptr<TransformationReplaceConstantWithUniform>
-MakeConstantUniformReplacement(opt::IRContext* ir_context,
-                               const FactManager& fact_manager,
-                               uint32_t constant_id,
-                               uint32_t greater_than_instruction,
-                               uint32_t in_operand_index) {
-  return MakeUnique<TransformationReplaceConstantWithUniform>(
-      MakeIdUseDescriptor(constant_id,
-                          MakeInstructionDescriptor(greater_than_instruction,
-                                                    SpvOpFOrdGreaterThan, 0),
-                          in_operand_index),
-      fact_manager.GetUniformDescriptorsForConstant(ir_context, constant_id)[0],
-      ir_context->TakeNextId(), ir_context->TakeNextId());
-}
-
-}  // namespace
-
-bool ForceRenderRed(
-    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;
-  spvtools::SpirvTools tools(target_env);
-  if (!tools.IsValid()) {
-    message_consumer(SPV_MSG_ERROR, nullptr, {},
-                     "Failed to create SPIRV-Tools interface; stopping.");
-    return false;
-  }
-
-  // Initial binary should be valid.
-  if (!tools.Validate(&binary_in[0], binary_in.size(), validator_options)) {
-    message_consumer(SPV_MSG_ERROR, nullptr, {},
-                     "Initial binary is invalid; stopping.");
-    return false;
-  }
-
-  // Build the module from the input binary.
-  std::unique_ptr<opt::IRContext> ir_context = BuildModule(
-      target_env, message_consumer, binary_in.data(), binary_in.size());
-  assert(ir_context);
-
-  // Set up a fact manager with any given initial facts.
-  FactManager fact_manager;
-  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);
-  auto output_variable =
-      FindVec4OutputVariable(ir_context.get(), message_consumer);
-  if (entry_point_function == nullptr || output_variable == nullptr) {
-    return false;
-  }
-
-  opt::analysis::Float temp_float_type(32);
-  opt::analysis::Float* float_type = ir_context->get_type_mgr()
-                                         ->GetRegisteredType(&temp_float_type)
-                                         ->AsFloat();
-  std::pair<uint32_t, uint32_t> zero_one_float_ids =
-      FindOrCreateFloatZeroAndOne(ir_context.get(), float_type);
-
-  // Make the new exit block
-  auto new_exit_block_id = ir_context->TakeNextId();
-  {
-    auto label = MakeUnique<opt::Instruction>(ir_context.get(), SpvOpLabel, 0,
-                                              new_exit_block_id,
-                                              opt::Instruction::OperandList());
-    auto new_exit_block = MakeUnique<opt::BasicBlock>(std::move(label));
-    new_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context.get(), SpvOpReturn, 0, 0, opt::Instruction::OperandList()));
-    entry_point_function->AddBasicBlock(std::move(new_exit_block));
-  }
-
-  // Make the new entry block
-  {
-    auto label = MakeUnique<opt::Instruction>(ir_context.get(), SpvOpLabel, 0,
-                                              ir_context->TakeNextId(),
-                                              opt::Instruction::OperandList());
-    auto new_entry_block = MakeUnique<opt::BasicBlock>(std::move(label));
-
-    // Make an instruction to construct vec4(1.0, 0.0, 0.0, 1.0), representing
-    // the colour red.
-    opt::Operand zero_float = {SPV_OPERAND_TYPE_ID, {zero_one_float_ids.first}};
-    opt::Operand one_float = {SPV_OPERAND_TYPE_ID, {zero_one_float_ids.second}};
-    opt::Instruction::OperandList op_composite_construct_operands = {
-        one_float, zero_float, zero_float, one_float};
-    auto temp_vec4 = opt::analysis::Vector(float_type, 4);
-    auto vec4_id = ir_context->get_type_mgr()->GetId(&temp_vec4);
-    auto red = MakeUnique<opt::Instruction>(
-        ir_context.get(), SpvOpCompositeConstruct, vec4_id,
-        ir_context->TakeNextId(), op_composite_construct_operands);
-    auto red_id = red->result_id();
-    new_entry_block->AddInstruction(std::move(red));
-
-    // Make an instruction to store red into the output color.
-    opt::Operand variable_to_store_into = {SPV_OPERAND_TYPE_ID,
-                                           {output_variable->result_id()}};
-    opt::Operand value_to_be_stored = {SPV_OPERAND_TYPE_ID, {red_id}};
-    opt::Instruction::OperandList op_store_operands = {variable_to_store_into,
-                                                       value_to_be_stored};
-    new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context.get(), SpvOpStore, 0, 0, op_store_operands));
-
-    // We are going to attempt to construct 'false' as an expression of the form
-    // 'literal1 > literal2'. If we succeed, we will later replace each literal
-    // with a uniform of the same value - we can only do that replacement once
-    // we have added the entry block to the module.
-    std::unique_ptr<TransformationReplaceConstantWithUniform>
-        first_greater_then_operand_replacement = nullptr;
-    std::unique_ptr<TransformationReplaceConstantWithUniform>
-        second_greater_then_operand_replacement = nullptr;
-    uint32_t id_guaranteed_to_be_false = 0;
-
-    opt::analysis::Bool temp_bool_type;
-    opt::analysis::Bool* registered_bool_type =
-        ir_context->get_type_mgr()
-            ->GetRegisteredType(&temp_bool_type)
-            ->AsBool();
-
-    auto float_type_id = ir_context->get_type_mgr()->GetId(float_type);
-    auto types_for_which_uniforms_are_known =
-        fact_manager.GetTypesForWhichUniformValuesAreKnown();
-
-    // Check whether we have any float uniforms.
-    if (std::find(types_for_which_uniforms_are_known.begin(),
-                  types_for_which_uniforms_are_known.end(),
-                  float_type_id) != types_for_which_uniforms_are_known.end()) {
-      // We have at least one float uniform; let's see whether we have at least
-      // two.
-      auto available_constants =
-          fact_manager.GetConstantsAvailableFromUniformsForType(
-              ir_context.get(), float_type_id);
-      if (available_constants.size() > 1) {
-        // Grab the float constants associated with the first two known float
-        // uniforms.
-        auto first_constant =
-            ir_context->get_constant_mgr()
-                ->GetConstantFromInst(ir_context->get_def_use_mgr()->GetDef(
-                    available_constants[0]))
-                ->AsFloatConstant();
-        auto second_constant =
-            ir_context->get_constant_mgr()
-                ->GetConstantFromInst(ir_context->get_def_use_mgr()->GetDef(
-                    available_constants[1]))
-                ->AsFloatConstant();
-
-        // Now work out which of the two constants is larger than the other.
-        uint32_t larger_constant_index = 0;
-        uint32_t smaller_constant_index = 0;
-        if (first_constant->GetFloat() > second_constant->GetFloat()) {
-          larger_constant_index = 0;
-          smaller_constant_index = 1;
-        } else if (first_constant->GetFloat() < second_constant->GetFloat()) {
-          larger_constant_index = 1;
-          smaller_constant_index = 0;
-        }
-
-        // Only proceed with these constants if they have turned out to be
-        // distinct.
-        if (larger_constant_index != smaller_constant_index) {
-          // We are in a position to create 'false' as 'literal1 > literal2', so
-          // reserve an id for this computation; this id will end up being
-          // guaranteed to be 'false'.
-          id_guaranteed_to_be_false = ir_context->TakeNextId();
-
-          auto smaller_constant = available_constants[smaller_constant_index];
-          auto larger_constant = available_constants[larger_constant_index];
-
-          opt::Instruction::OperandList greater_than_operands = {
-              {SPV_OPERAND_TYPE_ID, {smaller_constant}},
-              {SPV_OPERAND_TYPE_ID, {larger_constant}}};
-          new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-              ir_context.get(), SpvOpFOrdGreaterThan,
-              ir_context->get_type_mgr()->GetId(registered_bool_type),
-              id_guaranteed_to_be_false, greater_than_operands));
-
-          first_greater_then_operand_replacement =
-              MakeConstantUniformReplacement(ir_context.get(), fact_manager,
-                                             smaller_constant,
-                                             id_guaranteed_to_be_false, 0);
-          second_greater_then_operand_replacement =
-              MakeConstantUniformReplacement(ir_context.get(), fact_manager,
-                                             larger_constant,
-                                             id_guaranteed_to_be_false, 1);
-        }
-      }
-    }
-
-    if (id_guaranteed_to_be_false == 0) {
-      auto constant_false = ir_context->get_constant_mgr()->RegisterConstant(
-          MakeUnique<opt::analysis::BoolConstant>(registered_bool_type, false));
-      id_guaranteed_to_be_false = ir_context->get_constant_mgr()
-                                      ->GetDefiningInstruction(constant_false)
-                                      ->result_id();
-    }
-
-    opt::Operand false_condition = {SPV_OPERAND_TYPE_ID,
-                                    {id_guaranteed_to_be_false}};
-    opt::Operand then_block = {SPV_OPERAND_TYPE_ID,
-                               {entry_point_function->entry()->id()}};
-    opt::Operand else_block = {SPV_OPERAND_TYPE_ID, {new_exit_block_id}};
-    opt::Instruction::OperandList op_branch_conditional_operands = {
-        false_condition, then_block, else_block};
-    new_entry_block->AddInstruction(
-        MakeUnique<opt::Instruction>(ir_context.get(), SpvOpBranchConditional,
-                                     0, 0, op_branch_conditional_operands));
-
-    entry_point_function->InsertBasicBlockBefore(
-        std::move(new_entry_block), entry_point_function->entry().get());
-
-    for (auto& replacement : {first_greater_then_operand_replacement.get(),
-                              second_greater_then_operand_replacement.get()}) {
-      if (replacement) {
-        assert(replacement->IsApplicable(ir_context.get(),
-                                         transformation_context));
-        replacement->Apply(ir_context.get(), &transformation_context);
-      }
-    }
-  }
-
-  // Write out the module as a binary.
-  ir_context->module()->ToBinary(binary_out, false);
-  return true;
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 49
3rdparty/spirv-tools/source/fuzz/force_render_red.h

@@ -1,49 +0,0 @@
-// Copyright (c) 2019 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_FORCE_RENDER_RED_H_
-#define SOURCE_FORCE_RENDER_RED_H_
-
-#include <vector>
-
-#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
-#include "spirv-tools/libspirv.hpp"
-
-namespace spvtools {
-namespace fuzz {
-
-// Requires |binary_in| to be a valid SPIR-V module with Shader capability,
-// containing an entry point with the Fragment execution model, and a single
-// output variable of type vec4.
-//
-// Turns the body of this entry point into effectively:
-//
-// output_variable = vec4(1.0, 0.0, 0.0, 1.0);
-// if (false) {
-//    original_body
-// }
-//
-// If suitable facts about values of uniforms are available, the 'false' will
-// 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, 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);
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FORCE_RENDER_RED_H_

+ 0 - 394
3rdparty/spirv-tools/source/fuzz/fuzzer.cpp

@@ -1,394 +0,0 @@
-// Copyright (c) 2019 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/fuzzer.h"
-
-#include <cassert>
-#include <memory>
-
-#include "source/fuzz/fact_manager/fact_manager.h"
-#include "source/fuzz/fuzzer_context.h"
-#include "source/fuzz/fuzzer_pass_add_access_chains.h"
-#include "source/fuzz/fuzzer_pass_add_composite_inserts.h"
-#include "source/fuzz/fuzzer_pass_add_composite_types.h"
-#include "source/fuzz/fuzzer_pass_add_copy_memory.h"
-#include "source/fuzz/fuzzer_pass_add_dead_blocks.h"
-#include "source/fuzz/fuzzer_pass_add_dead_breaks.h"
-#include "source/fuzz/fuzzer_pass_add_dead_continues.h"
-#include "source/fuzz/fuzzer_pass_add_equation_instructions.h"
-#include "source/fuzz/fuzzer_pass_add_function_calls.h"
-#include "source/fuzz/fuzzer_pass_add_global_variables.h"
-#include "source/fuzz/fuzzer_pass_add_image_sample_unused_components.h"
-#include "source/fuzz/fuzzer_pass_add_loads.h"
-#include "source/fuzz/fuzzer_pass_add_local_variables.h"
-#include "source/fuzz/fuzzer_pass_add_loop_preheaders.h"
-#include "source/fuzz/fuzzer_pass_add_no_contraction_decorations.h"
-#include "source/fuzz/fuzzer_pass_add_opphi_synonyms.h"
-#include "source/fuzz/fuzzer_pass_add_parameters.h"
-#include "source/fuzz/fuzzer_pass_add_relaxed_decorations.h"
-#include "source/fuzz/fuzzer_pass_add_stores.h"
-#include "source/fuzz/fuzzer_pass_add_synonyms.h"
-#include "source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.h"
-#include "source/fuzz/fuzzer_pass_adjust_branch_weights.h"
-#include "source/fuzz/fuzzer_pass_adjust_function_controls.h"
-#include "source/fuzz/fuzzer_pass_adjust_loop_controls.h"
-#include "source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h"
-#include "source/fuzz/fuzzer_pass_adjust_selection_controls.h"
-#include "source/fuzz/fuzzer_pass_apply_id_synonyms.h"
-#include "source/fuzz/fuzzer_pass_construct_composites.h"
-#include "source/fuzz/fuzzer_pass_copy_objects.h"
-#include "source/fuzz/fuzzer_pass_donate_modules.h"
-#include "source/fuzz/fuzzer_pass_inline_functions.h"
-#include "source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.h"
-#include "source/fuzz/fuzzer_pass_interchange_zero_like_constants.h"
-#include "source/fuzz/fuzzer_pass_invert_comparison_operators.h"
-#include "source/fuzz/fuzzer_pass_make_vector_operations_dynamic.h"
-#include "source/fuzz/fuzzer_pass_merge_blocks.h"
-#include "source/fuzz/fuzzer_pass_obfuscate_constants.h"
-#include "source/fuzz/fuzzer_pass_outline_functions.h"
-#include "source/fuzz/fuzzer_pass_permute_blocks.h"
-#include "source/fuzz/fuzzer_pass_permute_function_parameters.h"
-#include "source/fuzz/fuzzer_pass_permute_instructions.h"
-#include "source/fuzz/fuzzer_pass_permute_phi_operands.h"
-#include "source/fuzz/fuzzer_pass_propagate_instructions_up.h"
-#include "source/fuzz/fuzzer_pass_push_ids_through_variables.h"
-#include "source/fuzz/fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.h"
-#include "source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.h"
-#include "source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.h"
-#include "source/fuzz/fuzzer_pass_replace_linear_algebra_instructions.h"
-#include "source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.h"
-#include "source/fuzz/fuzzer_pass_replace_parameter_with_global.h"
-#include "source/fuzz/fuzzer_pass_replace_params_with_struct.h"
-#include "source/fuzz/fuzzer_pass_split_blocks.h"
-#include "source/fuzz/fuzzer_pass_swap_commutable_operands.h"
-#include "source/fuzz/fuzzer_pass_swap_conditional_branch_operands.h"
-#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"
-
-namespace spvtools {
-namespace fuzz {
-
-namespace {
-const uint32_t kIdBoundGap = 100;
-
-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|, |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, 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, transformation_context,
-                                    fuzzer_context, transformation_sequence_out,
-                                    std::forward<Args>(extra_args)...));
-  }
-}
-
-}  // namespace
-
-Fuzzer::Fuzzer(spv_target_env target_env, uint32_t seed,
-               bool validate_after_each_fuzzer_pass,
-               spv_validator_options validator_options)
-    : target_env_(target_env),
-      seed_(seed),
-      validate_after_each_fuzzer_pass_(validate_after_each_fuzzer_pass),
-      validator_options_(validator_options) {}
-
-Fuzzer::~Fuzzer() = default;
-
-void Fuzzer::SetMessageConsumer(MessageConsumer consumer) {
-  consumer_ = std::move(consumer);
-}
-
-bool Fuzzer::ApplyPassAndCheckValidity(
-    FuzzerPass* pass, const opt::IRContext& ir_context,
-    const spvtools::SpirvTools& tools) const {
-  pass->Apply();
-  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(),
-                        validator_options_)) {
-      consumer_(SPV_MSG_INFO, nullptr, {},
-                "Binary became invalid during fuzzing (set a breakpoint to "
-                "inspect); stopping.");
-      return false;
-    }
-  }
-  return true;
-}
-
-Fuzzer::FuzzerResultStatus Fuzzer::Run(
-    const std::vector<uint32_t>& binary_in,
-    const protobufs::FactSequence& initial_facts,
-    const std::vector<fuzzerutil::ModuleSupplier>& donor_suppliers,
-    std::vector<uint32_t>* binary_out,
-    protobufs::TransformationSequence* transformation_sequence_out) const {
-  // Check compatibility between the library version being linked with and the
-  // header files being used.
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  spvtools::SpirvTools tools(target_env_);
-  tools.SetMessageConsumer(consumer_);
-  if (!tools.IsValid()) {
-    consumer_(SPV_MSG_ERROR, nullptr, {},
-              "Failed to create SPIRV-Tools interface; stopping.");
-    return Fuzzer::FuzzerResultStatus::kFailedToCreateSpirvToolsInterface;
-  }
-
-  // Initial binary should be valid.
-  if (!tools.Validate(&binary_in[0], binary_in.size(), validator_options_)) {
-    consumer_(SPV_MSG_ERROR, nullptr, {},
-              "Initial binary is invalid; stopping.");
-    return Fuzzer::FuzzerResultStatus::kInitialBinaryInvalid;
-  }
-
-  // Build the module from the input binary.
-  std::unique_ptr<opt::IRContext> ir_context =
-      BuildModule(target_env_, consumer_, binary_in.data(), binary_in.size());
-  assert(ir_context);
-
-  // Make a PRNG from the seed passed to the fuzzer on creation.
-  PseudoRandomGenerator random_generator(seed_);
-
-  // The fuzzer will introduce new ids into the module.  The module's id bound
-  // gives the smallest id that can be used for this purpose.  We add an offset
-  // to this so that there is a sizeable gap between the ids used in the
-  // original module and the ids used for fuzzing, as a readability aid.
-  //
-  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2541) consider the
-  //  case where the maximum id bound is reached.
-  auto minimum_fresh_id = ir_context->module()->id_bound() + kIdBoundGap;
-  FuzzerContext fuzzer_context(&random_generator, minimum_fresh_id);
-
-  FactManager fact_manager;
-  fact_manager.AddFacts(consumer_, initial_facts, ir_context.get());
-  TransformationContext transformation_context(&fact_manager,
-                                               validator_options_);
-
-  // Apply some semantics-preserving passes.
-  std::vector<std::unique_ptr<FuzzerPass>> passes;
-  while (passes.empty()) {
-    MaybeAddPass<FuzzerPassAddAccessChains>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddCompositeInserts>(
-        &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<FuzzerPassAddCopyMemory>(
-        &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(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    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<FuzzerPassAddImageSampleUnusedComponents>(
-        &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(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddLoopPreheaders>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddOpPhiSynonyms>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddParameters>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddRelaxedDecorations>(
-        &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<FuzzerPassAddSynonyms>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddVectorShuffleInstructions>(
-        &passes, ir_context.get(), &transformation_context, &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(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out, donor_suppliers);
-    MaybeAddPass<FuzzerPassInlineFunctions>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassInvertComparisonOperators>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassMakeVectorOperationsDynamic>(
-        &passes, ir_context.get(), &transformation_context, &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(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassPermuteInstructions>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassPropagateInstructionsUp>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassPushIdsThroughVariables>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassReplaceAddsSubsMulsWithCarryingExtended>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassReplaceCopyMemoriesWithLoadsStores>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassReplaceCopyObjectsWithStoresLoads>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassReplaceLoadsStoresWithCopyMemories>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassReplaceParameterWithGlobal>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassReplaceLinearAlgebraInstructions>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassReplaceParamsWithStruct>(
-        &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<FuzzerPassSwapBranchConditionalOperands>(
-        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
-        transformation_sequence_out);
-  }
-
-  bool is_first = true;
-  while (static_cast<uint32_t>(
-             transformation_sequence_out->transformation_size()) <
-             kTransformationLimit &&
-         (is_first ||
-          fuzzer_context.ChoosePercentage(kChanceOfApplyingAnotherPass))) {
-    is_first = false;
-    if (!ApplyPassAndCheckValidity(
-            passes[fuzzer_context.RandomIndex(passes)].get(), *ir_context,
-            tools)) {
-      return Fuzzer::FuzzerResultStatus::kFuzzerPassLedToInvalidModule;
-    }
-  }
-
-  // Now apply some passes that it does not make sense to apply repeatedly,
-  // as they do not unlock other passes.
-  std::vector<std::unique_ptr<FuzzerPass>> final_passes;
-  MaybeAddPass<FuzzerPassAdjustBranchWeights>(
-      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
-      transformation_sequence_out);
-  MaybeAddPass<FuzzerPassAdjustFunctionControls>(
-      &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<FuzzerPassAdjustMemoryOperandsMasks>(
-      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
-      transformation_sequence_out);
-  MaybeAddPass<FuzzerPassAdjustSelectionControls>(
-      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
-      transformation_sequence_out);
-  MaybeAddPass<FuzzerPassAddNoContractionDecorations>(
-      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
-      transformation_sequence_out);
-  MaybeAddPass<FuzzerPassInterchangeSignednessOfIntegerOperands>(
-      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
-      transformation_sequence_out);
-  MaybeAddPass<FuzzerPassInterchangeZeroLikeConstants>(
-      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
-      transformation_sequence_out);
-  MaybeAddPass<FuzzerPassPermutePhiOperands>(
-      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
-      transformation_sequence_out);
-  MaybeAddPass<FuzzerPassSwapCommutableOperands>(
-      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
-      transformation_sequence_out);
-  MaybeAddPass<FuzzerPassToggleAccessChainInstruction>(
-      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
-      transformation_sequence_out);
-  for (auto& pass : final_passes) {
-    if (!ApplyPassAndCheckValidity(pass.get(), *ir_context, tools)) {
-      return Fuzzer::FuzzerResultStatus::kFuzzerPassLedToInvalidModule;
-    }
-  }
-
-  // Encode the module as a binary.
-  ir_context->module()->ToBinary(binary_out, false);
-
-  return Fuzzer::FuzzerResultStatus::kComplete;
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,101 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_H_
-#define SOURCE_FUZZ_FUZZER_H_
-
-#include <memory>
-#include <vector>
-
-#include "source/fuzz/fuzzer_pass.h"
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
-#include "spirv-tools/libspirv.hpp"
-
-namespace spvtools {
-namespace fuzz {
-
-// Transforms a SPIR-V module into a semantically equivalent SPIR-V module by
-// running a number of randomized fuzzer passes.
-class Fuzzer {
- public:
-  // Possible statuses that can result from running the fuzzer.
-  enum class FuzzerResultStatus {
-    kComplete,
-    kFailedToCreateSpirvToolsInterface,
-    kFuzzerPassLedToInvalidModule,
-    kInitialBinaryInvalid,
-  };
-
-  // Constructs a fuzzer from the given target environment |target_env|.  |seed|
-  // is a seed for pseudo-random number generation.
-  // |validate_after_each_fuzzer_pass| controls whether the validator will be
-  // invoked after every fuzzer pass is applied.
-  Fuzzer(spv_target_env target_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;
-  Fuzzer(Fuzzer&&) = delete;
-  Fuzzer& operator=(const Fuzzer&) = delete;
-  Fuzzer& operator=(Fuzzer&&) = delete;
-
-  ~Fuzzer();
-
-  // Sets the message consumer to the given |consumer|. The |consumer| will be
-  // invoked once for each message communicated from the library.
-  void SetMessageConsumer(MessageConsumer consumer);
-
-  // Transforms |binary_in| to |binary_out| by running a number of randomized
-  // fuzzer passes.  Initial facts about the input binary and the context in
-  // which it will execute are provided via |initial_facts|.  A source of donor
-  // modules to be used by transformations is provided via |donor_suppliers|.
-  // The transformation sequence that was applied is returned via
-  // |transformation_sequence_out|.
-  FuzzerResultStatus Run(
-      const std::vector<uint32_t>& binary_in,
-      const protobufs::FactSequence& initial_facts,
-      const std::vector<fuzzerutil::ModuleSupplier>& donor_suppliers,
-      std::vector<uint32_t>* binary_out,
-      protobufs::TransformationSequence* transformation_sequence_out) const;
-
- private:
-  // Applies |pass|, which must be a pass constructed with |ir_context|, and
-  // then returns true if and only if |ir_context| is valid.  |tools| is used to
-  // check validity.
-  bool ApplyPassAndCheckValidity(FuzzerPass* pass,
-                                 const opt::IRContext& ir_context,
-                                 const spvtools::SpirvTools& tools) const;
-
-  // Target environment.
-  const spv_target_env target_env_;
-
-  // Message consumer.
-  MessageConsumer consumer_;
-
-  // Seed for random number generator.
-  const uint32_t seed_;
-
-  // Determines whether the validator should be invoked after every fuzzer pass.
-  bool validate_after_each_fuzzer_pass_;
-
-  // Options to control validation.
-  spv_validator_options validator_options_;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_H_

+ 0 - 320
3rdparty/spirv-tools/source/fuzz/fuzzer_context.cpp

@@ -1,320 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_context.h"
-
-#include <cmath>
-
-namespace spvtools {
-namespace fuzz {
-
-namespace {
-// Default <minimum, maximum> pairs of probabilities for applying various
-// transformations. All values are percentages. Keep them in alphabetical order.
-
-const std::pair<uint32_t, uint32_t> kChanceOfAddingAccessChain = {5, 50};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingAnotherStructField = {20,
-                                                                         90};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingArrayOrStructType = {20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingCompositeInsert = {20, 50};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingCopyMemory = {20, 50};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingDeadBlock = {20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingDeadBreak = {5, 80};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingDeadContinue = {5, 80};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingEquationInstruction = {5,
-                                                                          90};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingGlobalVariable = {20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingImageSampleUnusedComponents =
-    {20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingLoad = {5, 50};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingLocalVariable = {20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingLoopPreheader = {20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingMatrixType = {20, 70};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingNoContractionDecoration = {
-    5, 70};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingOpPhiSynonym = {5, 70};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingParameters = {5, 70};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingRelaxedDecoration = {20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingStore = {5, 50};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingSynonyms = {20, 50};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingVectorType = {20, 70};
-const std::pair<uint32_t, uint32_t> kChanceOfAddingVectorShuffle = {20, 70};
-const std::pair<uint32_t, uint32_t> kChanceOfAdjustingBranchWeights = {20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfAdjustingFunctionControl = {20,
-                                                                         70};
-const std::pair<uint32_t, uint32_t> kChanceOfAdjustingLoopControl = {20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfAdjustingMemoryOperandsMask = {20,
-                                                                            90};
-const std::pair<uint32_t, uint32_t> kChanceOfAdjustingSelectionControl = {20,
-                                                                          90};
-const std::pair<uint32_t, uint32_t> kChanceOfCallingFunction = {1, 10};
-const std::pair<uint32_t, uint32_t> kChanceOfChoosingStructTypeVsArrayType = {
-    20, 80};
-const std::pair<uint32_t, uint32_t> kChanceOfChoosingWorkgroupStorageClass = {
-    50, 50};
-const std::pair<uint32_t, uint32_t> kChanceOfConstructingComposite = {20, 50};
-const std::pair<uint32_t, uint32_t> kChanceOfCopyingObject = {20, 50};
-const std::pair<uint32_t, uint32_t> kChanceOfDonatingAdditionalModule = {5, 50};
-const std::pair<uint32_t, uint32_t> kChanceOfGoingDeeperToInsertInComposite = {
-    30, 70};
-const std::pair<uint32_t, uint32_t> kChanceOfGoingDeeperWhenMakingAccessChain =
-    {50, 95};
-const std::pair<uint32_t, uint32_t> kChanceOfInliningFunction = {10, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfInterchangingZeroLikeConstants = {
-    10, 90};
-const std::pair<uint32_t, uint32_t>
-    kChanceOfInterchangingSignednessOfIntegerOperands = {10, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfInvertingComparisonOperators = {
-    20, 50};
-const std::pair<uint32_t, uint32_t> kChanceOfMakingDonorLivesafe = {40, 60};
-const std::pair<uint32_t, uint32_t> kChanceOfMakingVectorOperationDynamic = {
-    20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfMergingBlocks = {20, 95};
-const std::pair<uint32_t, uint32_t> kChanceOfMovingBlockDown = {20, 50};
-const std::pair<uint32_t, uint32_t> kChanceOfObfuscatingConstant = {10, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfOutliningFunction = {10, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfPermutingInstructions = {20, 70};
-const std::pair<uint32_t, uint32_t> kChanceOfPermutingParameters = {30, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfPermutingPhiOperands = {30, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfPropagatingInstructionsUp = {20,
-                                                                          70};
-const std::pair<uint32_t, uint32_t> kChanceOfPushingIdThroughVariable = {5, 50};
-const std::pair<uint32_t, uint32_t>
-    kChanceOfReplacingAddSubMulWithCarryingExtended = {20, 70};
-const std::pair<uint32_t, uint32_t> kChanceOfReplacingCopyMemoryWithLoadStore =
-    {20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfReplacingCopyObjectWithStoreLoad =
-    {20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfReplacingIdWithSynonym = {10, 90};
-const std::pair<uint32_t, uint32_t>
-    kChanceOfReplacingLinearAlgebraInstructions = {10, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfReplacingLoadStoreWithCopyMemory =
-    {20, 90};
-const std::pair<uint32_t, uint32_t> kChanceOfReplacingParametersWithGlobals = {
-    30, 70};
-const std::pair<uint32_t, uint32_t> kChanceOfReplacingParametersWithStruct = {
-    20, 40};
-const std::pair<uint32_t, uint32_t> kChanceOfSplittingBlock = {40, 95};
-const std::pair<uint32_t, uint32_t> kChanceOfSwappingConditionalBranchOperands =
-    {10, 70};
-const std::pair<uint32_t, uint32_t> kChanceOfTogglingAccessChainInstruction = {
-    20, 90};
-
-// Default limits for various quantities that are chosen during fuzzing.
-// Keep them in alphabetical order.
-const uint32_t kDefaultMaxEquivalenceClassSizeForDataSynonymFactClosure = 1000;
-const uint32_t kDefaultMaxLoopControlPartialCount = 100;
-const uint32_t kDefaultMaxLoopControlPeelCount = 100;
-const uint32_t kDefaultMaxLoopLimit = 20;
-const uint32_t kDefaultMaxNewArraySizeLimit = 100;
-// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3424):
-//  think whether there is a better limit on the maximum number of parameters.
-const uint32_t kDefaultMaxNumberOfFunctionParameters = 128;
-const uint32_t kDefaultMaxNumberOfNewParameters = 15;
-const uint32_t kGetDefaultMaxNumberOfParametersReplacedWithStruct = 5;
-
-// Default functions for controlling how deep to go during recursive
-// generation/transformation. Keep them in alphabetical order.
-
-const std::function<bool(uint32_t, RandomGenerator*)>
-    kDefaultGoDeeperInConstantObfuscation =
-        [](uint32_t current_depth, RandomGenerator* random_generator) -> bool {
-  double chance = 1.0 / std::pow(3.0, static_cast<float>(current_depth + 1));
-  return random_generator->RandomDouble() < chance;
-};
-
-}  // namespace
-
-FuzzerContext::FuzzerContext(RandomGenerator* random_generator,
-                             uint32_t min_fresh_id)
-    : random_generator_(random_generator),
-      next_fresh_id_(min_fresh_id),
-      max_equivalence_class_size_for_data_synonym_fact_closure_(
-          kDefaultMaxEquivalenceClassSizeForDataSynonymFactClosure),
-      max_loop_control_partial_count_(kDefaultMaxLoopControlPartialCount),
-      max_loop_control_peel_count_(kDefaultMaxLoopControlPeelCount),
-      max_loop_limit_(kDefaultMaxLoopLimit),
-      max_new_array_size_limit_(kDefaultMaxNewArraySizeLimit),
-      max_number_of_function_parameters_(kDefaultMaxNumberOfFunctionParameters),
-      max_number_of_new_parameters_(kDefaultMaxNumberOfNewParameters),
-      max_number_of_parameters_replaced_with_struct_(
-          kGetDefaultMaxNumberOfParametersReplacedWithStruct),
-      go_deeper_in_constant_obfuscation_(
-          kDefaultGoDeeperInConstantObfuscation) {
-  chance_of_adding_access_chain_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingAccessChain);
-  chance_of_adding_another_struct_field_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingAnotherStructField);
-  chance_of_adding_array_or_struct_type_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingArrayOrStructType);
-  chance_of_adding_composite_insert_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingCompositeInsert);
-  chance_of_adding_copy_memory_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingCopyMemory);
-  chance_of_adding_dead_block_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingDeadBlock);
-  chance_of_adding_dead_break_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingDeadBreak);
-  chance_of_adding_dead_continue_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingDeadContinue);
-  chance_of_adding_equation_instruction_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingEquationInstruction);
-  chance_of_adding_global_variable_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingGlobalVariable);
-  chance_of_adding_load_ = ChooseBetweenMinAndMax(kChanceOfAddingLoad);
-  chance_of_adding_loop_preheader_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingLoopPreheader);
-  chance_of_adding_image_sample_unused_components_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingImageSampleUnusedComponents);
-  chance_of_adding_local_variable_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingLocalVariable);
-  chance_of_adding_matrix_type_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingMatrixType);
-  chance_of_adding_no_contraction_decoration_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingNoContractionDecoration);
-  chance_of_adding_opphi_synonym_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingOpPhiSynonym);
-  chance_of_adding_parameters =
-      ChooseBetweenMinAndMax(kChanceOfAddingParameters);
-  chance_of_adding_relaxed_decoration_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingRelaxedDecoration);
-  chance_of_adding_store_ = ChooseBetweenMinAndMax(kChanceOfAddingStore);
-  chance_of_adding_vector_shuffle_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingVectorShuffle);
-  chance_of_adding_vector_type_ =
-      ChooseBetweenMinAndMax(kChanceOfAddingVectorType);
-  chance_of_adjusting_branch_weights_ =
-      ChooseBetweenMinAndMax(kChanceOfAdjustingBranchWeights);
-  chance_of_adjusting_function_control_ =
-      ChooseBetweenMinAndMax(kChanceOfAdjustingFunctionControl);
-  chance_of_adding_synonyms_ = ChooseBetweenMinAndMax(kChanceOfAddingSynonyms);
-  chance_of_adjusting_loop_control_ =
-      ChooseBetweenMinAndMax(kChanceOfAdjustingLoopControl);
-  chance_of_adjusting_memory_operands_mask_ =
-      ChooseBetweenMinAndMax(kChanceOfAdjustingMemoryOperandsMask);
-  chance_of_adjusting_selection_control_ =
-      ChooseBetweenMinAndMax(kChanceOfAdjustingSelectionControl);
-  chance_of_calling_function_ =
-      ChooseBetweenMinAndMax(kChanceOfCallingFunction);
-  chance_of_choosing_struct_type_vs_array_type_ =
-      ChooseBetweenMinAndMax(kChanceOfChoosingStructTypeVsArrayType);
-  chance_of_choosing_workgroup_storage_class_ =
-      ChooseBetweenMinAndMax(kChanceOfChoosingWorkgroupStorageClass);
-  chance_of_constructing_composite_ =
-      ChooseBetweenMinAndMax(kChanceOfConstructingComposite);
-  chance_of_copying_object_ = ChooseBetweenMinAndMax(kChanceOfCopyingObject);
-  chance_of_donating_additional_module_ =
-      ChooseBetweenMinAndMax(kChanceOfDonatingAdditionalModule);
-  chance_of_going_deeper_to_insert_in_composite_ =
-      ChooseBetweenMinAndMax(kChanceOfGoingDeeperToInsertInComposite);
-  chance_of_going_deeper_when_making_access_chain_ =
-      ChooseBetweenMinAndMax(kChanceOfGoingDeeperWhenMakingAccessChain);
-  chance_of_inlining_function_ =
-      ChooseBetweenMinAndMax(kChanceOfInliningFunction);
-  chance_of_interchanging_signedness_of_integer_operands_ =
-      ChooseBetweenMinAndMax(kChanceOfInterchangingSignednessOfIntegerOperands);
-  chance_of_interchanging_zero_like_constants_ =
-      ChooseBetweenMinAndMax(kChanceOfInterchangingZeroLikeConstants);
-  chance_of_inverting_comparison_operators_ =
-      ChooseBetweenMinAndMax(kChanceOfInvertingComparisonOperators);
-  chance_of_making_donor_livesafe_ =
-      ChooseBetweenMinAndMax(kChanceOfMakingDonorLivesafe);
-  chance_of_making_vector_operation_dynamic_ =
-      ChooseBetweenMinAndMax(kChanceOfMakingVectorOperationDynamic);
-  chance_of_merging_blocks_ = ChooseBetweenMinAndMax(kChanceOfMergingBlocks);
-  chance_of_moving_block_down_ =
-      ChooseBetweenMinAndMax(kChanceOfMovingBlockDown);
-  chance_of_obfuscating_constant_ =
-      ChooseBetweenMinAndMax(kChanceOfObfuscatingConstant);
-  chance_of_outlining_function_ =
-      ChooseBetweenMinAndMax(kChanceOfOutliningFunction);
-  chance_of_permuting_instructions_ =
-      ChooseBetweenMinAndMax(kChanceOfPermutingInstructions);
-  chance_of_permuting_parameters_ =
-      ChooseBetweenMinAndMax(kChanceOfPermutingParameters);
-  chance_of_permuting_phi_operands_ =
-      ChooseBetweenMinAndMax(kChanceOfPermutingPhiOperands);
-  chance_of_propagating_instructions_up_ =
-      ChooseBetweenMinAndMax(kChanceOfPropagatingInstructionsUp);
-  chance_of_pushing_id_through_variable_ =
-      ChooseBetweenMinAndMax(kChanceOfPushingIdThroughVariable);
-  chance_of_replacing_add_sub_mul_with_carrying_extended_ =
-      ChooseBetweenMinAndMax(kChanceOfReplacingAddSubMulWithCarryingExtended);
-  chance_of_replacing_copy_memory_with_load_store_ =
-      ChooseBetweenMinAndMax(kChanceOfReplacingCopyMemoryWithLoadStore);
-  chance_of_replacing_copyobject_with_store_load_ =
-      ChooseBetweenMinAndMax(kChanceOfReplacingCopyObjectWithStoreLoad);
-  chance_of_replacing_id_with_synonym_ =
-      ChooseBetweenMinAndMax(kChanceOfReplacingIdWithSynonym);
-  chance_of_replacing_linear_algebra_instructions_ =
-      ChooseBetweenMinAndMax(kChanceOfReplacingLinearAlgebraInstructions);
-  chance_of_replacing_load_store_with_copy_memory_ =
-      ChooseBetweenMinAndMax(kChanceOfReplacingLoadStoreWithCopyMemory);
-  chance_of_replacing_parameters_with_globals_ =
-      ChooseBetweenMinAndMax(kChanceOfReplacingParametersWithGlobals);
-  chance_of_replacing_parameters_with_struct_ =
-      ChooseBetweenMinAndMax(kChanceOfReplacingParametersWithStruct);
-  chance_of_splitting_block_ = ChooseBetweenMinAndMax(kChanceOfSplittingBlock);
-  chance_of_swapping_conditional_branch_operands_ =
-      ChooseBetweenMinAndMax(kChanceOfSwappingConditionalBranchOperands);
-  chance_of_toggling_access_chain_instruction_ =
-      ChooseBetweenMinAndMax(kChanceOfTogglingAccessChainInstruction);
-}
-
-FuzzerContext::~FuzzerContext() = default;
-
-uint32_t FuzzerContext::GetFreshId() { return next_fresh_id_++; }
-
-std::vector<uint32_t> FuzzerContext::GetFreshIds(const uint32_t count) {
-  std::vector<uint32_t> fresh_ids(count);
-
-  for (uint32_t& fresh_id : fresh_ids) {
-    fresh_id = next_fresh_id_++;
-  }
-
-  return fresh_ids;
-}
-
-bool FuzzerContext::ChooseEven() { return random_generator_->RandomBool(); }
-
-bool FuzzerContext::ChoosePercentage(uint32_t percentage_chance) {
-  assert(percentage_chance <= 100);
-  return random_generator_->RandomPercentage() < percentage_chance;
-}
-
-uint32_t FuzzerContext::ChooseBetweenMinAndMax(
-    const std::pair<uint32_t, uint32_t>& min_max) {
-  assert(min_max.first <= min_max.second);
-  return min_max.first +
-         random_generator_->RandomUint32(min_max.second - min_max.first + 1);
-}
-
-protobufs::TransformationAddSynonym::SynonymType
-FuzzerContext::GetRandomSynonymType() {
-  // value_count method is guaranteed to return a value greater than 0.
-  auto result_index = ChooseBetweenMinAndMax(
-      {0, static_cast<uint32_t>(
-              protobufs::TransformationAddSynonym::SynonymType_descriptor()
-                  ->value_count() -
-              1)});
-  auto result = protobufs::TransformationAddSynonym::SynonymType_descriptor()
-                    ->value(result_index)
-                    ->number();
-  assert(protobufs::TransformationAddSynonym::SynonymType_IsValid(result) &&
-         "|result| is not a value of SynonymType");
-  return static_cast<protobufs::TransformationAddSynonym::SynonymType>(result);
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 445
3rdparty/spirv-tools/source/fuzz/fuzzer_context.h

@@ -1,445 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_CONTEXT_H_
-#define SOURCE_FUZZ_FUZZER_CONTEXT_H_
-
-#include <functional>
-#include <utility>
-
-#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
-#include "source/fuzz/random_generator.h"
-#include "source/opt/function.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Encapsulates all parameters that control the fuzzing process, such as the
-// source of randomness and the probabilities with which transformations are
-// applied.
-class FuzzerContext {
- public:
-  // Constructs a fuzzer context with a given random generator and the minimum
-  // value that can be used for fresh ids.
-  FuzzerContext(RandomGenerator* random_generator, uint32_t min_fresh_id);
-
-  ~FuzzerContext();
-
-  // Returns a random boolean.
-  bool ChooseEven();
-
-  // Returns true if and only if a randomly-chosen integer in the range [0, 100]
-  // is less than |percentage_chance|.
-  bool ChoosePercentage(uint32_t percentage_chance);
-
-  // Returns a random index into |sequence|, which is expected to have a 'size'
-  // method, and which must be non-empty.  Typically 'HasSizeMethod' will be an
-  // std::vector.
-  template <typename HasSizeMethod>
-  uint32_t RandomIndex(const HasSizeMethod& sequence) const {
-    assert(sequence.size() > 0);
-    return random_generator_->RandomUint32(
-        static_cast<uint32_t>(sequence.size()));
-  }
-
-  // Selects a random index into |sequence|, removes the element at that index
-  // and returns it.
-  template <typename T>
-  T RemoveAtRandomIndex(std::vector<T>* sequence) const {
-    uint32_t index = RandomIndex(*sequence);
-    T result = sequence->at(index);
-    sequence->erase(sequence->begin() + index);
-    return result;
-  }
-
-  // Randomly shuffles a |sequence| between |lo| and |hi| indices inclusively.
-  // |lo| and |hi| must be valid indices to the |sequence|
-  template <typename T>
-  void Shuffle(std::vector<T>* sequence, size_t lo, size_t hi) const {
-    auto& array = *sequence;
-
-    if (array.empty()) {
-      return;
-    }
-
-    assert(lo <= hi && hi < array.size() && "lo and/or hi indices are invalid");
-
-    // i > lo to account for potential infinite loop when lo == 0
-    for (size_t i = hi; i > lo; --i) {
-      auto index =
-          random_generator_->RandomUint32(static_cast<uint32_t>(i - lo + 1));
-
-      if (lo + index != i) {
-        // Introduce std::swap to the scope but don't use it
-        // directly since there might be a better overload
-        using std::swap;
-        swap(array[lo + index], array[i]);
-      }
-    }
-  }
-
-  // Ramdomly shuffles a |sequence|
-  template <typename T>
-  void Shuffle(std::vector<T>* sequence) const {
-    if (!sequence->empty()) {
-      Shuffle(sequence, 0, sequence->size() - 1);
-    }
-  }
-
-  // Yields an id that is guaranteed not to be used in the module being fuzzed,
-  // or to have been issued before.
-  uint32_t GetFreshId();
-
-  // Returns a vector of |count| fresh ids.
-  std::vector<uint32_t> GetFreshIds(const uint32_t count);
-
-  // Probabilities associated with applying various transformations.
-  // Keep them in alphabetical order.
-  uint32_t GetChanceOfAddingAccessChain() {
-    return chance_of_adding_access_chain_;
-  }
-  uint32_t GetChanceOfAddingAnotherStructField() {
-    return chance_of_adding_another_struct_field_;
-  }
-  uint32_t GetChanceOfAddingArrayOrStructType() {
-    return chance_of_adding_array_or_struct_type_;
-  }
-  uint32_t GetChanceOfAddingCompositeInsert() {
-    return chance_of_adding_composite_insert_;
-  }
-  uint32_t GetChanceOfAddingCopyMemory() {
-    return chance_of_adding_copy_memory_;
-  }
-  uint32_t GetChanceOfAddingDeadBlock() { return chance_of_adding_dead_block_; }
-  uint32_t GetChanceOfAddingDeadBreak() { return chance_of_adding_dead_break_; }
-  uint32_t GetChanceOfAddingDeadContinue() {
-    return chance_of_adding_dead_continue_;
-  }
-  uint32_t GetChanceOfAddingEquationInstruction() {
-    return chance_of_adding_equation_instruction_;
-  }
-  uint32_t GetChanceOfAddingGlobalVariable() {
-    return chance_of_adding_global_variable_;
-  }
-  uint32_t GetChanceOfAddingImageSampleUnusedComponents() {
-    return chance_of_adding_image_sample_unused_components_;
-  }
-  uint32_t GetChanceOfAddingLoad() { return chance_of_adding_load_; }
-  uint32_t GetChanceOfAddingLocalVariable() {
-    return chance_of_adding_local_variable_;
-  }
-  uint32_t GetChanceOfAddingLoopPreheader() {
-    return chance_of_adding_loop_preheader_;
-  }
-  uint32_t GetChanceOfAddingMatrixType() {
-    return chance_of_adding_matrix_type_;
-  }
-  uint32_t GetChanceOfAddingNoContractionDecoration() {
-    return chance_of_adding_no_contraction_decoration_;
-  }
-  uint32_t GetChanceOfAddingOpPhiSynonym() {
-    return chance_of_adding_opphi_synonym_;
-  }
-  uint32_t GetChanceOfAddingParameters() { return chance_of_adding_parameters; }
-  uint32_t GetChanceOfAddingRelaxedDecoration() {
-    return chance_of_adding_relaxed_decoration_;
-  }
-  uint32_t GetChanceOfAddingStore() { return chance_of_adding_store_; }
-  uint32_t GetChanceOfAddingSynonyms() { return chance_of_adding_synonyms_; }
-  uint32_t GetChanceOfAddingVectorShuffle() {
-    return chance_of_adding_vector_shuffle_;
-  }
-  uint32_t GetChanceOfAddingVectorType() {
-    return chance_of_adding_vector_type_;
-  }
-  uint32_t GetChanceOfAdjustingBranchWeights() {
-    return chance_of_adjusting_branch_weights_;
-  }
-  uint32_t GetChanceOfAdjustingFunctionControl() {
-    return chance_of_adjusting_function_control_;
-  }
-  uint32_t GetChanceOfAdjustingLoopControl() {
-    return chance_of_adjusting_loop_control_;
-  }
-  uint32_t GetChanceOfAdjustingMemoryOperandsMask() {
-    return chance_of_adjusting_memory_operands_mask_;
-  }
-  uint32_t GetChanceOfAdjustingSelectionControl() {
-    return chance_of_adjusting_selection_control_;
-  }
-  uint32_t GetChanceOfCallingFunction() { return chance_of_calling_function_; }
-  uint32_t GetChanceOfChoosingStructTypeVsArrayType() {
-    return chance_of_choosing_struct_type_vs_array_type_;
-  }
-  uint32_t GetChanceOfChoosingWorkgroupStorageClass() {
-    return chance_of_choosing_workgroup_storage_class_;
-  }
-  uint32_t GetChanceOfConstructingComposite() {
-    return chance_of_constructing_composite_;
-  }
-  uint32_t GetChanceOfCopyingObject() { return chance_of_copying_object_; }
-  uint32_t GetChanceOfDonatingAdditionalModule() {
-    return chance_of_donating_additional_module_;
-  }
-  uint32_t GetChanceOfGoingDeeperToInsertInComposite() {
-    return chance_of_going_deeper_to_insert_in_composite_;
-  }
-  uint32_t GetChanceOfGoingDeeperWhenMakingAccessChain() {
-    return chance_of_going_deeper_when_making_access_chain_;
-  }
-  uint32_t GetChanceOfInliningFunction() {
-    return chance_of_inlining_function_;
-  }
-  uint32_t GetChanceOfInterchangingSignednessOfIntegerOperands() {
-    return chance_of_interchanging_signedness_of_integer_operands_;
-  }
-  uint32_t GetChanceOfInterchangingZeroLikeConstants() {
-    return chance_of_interchanging_zero_like_constants_;
-  }
-  uint32_t GetChanceOfInvertingComparisonOperators() {
-    return chance_of_inverting_comparison_operators_;
-  }
-  uint32_t ChanceOfMakingDonorLivesafe() {
-    return chance_of_making_donor_livesafe_;
-  }
-  uint32_t GetChanceOfMakingVectorOperationDynamic() {
-    return chance_of_making_vector_operation_dynamic_;
-  }
-  uint32_t GetChanceOfMergingBlocks() { return chance_of_merging_blocks_; }
-  uint32_t GetChanceOfMovingBlockDown() { return chance_of_moving_block_down_; }
-  uint32_t GetChanceOfObfuscatingConstant() {
-    return chance_of_obfuscating_constant_;
-  }
-  uint32_t GetChanceOfOutliningFunction() {
-    return chance_of_outlining_function_;
-  }
-  uint32_t GetChanceOfPermutingInstructions() {
-    return chance_of_permuting_instructions_;
-  }
-  uint32_t GetChanceOfPermutingParameters() {
-    return chance_of_permuting_parameters_;
-  }
-  uint32_t GetChanceOfPermutingPhiOperands() {
-    return chance_of_permuting_phi_operands_;
-  }
-  uint32_t GetChanceOfPropagatingInstructionsUp() {
-    return chance_of_propagating_instructions_up_;
-  }
-  uint32_t GetChanceOfPushingIdThroughVariable() {
-    return chance_of_pushing_id_through_variable_;
-  }
-  uint32_t GetChanceOfReplacingAddSubMulWithCarryingExtended() {
-    return chance_of_replacing_add_sub_mul_with_carrying_extended_;
-  }
-  uint32_t GetChanceOfReplacingCopyMemoryWithLoadStore() {
-    return chance_of_replacing_copy_memory_with_load_store_;
-  }
-  uint32_t GetChanceOfReplacingCopyObjectWithStoreLoad() {
-    return chance_of_replacing_copyobject_with_store_load_;
-  }
-  uint32_t GetChanceOfReplacingIdWithSynonym() {
-    return chance_of_replacing_id_with_synonym_;
-  }
-  uint32_t GetChanceOfReplacingLinearAlgebraInstructions() {
-    return chance_of_replacing_linear_algebra_instructions_;
-  }
-  uint32_t GetChanceOfReplacingLoadStoreWithCopyMemory() {
-    return chance_of_replacing_load_store_with_copy_memory_;
-  }
-  uint32_t GetChanceOfReplacingParametersWithGlobals() {
-    return chance_of_replacing_parameters_with_globals_;
-  }
-  uint32_t GetChanceOfReplacingParametersWithStruct() {
-    return chance_of_replacing_parameters_with_struct_;
-  }
-  uint32_t GetChanceOfSplittingBlock() { return chance_of_splitting_block_; }
-  uint32_t GetChanceOfSwappingConditionalBranchOperands() {
-    return chance_of_swapping_conditional_branch_operands_;
-  }
-  uint32_t GetChanceOfTogglingAccessChainInstruction() {
-    return chance_of_toggling_access_chain_instruction_;
-  }
-
-  // Other functions to control transformations. Keep them in alphabetical
-  // order.
-  uint32_t GetMaximumEquivalenceClassSizeForDataSynonymFactClosure() {
-    return max_equivalence_class_size_for_data_synonym_fact_closure_;
-  }
-  uint32_t GetMaximumNumberOfFunctionParameters() {
-    return max_number_of_function_parameters_;
-  }
-  uint32_t GetMaximumNumberOfParametersReplacedWithStruct() {
-    return max_number_of_parameters_replaced_with_struct_;
-  }
-  std::pair<uint32_t, uint32_t> GetRandomBranchWeights() {
-    std::pair<uint32_t, uint32_t> branch_weights = {0, 0};
-
-    while (branch_weights.first == 0 && branch_weights.second == 0) {
-      // Using INT32_MAX to do not overflow UINT32_MAX when the branch weights
-      // are added together.
-      branch_weights.first = random_generator_->RandomUint32(INT32_MAX);
-      branch_weights.second = random_generator_->RandomUint32(INT32_MAX);
-    }
-
-    return branch_weights;
-  }
-  std::vector<uint32_t> GetRandomComponentsForVectorShuffle(
-      uint32_t max_component_index) {
-    // Component count must be in range [2, 4].
-    std::vector<uint32_t> components(random_generator_->RandomUint32(2) + 2);
-
-    for (uint32_t& component : components) {
-      component = random_generator_->RandomUint32(max_component_index);
-    }
-
-    return components;
-  }
-  uint32_t GetRandomIndexForAccessChain(uint32_t composite_size_bound) {
-    return random_generator_->RandomUint32(composite_size_bound);
-  }
-  uint32_t GetRandomIndexForCompositeInsert(uint32_t number_of_components) {
-    return random_generator_->RandomUint32(number_of_components);
-  }
-  uint32_t GetRandomLoopControlPartialCount() {
-    return random_generator_->RandomUint32(max_loop_control_partial_count_);
-  }
-  uint32_t GetRandomLoopControlPeelCount() {
-    return random_generator_->RandomUint32(max_loop_control_peel_count_);
-  }
-  uint32_t GetRandomLoopLimit() {
-    return random_generator_->RandomUint32(max_loop_limit_);
-  }
-  uint32_t GetRandomNumberOfNewParameters(uint32_t num_of_params) {
-    assert(num_of_params < GetMaximumNumberOfFunctionParameters());
-    return ChooseBetweenMinAndMax(
-        {1, std::min(max_number_of_new_parameters_,
-                     GetMaximumNumberOfFunctionParameters() - num_of_params)});
-  }
-  uint32_t GetRandomNumberOfParametersReplacedWithStruct(uint32_t num_params) {
-    assert(num_params != 0 && "A function must have parameters to replace");
-    return ChooseBetweenMinAndMax(
-        {1, std::min(num_params,
-                     GetMaximumNumberOfParametersReplacedWithStruct())});
-  }
-  uint32_t GetRandomSizeForNewArray() {
-    // Ensure that the array size is non-zero.
-    return random_generator_->RandomUint32(max_new_array_size_limit_ - 1) + 1;
-  }
-  protobufs::TransformationAddSynonym::SynonymType GetRandomSynonymType();
-  uint32_t GetRandomUnusedComponentCountForImageSample(
-      uint32_t max_unused_component_count) {
-    // Ensure that the number of unused components is non-zero.
-    return random_generator_->RandomUint32(max_unused_component_count) + 1;
-  }
-  bool GoDeeperInConstantObfuscation(uint32_t depth) {
-    return go_deeper_in_constant_obfuscation_(depth, random_generator_);
-  }
-
- private:
-  // The source of randomness.
-  RandomGenerator* random_generator_;
-  // The next fresh id to be issued.
-  uint32_t next_fresh_id_;
-
-  // Probabilities associated with applying various transformations.
-  // Keep them in alphabetical order.
-  uint32_t chance_of_adding_access_chain_;
-  uint32_t chance_of_adding_another_struct_field_;
-  uint32_t chance_of_adding_array_or_struct_type_;
-  uint32_t chance_of_adding_composite_insert_;
-  uint32_t chance_of_adding_copy_memory_;
-  uint32_t chance_of_adding_dead_block_;
-  uint32_t chance_of_adding_dead_break_;
-  uint32_t chance_of_adding_dead_continue_;
-  uint32_t chance_of_adding_equation_instruction_;
-  uint32_t chance_of_adding_global_variable_;
-  uint32_t chance_of_adding_image_sample_unused_components_;
-  uint32_t chance_of_adding_load_;
-  uint32_t chance_of_adding_local_variable_;
-  uint32_t chance_of_adding_loop_preheader_;
-  uint32_t chance_of_adding_matrix_type_;
-  uint32_t chance_of_adding_no_contraction_decoration_;
-  uint32_t chance_of_adding_opphi_synonym_;
-  uint32_t chance_of_adding_parameters;
-  uint32_t chance_of_adding_relaxed_decoration_;
-  uint32_t chance_of_adding_store_;
-  uint32_t chance_of_adding_synonyms_;
-  uint32_t chance_of_adding_vector_shuffle_;
-  uint32_t chance_of_adding_vector_type_;
-  uint32_t chance_of_adjusting_branch_weights_;
-  uint32_t chance_of_adjusting_function_control_;
-  uint32_t chance_of_adjusting_loop_control_;
-  uint32_t chance_of_adjusting_memory_operands_mask_;
-  uint32_t chance_of_adjusting_selection_control_;
-  uint32_t chance_of_calling_function_;
-  uint32_t chance_of_choosing_struct_type_vs_array_type_;
-  uint32_t chance_of_choosing_workgroup_storage_class_;
-  uint32_t chance_of_constructing_composite_;
-  uint32_t chance_of_copying_object_;
-  uint32_t chance_of_donating_additional_module_;
-  uint32_t chance_of_going_deeper_to_insert_in_composite_;
-  uint32_t chance_of_going_deeper_when_making_access_chain_;
-  uint32_t chance_of_inlining_function_;
-  uint32_t chance_of_interchanging_signedness_of_integer_operands_;
-  uint32_t chance_of_interchanging_zero_like_constants_;
-  uint32_t chance_of_inverting_comparison_operators_;
-  uint32_t chance_of_making_donor_livesafe_;
-  uint32_t chance_of_making_vector_operation_dynamic_;
-  uint32_t chance_of_merging_blocks_;
-  uint32_t chance_of_moving_block_down_;
-  uint32_t chance_of_obfuscating_constant_;
-  uint32_t chance_of_outlining_function_;
-  uint32_t chance_of_permuting_instructions_;
-  uint32_t chance_of_permuting_parameters_;
-  uint32_t chance_of_permuting_phi_operands_;
-  uint32_t chance_of_propagating_instructions_up_;
-  uint32_t chance_of_pushing_id_through_variable_;
-  uint32_t chance_of_replacing_add_sub_mul_with_carrying_extended_;
-  uint32_t chance_of_replacing_copy_memory_with_load_store_;
-  uint32_t chance_of_replacing_copyobject_with_store_load_;
-  uint32_t chance_of_replacing_id_with_synonym_;
-  uint32_t chance_of_replacing_linear_algebra_instructions_;
-  uint32_t chance_of_replacing_load_store_with_copy_memory_;
-  uint32_t chance_of_replacing_parameters_with_globals_;
-  uint32_t chance_of_replacing_parameters_with_struct_;
-  uint32_t chance_of_splitting_block_;
-  uint32_t chance_of_swapping_conditional_branch_operands_;
-  uint32_t chance_of_toggling_access_chain_instruction_;
-
-  // Limits associated with various quantities for which random values are
-  // chosen during fuzzing.
-  // Keep them in alphabetical order.
-  uint32_t max_equivalence_class_size_for_data_synonym_fact_closure_;
-  uint32_t max_loop_control_partial_count_;
-  uint32_t max_loop_control_peel_count_;
-  uint32_t max_loop_limit_;
-  uint32_t max_new_array_size_limit_;
-  uint32_t max_number_of_function_parameters_;
-  uint32_t max_number_of_new_parameters_;
-  uint32_t max_number_of_parameters_replaced_with_struct_;
-
-  // Functions to determine with what probability to go deeper when generating
-  // or mutating constructs recursively.
-  const std::function<bool(uint32_t, RandomGenerator*)>&
-      go_deeper_in_constant_obfuscation_;
-
-  // Requires |min_max.first| <= |min_max.second|, and returns a value in the
-  // range [ |min_max.first|, |min_max.second| ]
-  uint32_t ChooseBetweenMinAndMax(const std::pair<uint32_t, uint32_t>& min_max);
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_CONTEXT_H_

+ 0 - 715
3rdparty/spirv-tools/source/fuzz/fuzzer_pass.cpp

@@ -1,715 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass.h"
-
-#include <set>
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/id_use_descriptor.h"
-#include "source/fuzz/instruction_descriptor.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_global_undef.h"
-#include "source/fuzz/transformation_add_global_variable.h"
-#include "source/fuzz/transformation_add_local_variable.h"
-#include "source/fuzz/transformation_add_loop_preheader.h"
-#include "source/fuzz/transformation_add_type_boolean.h"
-#include "source/fuzz/transformation_add_type_float.h"
-#include "source/fuzz/transformation_add_type_function.h"
-#include "source/fuzz/transformation_add_type_int.h"
-#include "source/fuzz/transformation_add_type_matrix.h"
-#include "source/fuzz/transformation_add_type_pointer.h"
-#include "source/fuzz/transformation_add_type_struct.h"
-#include "source/fuzz/transformation_add_type_vector.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPass::FuzzerPass(opt::IRContext* ir_context,
-                       TransformationContext* transformation_context,
-                       FuzzerContext* fuzzer_context,
-                       protobufs::TransformationSequence* transformations)
-    : ir_context_(ir_context),
-      transformation_context_(transformation_context),
-      fuzzer_context_(fuzzer_context),
-      transformations_(transformations) {}
-
-FuzzerPass::~FuzzerPass() = default;
-
-std::vector<opt::Instruction*> FuzzerPass::FindAvailableInstructions(
-    opt::Function* function, opt::BasicBlock* block,
-    const opt::BasicBlock::iterator& inst_it,
-    std::function<bool(opt::IRContext*, opt::Instruction*)>
-        instruction_is_relevant) const {
-  // TODO(afd) The following is (relatively) simple, but may end up being
-  //  prohibitively inefficient, as it walks the whole dominator tree for
-  //  every instruction that is considered.
-
-  std::vector<opt::Instruction*> result;
-  // Consider all global declarations
-  for (auto& global : GetIRContext()->module()->types_values()) {
-    if (instruction_is_relevant(GetIRContext(), &global)) {
-      result.push_back(&global);
-    }
-  }
-
-  // Consider all function parameters
-  function->ForEachParam(
-      [this, &instruction_is_relevant, &result](opt::Instruction* param) {
-        if (instruction_is_relevant(GetIRContext(), param)) {
-          result.push_back(param);
-        }
-      });
-
-  // Consider all previous instructions in this block
-  for (auto prev_inst_it = block->begin(); prev_inst_it != inst_it;
-       ++prev_inst_it) {
-    if (instruction_is_relevant(GetIRContext(), &*prev_inst_it)) {
-      result.push_back(&*prev_inst_it);
-    }
-  }
-
-  // Walk the dominator tree to consider all instructions from dominating
-  // blocks
-  auto dominator_analysis = GetIRContext()->GetDominatorAnalysis(function);
-  for (auto next_dominator = dominator_analysis->ImmediateDominator(block);
-       next_dominator != nullptr;
-       next_dominator =
-           dominator_analysis->ImmediateDominator(next_dominator)) {
-    for (auto& dominating_inst : *next_dominator) {
-      if (instruction_is_relevant(GetIRContext(), &dominating_inst)) {
-        result.push_back(&dominating_inst);
-      }
-    }
-  }
-  return result;
-}
-
-void FuzzerPass::ForEachInstructionWithInstructionDescriptor(
-    std::function<
-        void(opt::Function* function, opt::BasicBlock* block,
-             opt::BasicBlock::iterator inst_it,
-             const protobufs::InstructionDescriptor& instruction_descriptor)>
-        action) {
-  // Consider every block in every function.
-  for (auto& function : *GetIRContext()->module()) {
-    for (auto& block : function) {
-      // We now consider every instruction in the block, randomly deciding
-      // whether to apply a transformation before it.
-
-      // In order for transformations to insert new instructions, they need to
-      // be able to identify the instruction to insert before.  We describe an
-      // instruction via its opcode, 'opc', a base instruction 'base' that has a
-      // result id, and the number of instructions with opcode 'opc' that we
-      // should skip when searching from 'base' for the desired instruction.
-      // (An instruction that has a result id is represented by its own opcode,
-      // itself as 'base', and a skip-count of 0.)
-      std::vector<std::tuple<uint32_t, SpvOp, uint32_t>>
-          base_opcode_skip_triples;
-
-      // The initial base instruction is the block label.
-      uint32_t base = block.id();
-
-      // Counts the number of times we have seen each opcode since we reset the
-      // base instruction.
-      std::map<SpvOp, uint32_t> skip_count;
-
-      // Consider every instruction in the block.  The label is excluded: it is
-      // only necessary to consider it as a base in case the first instruction
-      // in the block does not have a result id.
-      for (auto inst_it = block.begin(); inst_it != block.end(); ++inst_it) {
-        if (inst_it->HasResultId()) {
-          // In the case that the instruction has a result id, we use the
-          // instruction as its own base, and clear the skip counts we have
-          // collected.
-          base = inst_it->result_id();
-          skip_count.clear();
-        }
-        const SpvOp opcode = inst_it->opcode();
-
-        // Invoke the provided function, which might apply a transformation.
-        action(&function, &block, inst_it,
-               MakeInstructionDescriptor(
-                   base, opcode,
-                   skip_count.count(opcode) ? skip_count.at(opcode) : 0));
-
-        if (!inst_it->HasResultId()) {
-          skip_count[opcode] =
-              skip_count.count(opcode) ? skip_count.at(opcode) + 1 : 1;
-        }
-      }
-    }
-  }
-}
-
-uint32_t FuzzerPass::FindOrCreateBoolType() {
-  if (auto existing_id = fuzzerutil::MaybeGetBoolType(GetIRContext())) {
-    return existing_id;
-  }
-  auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(TransformationAddTypeBoolean(result));
-  return result;
-}
-
-uint32_t FuzzerPass::FindOrCreateIntegerType(uint32_t width, bool is_signed) {
-  opt::analysis::Integer int_type(width, is_signed);
-  auto existing_id = GetIRContext()->get_type_mgr()->GetId(&int_type);
-  if (existing_id) {
-    return existing_id;
-  }
-  auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(TransformationAddTypeInt(result, width, is_signed));
-  return result;
-}
-
-uint32_t FuzzerPass::FindOrCreateFloatType(uint32_t width) {
-  opt::analysis::Float float_type(width);
-  auto existing_id = GetIRContext()->get_type_mgr()->GetId(&float_type);
-  if (existing_id) {
-    return existing_id;
-  }
-  auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(TransformationAddTypeFloat(result, width));
-  return result;
-}
-
-uint32_t FuzzerPass::FindOrCreateFunctionType(
-    uint32_t return_type_id, const std::vector<uint32_t>& argument_id) {
-  // FindFunctionType has a sigle argument for OpTypeFunction operands
-  // so we will have to copy them all in this vector
-  std::vector<uint32_t> type_ids(argument_id.size() + 1);
-  type_ids[0] = return_type_id;
-  std::copy(argument_id.begin(), argument_id.end(), type_ids.begin() + 1);
-
-  // Check if type exists
-  auto existing_id = fuzzerutil::FindFunctionType(GetIRContext(), type_ids);
-  if (existing_id) {
-    return existing_id;
-  }
-
-  auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(
-      TransformationAddTypeFunction(result, return_type_id, argument_id));
-  return result;
-}
-
-uint32_t FuzzerPass::FindOrCreateVectorType(uint32_t component_type_id,
-                                            uint32_t component_count) {
-  assert(component_count >= 2 && component_count <= 4 &&
-         "Precondition: component count must be in range [2, 4].");
-  opt::analysis::Type* component_type =
-      GetIRContext()->get_type_mgr()->GetType(component_type_id);
-  assert(component_type && "Precondition: the component type must exist.");
-  opt::analysis::Vector vector_type(component_type, component_count);
-  auto existing_id = GetIRContext()->get_type_mgr()->GetId(&vector_type);
-  if (existing_id) {
-    return existing_id;
-  }
-  auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(
-      TransformationAddTypeVector(result, component_type_id, component_count));
-  return result;
-}
-
-uint32_t FuzzerPass::FindOrCreateMatrixType(uint32_t column_count,
-                                            uint32_t row_count) {
-  assert(column_count >= 2 && column_count <= 4 &&
-         "Precondition: column count must be in range [2, 4].");
-  assert(row_count >= 2 && row_count <= 4 &&
-         "Precondition: row count must be in range [2, 4].");
-  uint32_t column_type_id =
-      FindOrCreateVectorType(FindOrCreateFloatType(32), row_count);
-  opt::analysis::Type* column_type =
-      GetIRContext()->get_type_mgr()->GetType(column_type_id);
-  opt::analysis::Matrix matrix_type(column_type, column_count);
-  auto existing_id = GetIRContext()->get_type_mgr()->GetId(&matrix_type);
-  if (existing_id) {
-    return existing_id;
-  }
-  auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(
-      TransformationAddTypeMatrix(result, column_type_id, column_count));
-  return result;
-}
-
-uint32_t FuzzerPass::FindOrCreateStructType(
-    const std::vector<uint32_t>& component_type_ids) {
-  if (auto existing_id =
-          fuzzerutil::MaybeGetStructType(GetIRContext(), component_type_ids)) {
-    return existing_id;
-  }
-  auto new_id = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(TransformationAddTypeStruct(new_id, component_type_ids));
-  return new_id;
-}
-
-uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id,
-                                             SpvStorageClass storage_class) {
-  // We do not use the type manager here, due to problems related to isomorphic
-  // but distinct structs not being regarded as different.
-  auto existing_id = fuzzerutil::MaybeGetPointerType(
-      GetIRContext(), base_type_id, storage_class);
-  if (existing_id) {
-    return existing_id;
-  }
-  auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(
-      TransformationAddTypePointer(result, storage_class, base_type_id));
-  return result;
-}
-
-uint32_t FuzzerPass::FindOrCreatePointerToIntegerType(
-    uint32_t width, bool is_signed, SpvStorageClass storage_class) {
-  return FindOrCreatePointerType(FindOrCreateIntegerType(width, is_signed),
-                                 storage_class);
-}
-
-uint32_t FuzzerPass::FindOrCreateIntegerConstant(
-    const std::vector<uint32_t>& words, uint32_t width, bool is_signed,
-    bool is_irrelevant) {
-  auto int_type_id = FindOrCreateIntegerType(width, is_signed);
-  if (auto constant_id = fuzzerutil::MaybeGetScalarConstant(
-          GetIRContext(), *GetTransformationContext(), words, int_type_id,
-          is_irrelevant)) {
-    return constant_id;
-  }
-  auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(TransformationAddConstantScalar(result, int_type_id,
-                                                      words, is_irrelevant));
-  return result;
-}
-
-uint32_t FuzzerPass::FindOrCreateFloatConstant(
-    const std::vector<uint32_t>& words, uint32_t width, bool is_irrelevant) {
-  auto float_type_id = FindOrCreateFloatType(width);
-  if (auto constant_id = fuzzerutil::MaybeGetScalarConstant(
-          GetIRContext(), *GetTransformationContext(), words, float_type_id,
-          is_irrelevant)) {
-    return constant_id;
-  }
-  auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(TransformationAddConstantScalar(result, float_type_id,
-                                                      words, is_irrelevant));
-  return result;
-}
-
-uint32_t FuzzerPass::FindOrCreateBoolConstant(bool value, bool is_irrelevant) {
-  auto bool_type_id = FindOrCreateBoolType();
-  if (auto constant_id = fuzzerutil::MaybeGetScalarConstant(
-          GetIRContext(), *GetTransformationContext(), {value ? 1u : 0u},
-          bool_type_id, is_irrelevant)) {
-    return constant_id;
-  }
-  auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(
-      TransformationAddConstantBoolean(result, value, is_irrelevant));
-  return result;
-}
-
-uint32_t FuzzerPass::FindOrCreateConstant(const std::vector<uint32_t>& words,
-                                          uint32_t type_id,
-                                          bool is_irrelevant) {
-  assert(type_id && "Constant's type id can't be 0.");
-
-  const auto* type = GetIRContext()->get_type_mgr()->GetType(type_id);
-  assert(type && "Type does not exist.");
-
-  if (type->AsBool()) {
-    assert(words.size() == 1);
-    return FindOrCreateBoolConstant(words[0], is_irrelevant);
-  } else if (const auto* integer = type->AsInteger()) {
-    return FindOrCreateIntegerConstant(words, integer->width(),
-                                       integer->IsSigned(), is_irrelevant);
-  } else if (const auto* floating = type->AsFloat()) {
-    return FindOrCreateFloatConstant(words, floating->width(), is_irrelevant);
-  }
-
-  // This assertion will fail in debug build but not in release build
-  // so we return 0 to make compiler happy.
-  assert(false && "Constant type is not supported");
-  return 0;
-}
-
-uint32_t FuzzerPass::FindOrCreateCompositeConstant(
-    const std::vector<uint32_t>& component_ids, uint32_t type_id,
-    bool is_irrelevant) {
-  if (auto existing_constant = fuzzerutil::MaybeGetCompositeConstant(
-          GetIRContext(), *GetTransformationContext(), component_ids, type_id,
-          is_irrelevant)) {
-    return existing_constant;
-  }
-  uint32_t result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(TransformationAddConstantComposite(
-      result, type_id, component_ids, is_irrelevant));
-  return result;
-}
-
-uint32_t FuzzerPass::FindOrCreateGlobalUndef(uint32_t type_id) {
-  for (auto& inst : GetIRContext()->types_values()) {
-    if (inst.opcode() == SpvOpUndef && inst.type_id() == type_id) {
-      return inst.result_id();
-    }
-  }
-  auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(TransformationAddGlobalUndef(result, type_id));
-  return result;
-}
-
-uint32_t FuzzerPass::FindOrCreateNullConstant(uint32_t type_id) {
-  // Find existing declaration
-  opt::analysis::NullConstant null_constant(
-      GetIRContext()->get_type_mgr()->GetType(type_id));
-  auto existing_constant =
-      GetIRContext()->get_constant_mgr()->FindConstant(&null_constant);
-
-  // Return if found
-  if (existing_constant) {
-    return GetIRContext()
-        ->get_constant_mgr()
-        ->GetDefiningInstruction(existing_constant)
-        ->result_id();
-  }
-
-  // Create new if not found
-  auto result = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(TransformationAddConstantNull(result, type_id));
-  return result;
-}
-
-std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
-FuzzerPass::GetAvailableBasicTypesAndPointers(
-    SpvStorageClass storage_class) const {
-  // Records all of the basic types available in the module.
-  std::set<uint32_t> basic_types;
-
-  // 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 SpvOpTypeBool:
-      case SpvOpTypeFloat:
-      case SpvOpTypeInt:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeVector:
-        // 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 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 {{basic_types.begin(), basic_types.end()}, basic_type_to_pointers};
-}
-
-uint32_t FuzzerPass::FindOrCreateZeroConstant(
-    uint32_t scalar_or_composite_type_id, bool is_irrelevant) {
-  auto type_instruction =
-      GetIRContext()->get_def_use_mgr()->GetDef(scalar_or_composite_type_id);
-  assert(type_instruction && "The type instruction must exist.");
-  switch (type_instruction->opcode()) {
-    case SpvOpTypeBool:
-      return FindOrCreateBoolConstant(false, is_irrelevant);
-    case SpvOpTypeFloat: {
-      auto width = type_instruction->GetSingleWordInOperand(0);
-      auto num_words = (width + 32 - 1) / 32;
-      return FindOrCreateFloatConstant(std::vector<uint32_t>(num_words, 0),
-                                       width, is_irrelevant);
-    }
-    case SpvOpTypeInt: {
-      auto width = type_instruction->GetSingleWordInOperand(0);
-      auto num_words = (width + 32 - 1) / 32;
-      return FindOrCreateIntegerConstant(
-          std::vector<uint32_t>(num_words, 0), width,
-          type_instruction->GetSingleWordInOperand(1), is_irrelevant);
-    }
-    case SpvOpTypeArray: {
-      auto component_type_id = type_instruction->GetSingleWordInOperand(0);
-      auto num_components =
-          fuzzerutil::GetArraySize(*type_instruction, GetIRContext());
-      return FindOrCreateCompositeConstant(
-          std::vector<uint32_t>(
-              num_components,
-              FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
-          scalar_or_composite_type_id, is_irrelevant);
-    }
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector: {
-      auto component_type_id = type_instruction->GetSingleWordInOperand(0);
-      auto num_components = type_instruction->GetSingleWordInOperand(1);
-      return FindOrCreateCompositeConstant(
-          std::vector<uint32_t>(
-              num_components,
-              FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
-          scalar_or_composite_type_id, is_irrelevant);
-    }
-    case SpvOpTypeStruct: {
-      std::vector<uint32_t> field_zero_ids;
-      for (uint32_t index = 0; index < type_instruction->NumInOperands();
-           index++) {
-        field_zero_ids.push_back(FindOrCreateZeroConstant(
-            type_instruction->GetSingleWordInOperand(index), is_irrelevant));
-      }
-      return FindOrCreateCompositeConstant(
-          field_zero_ids, scalar_or_composite_type_id, is_irrelevant);
-    }
-    default:
-      assert(false && "Unknown type.");
-      return 0;
-  }
-}
-
-bool FuzzerPass::CanFindOrCreateZeroConstant(const opt::analysis::Type& type) {
-  switch (type.kind()) {
-    case opt::analysis::Type::kBool:
-    case opt::analysis::Type::kInteger:
-    case opt::analysis::Type::kFloat:
-    case opt::analysis::Type::kArray:
-    case opt::analysis::Type::kMatrix:
-    case opt::analysis::Type::kVector:
-      return true;
-    case opt::analysis::Type::kStruct:
-      return std::all_of(type.AsStruct()->element_types().begin(),
-                         type.AsStruct()->element_types().end(),
-                         [this](const opt::analysis::Type* element_type) {
-                           return CanFindOrCreateZeroConstant(*element_type);
-                         });
-    default:
-      return false;
-  }
-}
-
-void FuzzerPass::MaybeAddUseToReplace(
-    opt::Instruction* use_inst, uint32_t use_index, uint32_t replacement_id,
-    std::vector<std::pair<protobufs::IdUseDescriptor, uint32_t>>*
-        uses_to_replace) {
-  // Only consider this use if it is in a block
-  if (!GetIRContext()->get_instr_block(use_inst)) {
-    return;
-  }
-
-  // Get the index of the operand restricted to input operands.
-  uint32_t in_operand_index =
-      fuzzerutil::InOperandIndexFromOperandIndex(*use_inst, use_index);
-  auto id_use_descriptor =
-      MakeIdUseDescriptorFromUse(GetIRContext(), use_inst, in_operand_index);
-  uses_to_replace->emplace_back(
-      std::make_pair(id_use_descriptor, replacement_id));
-}
-
-opt::BasicBlock* FuzzerPass::GetOrCreateSimpleLoopPreheader(
-    uint32_t header_id) {
-  auto header_block = fuzzerutil::MaybeFindBlock(GetIRContext(), header_id);
-
-  assert(header_block && header_block->IsLoopHeader() &&
-         "|header_id| should be the label id of a loop header");
-
-  auto predecessors = GetIRContext()->cfg()->preds(header_id);
-
-  assert(predecessors.size() >= 2 &&
-         "The block |header_id| should be reachable.");
-
-  auto function = header_block->GetParent();
-
-  if (predecessors.size() == 2) {
-    // The header has a single out-of-loop predecessor, which could be a
-    // preheader.
-
-    opt::BasicBlock* maybe_preheader;
-
-    if (GetIRContext()->GetDominatorAnalysis(function)->Dominates(
-            header_id, predecessors[0])) {
-      // The first predecessor is the back-edge block, because the header
-      // dominates it, so the second one is out of the loop.
-      maybe_preheader = &*function->FindBlock(predecessors[1]);
-    } else {
-      // The first predecessor is out of the loop.
-      maybe_preheader = &*function->FindBlock(predecessors[0]);
-    }
-
-    // |maybe_preheader| is a preheader if it branches unconditionally to
-    // the header. We also require it not to be a loop header.
-    if (maybe_preheader->terminator()->opcode() == SpvOpBranch &&
-        !maybe_preheader->IsLoopHeader()) {
-      return maybe_preheader;
-    }
-  }
-
-  // We need to add a preheader.
-
-  // Get a fresh id for the preheader.
-  uint32_t preheader_id = GetFuzzerContext()->GetFreshId();
-
-  // Get a fresh id for each OpPhi instruction, if there is more than one
-  // out-of-loop predecessor.
-  std::vector<uint32_t> phi_ids;
-  if (predecessors.size() > 2) {
-    header_block->ForEachPhiInst(
-        [this, &phi_ids](opt::Instruction* /* unused */) {
-          phi_ids.push_back(GetFuzzerContext()->GetFreshId());
-        });
-  }
-
-  // Add the preheader.
-  ApplyTransformation(
-      TransformationAddLoopPreheader(header_id, preheader_id, phi_ids));
-
-  // Make the newly-created preheader the new entry block.
-  return &*function->FindBlock(preheader_id);
-}
-
-uint32_t FuzzerPass::FindOrCreateLocalVariable(
-    uint32_t pointer_type_id, uint32_t function_id,
-    bool pointee_value_is_irrelevant) {
-  auto pointer_type = GetIRContext()->get_type_mgr()->GetType(pointer_type_id);
-  // No unused variables in release mode.
-  (void)pointer_type;
-  assert(pointer_type && pointer_type->AsPointer() &&
-         pointer_type->AsPointer()->storage_class() ==
-             SpvStorageClassFunction &&
-         "The pointer_type_id must refer to a defined pointer type with "
-         "storage class Function");
-  auto function = fuzzerutil::FindFunction(GetIRContext(), function_id);
-  assert(function && "The function must be defined.");
-
-  // First we try to find a suitable existing variable.
-  // All of the local variable declarations are located in the first block.
-  for (auto& instruction : *function->begin()) {
-    if (instruction.opcode() != SpvOpVariable) {
-      continue;
-    }
-    // The existing OpVariable must have type |pointer_type_id|.
-    if (instruction.type_id() != pointer_type_id) {
-      continue;
-    }
-    // Check if the found variable is marked with PointeeValueIsIrrelevant
-    // according to |pointee_value_is_irrelevant|.
-    if (GetTransformationContext()->GetFactManager()->PointeeValueIsIrrelevant(
-            instruction.result_id()) != pointee_value_is_irrelevant) {
-      continue;
-    }
-    return instruction.result_id();
-  }
-
-  // No such variable was found. Apply a transformation to get one.
-  uint32_t pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
-      GetIRContext(), pointer_type_id);
-  uint32_t result_id = GetFuzzerContext()->GetFreshId();
-  ApplyTransformation(TransformationAddLocalVariable(
-      result_id, pointer_type_id, function_id,
-      FindOrCreateZeroConstant(pointee_type_id, pointee_value_is_irrelevant),
-      pointee_value_is_irrelevant));
-  return result_id;
-}
-
-uint32_t FuzzerPass::FindOrCreateGlobalVariable(
-    uint32_t pointer_type_id, bool pointee_value_is_irrelevant) {
-  auto pointer_type = GetIRContext()->get_type_mgr()->GetType(pointer_type_id);
-  // No unused variables in release mode.
-  (void)pointer_type;
-  assert(
-      pointer_type && pointer_type->AsPointer() &&
-      (pointer_type->AsPointer()->storage_class() == SpvStorageClassPrivate ||
-       pointer_type->AsPointer()->storage_class() ==
-           SpvStorageClassWorkgroup) &&
-      "The pointer_type_id must refer to a defined pointer type with storage "
-      "class Private or Workgroup");
-
-  // First we try to find a suitable existing variable.
-  for (auto& instruction : GetIRContext()->module()->types_values()) {
-    if (instruction.opcode() != SpvOpVariable) {
-      continue;
-    }
-    // The existing OpVariable must have type |pointer_type_id|.
-    if (instruction.type_id() != pointer_type_id) {
-      continue;
-    }
-    // Check if the found variable is marked with PointeeValueIsIrrelevant
-    // according to |pointee_value_is_irrelevant|.
-    if (GetTransformationContext()->GetFactManager()->PointeeValueIsIrrelevant(
-            instruction.result_id()) != pointee_value_is_irrelevant) {
-      continue;
-    }
-    return instruction.result_id();
-  }
-
-  // No such variable was found. Apply a transformation to get one.
-  uint32_t pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
-      GetIRContext(), pointer_type_id);
-  auto storage_class = fuzzerutil::GetStorageClassFromPointerType(
-      GetIRContext(), pointer_type_id);
-  uint32_t result_id = GetFuzzerContext()->GetFreshId();
-
-  // A variable with storage class Workgroup shouldn't have an initializer.
-  if (storage_class == SpvStorageClassWorkgroup) {
-    ApplyTransformation(TransformationAddGlobalVariable(
-        result_id, pointer_type_id, SpvStorageClassWorkgroup, 0,
-        pointee_value_is_irrelevant));
-  } else {
-    ApplyTransformation(TransformationAddGlobalVariable(
-        result_id, pointer_type_id, SpvStorageClassPrivate,
-        FindOrCreateZeroConstant(pointee_type_id, pointee_value_is_irrelevant),
-        pointee_value_is_irrelevant));
-  }
-  return result_id;
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 330
3rdparty/spirv-tools/source/fuzz/fuzzer_pass.h

@@ -1,330 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_H_
-
-#include <functional>
-#include <vector>
-
-#include "source/fuzz/fuzzer_context.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 {
-
-// Interface for applying a pass of transformations to a module.
-class FuzzerPass {
- public:
-  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
-  // 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_; }
-
-  TransformationContext* GetTransformationContext() const {
-    return transformation_context_;
-  }
-
-  FuzzerContext* GetFuzzerContext() const { return fuzzer_context_; }
-
-  protobufs::TransformationSequence* GetTransformations() const {
-    return transformations_;
-  }
-
-  // Returns all instructions that are *available* at |inst_it|, which is
-  // required to be inside block |block| of function |function| - that is, all
-  // instructions at global scope and all instructions that strictly dominate
-  // |inst_it|.
-  //
-  // Filters said instructions to return only those that satisfy the
-  // |instruction_is_relevant| predicate.  This, for instance, could ignore all
-  // instructions that have a particular decoration.
-  std::vector<opt::Instruction*> FindAvailableInstructions(
-      opt::Function* function, opt::BasicBlock* block,
-      const opt::BasicBlock::iterator& inst_it,
-      std::function<bool(opt::IRContext*, opt::Instruction*)>
-          instruction_is_relevant) const;
-
-  // A helper method that iterates through each instruction in each block, at
-  // all times tracking an instruction descriptor that allows the latest
-  // instruction to be located even if it has no result id.
-  //
-  // The code to manipulate the instruction descriptor is a bit fiddly.  The
-  // point of this method is to avoiding having to duplicate it in multiple
-  // transformation passes.
-  //
-  // The function |action| is invoked for each instruction |inst_it| in block
-  // |block| of function |function| that is encountered.  The
-  // |instruction_descriptor| parameter to the function object allows |inst_it|
-  // to be identified.
-  //
-  // In most intended use cases, the job of |action| is to randomly decide
-  // whether to try to apply some transformation, and then - if selected - to
-  // attempt to apply it.
-  void ForEachInstructionWithInstructionDescriptor(
-      std::function<
-          void(opt::Function* function, opt::BasicBlock* block,
-               opt::BasicBlock::iterator inst_it,
-               const protobufs::InstructionDescriptor& instruction_descriptor)>
-          action);
-
-  // A generic helper for applying a transformation that should be applicable
-  // by construction, and adding it to the sequence of applied transformations.
-  void ApplyTransformation(const Transformation& transformation) {
-    assert(transformation.IsApplicable(GetIRContext(),
-                                       *GetTransformationContext()) &&
-           "Transformation should be applicable by construction.");
-    transformation.Apply(GetIRContext(), GetTransformationContext());
-    *GetTransformations()->add_transformation() = transformation.ToMessage();
-  }
-
-  // A generic helper for applying a transformation only if it is applicable.
-  // If it is applicable, the transformation is applied and then added to the
-  // sequence of applied transformations and the function returns true.
-  // Otherwise, the function returns false.
-  bool MaybeApplyTransformation(const Transformation& transformation) {
-    if (transformation.IsApplicable(GetIRContext(),
-                                    *GetTransformationContext())) {
-      transformation.Apply(GetIRContext(), GetTransformationContext());
-      *GetTransformations()->add_transformation() = transformation.ToMessage();
-      return true;
-    }
-    return false;
-  }
-
-  // Returns the id of an OpTypeBool instruction.  If such an instruction does
-  // not exist, a transformation is applied to add it.
-  uint32_t FindOrCreateBoolType();
-
-  // Returns the id of an OpTypeInt instruction, with width and signedness
-  // specified by |width| and |is_signed|, respectively.  If such an instruction
-  // does not exist, a transformation is applied to add it.
-  uint32_t FindOrCreateIntegerType(uint32_t width, bool is_signed);
-
-  // Returns the id of an OpTypeFloat instruction, with width specified by
-  // |width|.  If such an instruction does not exist, a transformation is
-  // applied to add it.
-  uint32_t FindOrCreateFloatType(uint32_t width);
-
-  // Returns the id of an OpTypeFunction %<return_type_id> %<...argument_id>
-  // instruction. If such an instruction doesn't exist, a transformation
-  // is applied to create a new one.
-  uint32_t FindOrCreateFunctionType(uint32_t return_type_id,
-                                    const std::vector<uint32_t>& argument_id);
-
-  // Returns the id of an OpTypeVector instruction, with |component_type_id|
-  // (which must already exist) as its base type, and |component_count|
-  // elements (which must be in the range [2, 4]).  If such an instruction does
-  // not exist, a transformation is applied to add it.
-  uint32_t FindOrCreateVectorType(uint32_t component_type_id,
-                                  uint32_t component_count);
-
-  // Returns the id of an OpTypeMatrix instruction, with |column_count| columns
-  // and |row_count| rows (each of which must be in the range [2, 4]).  If the
-  // float and vector types required to build this matrix type or the matrix
-  // type itself do not exist, transformations are applied to add them.
-  uint32_t FindOrCreateMatrixType(uint32_t column_count, uint32_t row_count);
-
-  // Returns the id of an OpTypeStruct instruction with |component_type_ids| as
-  // type ids for struct's components. If no such a struct type exists,
-  // transformations are applied to add it. |component_type_ids| may not contain
-  // a result id of an OpTypeFunction.
-  uint32_t FindOrCreateStructType(
-      const std::vector<uint32_t>& component_type_ids);
-
-  // Returns the id of a pointer type with base type |base_type_id| (which must
-  // already exist) and storage class |storage_class|.  A transformation is
-  // applied to add the pointer if it does not already exist.
-  uint32_t FindOrCreatePointerType(uint32_t base_type_id,
-                                   SpvStorageClass storage_class);
-
-  // Returns the id of an OpTypePointer instruction, with a integer base
-  // type of width and signedness specified by |width| and |is_signed|,
-  // respectively.  If the pointer type or required integer base type do not
-  // exist, transformations are applied to add them.
-  uint32_t FindOrCreatePointerToIntegerType(uint32_t width, bool is_signed,
-                                            SpvStorageClass storage_class);
-
-  // Returns the id of an OpConstant instruction, with a integer type of
-  // width and signedness specified by |width| and |is_signed|, respectively,
-  // with |words| as its value.  If either the required integer type or the
-  // constant do not exist, transformations are applied to add them.
-  // The returned id either participates in IdIsIrrelevant fact or not,
-  // depending on the |is_irrelevant| parameter.
-  uint32_t FindOrCreateIntegerConstant(const std::vector<uint32_t>& words,
-                                       uint32_t width, bool is_signed,
-                                       bool is_irrelevant);
-
-  // Returns the id of an OpConstant instruction, with a floating-point
-  // type of width specified by |width|, with |words| as its value.  If either
-  // the required floating-point type or the constant do not exist,
-  // transformations are applied to add them. The returned id either
-  // participates in IdIsIrrelevant fact or not, depending on the
-  // |is_irrelevant| parameter.
-  uint32_t FindOrCreateFloatConstant(const std::vector<uint32_t>& words,
-                                     uint32_t width, bool is_irrelevant);
-
-  // Returns the id of an OpConstantTrue or OpConstantFalse instruction,
-  // according to |value|.  If either the required instruction or the bool
-  // type do not exist, transformations are applied to add them.
-  // The returned id either participates in IdIsIrrelevant fact or not,
-  // depending on the |is_irrelevant| parameter.
-  uint32_t FindOrCreateBoolConstant(bool value, bool is_irrelevant);
-
-  // Returns the id of an OpConstant instruction of type with |type_id|
-  // that consists of |words|. If that instruction doesn't exist,
-  // transformations are applied to add it. |type_id| must be a valid
-  // result id of either scalar or boolean OpType* instruction that exists
-  // in the module. The returned id either participates in IdIsIrrelevant fact
-  // or not, depending on the |is_irrelevant| parameter.
-  uint32_t FindOrCreateConstant(const std::vector<uint32_t>& words,
-                                uint32_t type_id, bool is_irrelevant);
-
-  // Returns the id of an OpConstantComposite instruction of type with |type_id|
-  // that consists of |component_ids|. If that instruction doesn't exist,
-  // transformations are applied to add it. |type_id| must be a valid
-  // result id of an OpType* instruction that represents a composite type
-  // (i.e. a vector, matrix, struct or array).
-  // The returned id either participates in IdIsIrrelevant fact or not,
-  // depending on the |is_irrelevant| parameter.
-  uint32_t FindOrCreateCompositeConstant(
-      const std::vector<uint32_t>& component_ids, uint32_t type_id,
-      bool is_irrelevant);
-
-  // Returns the result id of an instruction of the form:
-  //   %id = OpUndef %|type_id|
-  // If no such instruction exists, a transformation is applied to add it.
-  uint32_t FindOrCreateGlobalUndef(uint32_t type_id);
-
-  // Returns the id of an OpNullConstant instruction of type |type_id|. If
-  // that instruction doesn't exist, it is added through a transformation.
-  // |type_id| must be a valid result id of an OpType* instruction that exists
-  // in the module.
-  uint32_t FindOrCreateNullConstant(uint32_t type_id);
-
-  // 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 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 basic type and storage class.
-  std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
-  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
-  // defining a constant of the given type that is zero or false at everywhere.
-  // If such an instruction does not yet exist, transformations are applied to
-  // add it. The returned id either participates in IdIsIrrelevant fact or not,
-  // depending on the |is_irrelevant| parameter.
-  //
-  // Examples:
-  // --------------+-------------------------------
-  //   TYPE        | RESULT is id corresponding to
-  // --------------+-------------------------------
-  //   bool        | false
-  // --------------+-------------------------------
-  //   bvec4       | (false, false, false, false)
-  // --------------+-------------------------------
-  //   float       | 0.0
-  // --------------+-------------------------------
-  //   vec2        | (0.0, 0.0)
-  // --------------+-------------------------------
-  //   int[3]      | [0, 0, 0]
-  // --------------+-------------------------------
-  //   struct S {  |
-  //     int i;    | S(0, false, (0u, 0u))
-  //     bool b;   |
-  //     uint2 u;  |
-  //   }           |
-  // --------------+-------------------------------
-  uint32_t FindOrCreateZeroConstant(uint32_t scalar_or_composite_type_id,
-                                    bool is_irrelevant);
-
-  // Checks if FindOrCreateZeroConstant can be called on this type.
-  bool CanFindOrCreateZeroConstant(const opt::analysis::Type& type);
-
-  // Adds a pair (id_use_descriptor, |replacement_id|) to the vector
-  // |uses_to_replace|, where id_use_descriptor is the id use descriptor
-  // representing the usage of an id in the |use_inst| instruction, at operand
-  // index |use_index|, only if the instruction is in a basic block.
-  // If the instruction is not in a basic block, it does nothing.
-  void MaybeAddUseToReplace(
-      opt::Instruction* use_inst, uint32_t use_index, uint32_t replacement_id,
-      std::vector<std::pair<protobufs::IdUseDescriptor, uint32_t>>*
-          uses_to_replace);
-
-  // Returns the preheader of the loop with header |header_id|, which satisfies
-  // all of the following conditions:
-  // - It is the only out-of-loop predecessor of the header
-  // - It unconditionally branches to the header
-  // - It is not a loop header itself
-  // If such preheader does not exist, a new one is added and returned.
-  // Requires |header_id| to be the label id of a loop header block that is
-  // reachable in the CFG (and thus has at least 2 predecessors).
-  opt::BasicBlock* GetOrCreateSimpleLoopPreheader(uint32_t header_id);
-
-  // Returns the id of an available local variable (storage class Function) with
-  // the fact PointeeValueIsIrrelevant set according to
-  // |pointee_value_is_irrelevant|. If there is no such variable, it creates one
-  // in the |function| adding a zero initializer constant that is irrelevant.
-  // The new variable has the fact PointeeValueIsIrrelevant set according to
-  // |pointee_value_is_irrelevant|. The function returns the id of the created
-  // variable.
-  uint32_t FindOrCreateLocalVariable(uint32_t pointer_type_id,
-                                     uint32_t function_id,
-                                     bool pointee_value_is_irrelevant);
-
-  // Returns the id of an available global variable (storage class Private or
-  // Workgroup) with the fact PointeeValueIsIrrelevant set according to
-  // |pointee_value_is_irrelevant|. If there is no such variable, it creates
-  // one, adding a zero initializer constant that is irrelevant. The new
-  // variable has the fact PointeeValueIsIrrelevant set according to
-  // |pointee_value_is_irrelevant|. The function returns the id of the created
-  // variable.
-  uint32_t FindOrCreateGlobalVariable(uint32_t pointer_type_id,
-                                      bool pointee_value_is_irrelevant);
-
- private:
-  opt::IRContext* ir_context_;
-  TransformationContext* transformation_context_;
-  FuzzerContext* fuzzer_context_;
-  protobufs::TransformationSequence* transformations_;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_H_

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

@@ -1,192 +0,0 @@
-// 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/fuzzer_pass_add_access_chains.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_access_chain.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddAccessChains::FuzzerPassAddAccessChains(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddAccessChains::~FuzzerPassAddAccessChains() = default;
-
-void FuzzerPassAddAccessChains::Apply() {
-  ForEachInstructionWithInstructionDescriptor(
-      [this](opt::Function* function, opt::BasicBlock* block,
-             opt::BasicBlock::iterator inst_it,
-             const protobufs::InstructionDescriptor& instruction_descriptor)
-          -> void {
-        assert(inst_it->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
-
-        // Check whether it is legitimate to insert an access chain
-        // instruction before this instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAccessChain,
-                                                          inst_it)) {
-          return;
-        }
-
-        // Randomly decide whether to try inserting a load here.
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfAddingAccessChain())) {
-          return;
-        }
-
-        // Get all of the pointers that are currently in scope, excluding
-        // explicitly null and undefined pointers.
-        std::vector<opt::Instruction*> relevant_pointer_instructions =
-            FindAvailableInstructions(
-                function, block, inst_it,
-                [](opt::IRContext* context,
-                   opt::Instruction* instruction) -> bool {
-                  if (!instruction->result_id() || !instruction->type_id()) {
-                    // A pointer needs both a result and type id.
-                    return false;
-                  }
-                  switch (instruction->opcode()) {
-                    case SpvOpConstantNull:
-                    case SpvOpUndef:
-                      // Do not allow making an access chain from a null or
-                      // undefined pointer.  (We can eliminate these cases
-                      // before actually checking that the instruction is a
-                      // pointer.)
-                      return false;
-                    default:
-                      break;
-                  }
-                  // If the instruction has pointer type, we can legitimately
-                  // make an access chain from it.
-                  return context->get_def_use_mgr()
-                             ->GetDef(instruction->type_id())
-                             ->opcode() == SpvOpTypePointer;
-                });
-
-        // At this point, |relevant_instructions| contains all the pointers
-        // we might think of making an access chain from.
-        if (relevant_pointer_instructions.empty()) {
-          return;
-        }
-
-        auto chosen_pointer =
-            relevant_pointer_instructions[GetFuzzerContext()->RandomIndex(
-                relevant_pointer_instructions)];
-        std::vector<uint32_t> index_ids;
-
-        // Each index accessing a non-struct composite will be clamped, thus
-        // needing a pair of fresh ids
-        std::vector<std::pair<uint32_t, uint32_t>> fresh_ids_for_clamping;
-
-        auto pointer_type = GetIRContext()->get_def_use_mgr()->GetDef(
-            chosen_pointer->type_id());
-        uint32_t subobject_type_id = pointer_type->GetSingleWordInOperand(1);
-        while (true) {
-          auto subobject_type =
-              GetIRContext()->get_def_use_mgr()->GetDef(subobject_type_id);
-          if (!spvOpcodeIsComposite(subobject_type->opcode())) {
-            break;
-          }
-          if (!GetFuzzerContext()->ChoosePercentage(
-                  GetFuzzerContext()
-                      ->GetChanceOfGoingDeeperWhenMakingAccessChain())) {
-            break;
-          }
-          uint32_t bound;
-          switch (subobject_type->opcode()) {
-            case SpvOpTypeArray:
-              bound = fuzzerutil::GetArraySize(*subobject_type, GetIRContext());
-              break;
-            case SpvOpTypeMatrix:
-            case SpvOpTypeVector:
-              bound = subobject_type->GetSingleWordInOperand(1);
-              break;
-            case SpvOpTypeStruct:
-              bound = fuzzerutil::GetNumberOfStructMembers(*subobject_type);
-              break;
-            default:
-              assert(false && "Not a composite type opcode.");
-              // Set the bound to a value in order to keep release compilers
-              // happy.
-              bound = 0;
-              break;
-          }
-          if (bound == 0) {
-            // It is possible for a composite type to legitimately have zero
-            // sub-components, at least in the case of a struct, which
-            // can have no fields.
-            break;
-          }
-
-          uint32_t index_value =
-              GetFuzzerContext()->GetRandomIndexForAccessChain(bound);
-
-          switch (subobject_type->opcode()) {
-            case SpvOpTypeArray:
-            case SpvOpTypeMatrix:
-            case SpvOpTypeVector: {
-              // The index will be clamped
-
-              bool is_signed = GetFuzzerContext()->ChooseEven();
-
-              // Make the constant ready for clamping. We need:
-              // - an OpTypeBool to be present in the module
-              // - an OpConstant with the same type as the index and value
-              //   the maximum value for an index
-              // - a new pair of fresh ids for the clamping instructions
-              FindOrCreateBoolType();
-              FindOrCreateIntegerConstant({bound - 1}, 32, is_signed, false);
-              std::pair<uint32_t, uint32_t> fresh_pair_of_ids = {
-                  GetFuzzerContext()->GetFreshId(),
-                  GetFuzzerContext()->GetFreshId()};
-              fresh_ids_for_clamping.emplace_back(fresh_pair_of_ids);
-
-              index_ids.push_back(FindOrCreateIntegerConstant(
-                  {index_value}, 32, is_signed, false));
-              subobject_type_id = subobject_type->GetSingleWordInOperand(0);
-
-            } break;
-            case SpvOpTypeStruct:
-              index_ids.push_back(FindOrCreateIntegerConstant(
-                  {index_value}, 32, GetFuzzerContext()->ChooseEven(), false));
-              subobject_type_id =
-                  subobject_type->GetSingleWordInOperand(index_value);
-              break;
-            default:
-              assert(false && "Not a composite type opcode.");
-          }
-        }
-        // The transformation we are about to create will only apply if a
-        // pointer suitable for the access chain's result type exists, so we
-        // create one if it does not.
-        FindOrCreatePointerType(subobject_type_id,
-                                static_cast<SpvStorageClass>(
-                                    pointer_type->GetSingleWordInOperand(0)));
-        // Apply the transformation to add an access chain.
-        ApplyTransformation(TransformationAccessChain(
-            GetFuzzerContext()->GetFreshId(), chosen_pointer->result_id(),
-            index_ids, instruction_descriptor, fresh_ids_for_clamping));
-      });
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,41 +0,0 @@
-// 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_FUZZER_PASS_ADD_ACCESS_CHAINS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_ACCESS_CHAINS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Fuzzer pass that randomly adds access chains based on pointers available in
-// the module.  Other passes can use these access chains, e.g. by loading from
-// them.
-class FuzzerPassAddAccessChains : public FuzzerPass {
- public:
-  FuzzerPassAddAccessChains(opt::IRContext* ir_context,
-                            TransformationContext* transformation_context,
-                            FuzzerContext* fuzzer_context,
-                            protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddAccessChains();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_ACCESS_CHAINS_H_

+ 0 - 236
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_inserts.cpp

@@ -1,236 +0,0 @@
-// 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/fuzzer_pass_add_composite_inserts.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/instruction_descriptor.h"
-#include "source/fuzz/pseudo_random_generator.h"
-#include "source/fuzz/transformation_composite_insert.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddCompositeInserts::FuzzerPassAddCompositeInserts(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddCompositeInserts::~FuzzerPassAddCompositeInserts() = default;
-
-void FuzzerPassAddCompositeInserts::Apply() {
-  ForEachInstructionWithInstructionDescriptor(
-      [this](opt::Function* function, opt::BasicBlock* block,
-             opt::BasicBlock::iterator instruction_iterator,
-             const protobufs::InstructionDescriptor& instruction_descriptor)
-          -> void {
-        assert(instruction_iterator->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
-
-        // Randomly decide whether to try adding an OpCompositeInsert
-        // instruction.
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfAddingCompositeInsert())) {
-          return;
-        }
-
-        // It must be possible to insert an OpCompositeInsert instruction
-        // before |instruction_iterator|.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpCompositeInsert, instruction_iterator)) {
-          return;
-        }
-
-        // Look for available values that have composite type.
-        std::vector<opt::Instruction*> available_composites =
-            FindAvailableInstructions(
-                function, block, instruction_iterator,
-                [instruction_descriptor](
-                    opt::IRContext* ir_context,
-                    opt::Instruction* instruction) -> bool {
-                  // |instruction| must be a supported instruction of composite
-                  // type.
-                  if (!TransformationCompositeInsert::
-                          IsCompositeInstructionSupported(ir_context,
-                                                          instruction)) {
-                    return false;
-                  }
-
-                  auto instruction_type = ir_context->get_type_mgr()->GetType(
-                      instruction->type_id());
-
-                  // No components of the composite can have type
-                  // OpTypeRuntimeArray.
-                  if (ContainsRuntimeArray(*instruction_type)) {
-                    return false;
-                  }
-
-                  // No components of the composite can be pointers.
-                  // TODO:
-                  // (https://github.com/KhronosGroup/SPIRV-Tools/issues/3658)
-                  //       Structs can have components of pointer type.
-                  //       FindOrCreateZeroConstant cannot be called on a
-                  //       pointer. We ignore pointers for now. Consider adding
-                  //       support for pointer types.
-                  if (ContainsPointer(*instruction_type)) {
-                    return false;
-                  }
-
-                  return true;
-                });
-
-        // If there are no available values, then return.
-        if (available_composites.empty()) {
-          return;
-        }
-
-        // Choose randomly one available composite value.
-        auto available_composite =
-            available_composites[GetFuzzerContext()->RandomIndex(
-                available_composites)];
-
-        // Take a random component of the chosen composite value. If the chosen
-        // component is itself a composite, then randomly decide whether to take
-        // its component and repeat.
-        uint32_t current_node_type_id = available_composite->type_id();
-        std::vector<uint32_t> path_to_replaced;
-        while (true) {
-          auto current_node_type_inst =
-              GetIRContext()->get_def_use_mgr()->GetDef(current_node_type_id);
-          uint32_t num_of_components = fuzzerutil::GetBoundForCompositeIndex(
-              *current_node_type_inst, GetIRContext());
-
-          // If the composite is empty, then end the iteration.
-          if (num_of_components == 0) {
-            break;
-          }
-          uint32_t one_selected_index =
-              GetFuzzerContext()->GetRandomIndexForCompositeInsert(
-                  num_of_components);
-
-          // Construct a final index by appending the current index.
-          path_to_replaced.push_back(one_selected_index);
-          current_node_type_id = fuzzerutil::WalkOneCompositeTypeIndex(
-              GetIRContext(), current_node_type_id, one_selected_index);
-
-          // If the component is not a composite then end the iteration.
-          if (!fuzzerutil::IsCompositeType(
-                  GetIRContext()->get_type_mgr()->GetType(
-                      current_node_type_id))) {
-            break;
-          }
-
-          // If the component is a composite, but we decide not to go deeper,
-          // then end the iteration.
-          if (!GetFuzzerContext()->ChoosePercentage(
-                  GetFuzzerContext()
-                      ->GetChanceOfGoingDeeperToInsertInComposite())) {
-            break;
-          }
-        }
-
-        // Look for available objects that have the type id
-        // |current_node_type_id| and can be inserted.
-        std::vector<opt::Instruction*> available_objects =
-            FindAvailableInstructions(
-                function, block, instruction_iterator,
-                [instruction_descriptor, current_node_type_id](
-                    opt::IRContext* /*unused*/,
-                    opt::Instruction* instruction) -> bool {
-                  if (instruction->result_id() == 0 ||
-                      instruction->type_id() == 0) {
-                    return false;
-                  }
-                  if (instruction->type_id() != current_node_type_id) {
-                    return false;
-                  }
-                  return true;
-                });
-
-        // If there are no objects of the specific type available, check if
-        // FindOrCreateZeroConstant can be called and create a zero constant of
-        // this type.
-        uint32_t available_object_id;
-        if (available_objects.empty()) {
-          auto current_node_type =
-              GetIRContext()->get_type_mgr()->GetType(current_node_type_id);
-          if (!CanFindOrCreateZeroConstant(*current_node_type)) {
-            return;
-          }
-          available_object_id =
-              FindOrCreateZeroConstant(current_node_type_id, false);
-        } else {
-          available_object_id =
-              available_objects[GetFuzzerContext()->RandomIndex(
-                                    available_objects)]
-                  ->result_id();
-        }
-        auto new_result_id = GetFuzzerContext()->GetFreshId();
-
-        // Insert an OpCompositeInsert instruction which copies
-        // |available_composite| and in the copy inserts the object
-        // of type |available_object_id| at index |index_to_replace|.
-        ApplyTransformation(TransformationCompositeInsert(
-            instruction_descriptor, new_result_id,
-            available_composite->result_id(), available_object_id,
-            path_to_replaced));
-      });
-}
-
-bool FuzzerPassAddCompositeInserts::ContainsPointer(
-    const opt::analysis::Type& type) {
-  switch (type.kind()) {
-    case opt::analysis::Type::kPointer:
-      return true;
-    case opt::analysis::Type::kArray:
-      return ContainsPointer(*type.AsArray()->element_type());
-    case opt::analysis::Type::kMatrix:
-      return ContainsPointer(*type.AsMatrix()->element_type());
-    case opt::analysis::Type::kVector:
-      return ContainsPointer(*type.AsVector()->element_type());
-    case opt::analysis::Type::kStruct:
-      return std::any_of(type.AsStruct()->element_types().begin(),
-                         type.AsStruct()->element_types().end(),
-                         [](const opt::analysis::Type* element_type) {
-                           return ContainsPointer(*element_type);
-                         });
-    default:
-      return false;
-  }
-}
-
-bool FuzzerPassAddCompositeInserts::ContainsRuntimeArray(
-    const opt::analysis::Type& type) {
-  switch (type.kind()) {
-    case opt::analysis::Type::kRuntimeArray:
-      return true;
-    case opt::analysis::Type::kStruct:
-      // If any component of a struct is of type OpTypeRuntimeArray, return
-      // true.
-      return std::any_of(type.AsStruct()->element_types().begin(),
-                         type.AsStruct()->element_types().end(),
-                         [](const opt::analysis::Type* element_type) {
-                           return ContainsRuntimeArray(*element_type);
-                         });
-    default:
-      return false;
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 45
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_composite_inserts.h

@@ -1,45 +0,0 @@
-// 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 SPIRV_TOOLS_FUZZER_PASS_ADD_COMPOSITE_INSERTS_H
-#define SPIRV_TOOLS_FUZZER_PASS_ADD_COMPOSITE_INSERTS_H
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Fuzzer pass that randomly adds new OpCompositeInsert instructions to
-// available values that have the composite type.
-class FuzzerPassAddCompositeInserts : public FuzzerPass {
- public:
-  FuzzerPassAddCompositeInserts(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddCompositeInserts();
-  void Apply() override;
-
-  // Checks if any component of a composite is a pointer.
-  static bool ContainsPointer(const opt::analysis::Type& type);
-
-  // Checks if any component of a composite has type OpTypeRuntimeArray.
-  static bool ContainsRuntimeArray(const opt::analysis::Type& type);
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SPIRV_TOOLS_FUZZER_PASS_ADD_COMPOSITE_INSERTS_H

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

@@ -1,139 +0,0 @@
-// 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/fuzzer_pass_add_composite_types.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_add_type_array.h"
-#include "source/fuzz/transformation_add_type_struct.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddCompositeTypes::FuzzerPassAddCompositeTypes(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddCompositeTypes::~FuzzerPassAddCompositeTypes() = default;
-
-void FuzzerPassAddCompositeTypes::Apply() {
-  MaybeAddMissingVectorTypes();
-  MaybeAddMissingMatrixTypes();
-
-  // Randomly interleave between adding struct and array composite types
-  while (GetFuzzerContext()->ChoosePercentage(
-      GetFuzzerContext()->GetChanceOfAddingArrayOrStructType())) {
-    if (GetFuzzerContext()->ChoosePercentage(
-            GetFuzzerContext()->GetChanceOfChoosingStructTypeVsArrayType())) {
-      AddNewStructType();
-    } else {
-      AddNewArrayType();
-    }
-  }
-}
-
-void FuzzerPassAddCompositeTypes::MaybeAddMissingVectorTypes() {
-  // Functions to lazily supply scalar base types on demand if we decide to
-  // create vectors with the relevant base types.
-  std::function<uint32_t()> bool_type_supplier = [this]() -> uint32_t {
-    return FindOrCreateBoolType();
-  };
-  std::function<uint32_t()> float_type_supplier = [this]() -> uint32_t {
-    return FindOrCreateFloatType(32);
-  };
-  std::function<uint32_t()> int_type_supplier = [this]() -> uint32_t {
-    return FindOrCreateIntegerType(32, true);
-  };
-  std::function<uint32_t()> uint_type_supplier = [this]() -> uint32_t {
-    return FindOrCreateIntegerType(32, false);
-  };
-
-  // Consider each of the base types with which we can make vectors.
-  for (auto& base_type_supplier : {bool_type_supplier, float_type_supplier,
-                                   int_type_supplier, uint_type_supplier}) {
-    // Consider each valid vector size.
-    for (uint32_t size = 2; size <= 4; size++) {
-      // Randomly decide whether to create (if it does not already exist) a
-      // vector with this size and base type.
-      if (GetFuzzerContext()->ChoosePercentage(
-              GetFuzzerContext()->GetChanceOfAddingVectorType())) {
-        FindOrCreateVectorType(base_type_supplier(), size);
-      }
-    }
-  }
-}
-
-void FuzzerPassAddCompositeTypes::MaybeAddMissingMatrixTypes() {
-  // Consider every valid matrix dimension.
-  for (uint32_t columns = 2; columns <= 4; columns++) {
-    for (uint32_t rows = 2; rows <= 4; rows++) {
-      // Randomly decide whether to create (if it does not already exist) a
-      // matrix with these dimensions.  As matrices can only have floating-point
-      // base type, we do not need to consider multiple base types as in the
-      // case for vectors.
-      if (GetFuzzerContext()->ChoosePercentage(
-              GetFuzzerContext()->GetChanceOfAddingMatrixType())) {
-        FindOrCreateMatrixType(columns, rows);
-      }
-    }
-  }
-}
-
-void FuzzerPassAddCompositeTypes::AddNewArrayType() {
-  ApplyTransformation(TransformationAddTypeArray(
-      GetFuzzerContext()->GetFreshId(), ChooseScalarOrCompositeType(),
-      FindOrCreateIntegerConstant(
-          {GetFuzzerContext()->GetRandomSizeForNewArray()}, 32, false, false)));
-}
-
-void FuzzerPassAddCompositeTypes::AddNewStructType() {
-  std::vector<uint32_t> field_type_ids;
-  do {
-    field_type_ids.push_back(ChooseScalarOrCompositeType());
-  } while (GetFuzzerContext()->ChoosePercentage(
-      GetFuzzerContext()->GetChanceOfAddingAnotherStructField()));
-  ApplyTransformation(TransformationAddTypeStruct(
-      GetFuzzerContext()->GetFreshId(), field_type_ids));
-}
-
-uint32_t FuzzerPassAddCompositeTypes::ChooseScalarOrCompositeType() {
-  // Gather up all the possibly-relevant types.
-  std::vector<uint32_t> candidates;
-  for (auto& inst : GetIRContext()->types_values()) {
-    switch (inst.opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeBool:
-      case SpvOpTypeFloat:
-      case SpvOpTypeInt:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeStruct:
-      case SpvOpTypeVector:
-        candidates.push_back(inst.result_id());
-        break;
-      default:
-        break;
-    }
-  }
-  assert(!candidates.empty() &&
-         "This function should only be called if there is at least one scalar "
-         "or composite type available.");
-  // Return one of these types at random.
-  return candidates[GetFuzzerContext()->RandomIndex(candidates)];
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,61 +0,0 @@
-// 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_FUZZER_PASS_ADD_COMPOSITE_TYPES_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_COMPOSITE_TYPES_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Fuzzer pass that randomly adds missing vector and matrix types, and new
-// array and struct types, to the module.
-class FuzzerPassAddCompositeTypes : public FuzzerPass {
- public:
-  FuzzerPassAddCompositeTypes(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddCompositeTypes();
-
-  void Apply() override;
-
- private:
-  // Creates an array of a random size with a random existing base type and adds
-  // it to the module.
-  void AddNewArrayType();
-
-  // Creates a struct with fields of random existing types and adds it to the
-  // module.
-  void AddNewStructType();
-
-  // For each vector type not already present in the module, randomly decides
-  // whether to add it to the module.
-  void MaybeAddMissingVectorTypes();
-
-  // For each matrix type not already present in the module, randomly decides
-  // whether to add it to the module.
-  void MaybeAddMissingMatrixTypes();
-
-  // Returns the id of a scalar or composite type declared in the module,
-  // chosen randomly.
-  uint32_t ChooseScalarOrCompositeType();
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_COMPOSITE_TYPES_H_

+ 0 - 82
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_copy_memory.cpp

@@ -1,82 +0,0 @@
-// Copyright (c) 2020 Vasyl Teliman
-//
-// 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/fuzzer_pass_add_copy_memory.h"
-
-#include "source/fuzz/fuzzer_context.h"
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/instruction_descriptor.h"
-#include "source/fuzz/transformation_add_copy_memory.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddCopyMemory::FuzzerPassAddCopyMemory(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddCopyMemory::~FuzzerPassAddCopyMemory() = default;
-
-void FuzzerPassAddCopyMemory::Apply() {
-  ForEachInstructionWithInstructionDescriptor(
-      [this](opt::Function* function, opt::BasicBlock* block,
-             opt::BasicBlock::iterator inst_it,
-             const protobufs::InstructionDescriptor& instruction_descriptor) {
-        // Check that we can insert an OpCopyMemory before this instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyMemory,
-                                                          inst_it)) {
-          return;
-        }
-
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfAddingCopyMemory())) {
-          return;
-        }
-
-        // Get all instructions available before |inst_it| according to the
-        // domination rules.
-        auto instructions = FindAvailableInstructions(
-            function, block, inst_it,
-            TransformationAddCopyMemory::IsInstructionSupported);
-
-        if (instructions.empty()) {
-          return;
-        }
-
-        const auto* inst =
-            instructions[GetFuzzerContext()->RandomIndex(instructions)];
-
-        // Decide whether to create global or local variable.
-        auto storage_class = GetFuzzerContext()->ChooseEven()
-                                 ? SpvStorageClassPrivate
-                                 : SpvStorageClassFunction;
-
-        auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
-            GetIRContext(), inst->type_id());
-
-        // Create a pointer type with |storage_class| if needed.
-        FindOrCreatePointerType(pointee_type_id, storage_class);
-
-        ApplyTransformation(TransformationAddCopyMemory(
-            instruction_descriptor, GetFuzzerContext()->GetFreshId(),
-            inst->result_id(), storage_class,
-            FindOrCreateZeroConstant(pointee_type_id, false)));
-      });
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 40
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_copy_memory.h

@@ -1,40 +0,0 @@
-// Copyright (c) 2020 Vasyl Teliman
-//
-// 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_FUZZER_PASS_ADD_COPY_MEMORY_INSTRUCTIONS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_COPY_MEMORY_INSTRUCTIONS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Randomly decides whether to add OpCopyMemory before some instruction in the
-// module.
-class FuzzerPassAddCopyMemory : public FuzzerPass {
- public:
-  FuzzerPassAddCopyMemory(opt::IRContext* ir_context,
-                          TransformationContext* transformation_context,
-                          FuzzerContext* fuzzer_context,
-                          protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddCopyMemory() override;
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_COPY_MEMORY_INSTRUCTIONS_H_

+ 0 - 67
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.cpp

@@ -1,67 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_add_dead_blocks.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_add_dead_block.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddDeadBlocks::FuzzerPassAddDeadBlocks(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddDeadBlocks::~FuzzerPassAddDeadBlocks() = default;
-
-void FuzzerPassAddDeadBlocks::Apply() {
-  // We iterate over all blocks in the module collecting up those at which we
-  // might add a branch to a new dead block.  We then loop over all such
-  // candidates and actually apply transformations.  This separation is to
-  // avoid modifying the module as we traverse it.
-  std::vector<TransformationAddDeadBlock> candidate_transformations;
-  for (auto& function : *GetIRContext()->module()) {
-    for (auto& block : function) {
-      if (!GetFuzzerContext()->ChoosePercentage(
-              GetFuzzerContext()->GetChanceOfAddingDeadBlock())) {
-        continue;
-      }
-
-      // Make sure the module contains a boolean constant equal to
-      // |condition_value|.
-      bool condition_value = GetFuzzerContext()->ChooseEven();
-      FindOrCreateBoolConstant(condition_value, false);
-
-      // We speculatively create a transformation, and then apply it (below) if
-      // it turns out to be applicable.  This avoids duplicating the logic for
-      // applicability checking.
-      //
-      // It means that fresh ids for transformations that turn out not to be
-      // applicable end up being unused.
-      candidate_transformations.emplace_back(TransformationAddDeadBlock(
-          GetFuzzerContext()->GetFreshId(), block.id(), condition_value));
-    }
-  }
-  // Apply all those transformations that are in fact applicable.
-  for (auto& transformation : candidate_transformations) {
-    MaybeApplyTransformation(transformation);
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 40
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_blocks.h

@@ -1,40 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_ADD_DEAD_BLOCKS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_DEAD_BLOCKS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Fuzzer pass to add dynamically unreachable blocks to the module.  Future
-// passes can then manipulate such blocks.
-class FuzzerPassAddDeadBlocks : public FuzzerPass {
- public:
-  FuzzerPassAddDeadBlocks(opt::IRContext* ir_context,
-                          TransformationContext* transformation_context,
-                          FuzzerContext* fuzzer_context,
-                          protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddDeadBlocks();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_DEAD_BLOCKS_H_

+ 0 - 122
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.cpp

@@ -1,122 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_add_dead_breaks.h"
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_add_dead_break.h"
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddDeadBreaks::FuzzerPassAddDeadBreaks(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddDeadBreaks::~FuzzerPassAddDeadBreaks() = default;
-
-void FuzzerPassAddDeadBreaks::Apply() {
-  // We first collect up lots of possibly-applicable transformations.
-  std::vector<TransformationAddDeadBreak> candidate_transformations;
-  // We consider each function separately.
-  for (auto& function : *GetIRContext()->module()) {
-    // For a given function, we find all the merge blocks in that function.
-    std::vector<opt::BasicBlock*> merge_blocks;
-    for (auto& block : function) {
-      auto maybe_merge_id = block.MergeBlockIdIfAny();
-      if (maybe_merge_id) {
-        auto merge_block =
-            fuzzerutil::MaybeFindBlock(GetIRContext(), maybe_merge_id);
-
-        assert(merge_block && "Merge block can't be null");
-
-        merge_blocks.push_back(merge_block);
-      }
-    }
-    // We rather aggressively consider the possibility of adding a break from
-    // every block in the function to every merge block.  Many of these will be
-    // inapplicable as they would be illegal.  That's OK - we later discard the
-    // ones that turn out to be no good.
-    for (auto& block : function) {
-      for (auto* merge_block : merge_blocks) {
-        // Populate this vector with ids that are available at the branch point
-        // of this basic block. We will use these ids to update OpPhi
-        // instructions later.
-        std::vector<uint32_t> phi_ids;
-
-        // Determine how we need to adjust OpPhi instructions' operands
-        // for this transformation to be valid.
-        //
-        // If |block| has a branch to |merge_block|, the latter must have all of
-        // its OpPhi instructions set up correctly - we don't need to adjust
-        // anything.
-        if (!block.IsSuccessor(merge_block)) {
-          merge_block->ForEachPhiInst([this, &phi_ids](opt::Instruction* phi) {
-            // Add an additional operand for OpPhi instruction.
-            //
-            // We mark the constant as irrelevant so that we can replace it with
-            // a more interesting value later.
-            phi_ids.push_back(FindOrCreateZeroConstant(phi->type_id(), true));
-          });
-        }
-
-        // Make sure the module has a required boolean constant to be used in
-        // OpBranchConditional instruction.
-        auto break_condition = GetFuzzerContext()->ChooseEven();
-        FindOrCreateBoolConstant(break_condition, false);
-
-        auto candidate_transformation = TransformationAddDeadBreak(
-            block.id(), merge_block->id(), break_condition, std::move(phi_ids));
-        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));
-        }
-      }
-    }
-  }
-
-  // Go through the candidate transformations that were accumulated,
-  // probabilistically deciding whether to consider each one further and
-  // applying the still-applicable ones that are considered further.
-  //
-  // We iterate through the candidate transformations in a random order by
-  // repeatedly removing a random candidate transformation from the sequence
-  // until no candidate transformations remain.  This is done because
-  // transformations can potentially disable one another, so that iterating
-  // through them in order would lead to a higher probability of
-  // transformations appearing early in the sequence being applied compared
-  // with later transformations.
-  while (!candidate_transformations.empty()) {
-    // Choose a random index into the sequence of remaining candidate
-    // transformations.
-    auto index = GetFuzzerContext()->RandomIndex(candidate_transformations);
-    // Remove the transformation at the chosen index from the sequence.
-    auto transformation = std::move(candidate_transformations[index]);
-    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 (GetFuzzerContext()->ChoosePercentage(
-            GetFuzzerContext()->GetChanceOfAddingDeadBreak())) {
-      MaybeApplyTransformation(transformation);
-    }
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 39
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_breaks.h

@@ -1,39 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_ADD_DEAD_BREAKS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_DEAD_BREAKS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A fuzzer pass for adding dead break edges to the module.
-class FuzzerPassAddDeadBreaks : public FuzzerPass {
- public:
-  FuzzerPassAddDeadBreaks(opt::IRContext* ir_context,
-                          TransformationContext* transformation_context,
-                          FuzzerContext* fuzzer_context,
-                          protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddDeadBreaks();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_DEAD_BREAKS_H_

+ 0 - 89
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_dead_continues.cpp

@@ -1,89 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_add_dead_continues.h"
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_add_dead_continue.h"
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddDeadContinues::FuzzerPassAddDeadContinues(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddDeadContinues::~FuzzerPassAddDeadContinues() = default;
-
-void FuzzerPassAddDeadContinues::Apply() {
-  // Consider every block in every function.
-  for (auto& function : *GetIRContext()->module()) {
-    for (auto& block : function) {
-      // Get the label id of the continue target of the innermost loop.
-      auto continue_block_id =
-          block.IsLoopHeader()
-              ? block.ContinueBlockId()
-              : GetIRContext()->GetStructuredCFGAnalysis()->LoopContinueBlock(
-                    block.id());
-
-      // This transformation is not applicable if current block is not inside a
-      // loop.
-      if (continue_block_id == 0) {
-        continue;
-      }
-
-      auto* continue_block =
-          fuzzerutil::MaybeFindBlock(GetIRContext(), continue_block_id);
-      assert(continue_block && "Continue block is null");
-
-      // Analyze return type of each OpPhi instruction in the continue target
-      // and provide an id for the transformation if needed.
-      std::vector<uint32_t> phi_ids;
-      // Check whether current block has an edge to the continue target.
-      // If this is the case, we don't need to do anything.
-      if (!block.IsSuccessor(continue_block)) {
-        continue_block->ForEachPhiInst([this, &phi_ids](opt::Instruction* phi) {
-          // Add an additional operand for OpPhi instruction.
-          //
-          // We mark the constant as irrelevant so that we can replace it with a
-          // more interesting value later.
-          phi_ids.push_back(FindOrCreateZeroConstant(phi->type_id(), true));
-        });
-      }
-
-      // Make sure the module contains a boolean constant equal to
-      // |condition_value|.
-      bool condition_value = GetFuzzerContext()->ChooseEven();
-      FindOrCreateBoolConstant(condition_value, false);
-
-      // Make a transformation to add a dead continue from this node; if the
-      // node turns out to be inappropriate (e.g. by not being in a loop) the
-      // precondition for the transformation will fail and it will be ignored.
-      auto candidate_transformation = TransformationAddDeadContinue(
-          block.id(), condition_value, std::move(phi_ids));
-      // Probabilistically decide whether to apply the transformation in the
-      // case that it is applicable.
-      if (GetFuzzerContext()->ChoosePercentage(
-              GetFuzzerContext()->GetChanceOfAddingDeadContinue())) {
-        MaybeApplyTransformation(candidate_transformation);
-      }
-    }
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,39 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_ADD_DEAD_CONTINUES_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_DEAD_CONTINUES_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A fuzzer pass for adding dead continue edges to the module.
-class FuzzerPassAddDeadContinues : public FuzzerPass {
- public:
-  FuzzerPassAddDeadContinues(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddDeadContinues();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_DEAD_CONTINUES_H_

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

@@ -1,413 +0,0 @@
-// 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/fuzzer_pass_add_equation_instructions.h"
-
-#include <vector>
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_equation_instruction.h"
-
-namespace spvtools {
-namespace fuzz {
-namespace {
-
-bool IsBitWidthSupported(opt::IRContext* ir_context, uint32_t bit_width) {
-  switch (bit_width) {
-    case 32:
-      return true;
-    case 64:
-      return ir_context->get_feature_mgr()->HasCapability(
-                 SpvCapabilityFloat64) &&
-             ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt64);
-    case 16:
-      return ir_context->get_feature_mgr()->HasCapability(
-                 SpvCapabilityFloat16) &&
-             ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt16);
-    default:
-      return false;
-  }
-}
-
-}  // namespace
-
-FuzzerPassAddEquationInstructions::FuzzerPassAddEquationInstructions(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddEquationInstructions::~FuzzerPassAddEquationInstructions() =
-    default;
-
-void FuzzerPassAddEquationInstructions::Apply() {
-  ForEachInstructionWithInstructionDescriptor(
-      [this](opt::Function* function, opt::BasicBlock* block,
-             opt::BasicBlock::iterator inst_it,
-             const protobufs::InstructionDescriptor& instruction_descriptor) {
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfAddingEquationInstruction())) {
-          return;
-        }
-
-        // Check that it is OK to add an equation instruction before the given
-        // instruction in principle - e.g. check that this does not lead to
-        // inserting before an OpVariable or OpPhi instruction.  We use OpIAdd
-        // as an example opcode for this check, to be representative of *some*
-        // opcode that defines an equation, even though we may choose a
-        // different opcode below.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpIAdd, inst_it)) {
-          return;
-        }
-
-        // Get all available instructions with result ids and types that are not
-        // OpUndef.
-        std::vector<opt::Instruction*> available_instructions =
-            FindAvailableInstructions(
-                function, block, inst_it,
-                [this](opt::IRContext*, opt::Instruction* instruction) -> bool {
-                  return instruction->result_id() && instruction->type_id() &&
-                         instruction->opcode() != SpvOpUndef &&
-                         !GetTransformationContext()
-                              ->GetFactManager()
-                              ->IdIsIrrelevant(instruction->result_id());
-                });
-
-        // Try the opcodes for which we know how to make ids at random until
-        // something works.
-        std::vector<SpvOp> candidate_opcodes = {
-            SpvOpIAdd,        SpvOpISub,        SpvOpLogicalNot, SpvOpSNegate,
-            SpvOpConvertUToF, SpvOpConvertSToF, SpvOpBitcast};
-        do {
-          auto opcode =
-              GetFuzzerContext()->RemoveAtRandomIndex(&candidate_opcodes);
-          switch (opcode) {
-            case SpvOpConvertSToF:
-            case SpvOpConvertUToF: {
-              std::vector<const opt::Instruction*> candidate_instructions;
-              for (const auto* inst :
-                   GetIntegerInstructions(available_instructions)) {
-                const auto* type =
-                    GetIRContext()->get_type_mgr()->GetType(inst->type_id());
-                assert(type && "|inst| has invalid type");
-
-                if (const auto* vector_type = type->AsVector()) {
-                  type = vector_type->element_type();
-                }
-
-                if (IsBitWidthSupported(GetIRContext(),
-                                        type->AsInteger()->width())) {
-                  candidate_instructions.push_back(inst);
-                }
-              }
-
-              if (candidate_instructions.empty()) {
-                break;
-              }
-
-              const auto* operand =
-                  candidate_instructions[GetFuzzerContext()->RandomIndex(
-                      candidate_instructions)];
-
-              const auto* type =
-                  GetIRContext()->get_type_mgr()->GetType(operand->type_id());
-              assert(type && "Operand has invalid type");
-
-              // Make sure a result type exists in the module.
-              if (const auto* vector = type->AsVector()) {
-                // We store element count in a separate variable since the
-                // call FindOrCreate* functions below might invalidate
-                // |vector| pointer.
-                const auto element_count = vector->element_count();
-
-                FindOrCreateVectorType(
-                    FindOrCreateFloatType(
-                        vector->element_type()->AsInteger()->width()),
-                    element_count);
-              } else {
-                FindOrCreateFloatType(type->AsInteger()->width());
-              }
-
-              ApplyTransformation(TransformationEquationInstruction(
-                  GetFuzzerContext()->GetFreshId(), opcode,
-                  {operand->result_id()}, instruction_descriptor));
-              return;
-            }
-            case SpvOpBitcast: {
-              const auto candidate_instructions =
-                  GetNumericalInstructions(available_instructions);
-
-              if (!candidate_instructions.empty()) {
-                const auto* operand_inst =
-                    candidate_instructions[GetFuzzerContext()->RandomIndex(
-                        candidate_instructions)];
-                const auto* operand_type =
-                    GetIRContext()->get_type_mgr()->GetType(
-                        operand_inst->type_id());
-                assert(operand_type && "Operand instruction has invalid type");
-
-                // Make sure a result type exists in the module.
-                //
-                // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3539):
-                //  The only constraint on the types of OpBitcast's parameters
-                //  is that they must have the same number of bits. Consider
-                //  improving the code below to support this in full.
-                if (const auto* vector = operand_type->AsVector()) {
-                  // We store element count in a separate variable since the
-                  // call FindOrCreate* functions below might invalidate
-                  // |vector| pointer.
-                  const auto element_count = vector->element_count();
-
-                  uint32_t element_type_id;
-                  if (const auto* int_type =
-                          vector->element_type()->AsInteger()) {
-                    element_type_id = FindOrCreateFloatType(int_type->width());
-                  } else {
-                    assert(vector->element_type()->AsFloat() &&
-                           "Vector must have numerical elements");
-                    element_type_id = FindOrCreateIntegerType(
-                        vector->element_type()->AsFloat()->width(),
-                        GetFuzzerContext()->ChooseEven());
-                  }
-
-                  FindOrCreateVectorType(element_type_id, element_count);
-                } else if (const auto* int_type = operand_type->AsInteger()) {
-                  FindOrCreateFloatType(int_type->width());
-                } else {
-                  assert(operand_type->AsFloat() &&
-                         "Operand is not a scalar of numerical type");
-                  FindOrCreateIntegerType(operand_type->AsFloat()->width(),
-                                          GetFuzzerContext()->ChooseEven());
-                }
-
-                ApplyTransformation(TransformationEquationInstruction(
-                    GetFuzzerContext()->GetFreshId(), opcode,
-                    {operand_inst->result_id()}, instruction_descriptor));
-                return;
-              }
-            } break;
-            case SpvOpIAdd:
-            case SpvOpISub: {
-              // Instructions of integer (scalar or vector) result type are
-              // suitable for these opcodes.
-              auto integer_instructions =
-                  GetIntegerInstructions(available_instructions);
-              if (!integer_instructions.empty()) {
-                // There is at least one such instruction, so pick one at random
-                // for the LHS of an equation.
-                auto lhs = integer_instructions.at(
-                    GetFuzzerContext()->RandomIndex(integer_instructions));
-
-                // For the RHS, we can use any instruction with an integer
-                // scalar/vector result type of the same number of components
-                // and the same bit-width for the underlying integer type.
-
-                // Work out the element count and bit-width.
-                auto lhs_type =
-                    GetIRContext()->get_type_mgr()->GetType(lhs->type_id());
-                uint32_t lhs_element_count;
-                uint32_t lhs_bit_width;
-                if (lhs_type->AsVector()) {
-                  lhs_element_count = lhs_type->AsVector()->element_count();
-                  lhs_bit_width = lhs_type->AsVector()
-                                      ->element_type()
-                                      ->AsInteger()
-                                      ->width();
-                } else {
-                  lhs_element_count = 1;
-                  lhs_bit_width = lhs_type->AsInteger()->width();
-                }
-
-                // Get all the instructions that match on element count and
-                // bit-width.
-                auto candidate_rhs_instructions = RestrictToElementBitWidth(
-                    RestrictToVectorWidth(integer_instructions,
-                                          lhs_element_count),
-                    lhs_bit_width);
-
-                // Choose a RHS instruction at random; there is guaranteed to
-                // be at least one choice as the LHS will be available.
-                auto rhs = candidate_rhs_instructions.at(
-                    GetFuzzerContext()->RandomIndex(
-                        candidate_rhs_instructions));
-
-                // Add the equation instruction.
-                ApplyTransformation(TransformationEquationInstruction(
-                    GetFuzzerContext()->GetFreshId(), opcode,
-                    {lhs->result_id(), rhs->result_id()},
-                    instruction_descriptor));
-                return;
-              }
-              break;
-            }
-            case SpvOpLogicalNot: {
-              // Choose any available instruction of boolean scalar/vector
-              // result type and equate its negation with a fresh id.
-              auto boolean_instructions =
-                  GetBooleanInstructions(available_instructions);
-              if (!boolean_instructions.empty()) {
-                ApplyTransformation(TransformationEquationInstruction(
-                    GetFuzzerContext()->GetFreshId(), opcode,
-                    {boolean_instructions
-                         .at(GetFuzzerContext()->RandomIndex(
-                             boolean_instructions))
-                         ->result_id()},
-                    instruction_descriptor));
-                return;
-              }
-              break;
-            }
-            case SpvOpSNegate: {
-              // Similar to OpLogicalNot, but for signed integer negation.
-              auto integer_instructions =
-                  GetIntegerInstructions(available_instructions);
-              if (!integer_instructions.empty()) {
-                ApplyTransformation(TransformationEquationInstruction(
-                    GetFuzzerContext()->GetFreshId(), opcode,
-                    {integer_instructions
-                         .at(GetFuzzerContext()->RandomIndex(
-                             integer_instructions))
-                         ->result_id()},
-                    instruction_descriptor));
-                return;
-              }
-              break;
-            }
-            default:
-              assert(false && "Unexpected opcode.");
-              break;
-          }
-        } while (!candidate_opcodes.empty());
-        // Reaching here means that we did not manage to apply any
-        // transformation at this point of the module.
-      });
-}
-
-std::vector<opt::Instruction*>
-FuzzerPassAddEquationInstructions::GetIntegerInstructions(
-    const std::vector<opt::Instruction*>& instructions) const {
-  std::vector<opt::Instruction*> result;
-  for (auto& inst : instructions) {
-    auto type = GetIRContext()->get_type_mgr()->GetType(inst->type_id());
-    if (type->AsInteger() ||
-        (type->AsVector() && type->AsVector()->element_type()->AsInteger())) {
-      result.push_back(inst);
-    }
-  }
-  return result;
-}
-
-std::vector<opt::Instruction*>
-FuzzerPassAddEquationInstructions::GetFloatInstructions(
-    const std::vector<opt::Instruction*>& instructions) const {
-  std::vector<opt::Instruction*> result;
-  for (auto& inst : instructions) {
-    auto type = GetIRContext()->get_type_mgr()->GetType(inst->type_id());
-    if (type->AsFloat() ||
-        (type->AsVector() && type->AsVector()->element_type()->AsFloat())) {
-      result.push_back(inst);
-    }
-  }
-  return result;
-}
-
-std::vector<opt::Instruction*>
-FuzzerPassAddEquationInstructions::GetBooleanInstructions(
-    const std::vector<opt::Instruction*>& instructions) const {
-  std::vector<opt::Instruction*> result;
-  for (auto& inst : instructions) {
-    auto type = GetIRContext()->get_type_mgr()->GetType(inst->type_id());
-    if (type->AsBool() ||
-        (type->AsVector() && type->AsVector()->element_type()->AsBool())) {
-      result.push_back(inst);
-    }
-  }
-  return result;
-}
-
-std::vector<opt::Instruction*>
-FuzzerPassAddEquationInstructions::RestrictToVectorWidth(
-    const std::vector<opt::Instruction*>& instructions,
-    uint32_t vector_width) const {
-  std::vector<opt::Instruction*> result;
-  for (auto& inst : instructions) {
-    auto type = GetIRContext()->get_type_mgr()->GetType(inst->type_id());
-    // Get the vector width of |inst|, which is 1 if |inst| is a scalar and is
-    // otherwise derived from its vector type.
-    uint32_t other_vector_width =
-        type->AsVector() ? type->AsVector()->element_count() : 1;
-    // Keep |inst| if the vector widths match.
-    if (vector_width == other_vector_width) {
-      result.push_back(inst);
-    }
-  }
-  return result;
-}
-
-std::vector<opt::Instruction*>
-FuzzerPassAddEquationInstructions::RestrictToElementBitWidth(
-    const std::vector<opt::Instruction*>& instructions,
-    uint32_t bit_width) const {
-  std::vector<opt::Instruction*> result;
-  for (auto& inst : instructions) {
-    const opt::analysis::Type* type =
-        GetIRContext()->get_type_mgr()->GetType(inst->type_id());
-    if (type->AsVector()) {
-      type = type->AsVector()->element_type();
-    }
-    assert((type->AsInteger() || type->AsFloat()) &&
-           "Precondition: all input instructions must "
-           "have integer or float scalar or vector type.");
-    if ((type->AsInteger() && type->AsInteger()->width() == bit_width) ||
-        (type->AsFloat() && type->AsFloat()->width() == bit_width)) {
-      result.push_back(inst);
-    }
-  }
-  return result;
-}
-
-std::vector<opt::Instruction*>
-FuzzerPassAddEquationInstructions::GetNumericalInstructions(
-    const std::vector<opt::Instruction*>& instructions) const {
-  std::vector<opt::Instruction*> result;
-
-  for (auto* inst : instructions) {
-    const auto* type = GetIRContext()->get_type_mgr()->GetType(inst->type_id());
-    assert(type && "Instruction has invalid type");
-
-    if (const auto* vector_type = type->AsVector()) {
-      type = vector_type->element_type();
-    }
-
-    if (!type->AsInteger() && !type->AsFloat()) {
-      // Only numerical scalars or vectors of numerical components are
-      // supported.
-      continue;
-    }
-
-    if (!IsBitWidthSupported(GetIRContext(), type->AsInteger()
-                                                 ? type->AsInteger()->width()
-                                                 : type->AsFloat()->width())) {
-      continue;
-    }
-
-    result.push_back(inst);
-  }
-
-  return result;
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,80 +0,0 @@
-// 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_FUZZER_PASS_ADD_EQUATION_INSTRUCTIONS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_EQUATION_INSTRUCTIONS_H_
-
-#include <vector>
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Fuzzer pass that sprinkles instructions through the module that define
-// equations using various arithmetic and logical operators.
-class FuzzerPassAddEquationInstructions : public FuzzerPass {
- public:
-  FuzzerPassAddEquationInstructions(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddEquationInstructions();
-
-  void Apply() override;
-
- private:
-  // Yields those instructions in |instructions| that have integer scalar or
-  // vector result type.
-  std::vector<opt::Instruction*> GetIntegerInstructions(
-      const std::vector<opt::Instruction*>& instructions) const;
-
-  // Returns only instructions, that have either a scalar floating-point or a
-  // vector type.
-  std::vector<opt::Instruction*> GetFloatInstructions(
-      const std::vector<opt::Instruction*>& instructions) const;
-
-  // Yields those instructions in |instructions| that have boolean scalar or
-  // vector result type.
-  std::vector<opt::Instruction*> GetBooleanInstructions(
-      const std::vector<opt::Instruction*>& instructions) const;
-
-  // Yields those instructions in |instructions| that have a scalar numerical or
-  // a vector of numerical components type. Only 16, 32 and 64-bit numericals
-  // are supported if both OpTypeInt and OpTypeFloat instructions can be created
-  // with the specified width (e.g. for 16-bit types both Float16 and Int16
-  // capabilities must be present).
-  std::vector<opt::Instruction*> GetNumericalInstructions(
-      const std::vector<opt::Instruction*>& instructions) const;
-
-  // Requires that |instructions| are scalars or vectors of some type.  Returns
-  // only those instructions whose width is |width|. If |width| is 1 this means
-  // the scalars.
-  std::vector<opt::Instruction*> RestrictToVectorWidth(
-      const std::vector<opt::Instruction*>& instructions,
-      uint32_t vector_width) const;
-
-  // Requires that |instructions| are integer or float scalars or vectors.
-  // Returns only those instructions for which the bit-width of the underlying
-  // integer or floating-point type is |bit_width|.
-  std::vector<opt::Instruction*> RestrictToElementBitWidth(
-      const std::vector<opt::Instruction*>& instructions,
-      uint32_t bit_width) const;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_EQUATION_INSTRUCTIONS_H_

+ 0 - 199
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_function_calls.cpp

@@ -1,199 +0,0 @@
-// 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/fuzzer_pass_add_function_calls.h"
-
-#include "source/fuzz/call_graph.h"
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_add_global_variable.h"
-#include "source/fuzz/transformation_add_local_variable.h"
-#include "source/fuzz/transformation_function_call.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddFunctionCalls::FuzzerPassAddFunctionCalls(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddFunctionCalls::~FuzzerPassAddFunctionCalls() = default;
-
-void FuzzerPassAddFunctionCalls::Apply() {
-  ForEachInstructionWithInstructionDescriptor(
-      [this](opt::Function* function, opt::BasicBlock* block,
-             opt::BasicBlock::iterator inst_it,
-             const protobufs::InstructionDescriptor& instruction_descriptor)
-          -> void {
-        // Check whether it is legitimate to insert a function call before the
-        // instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpFunctionCall,
-                                                          inst_it)) {
-          return;
-        }
-
-        // Randomly decide whether to try inserting a function call here.
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfCallingFunction())) {
-          return;
-        }
-
-        // Compute the module's call graph - we don't cache it since it may
-        // change each time we apply a transformation.  If this proves to be
-        // a bottleneck the call graph data structure could be made updatable.
-        CallGraph call_graph(GetIRContext());
-
-        // Gather all the non-entry point functions different from this
-        // function.  It is important to ignore entry points as a function
-        // cannot be an entry point and the target of an OpFunctionCall
-        // instruction.  We ignore this function to avoid direct recursion.
-        std::vector<opt::Function*> candidate_functions;
-        for (auto& other_function : *GetIRContext()->module()) {
-          if (&other_function != function &&
-              !fuzzerutil::FunctionIsEntryPoint(GetIRContext(),
-                                                other_function.result_id())) {
-            candidate_functions.push_back(&other_function);
-          }
-        }
-
-        // Choose a function to call, at random, by considering candidate
-        // functions until a suitable one is found.
-        opt::Function* chosen_function = nullptr;
-        while (!candidate_functions.empty()) {
-          opt::Function* candidate_function =
-              GetFuzzerContext()->RemoveAtRandomIndex(&candidate_functions);
-          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;
-          }
-          if (call_graph.GetIndirectCallees(candidate_function->result_id())
-                  .count(function->result_id())) {
-            // Calling this function could lead to indirect recursion
-            continue;
-          }
-          chosen_function = candidate_function;
-          break;
-        }
-
-        if (!chosen_function) {
-          // No suitable function was found to call.  (This can happen, for
-          // instance, if the current function is the only function in the
-          // module.)
-          return;
-        }
-
-        ApplyTransformation(TransformationFunctionCall(
-            GetFuzzerContext()->GetFreshId(), chosen_function->result_id(),
-            ChooseFunctionCallArguments(*chosen_function, function, block,
-                                        inst_it),
-            instruction_descriptor));
-      });
-}
-
-std::vector<uint32_t> FuzzerPassAddFunctionCalls::ChooseFunctionCallArguments(
-    const opt::Function& callee, opt::Function* caller_function,
-    opt::BasicBlock* caller_block,
-    const opt::BasicBlock::iterator& caller_inst_it) {
-  auto available_pointers = FindAvailableInstructions(
-      caller_function, caller_block, caller_inst_it,
-      [this, caller_block](opt::IRContext* /*unused*/, opt::Instruction* inst) {
-        if (inst->opcode() != SpvOpVariable ||
-            inst->opcode() != SpvOpFunctionParameter) {
-          // Function parameters and variables are the only
-          // kinds of pointer that can be used as actual
-          // parameters.
-          return false;
-        }
-
-        return GetTransformationContext()->GetFactManager()->BlockIsDead(
-                   caller_block->id()) ||
-               GetTransformationContext()
-                   ->GetFactManager()
-                   ->PointeeValueIsIrrelevant(inst->result_id());
-      });
-
-  std::unordered_map<uint32_t, std::vector<uint32_t>> type_id_to_result_id;
-  for (const auto* inst : available_pointers) {
-    type_id_to_result_id[inst->type_id()].push_back(inst->result_id());
-  }
-
-  std::vector<uint32_t> result;
-  for (const auto* param :
-       fuzzerutil::GetParameters(GetIRContext(), callee.result_id())) {
-    const auto* param_type =
-        GetIRContext()->get_type_mgr()->GetType(param->type_id());
-    assert(param_type && "Parameter has invalid type");
-
-    if (!param_type->AsPointer()) {
-      // We mark the constant as irrelevant so that we can replace it with a
-      // more interesting value later.
-      result.push_back(FindOrCreateZeroConstant(param->type_id(), true));
-      continue;
-    }
-
-    if (type_id_to_result_id.count(param->type_id())) {
-      // Use an existing pointer if there are any.
-      const auto& candidates = type_id_to_result_id[param->type_id()];
-      result.push_back(candidates[GetFuzzerContext()->RandomIndex(candidates)]);
-      continue;
-    }
-
-    // Make a new variable, at function or global scope depending on the storage
-    // class of the pointer.
-
-    // Get a fresh id for the new variable.
-    uint32_t fresh_variable_id = GetFuzzerContext()->GetFreshId();
-
-    // The id of this variable is what we pass as the parameter to
-    // the call.
-    result.push_back(fresh_variable_id);
-    type_id_to_result_id[param->type_id()].push_back(fresh_variable_id);
-
-    // Now bring the variable into existence.
-    auto storage_class = param_type->AsPointer()->storage_class();
-    auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
-        GetIRContext(), param->type_id());
-    if (storage_class == SpvStorageClassFunction) {
-      // Add a new zero-initialized local variable to the current
-      // function, noting that its pointee value is irrelevant.
-      ApplyTransformation(TransformationAddLocalVariable(
-          fresh_variable_id, param->type_id(), caller_function->result_id(),
-          FindOrCreateZeroConstant(pointee_type_id, false), true));
-    } else {
-      assert((storage_class == SpvStorageClassPrivate ||
-              storage_class == SpvStorageClassWorkgroup) &&
-             "Only Function, Private and Workgroup storage classes are "
-             "supported at present.");
-      // Add a new global variable to the module, zero-initializing it if
-      // it has Private storage class, and noting that its pointee value is
-      // irrelevant.
-      ApplyTransformation(TransformationAddGlobalVariable(
-          fresh_variable_id, param->type_id(), storage_class,
-          storage_class == SpvStorageClassPrivate
-              ? FindOrCreateZeroConstant(pointee_type_id, false)
-              : 0,
-          true));
-    }
-  }
-
-  return result;
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,50 +0,0 @@
-// 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_FUZZER_PASS_ADD_FUNCTION_CALLS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_FUNCTION_CALLS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Fuzzer pass that adds calls at random to (a) livesafe functions, from
-// anywhere, and (b) any functions, from dead blocks.
-class FuzzerPassAddFunctionCalls : public FuzzerPass {
- public:
-  FuzzerPassAddFunctionCalls(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddFunctionCalls();
-
-  void Apply() override;
-
- private:
-  // Randomly chooses suitable arguments to invoke |callee| right before
-  // instruction |caller_inst_it| of block |caller_block| in |caller_function|,
-  // based on both existing available instructions and the addition of new
-  // instructions to the module.
-  std::vector<uint32_t> ChooseFunctionCallArguments(
-      const opt::Function& callee, opt::Function* caller_function,
-      opt::BasicBlock* caller_block,
-      const opt::BasicBlock::iterator& caller_inst_it);
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_FUNCTION_CALLS_H_

+ 0 - 95
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_global_variables.cpp

@@ -1,95 +0,0 @@
-// 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/fuzzer_pass_add_global_variables.h"
-
-#include "source/fuzz/transformation_add_global_variable.h"
-#include "source/fuzz/transformation_add_type_pointer.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddGlobalVariables::FuzzerPassAddGlobalVariables(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddGlobalVariables::~FuzzerPassAddGlobalVariables() = default;
-
-void FuzzerPassAddGlobalVariables::Apply() {
-  SpvStorageClass variable_storage_class = SpvStorageClassPrivate;
-  for (auto& entry_point : GetIRContext()->module()->entry_points()) {
-    // If the execution model of some entry point is GLCompute,
-    // then the variable storage class may be Workgroup.
-    if (entry_point.GetSingleWordInOperand(0) == SpvExecutionModelGLCompute) {
-      variable_storage_class =
-          GetFuzzerContext()->ChoosePercentage(
-              GetFuzzerContext()->GetChanceOfChoosingWorkgroupStorageClass())
-              ? SpvStorageClassWorkgroup
-              : SpvStorageClassPrivate;
-      break;
-    }
-  }
-
-  auto basic_type_ids_and_pointers =
-      GetAvailableBasicTypesAndPointers(variable_storage_class);
-
-  // 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 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 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 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_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 basic type so that future variables can potentially
-      // use it.
-      pointer_type_id = GetFuzzerContext()->GetFreshId();
-      available_pointers_to_basic_type.push_back(pointer_type_id);
-      ApplyTransformation(TransformationAddTypePointer(
-          pointer_type_id, variable_storage_class, basic_type));
-    } else {
-      // There is - grab one.
-      pointer_type_id =
-          available_pointers_to_basic_type[GetFuzzerContext()->RandomIndex(
-              available_pointers_to_basic_type)];
-    }
-
-    ApplyTransformation(TransformationAddGlobalVariable(
-        GetFuzzerContext()->GetFreshId(), pointer_type_id,
-        variable_storage_class,
-        variable_storage_class == SpvStorageClassPrivate
-            ? FindOrCreateZeroConstant(basic_type, false)
-            : 0,
-        true));
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,40 +0,0 @@
-// 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_FUZZER_PASS_ADD_GLOBAL_VARIABLES_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_GLOBAL_VARIABLES_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Fuzzer pass that randomly adds global variables, with Private storage class,
-// to the module.
-class FuzzerPassAddGlobalVariables : public FuzzerPass {
- public:
-  FuzzerPassAddGlobalVariables(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddGlobalVariables();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_GLOBAL_VARIABLES_H_

+ 0 - 200
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_image_sample_unused_components.cpp

@@ -1,200 +0,0 @@
-// Copyright (c) 2020 André Perez Maselco
-//
-// 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/fuzzer_pass_add_image_sample_unused_components.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/instruction_descriptor.h"
-#include "source/fuzz/transformation_add_image_sample_unused_components.h"
-#include "source/fuzz/transformation_composite_construct.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddImageSampleUnusedComponents::
-    FuzzerPassAddImageSampleUnusedComponents(
-        opt::IRContext* ir_context,
-        TransformationContext* transformation_context,
-        FuzzerContext* fuzzer_context,
-        protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddImageSampleUnusedComponents::
-    ~FuzzerPassAddImageSampleUnusedComponents() = default;
-
-void FuzzerPassAddImageSampleUnusedComponents::Apply() {
-  // SPIR-V module to help understand the transformation.
-  //
-  //       OpCapability Shader
-  //  %1 = OpExtInstImport "GLSL.std.450"
-  //       OpMemoryModel Logical GLSL450
-  //       OpEntryPoint Fragment %15 "main" %12 %14
-  //       OpExecutionMode %15 OriginUpperLeft
-  //
-  // ; Decorations
-  //        OpDecorate %12 Location 0 ; Input color variable location
-  //        OpDecorate %13 DescriptorSet 0 ; Image coordinate variable
-  //        descriptor set OpDecorate %13 Binding 0 ; Image coordinate
-  //        variable binding OpDecorate %14 Location 0 ; Fragment color
-  //        variable location
-  //
-  // ; Types
-  //  %2 = OpTypeVoid
-  //  %3 = OpTypeFunction %2
-  //  %4 = OpTypeFloat 32
-  //  %5 = OpTypeVector %4 2
-  //  %6 = OpTypeVector %4 4
-  //  %7 = OpTypeImage %4 2D 0 0 0 1 Rgba32f
-  //  %8 = OpTypeSampledImage %7
-  //  %9 = OpTypePointer Input %5
-  // %10 = OpTypePointer UniformConstant %8
-  // %11 = OpTypePointer Output %6
-  //
-  // ; Variables
-  // %12 = OpVariable %9 Input ; Input image coordinate variable
-  // %13 = OpVariable %10 UniformConstant ; Image variable
-  // %14 = OpVariable %11 Output ; Fragment color variable
-  //
-  // ; main function
-  // %15 = OpFunction %2 None %3
-  // %16 = OpLabel
-  // %17 = OpLoad %5 %12
-  // %18 = OpLoad %8 %13
-  // %19 = OpImageSampleImplicitLod %6 %18 %17
-  //       OpStore %14 %19
-  //       OpReturn
-  //       OpFunctionEnd
-
-  GetIRContext()->module()->ForEachInst([this](opt::Instruction* instruction) {
-    // |instruction| %19 = OpImageSampleImplicitLod %6 %18 %17
-    if (!spvOpcodeIsImageSample(instruction->opcode())) {
-      return;
-    }
-
-    if (!GetFuzzerContext()->ChoosePercentage(
-            GetFuzzerContext()
-                ->GetChanceOfAddingImageSampleUnusedComponents())) {
-      return;
-    }
-
-    // Gets image sample coordinate information.
-    // |coordinate_instruction| %17 = OpLoad %5 %12
-    uint32_t coordinate_id = instruction->GetSingleWordInOperand(1);
-    auto coordinate_instruction =
-        GetIRContext()->get_def_use_mgr()->GetDef(coordinate_id);
-    auto coordinate_type = GetIRContext()->get_type_mgr()->GetType(
-        coordinate_instruction->type_id());
-
-    // If the coordinate is a 4-dimensional vector, then no unused components
-    // may be added.
-    if (coordinate_type->AsVector() &&
-        coordinate_type->AsVector()->element_count() == 4) {
-      return;
-    }
-
-    // If the coordinate is a scalar, then at most 3 unused components may be
-    // added. If the coordinate is a vector, then the maximum number of unused
-    // components depends on the vector size.
-    // For the sample module, the coordinate type instruction is %5 =
-    // OpTypeVector %4 2, thus |max_unused_component_count| = 4 - 2 = 2.
-    uint32_t max_unused_component_count =
-        coordinate_type->AsInteger() || coordinate_type->AsFloat()
-            ? 3
-            : 4 - coordinate_type->AsVector()->element_count();
-
-    // |unused_component_count| may be 1 or 2.
-    uint32_t unused_component_count =
-        GetFuzzerContext()->GetRandomUnusedComponentCountForImageSample(
-            max_unused_component_count);
-
-    // Gets a type for the zero-unused components.
-    uint32_t zero_constant_type_id;
-    switch (unused_component_count) {
-      case 1:
-        // If the coordinate is an integer or float, then the unused components
-        // type is the same as the coordinate. If the coordinate is a vector,
-        // then the unused components type is the same as the vector components
-        // type.
-        zero_constant_type_id =
-            coordinate_type->AsInteger() || coordinate_type->AsFloat()
-                ? coordinate_instruction->type_id()
-                : GetIRContext()->get_type_mgr()->GetId(
-                      coordinate_type->AsVector()->element_type());
-        break;
-      case 2:
-      case 3:
-        // If the coordinate is an integer or float, then the unused components
-        // type is the same as the coordinate. If the coordinate is a vector,
-        // then the unused components type is the same as the coordinate
-        // components type.
-        // |zero_constant_type_id| %5 = OpTypeVector %4 2
-        zero_constant_type_id =
-            coordinate_type->AsInteger() || coordinate_type->AsFloat()
-                ? FindOrCreateVectorType(coordinate_instruction->type_id(),
-                                         unused_component_count)
-                : FindOrCreateVectorType(
-                      GetIRContext()->get_type_mgr()->GetId(
-                          coordinate_type->AsVector()->element_type()),
-                      unused_component_count);
-        break;
-      default:
-        assert(false && "Should be unreachable.");
-        zero_constant_type_id = 0;
-        break;
-    }
-
-    // Gets |coordinate_type| again because the module may have changed due to
-    // the use of FindOrCreateVectorType above.
-    coordinate_type = GetIRContext()->get_type_mgr()->GetType(
-        coordinate_instruction->type_id());
-
-    // If the new vector type with unused components does not exist, then create
-    // it. |coordinate_with_unused_components_type_id| %6 = OpTypeVector %4 4
-    uint32_t coordinate_with_unused_components_type_id =
-        coordinate_type->AsInteger() || coordinate_type->AsFloat()
-            ? FindOrCreateVectorType(coordinate_instruction->type_id(),
-                                     1 + unused_component_count)
-            : FindOrCreateVectorType(
-                  GetIRContext()->get_type_mgr()->GetId(
-                      coordinate_type->AsVector()->element_type()),
-                  coordinate_type->AsVector()->element_count() +
-                      unused_component_count);
-
-    // Inserts an OpCompositeConstruct instruction which
-    // represents the coordinate with unused components.
-    // |coordinate_with_unused_components_id|
-    // %22 = OpCompositeConstruct %6 %17 %21
-    uint32_t coordinate_with_unused_components_id =
-        GetFuzzerContext()->GetFreshId();
-    ApplyTransformation(TransformationCompositeConstruct(
-        coordinate_with_unused_components_type_id,
-        {coordinate_instruction->result_id(),
-         // FindOrCreateZeroConstant
-         // %20 = OpConstant %4 0
-         // %21 = OpConstantComposite %5 %20 %20
-         FindOrCreateZeroConstant(zero_constant_type_id, false)},
-        MakeInstructionDescriptor(GetIRContext(), instruction),
-        coordinate_with_unused_components_id));
-
-    // Tries to add unused components to the image sample coordinate.
-    // %19 = OpImageSampleImplicitLod %6 %18 %22
-    ApplyTransformation(TransformationAddImageSampleUnusedComponents(
-        coordinate_with_unused_components_id,
-        MakeInstructionDescriptor(GetIRContext(), instruction)));
-  });
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 41
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_image_sample_unused_components.h

@@ -1,41 +0,0 @@
-// Copyright (c) 2020 André Perez Maselco
-//
-// 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_FUZZER_PASS_ADD_IMAGE_SAMPLE_UNUSED_COMPONENTS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_IMAGE_SAMPLE_UNUSED_COMPONENTS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// This fuzzer pass searches for image sample instructions in the module and
-// randomly applies the transformation to add unused components to the image
-// sample coordinate.
-class FuzzerPassAddImageSampleUnusedComponents : public FuzzerPass {
- public:
-  FuzzerPassAddImageSampleUnusedComponents(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddImageSampleUnusedComponents();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_IMAGE_SAMPLE_UNUSED_COMPONENTS_H_

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

@@ -1,96 +0,0 @@
-// 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/fuzzer_pass_add_loads.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_load.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddLoads::FuzzerPassAddLoads(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddLoads::~FuzzerPassAddLoads() = default;
-
-void FuzzerPassAddLoads::Apply() {
-  ForEachInstructionWithInstructionDescriptor(
-      [this](opt::Function* function, opt::BasicBlock* block,
-             opt::BasicBlock::iterator inst_it,
-             const protobufs::InstructionDescriptor& instruction_descriptor)
-          -> void {
-        assert(inst_it->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
-
-        // Check whether it is legitimate to insert a load before this
-        // instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, inst_it)) {
-          return;
-        }
-
-        // Randomly decide whether to try inserting a load here.
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfAddingLoad())) {
-          return;
-        }
-
-        std::vector<opt::Instruction*> relevant_instructions =
-            FindAvailableInstructions(
-                function, block, inst_it,
-                [](opt::IRContext* context,
-                   opt::Instruction* instruction) -> bool {
-                  if (!instruction->result_id() || !instruction->type_id()) {
-                    return false;
-                  }
-                  switch (instruction->opcode()) {
-                    case SpvOpConstantNull:
-                    case SpvOpUndef:
-                      // Do not allow loading from a null or undefined pointer;
-                      // this might be OK if the block is dead, but for now we
-                      // conservatively avoid it.
-                      return false;
-                    default:
-                      break;
-                  }
-                  return context->get_def_use_mgr()
-                             ->GetDef(instruction->type_id())
-                             ->opcode() == SpvOpTypePointer;
-                });
-
-        // At this point, |relevant_instructions| contains all the pointers
-        // we might think of loading from.
-        if (relevant_instructions.empty()) {
-          return;
-        }
-
-        // Choose a pointer at random, and create and apply a loading
-        // transformation based on it.
-        ApplyTransformation(TransformationLoad(
-            GetFuzzerContext()->GetFreshId(),
-            relevant_instructions[GetFuzzerContext()->RandomIndex(
-                                      relevant_instructions)]
-                ->result_id(),
-            instruction_descriptor));
-      });
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 39
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loads.h

@@ -1,39 +0,0 @@
-// 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_FUZZER_PASS_ADD_LOADS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_LOADS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Fuzzer pass that adds stores, at random, from pointers in the module.
-class FuzzerPassAddLoads : public FuzzerPass {
- public:
-  FuzzerPassAddLoads(opt::IRContext* ir_context,
-                     TransformationContext* transformation_context,
-                     FuzzerContext* fuzzer_context,
-                     protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddLoads();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_LOADS_H_

+ 0 - 80
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_local_variables.cpp

@@ -1,80 +0,0 @@
-// 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/fuzzer_pass_add_local_variables.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_add_local_variable.h"
-#include "source/fuzz/transformation_add_type_pointer.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddLocalVariables::FuzzerPassAddLocalVariables(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddLocalVariables::~FuzzerPassAddLocalVariables() = default;
-
-void FuzzerPassAddLocalVariables::Apply() {
-  auto basic_type_ids_and_pointers =
-      GetAvailableBasicTypesAndPointers(SpvStorageClassFunction);
-
-  // 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 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 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 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_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 basic type so that future variables can potentially
-        // use it.
-        pointer_type = GetFuzzerContext()->GetFreshId();
-        ApplyTransformation(TransformationAddTypePointer(
-            pointer_type, SpvStorageClassFunction, basic_type));
-        available_pointers_to_basic_type.push_back(pointer_type);
-      } else {
-        // There is - grab one.
-        pointer_type =
-            available_pointers_to_basic_type[GetFuzzerContext()->RandomIndex(
-                available_pointers_to_basic_type)];
-      }
-      ApplyTransformation(TransformationAddLocalVariable(
-          GetFuzzerContext()->GetFreshId(), pointer_type, function.result_id(),
-          FindOrCreateZeroConstant(basic_type, false), true));
-    }
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,40 +0,0 @@
-// 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_FUZZER_PASS_ADD_LOCAL_VARIABLES_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_LOCAL_VARIABLES_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Fuzzer pass that randomly adds local variables, with Function storage class,
-// to the module.
-class FuzzerPassAddLocalVariables : public FuzzerPass {
- public:
-  FuzzerPassAddLocalVariables(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddLocalVariables();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_LOCAL_VARIABLES_H_

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

@@ -1,66 +0,0 @@
-// 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/fuzzer_pass_add_loop_preheaders.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_add_loop_preheader.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddLoopPreheaders::FuzzerPassAddLoopPreheaders(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddLoopPreheaders::~FuzzerPassAddLoopPreheaders() = default;
-
-void FuzzerPassAddLoopPreheaders::Apply() {
-  for (auto& function : *GetIRContext()->module()) {
-    // Keep track of all the loop headers we want to add a preheader to.
-    std::vector<uint32_t> loop_header_ids_to_consider;
-    for (auto& block : function) {
-      // We only care about loop headers.
-      if (!block.IsLoopHeader()) {
-        continue;
-      }
-
-      // Randomly decide whether to consider this header.
-      if (!GetFuzzerContext()->ChoosePercentage(
-              GetFuzzerContext()->GetChanceOfAddingLoopPreheader())) {
-        continue;
-      }
-
-      // We exclude loop headers with just one predecessor (the back-edge block)
-      // because they are unreachable.
-      if (GetIRContext()->cfg()->preds(block.id()).size() < 2) {
-        continue;
-      }
-
-      loop_header_ids_to_consider.push_back(block.id());
-    }
-
-    for (uint32_t header_id : loop_header_ids_to_consider) {
-      // If not already present, add a preheader which is not also a loop
-      // header.
-      GetOrCreateSimpleLoopPreheader(header_id);
-    }
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 43
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_loop_preheaders.h

@@ -1,43 +0,0 @@
-// 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_FUZZER_PASS_ADD_LOOP_PREHEADERS_H
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_LOOP_PREHEADERS_H
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A fuzzer pass that randomly adds simple loop preheaders to loops that do not
-// have one. A simple loop preheader is a block that:
-// - is the only out-of-loop predecessor of the header
-// - branches unconditionally to the header
-// - is not a loop header itself
-class FuzzerPassAddLoopPreheaders : public FuzzerPass {
- public:
-  FuzzerPassAddLoopPreheaders(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddLoopPreheaders();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_LOOP_PREHEADERS_H

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

@@ -1,57 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_add_no_contraction_decorations.h"
-
-#include "source/fuzz/transformation_add_no_contraction_decoration.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddNoContractionDecorations::FuzzerPassAddNoContractionDecorations(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddNoContractionDecorations::
-    ~FuzzerPassAddNoContractionDecorations() = default;
-
-void FuzzerPassAddNoContractionDecorations::Apply() {
-  // Consider every instruction in every block in every function.
-  for (auto& function : *GetIRContext()->module()) {
-    for (auto& block : function) {
-      for (auto& inst : block) {
-        // Restrict attention to arithmetic instructions (as defined in the
-        // SPIR-V specification).
-        if (TransformationAddNoContractionDecoration::IsArithmetic(
-                inst.opcode())) {
-          // Randomly choose whether to apply the NoContraction decoration to
-          // this arithmetic instruction.
-          if (GetFuzzerContext()->ChoosePercentage(
-                  GetFuzzerContext()
-                      ->GetChanceOfAddingNoContractionDecoration())) {
-            TransformationAddNoContractionDecoration transformation(
-                inst.result_id());
-            ApplyTransformation(transformation);
-          }
-        }
-      }
-    }
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,39 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_ADD_NO_CONTRACTION_DECORATIONS_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_NO_CONTRACTION_DECORATIONS_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A pass that applies the NoContraction decoration to arithmetic instructions.
-class FuzzerPassAddNoContractionDecorations : public FuzzerPass {
- public:
-  FuzzerPassAddNoContractionDecorations(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddNoContractionDecorations() override;
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_NO_CONTRACTION_DECORATIONS_

+ 0 - 297
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp

@@ -1,297 +0,0 @@
-// 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/fuzzer_pass_add_opphi_synonyms.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_add_opphi_synonym.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddOpPhiSynonyms::FuzzerPassAddOpPhiSynonyms(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddOpPhiSynonyms::~FuzzerPassAddOpPhiSynonyms() = default;
-
-void FuzzerPassAddOpPhiSynonyms::Apply() {
-  // Get a list of synonymous ids with the same type that can be used in the
-  // same OpPhi instruction.
-  auto equivalence_classes = GetIdEquivalenceClasses();
-
-  // Make a list of references, to avoid copying sets unnecessarily.
-  std::vector<std::set<uint32_t>*> equivalence_class_pointers;
-  for (auto& set : equivalence_classes) {
-    equivalence_class_pointers.push_back(&set);
-  }
-
-  // Keep a list of transformations to apply at the end.
-  std::vector<TransformationAddOpPhiSynonym> transformations_to_apply;
-
-  for (auto& function : *GetIRContext()->module()) {
-    for (auto& block : function) {
-      // Randomly decide whether to consider this block.
-      if (!GetFuzzerContext()->ChoosePercentage(
-              GetFuzzerContext()->GetChanceOfAddingOpPhiSynonym())) {
-        continue;
-      }
-
-      // The block must have at least one predecessor.
-      size_t num_preds = GetIRContext()->cfg()->preds(block.id()).size();
-      if (num_preds == 0) {
-        continue;
-      }
-
-      std::set<uint32_t>* chosen_equivalence_class = nullptr;
-
-      if (num_preds > 1) {
-        // If the block has more than one predecessor, prioritise sets with at
-        // least 2 ids available at some predecessor.
-        chosen_equivalence_class = MaybeFindSuitableEquivalenceClassRandomly(
-            equivalence_class_pointers, block.id(), 2);
-      }
-
-      // If a set was not already chosen, choose one with at least one available
-      // id.
-      if (!chosen_equivalence_class) {
-        chosen_equivalence_class = MaybeFindSuitableEquivalenceClassRandomly(
-            equivalence_class_pointers, block.id(), 1);
-      }
-
-      // If no suitable set was found, we cannot apply the transformation to
-      // this block.
-      if (!chosen_equivalence_class) {
-        continue;
-      }
-
-      // Initialise the map from predecessor labels to ids.
-      std::map<uint32_t, uint32_t> preds_to_ids;
-
-      // Keep track of the ids used and of the id of a predecessor with at least
-      // two ids to choose from. This is to ensure that, if possible, at least
-      // two distinct ids will be used.
-      std::set<uint32_t> ids_chosen;
-      uint32_t pred_with_alternatives = 0;
-
-      // Choose an id for each predecessor.
-      for (uint32_t pred_id : GetIRContext()->cfg()->preds(block.id())) {
-        auto suitable_ids = GetSuitableIds(*chosen_equivalence_class, pred_id);
-        assert(!suitable_ids.empty() &&
-               "We must be able to find at least one suitable id because the "
-               "equivalence class was chosen among suitable ones.");
-
-        // If this predecessor has more than one id to choose from and it is the
-        // first one of this kind that we found, remember its id.
-        if (suitable_ids.size() > 1 && !pred_with_alternatives) {
-          pred_with_alternatives = pred_id;
-        }
-
-        uint32_t chosen_id =
-            suitable_ids[GetFuzzerContext()->RandomIndex(suitable_ids)];
-
-        // Add this id to the set of ids chosen.
-        ids_chosen.emplace(chosen_id);
-
-        // Add the pair (predecessor, chosen id) to the map.
-        preds_to_ids[pred_id] = chosen_id;
-      }
-
-      // If:
-      // - the block has more than one predecessor
-      // - at least one predecessor has more than one alternative
-      // - the same id has been chosen by all the predecessors
-      // then choose another one for the predecessor with more than one
-      // alternative.
-      if (num_preds > 1 && pred_with_alternatives != 0 &&
-          ids_chosen.size() == 1) {
-        auto suitable_ids =
-            GetSuitableIds(*chosen_equivalence_class, pred_with_alternatives);
-        uint32_t chosen_id =
-            GetFuzzerContext()->RemoveAtRandomIndex(&suitable_ids);
-        if (chosen_id == preds_to_ids[pred_with_alternatives]) {
-          chosen_id = GetFuzzerContext()->RemoveAtRandomIndex(&suitable_ids);
-        }
-
-        preds_to_ids[pred_with_alternatives] = chosen_id;
-      }
-
-      // Add the transformation to the list of transformations to apply.
-      transformations_to_apply.emplace_back(block.id(), preds_to_ids,
-                                            GetFuzzerContext()->GetFreshId());
-    }
-  }
-
-  // Apply the transformations.
-  for (const auto& transformation : transformations_to_apply) {
-    ApplyTransformation(transformation);
-  }
-}
-
-std::vector<std::set<uint32_t>>
-FuzzerPassAddOpPhiSynonyms::GetIdEquivalenceClasses() {
-  std::vector<std::set<uint32_t>> id_equivalence_classes;
-
-  // Keep track of all the ids that have already be assigned to a class.
-  std::set<uint32_t> already_in_a_class;
-
-  for (const auto& pair : GetIRContext()->get_def_use_mgr()->id_to_defs()) {
-    // Exclude ids that have already been assigned to a class.
-    if (already_in_a_class.count(pair.first)) {
-      continue;
-    }
-
-    // Exclude irrelevant ids.
-    if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
-            pair.first)) {
-      continue;
-    }
-
-    // Exclude ids having a type that is not allowed by the transformation.
-    if (!TransformationAddOpPhiSynonym::CheckTypeIsAllowed(
-            GetIRContext(), pair.second->type_id())) {
-      continue;
-    }
-
-    // We need a new equivalence class for this id.
-    std::set<uint32_t> new_equivalence_class;
-
-    // Add this id to the class.
-    new_equivalence_class.emplace(pair.first);
-    already_in_a_class.emplace(pair.first);
-
-    // Add all the synonyms with the same type to this class.
-    for (auto synonym :
-         GetTransformationContext()->GetFactManager()->GetSynonymsForId(
-             pair.first)) {
-      // The synonym must be a plain id - it cannot be an indexed access into a
-      // composite.
-      if (synonym->index_size() > 0) {
-        continue;
-      }
-
-      // The synonym must not be irrelevant.
-      if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
-              synonym->object())) {
-        continue;
-      }
-
-      auto synonym_def =
-          GetIRContext()->get_def_use_mgr()->GetDef(synonym->object());
-      // The synonym must exist and have the same type as the id we are
-      // considering.
-      if (!synonym_def || synonym_def->type_id() != pair.second->type_id()) {
-        continue;
-      }
-
-      // We can add this synonym to the new equivalence class.
-      new_equivalence_class.emplace(synonym->object());
-      already_in_a_class.emplace(synonym->object());
-    }
-
-    // Add the new equivalence class to the list of equivalence classes.
-    id_equivalence_classes.emplace_back(std::move(new_equivalence_class));
-  }
-
-  return id_equivalence_classes;
-}
-
-bool FuzzerPassAddOpPhiSynonyms::EquivalenceClassIsSuitableForBlock(
-    const std::set<uint32_t>& equivalence_class, uint32_t block_id,
-    uint32_t distinct_ids_required) {
-  bool at_least_one_id_for_each_pred = true;
-
-  // Keep a set of the suitable ids found.
-  std::set<uint32_t> suitable_ids_found;
-
-  // Loop through all the predecessors of the block.
-  for (auto pred_id : GetIRContext()->cfg()->preds(block_id)) {
-    // Find the last instruction in the predecessor block.
-    auto last_instruction =
-        GetIRContext()->get_instr_block(pred_id)->terminator();
-
-    // Initially assume that there is not a suitable id for this predecessor.
-    bool at_least_one_suitable_id_found = false;
-    for (uint32_t id : equivalence_class) {
-      if (fuzzerutil::IdIsAvailableBeforeInstruction(GetIRContext(),
-                                                     last_instruction, id)) {
-        // We have found a suitable id.
-        at_least_one_suitable_id_found = true;
-        suitable_ids_found.emplace(id);
-
-        // If we have already found enough distinct suitable ids, we don't need
-        // to check the remaining ones for this predecessor.
-        if (suitable_ids_found.size() >= distinct_ids_required) {
-          break;
-        }
-      }
-    }
-    // If no suitable id was found for this predecessor, this equivalence class
-    // is not suitable and we don't need to check the other predecessors.
-    if (!at_least_one_suitable_id_found) {
-      at_least_one_id_for_each_pred = false;
-      break;
-    }
-  }
-
-  // The equivalence class is suitable if at least one suitable id was found for
-  // each predecessor and we have found at least |distinct_ids_required|
-  // distinct suitable ids in general.
-  return at_least_one_id_for_each_pred &&
-         suitable_ids_found.size() >= distinct_ids_required;
-}
-
-std::vector<uint32_t> FuzzerPassAddOpPhiSynonyms::GetSuitableIds(
-    const std::set<uint32_t>& ids, uint32_t pred_id) {
-  // Initialise an empty vector of suitable ids.
-  std::vector<uint32_t> suitable_ids;
-
-  // Get the predecessor block.
-  auto predecessor = fuzzerutil::MaybeFindBlock(GetIRContext(), pred_id);
-
-  // Loop through the ids to find the suitable ones.
-  for (uint32_t id : ids) {
-    if (fuzzerutil::IdIsAvailableBeforeInstruction(
-            GetIRContext(), predecessor->terminator(), id)) {
-      suitable_ids.push_back(id);
-    }
-  }
-
-  return suitable_ids;
-}
-
-std::set<uint32_t>*
-FuzzerPassAddOpPhiSynonyms::MaybeFindSuitableEquivalenceClassRandomly(
-    const std::vector<std::set<uint32_t>*>& candidates, uint32_t block_id,
-    uint32_t distinct_ids_required) {
-  auto remaining_candidates = candidates;
-  while (!remaining_candidates.empty()) {
-    // Choose one set randomly and return it if it is suitable.
-    auto chosen =
-        GetFuzzerContext()->RemoveAtRandomIndex(&remaining_candidates);
-    if (EquivalenceClassIsSuitableForBlock(*chosen, block_id,
-                                           distinct_ids_required)) {
-      return chosen;
-    }
-  }
-
-  // No suitable sets were found.
-  return nullptr;
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 73
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_opphi_synonyms.h

@@ -1,73 +0,0 @@
-// 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_FUZZER_PASS_ADD_OPPHI_SYNONYMS_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_OPPHI_SYNONYMS_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A fuzzer pass to add OpPhi instructions which can take the values of ids that
-// have been marked as synonymous. This instruction will itself be marked as
-// synonymous with the others.
-class FuzzerPassAddOpPhiSynonyms : public FuzzerPass {
- public:
-  FuzzerPassAddOpPhiSynonyms(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddOpPhiSynonyms() override;
-
-  void Apply() override;
-
-  // Computes the equivalence classes for the non-pointer and non-irrelevant ids
-  // in the module, where two ids are considered equivalent iff they have been
-  // declared synonymous and they have the same type.
-  std::vector<std::set<uint32_t>> GetIdEquivalenceClasses();
-
-  // Returns true iff |equivalence_class| contains at least
-  // |distinct_ids_required| ids so that all of these ids are available at the
-  // end of at least one predecessor of the block with label |block_id|.
-  // Assumes that the block has at least one predecessor.
-  bool EquivalenceClassIsSuitableForBlock(
-      const std::set<uint32_t>& equivalence_class, uint32_t block_id,
-      uint32_t distinct_ids_required);
-
-  // Returns a vector with the ids that are available to use at the end of the
-  // block with id |pred_id|, selected among the given |ids|. Assumes that
-  // |pred_id| is the label of a block and all ids in |ids| exist in the module.
-  std::vector<uint32_t> GetSuitableIds(const std::set<uint32_t>& ids,
-                                       uint32_t pred_id);
-
- private:
-  // Randomly chooses one of the equivalence classes in |candidates|, so that it
-  // satisfies all of the following conditions:
-  // - For each of the predecessors of the |block_id| block, there is at least
-  //   one id in the chosen equivalence class that is available at the end of
-  //   it.
-  // - There are at least |distinct_ids_required| ids available at the end of
-  //   some predecessor.
-  // Returns nullptr if no equivalence class in |candidates| satisfies the
-  // requirements.
-  std::set<uint32_t>* MaybeFindSuitableEquivalenceClassRandomly(
-      const std::vector<std::set<uint32_t>*>& candidates, uint32_t block_id,
-      uint32_t distinct_ids_required);
-};
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_OPPHI_SYNONYMS_

+ 0 - 147
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_parameters.cpp

@@ -1,147 +0,0 @@
-// Copyright (c) 2020 Vasyl Teliman
-//
-// 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/fuzzer_pass_add_parameters.h"
-
-#include "source/fuzz/fuzzer_context.h"
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/instruction_descriptor.h"
-#include "source/fuzz/transformation_add_parameter.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddParameters::FuzzerPassAddParameters(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddParameters::~FuzzerPassAddParameters() = default;
-
-void FuzzerPassAddParameters::Apply() {
-  // Compute type candidates for the new parameter.
-  std::vector<uint32_t> type_candidates;
-  for (const auto& type_inst : GetIRContext()->module()->GetTypes()) {
-    const auto* type =
-        GetIRContext()->get_type_mgr()->GetType(type_inst->result_id());
-    assert(type && "Type instruction is not registered in the type manager");
-    if (TransformationAddParameter::IsParameterTypeSupported(*type)) {
-      type_candidates.push_back(type_inst->result_id());
-    }
-  }
-
-  if (type_candidates.empty()) {
-    // The module contains no suitable types to use in new parameters.
-    return;
-  }
-
-  // Iterate over all functions in the module.
-  for (const auto& function : *GetIRContext()->module()) {
-    // Skip all entry-point functions - we don't want to change those.
-    if (fuzzerutil::FunctionIsEntryPoint(GetIRContext(),
-                                         function.result_id())) {
-      continue;
-    }
-
-    if (GetNumberOfParameters(function) >=
-        GetFuzzerContext()->GetMaximumNumberOfFunctionParameters()) {
-      continue;
-    }
-
-    if (!GetFuzzerContext()->ChoosePercentage(
-            GetFuzzerContext()->GetChanceOfAddingParameters())) {
-      continue;
-    }
-
-    auto num_new_parameters =
-        GetFuzzerContext()->GetRandomNumberOfNewParameters(
-            GetNumberOfParameters(function));
-
-    for (uint32_t i = 0; i < num_new_parameters; ++i) {
-      auto current_type_id =
-          type_candidates[GetFuzzerContext()->RandomIndex(type_candidates)];
-      auto current_type =
-          GetIRContext()->get_type_mgr()->GetType(current_type_id);
-      std::map<uint32_t, uint32_t> call_parameter_ids;
-
-      // Consider the case when a pointer type was selected.
-      if (current_type->kind() == opt::analysis::Type::kPointer) {
-        auto storage_class = fuzzerutil::GetStorageClassFromPointerType(
-            GetIRContext(), current_type_id);
-        switch (storage_class) {
-          case SpvStorageClassFunction: {
-            // In every caller find or create a local variable that has the
-            // selected type.
-            for (auto* instr :
-                 fuzzerutil::GetCallers(GetIRContext(), function.result_id())) {
-              auto block = GetIRContext()->get_instr_block(instr);
-              auto function_id = block->GetParent()->result_id();
-              uint32_t variable_id =
-                  FindOrCreateLocalVariable(current_type_id, function_id, true);
-              call_parameter_ids[instr->result_id()] = variable_id;
-            }
-          } break;
-          case SpvStorageClassPrivate:
-          case SpvStorageClassWorkgroup: {
-            // If there exists at least one caller, find or create a global
-            // variable that has the selected type.
-            std::vector<opt::Instruction*> callers =
-                fuzzerutil::GetCallers(GetIRContext(), function.result_id());
-            if (!callers.empty()) {
-              uint32_t variable_id =
-                  FindOrCreateGlobalVariable(current_type_id, true);
-              for (auto* instr : callers) {
-                call_parameter_ids[instr->result_id()] = variable_id;
-              }
-            }
-          } break;
-          default:
-            break;
-        }
-      } else {
-        // If there exists at least one caller, find or create a zero constant
-        // that has the selected type.
-        std::vector<opt::Instruction*> callers =
-            fuzzerutil::GetCallers(GetIRContext(), function.result_id());
-        if (!callers.empty()) {
-          uint32_t constant_id =
-              FindOrCreateZeroConstant(current_type_id, true);
-          for (auto* instr :
-               fuzzerutil::GetCallers(GetIRContext(), function.result_id())) {
-            call_parameter_ids[instr->result_id()] = constant_id;
-          }
-        }
-      }
-
-      ApplyTransformation(TransformationAddParameter(
-          function.result_id(), GetFuzzerContext()->GetFreshId(),
-          current_type_id, std::move(call_parameter_ids),
-          GetFuzzerContext()->GetFreshId()));
-    }
-  }
-}
-
-uint32_t FuzzerPassAddParameters::GetNumberOfParameters(
-    const opt::Function& function) const {
-  const auto* type = GetIRContext()->get_type_mgr()->GetType(
-      function.DefInst().GetSingleWordInOperand(1));
-  assert(type && type->AsFunction());
-
-  return static_cast<uint32_t>(type->AsFunction()->param_types().size());
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 47
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_parameters.h

@@ -1,47 +0,0 @@
-// Copyright (c) 2020 Vasyl Teliman
-//
-// 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_FUZZER_PASS_ADD_PARAMETERS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_PARAMETERS_H_
-
-#include <vector>
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Randomly decides for each non-entry-point function in the module whether to
-// add new parameters to it. If so, randomly determines the number of parameters
-// to add, their type and creates constants used to initialize them.
-class FuzzerPassAddParameters : public FuzzerPass {
- public:
-  FuzzerPassAddParameters(opt::IRContext* ir_context,
-                          TransformationContext* transformation_context,
-                          FuzzerContext* fuzzer_context,
-                          protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddParameters() override;
-
-  void Apply() override;
-
- private:
-  // Returns number of parameters of |function|.
-  uint32_t GetNumberOfParameters(const opt::Function& function) const;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_PARAMETERS_H_

+ 0 - 55
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_relaxed_decorations.cpp

@@ -1,55 +0,0 @@
-// 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/fuzzer_pass_add_relaxed_decorations.h"
-
-#include "source/fuzz/transformation_add_relaxed_decoration.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddRelaxedDecorations::FuzzerPassAddRelaxedDecorations(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddRelaxedDecorations::~FuzzerPassAddRelaxedDecorations() = default;
-
-void FuzzerPassAddRelaxedDecorations::Apply() {
-  // Consider every instruction in every block in every function.
-  for (auto& function : *GetIRContext()->module()) {
-    for (auto& block : function) {
-      for (auto& inst : block) {
-        // Randomly choose whether to apply the RelaxedPrecision decoration
-        // to this instruction.
-        if (GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfAddingRelaxedDecoration())) {
-          TransformationAddRelaxedDecoration transformation(inst.result_id());
-          // Restrict attention to numeric instructions (returning 32-bit
-          // floats or ints according to SPIR-V documentation) in dead blocks.
-          if (transformation.IsApplicable(GetIRContext(),
-                                          *GetTransformationContext())) {
-            transformation.Apply(GetIRContext(), GetTransformationContext());
-            *GetTransformations()->add_transformation() =
-                transformation.ToMessage();
-          }
-        }
-      }
-    }
-  }
-}
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 39
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_relaxed_decorations.h

@@ -1,39 +0,0 @@
-// 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 SPIRV_TOOLS_FUZZER_PASS_ADD_RELAXED_DECORATIONS_H
-#define SPIRV_TOOLS_FUZZER_PASS_ADD_RELAXED_DECORATIONS_H
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A pass that applies the Relaxed decoration to numeric instructions.
-class FuzzerPassAddRelaxedDecorations : public FuzzerPass {
- public:
-  FuzzerPassAddRelaxedDecorations(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddRelaxedDecorations() override;
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SPIRV_TOOLS_FUZZER_PASS_ADD_RELAXED_DECORATIONS_H

+ 0 - 132
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.cpp

@@ -1,132 +0,0 @@
-// 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/fuzzer_pass_add_stores.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_store.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddStores::FuzzerPassAddStores(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddStores::~FuzzerPassAddStores() = default;
-
-void FuzzerPassAddStores::Apply() {
-  ForEachInstructionWithInstructionDescriptor(
-      [this](opt::Function* function, opt::BasicBlock* block,
-             opt::BasicBlock::iterator inst_it,
-             const protobufs::InstructionDescriptor& instruction_descriptor)
-          -> void {
-        assert(inst_it->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
-
-        // Check whether it is legitimate to insert a store before this
-        // instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore,
-                                                          inst_it)) {
-          return;
-        }
-
-        // Randomly decide whether to try inserting a store here.
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfAddingStore())) {
-          return;
-        }
-
-        // Look for pointers we might consider storing to.
-        std::vector<opt::Instruction*> relevant_pointers =
-            FindAvailableInstructions(
-                function, block, inst_it,
-                [this, block](opt::IRContext* context,
-                              opt::Instruction* instruction) -> bool {
-                  if (!instruction->result_id() || !instruction->type_id()) {
-                    return false;
-                  }
-                  auto type_inst = context->get_def_use_mgr()->GetDef(
-                      instruction->type_id());
-                  if (type_inst->opcode() != SpvOpTypePointer) {
-                    // Not a pointer.
-                    return false;
-                  }
-                  if (instruction->IsReadOnlyPointer()) {
-                    // Read only: cannot store to it.
-                    return false;
-                  }
-                  switch (instruction->opcode()) {
-                    case SpvOpConstantNull:
-                    case SpvOpUndef:
-                      // Do not allow storing to a null or undefined pointer;
-                      // this might be OK if the block is dead, but for now we
-                      // conservatively avoid it.
-                      return false;
-                    default:
-                      break;
-                  }
-                  return GetTransformationContext()
-                             ->GetFactManager()
-                             ->BlockIsDead(block->id()) ||
-                         GetTransformationContext()
-                             ->GetFactManager()
-                             ->PointeeValueIsIrrelevant(
-                                 instruction->result_id());
-                });
-
-        // At this point, |relevant_pointers| contains all the pointers we might
-        // think of storing to.
-        if (relevant_pointers.empty()) {
-          return;
-        }
-
-        auto pointer = relevant_pointers[GetFuzzerContext()->RandomIndex(
-            relevant_pointers)];
-
-        std::vector<opt::Instruction*> relevant_values =
-            FindAvailableInstructions(
-                function, block, inst_it,
-                [pointer](opt::IRContext* context,
-                          opt::Instruction* instruction) -> bool {
-                  if (!instruction->result_id() || !instruction->type_id()) {
-                    return false;
-                  }
-                  return instruction->type_id() ==
-                         context->get_def_use_mgr()
-                             ->GetDef(pointer->type_id())
-                             ->GetSingleWordInOperand(1);
-                });
-
-        if (relevant_values.empty()) {
-          return;
-        }
-
-        // Choose a value at random, and create and apply a storing
-        // transformation based on it and the pointer.
-        ApplyTransformation(TransformationStore(
-            pointer->result_id(),
-            relevant_values[GetFuzzerContext()->RandomIndex(relevant_values)]
-                ->result_id(),
-            instruction_descriptor));
-      });
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 41
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_stores.h

@@ -1,41 +0,0 @@
-// 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_FUZZER_PASS_ADD_STORES_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_STORES_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Fuzzer pass that adds stores, at random, through pointers in the module,
-// either (a) from dead blocks, or (b) through pointers whose pointee values
-// are known not to affect the module's overall behaviour.
-class FuzzerPassAddStores : public FuzzerPass {
- public:
-  FuzzerPassAddStores(opt::IRContext* ir_context,
-                      TransformationContext* transformation_context,
-                      FuzzerContext* fuzzer_context,
-                      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddStores();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_STORES_H_

+ 0 - 127
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_synonyms.cpp

@@ -1,127 +0,0 @@
-// Copyright (c) 2020 Vasyl Teliman
-//
-// 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/fuzzer_pass_add_synonyms.h"
-
-#include "source/fuzz/fuzzer_context.h"
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/instruction_descriptor.h"
-#include "source/fuzz/transformation_add_synonym.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddSynonyms::FuzzerPassAddSynonyms(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddSynonyms::~FuzzerPassAddSynonyms() = default;
-
-void FuzzerPassAddSynonyms::Apply() {
-  ForEachInstructionWithInstructionDescriptor(
-      [this](opt::Function* function, opt::BasicBlock* block,
-             opt::BasicBlock::iterator inst_it,
-             const protobufs::InstructionDescriptor& instruction_descriptor) {
-        // Skip |inst_it| if we can't insert anything above it. OpIAdd is just
-        // a representative of some instruction that might be produced by the
-        // transformation.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpIAdd, inst_it)) {
-          return;
-        }
-
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfAddingSynonyms())) {
-          return;
-        }
-
-        auto synonym_type = GetFuzzerContext()->GetRandomSynonymType();
-
-        // Select all instructions that can be used to create a synonym to.
-        auto available_instructions = FindAvailableInstructions(
-            function, block, inst_it,
-            [synonym_type, this](opt::IRContext* ir_context,
-                                 opt::Instruction* inst) {
-              // Check that we can create a synonym to |inst| as described by
-              // the |synonym_type| and insert it before |inst_it|.
-              return TransformationAddSynonym::IsInstructionValid(
-                  ir_context, *GetTransformationContext(), inst, synonym_type);
-            });
-
-        if (available_instructions.empty()) {
-          return;
-        }
-
-        const auto* existing_synonym =
-            available_instructions[GetFuzzerContext()->RandomIndex(
-                available_instructions)];
-
-        // Make sure the module contains all instructions required to apply the
-        // transformation.
-        switch (synonym_type) {
-          case protobufs::TransformationAddSynonym::ADD_ZERO:
-          case protobufs::TransformationAddSynonym::SUB_ZERO:
-          case protobufs::TransformationAddSynonym::LOGICAL_OR:
-            // Create a zero constant to be used as an operand of the synonymous
-            // instruction.
-            FindOrCreateZeroConstant(existing_synonym->type_id(), false);
-            break;
-          case protobufs::TransformationAddSynonym::MUL_ONE:
-          case protobufs::TransformationAddSynonym::LOGICAL_AND: {
-            const auto* existing_synonym_type =
-                GetIRContext()->get_type_mgr()->GetType(
-                    existing_synonym->type_id());
-            assert(existing_synonym_type && "Instruction has invalid type");
-
-            if (const auto* vector = existing_synonym_type->AsVector()) {
-              auto element_type_id =
-                  GetIRContext()->get_type_mgr()->GetId(vector->element_type());
-              assert(element_type_id && "Vector's element type is invalid");
-
-              auto one_word = vector->element_type()->AsFloat()
-                                  ? fuzzerutil::FloatToWord(1)
-                                  : 1u;
-              FindOrCreateCompositeConstant(
-                  std::vector<uint32_t>(
-                      vector->element_count(),
-                      FindOrCreateConstant({one_word}, element_type_id, false)),
-                  existing_synonym->type_id(), false);
-            } else {
-              FindOrCreateConstant(
-                  {existing_synonym_type->AsFloat() ? fuzzerutil::FloatToWord(1)
-                                                    : 1u},
-                  existing_synonym->type_id(), false);
-            }
-          } break;
-          default:
-            // This assertion will fail if some SynonymType is missing from the
-            // switch statement.
-            assert(
-                !TransformationAddSynonym::IsAdditionalConstantRequired(
-                    synonym_type) &&
-                "|synonym_type| requires an additional constant to be present "
-                "in the module");
-            break;
-        }
-
-        ApplyTransformation(TransformationAddSynonym(
-            existing_synonym->result_id(), synonym_type,
-            GetFuzzerContext()->GetFreshId(), instruction_descriptor));
-      });
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 40
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_synonyms.h

@@ -1,40 +0,0 @@
-// Copyright (c) 2020 Vasyl Teliman
-//
-// 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_FUZZER_PASS_ADD_SYNONYMS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_SYNONYMS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Sprinkles instructions through the module that produce ids, synonymous to
-// some other instructions.
-class FuzzerPassAddSynonyms : public FuzzerPass {
- public:
-  FuzzerPassAddSynonyms(opt::IRContext* ir_context,
-                        TransformationContext* transformation_context,
-                        FuzzerContext* fuzzer_context,
-                        protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddSynonyms() override;
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_SYNONYMS_H_

+ 0 - 145
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp

@@ -1,145 +0,0 @@
-// Copyright (c) 2020 André Perez Maselco
-//
-// 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/fuzzer_pass_add_vector_shuffle_instructions.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/instruction_descriptor.h"
-#include "source/fuzz/transformation_vector_shuffle.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAddVectorShuffleInstructions::FuzzerPassAddVectorShuffleInstructions(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAddVectorShuffleInstructions::
-    ~FuzzerPassAddVectorShuffleInstructions() = default;
-
-void FuzzerPassAddVectorShuffleInstructions::Apply() {
-  ForEachInstructionWithInstructionDescriptor(
-      [this](opt::Function* function, opt::BasicBlock* block,
-             opt::BasicBlock::iterator instruction_iterator,
-             const protobufs::InstructionDescriptor& instruction_descriptor)
-          -> void {
-        assert(instruction_iterator->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
-
-        // Randomly decide whether to try adding an OpVectorShuffle instruction.
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfAddingVectorShuffle())) {
-          return;
-        }
-
-        // It must be valid to insert an OpVectorShuffle instruction
-        // before |instruction_iterator|.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpVectorShuffle, instruction_iterator)) {
-          return;
-        }
-
-        // Looks for vectors that we might consider to use as OpVectorShuffle
-        // operands.
-        std::vector<opt::Instruction*> vector_instructions =
-            FindAvailableInstructions(
-                function, block, instruction_iterator,
-                [this, instruction_descriptor](
-                    opt::IRContext* ir_context,
-                    opt::Instruction* instruction) -> bool {
-                  if (!instruction->result_id() || !instruction->type_id()) {
-                    return false;
-                  }
-
-                  if (!ir_context->get_type_mgr()
-                           ->GetType(instruction->type_id())
-                           ->AsVector()) {
-                    return false;
-                  }
-
-                  if (!GetTransformationContext()
-                           ->GetFactManager()
-                           ->IdIsIrrelevant(instruction->result_id()) &&
-                      !fuzzerutil::CanMakeSynonymOf(ir_context,
-                                                    *GetTransformationContext(),
-                                                    instruction)) {
-                    // If the id is irrelevant, we can use it since it will not
-                    // participate in DataSynonym fact. Otherwise, we should be
-                    // able to produce a synonym out of the id.
-                    return false;
-                  }
-
-                  return fuzzerutil::IdIsAvailableBeforeInstruction(
-                      ir_context,
-                      FindInstruction(instruction_descriptor, ir_context),
-                      instruction->result_id());
-                });
-
-        // If there are no vector instructions, then return.
-        if (vector_instructions.empty()) {
-          return;
-        }
-
-        auto vector_1_instruction =
-            vector_instructions[GetFuzzerContext()->RandomIndex(
-                vector_instructions)];
-        auto vector_1_type = GetIRContext()
-                                 ->get_type_mgr()
-                                 ->GetType(vector_1_instruction->type_id())
-                                 ->AsVector();
-
-        auto vector_2_instruction =
-            GetFuzzerContext()->RemoveAtRandomIndex(&vector_instructions);
-        auto vector_2_type = GetIRContext()
-                                 ->get_type_mgr()
-                                 ->GetType(vector_2_instruction->type_id())
-                                 ->AsVector();
-
-        // |vector_1| and |vector_2| must have the same element type as each
-        // other. The loop is guaranteed to terminate because each iteration
-        // removes on possible choice for |vector_2|, and there is at least one
-        // choice that will cause the loop to exit - namely |vector_1|.
-        while (vector_1_type->element_type() != vector_2_type->element_type()) {
-          vector_2_instruction =
-              GetFuzzerContext()->RemoveAtRandomIndex(&vector_instructions);
-          vector_2_type = GetIRContext()
-                              ->get_type_mgr()
-                              ->GetType(vector_2_instruction->type_id())
-                              ->AsVector();
-        }
-
-        // Gets components and creates the appropriate result vector type.
-        std::vector<uint32_t> components =
-            GetFuzzerContext()->GetRandomComponentsForVectorShuffle(
-                vector_1_type->element_count() +
-                vector_2_type->element_count());
-        FindOrCreateVectorType(GetIRContext()->get_type_mgr()->GetId(
-                                   vector_1_type->element_type()),
-                               static_cast<uint32_t>(components.size()));
-
-        // Applies the vector shuffle transformation.
-        ApplyTransformation(TransformationVectorShuffle(
-            instruction_descriptor, GetFuzzerContext()->GetFreshId(),
-            vector_1_instruction->result_id(),
-            vector_2_instruction->result_id(), components));
-      });
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 39
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.h

@@ -1,39 +0,0 @@
-// Copyright (c) 2020 André Perez Maselco
-//
-// 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_FUZZER_PASS_ADD_VECTOR_SHUFFLE_INSTRUCTIONS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADD_VECTOR_SHUFFLE_INSTRUCTIONS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Adds OpVectorShuffle instructions to the module.
-class FuzzerPassAddVectorShuffleInstructions : public FuzzerPass {
- public:
-  FuzzerPassAddVectorShuffleInstructions(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAddVectorShuffleInstructions();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADD_VECTOR_SHUFFLE_INSTRUCTIONS_H_

+ 0 - 48
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp

@@ -1,48 +0,0 @@
-// Copyright (c) 2020 André Perez Maselco
-//
-// 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/fuzzer_pass_adjust_branch_weights.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/instruction_descriptor.h"
-#include "source/fuzz/transformation_adjust_branch_weights.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAdjustBranchWeights::FuzzerPassAdjustBranchWeights(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAdjustBranchWeights::~FuzzerPassAdjustBranchWeights() = default;
-
-void FuzzerPassAdjustBranchWeights::Apply() {
-  // For all OpBranchConditional instructions,
-  // randomly applies the transformation.
-  GetIRContext()->module()->ForEachInst([this](opt::Instruction* instruction) {
-    if (instruction->opcode() == SpvOpBranchConditional &&
-        GetFuzzerContext()->ChoosePercentage(
-            GetFuzzerContext()->GetChanceOfAdjustingBranchWeights())) {
-      ApplyTransformation(TransformationAdjustBranchWeights(
-          MakeInstructionDescriptor(GetIRContext(), instruction),
-          GetFuzzerContext()->GetRandomBranchWeights()));
-    }
-  });
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 41
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_branch_weights.h

@@ -1,41 +0,0 @@
-// Copyright (c) 2020 André Perez Maselco
-//
-// 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_FUZZER_PASS_ADJUST_BRANCH_WEIGHTS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADJUST_BRANCH_WEIGHTS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// This fuzzer pass searches for branch conditional instructions
-// and randomly chooses which of these instructions will have their weights
-// adjusted.
-class FuzzerPassAdjustBranchWeights : public FuzzerPass {
- public:
-  FuzzerPassAdjustBranchWeights(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAdjustBranchWeights();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADJUST_BRANCH_WEIGHTS_H_

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

@@ -1,71 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_adjust_function_controls.h"
-
-#include "source/fuzz/transformation_set_function_control.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAdjustFunctionControls::FuzzerPassAdjustFunctionControls(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAdjustFunctionControls::~FuzzerPassAdjustFunctionControls() = default;
-
-void FuzzerPassAdjustFunctionControls::Apply() {
-  // Consider every function in the module.
-  for (auto& function : *GetIRContext()->module()) {
-    // Randomly decide whether to adjust this function's controls.
-    if (GetFuzzerContext()->ChoosePercentage(
-            GetFuzzerContext()->GetChanceOfAdjustingFunctionControl())) {
-      // Grab the function control mask for the function in its present form.
-      uint32_t existing_function_control_mask =
-          function.DefInst().GetSingleWordInOperand(0);
-
-      // For the new mask, we first randomly select one of three basic masks:
-      // None, Inline or DontInline.  These are always valid (and are mutually
-      // exclusive).
-      std::vector<uint32_t> basic_function_control_masks = {
-          SpvFunctionControlMaskNone, SpvFunctionControlInlineMask,
-          SpvFunctionControlDontInlineMask};
-      uint32_t new_function_control_mask =
-          basic_function_control_masks[GetFuzzerContext()->RandomIndex(
-              basic_function_control_masks)];
-
-      // We now consider the Pure and Const mask bits.  If these are already
-      // set on the function then it's OK to keep them, but also interesting
-      // to consider dropping them, so we decide randomly in each case.
-      for (auto mask_bit :
-           {SpvFunctionControlPureMask, SpvFunctionControlConstMask}) {
-        if ((existing_function_control_mask & mask_bit) &&
-            GetFuzzerContext()->ChooseEven()) {
-          new_function_control_mask |= mask_bit;
-        }
-      }
-
-      // Create and add a transformation.
-      TransformationSetFunctionControl transformation(
-          function.DefInst().result_id(), new_function_control_mask);
-      ApplyTransformation(transformation);
-    }
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,39 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_ADJUST_FUNCTION_CONTROLS_
-#define SOURCE_FUZZ_FUZZER_PASS_ADJUST_FUNCTION_CONTROLS_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A pass that adjusts the function controls on OpFunction instructions.
-class FuzzerPassAdjustFunctionControls : public FuzzerPass {
- public:
-  FuzzerPassAdjustFunctionControls(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAdjustFunctionControls() override;
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADJUST_FUNCTION_CONTROLS_

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

@@ -1,118 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_adjust_loop_controls.h"
-
-#include "source/fuzz/transformation_set_loop_control.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAdjustLoopControls::FuzzerPassAdjustLoopControls(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAdjustLoopControls::~FuzzerPassAdjustLoopControls() = default;
-
-void FuzzerPassAdjustLoopControls::Apply() {
-  // Consider every merge instruction in the module (via looking through all
-  // functions and blocks).
-  for (auto& function : *GetIRContext()->module()) {
-    for (auto& block : function) {
-      if (auto merge_inst = block.GetMergeInst()) {
-        // Ignore the instruction if it is not a loop merge.
-        if (merge_inst->opcode() != SpvOpLoopMerge) {
-          continue;
-        }
-
-        // Decide randomly whether to adjust this loop merge.
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfAdjustingLoopControl())) {
-          continue;
-        }
-
-        uint32_t existing_mask = merge_inst->GetSingleWordOperand(
-            TransformationSetLoopControl::kLoopControlMaskInOperandIndex);
-
-        // First, set the new mask to one of None, Unroll or DontUnroll.
-        std::vector<uint32_t> basic_masks = {SpvLoopControlMaskNone,
-                                             SpvLoopControlUnrollMask,
-                                             SpvLoopControlDontUnrollMask};
-        uint32_t new_mask =
-            basic_masks[GetFuzzerContext()->RandomIndex(basic_masks)];
-
-        // For the loop controls that depend on guarantees about what the loop
-        // does, check which of these were present in the existing mask and
-        // randomly decide whether to keep them.  They are just hints, so
-        // removing them should not change the semantics of the module.
-        for (auto mask_bit :
-             {SpvLoopControlDependencyInfiniteMask,
-              SpvLoopControlDependencyLengthMask,
-              SpvLoopControlMinIterationsMask, SpvLoopControlMaxIterationsMask,
-              SpvLoopControlIterationMultipleMask}) {
-          if ((existing_mask & mask_bit) && GetFuzzerContext()->ChooseEven()) {
-            // The mask bits we are considering are not available in all SPIR-V
-            // versions.  However, we only include a mask bit if it was present
-            // in the original loop control mask, and we work under the
-            // assumption that we are transforming a valid module, thus we don't
-            // need to actually check whether the SPIR-V version being used
-            // supports these loop control mask bits.
-            new_mask |= mask_bit;
-          }
-        }
-
-        // We use 0 for peel count and partial count in the case that we choose
-        // not to set these controls.
-        uint32_t peel_count = 0;
-        uint32_t partial_count = 0;
-
-        // PeelCount and PartialCount are not compatible with DontUnroll, so
-        // we check whether DontUnroll is set.
-        if (!(new_mask & SpvLoopControlDontUnrollMask)) {
-          // If PeelCount is supported by this SPIR-V version, randomly choose
-          // whether to set it.  If it was set in the original mask and is not
-          // selected for setting here, that amounts to dropping it.
-          if (TransformationSetLoopControl::PeelCountIsSupported(
-                  GetIRContext()) &&
-              GetFuzzerContext()->ChooseEven()) {
-            new_mask |= SpvLoopControlPeelCountMask;
-            // The peel count is chosen randomly - if PeelCount was already set
-            // this will overwrite whatever peel count was previously used.
-            peel_count = GetFuzzerContext()->GetRandomLoopControlPeelCount();
-          }
-          // Similar, but for PartialCount.
-          if (TransformationSetLoopControl::PartialCountIsSupported(
-                  GetIRContext()) &&
-              GetFuzzerContext()->ChooseEven()) {
-            new_mask |= SpvLoopControlPartialCountMask;
-            partial_count =
-                GetFuzzerContext()->GetRandomLoopControlPartialCount();
-          }
-        }
-
-        // Apply the transformation and add it to the output transformation
-        // sequence.
-        TransformationSetLoopControl transformation(block.id(), new_mask,
-                                                    peel_count, partial_count);
-        ApplyTransformation(transformation);
-      }
-    }
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,39 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_ADJUST_LOOP_CONTROLS_
-#define SOURCE_FUZZ_FUZZER_PASS_ADJUST_LOOP_CONTROLS_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A pass that adjusts the loop controls on OpLoopMerge instructions.
-class FuzzerPassAdjustLoopControls : public FuzzerPass {
- public:
-  FuzzerPassAdjustLoopControls(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAdjustLoopControls() override;
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADJUST_LOOP_CONTROLS_

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

@@ -1,109 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_adjust_memory_operands_masks.h"
-
-#include "source/fuzz/instruction_descriptor.h"
-#include "source/fuzz/transformation_set_memory_operands_mask.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAdjustMemoryOperandsMasks::FuzzerPassAdjustMemoryOperandsMasks(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAdjustMemoryOperandsMasks::~FuzzerPassAdjustMemoryOperandsMasks() =
-    default;
-
-void FuzzerPassAdjustMemoryOperandsMasks::Apply() {
-  // Consider every block in every function.
-  for (auto& function : *GetIRContext()->module()) {
-    for (auto& block : function) {
-      // Consider every instruction in this block, using an explicit iterator so
-      // that when we find an instruction of interest we can search backwards to
-      // create an id descriptor for it.
-      for (auto inst_it = block.cbegin(); inst_it != block.cend(); ++inst_it) {
-        if (!TransformationSetMemoryOperandsMask::IsMemoryAccess(*inst_it)) {
-          // We are only interested in memory access instructions.
-          continue;
-        }
-
-        std::vector<uint32_t> indices_of_available_masks_to_adjust;
-        // All memory instructions have at least one memory operands mask.
-        indices_of_available_masks_to_adjust.push_back(0);
-        // From SPIR-V 1.4 onwards, OpCopyMemory and OpCopyMemorySized have a
-        // second mask.
-        switch (inst_it->opcode()) {
-          case SpvOpCopyMemory:
-          case SpvOpCopyMemorySized:
-            if (TransformationSetMemoryOperandsMask::
-                    MultipleMemoryOperandMasksAreSupported(GetIRContext())) {
-              indices_of_available_masks_to_adjust.push_back(1);
-            }
-            break;
-          default:
-            break;
-        }
-
-        // Consider the available masks
-        for (auto mask_index : indices_of_available_masks_to_adjust) {
-          // Randomly decide whether to adjust this mask.
-          if (!GetFuzzerContext()->ChoosePercentage(
-                  GetFuzzerContext()
-                      ->GetChanceOfAdjustingMemoryOperandsMask())) {
-            continue;
-          }
-          // Get the existing mask, using None if there was no mask present at
-          // all.
-          auto existing_mask_in_operand_index =
-              TransformationSetMemoryOperandsMask::GetInOperandIndexForMask(
-                  *inst_it, mask_index);
-          auto existing_mask =
-              existing_mask_in_operand_index < inst_it->NumInOperands()
-                  ? inst_it->GetSingleWordInOperand(
-                        existing_mask_in_operand_index)
-                  : static_cast<uint32_t>(SpvMemoryAccessMaskNone);
-
-          // There are two things we can do to a mask:
-          // - add Volatile if not already present
-          // - toggle Nontemporal
-          // The following ensures that we do at least one of these
-          bool add_volatile = !(existing_mask & SpvMemoryAccessVolatileMask) &&
-                              GetFuzzerContext()->ChooseEven();
-          bool toggle_nontemporal =
-              !add_volatile || GetFuzzerContext()->ChooseEven();
-
-          // These bitwise operations use '|' to add Volatile if desired, and
-          // '^' to toggle Nontemporal if desired.
-          uint32_t new_mask =
-              (existing_mask | (add_volatile ? SpvMemoryAccessVolatileMask
-                                             : SpvMemoryAccessMaskNone)) ^
-              (toggle_nontemporal ? SpvMemoryAccessNontemporalMask
-                                  : SpvMemoryAccessMaskNone);
-
-          TransformationSetMemoryOperandsMask transformation(
-              MakeInstructionDescriptor(block, inst_it), new_mask, mask_index);
-          ApplyTransformation(transformation);
-        }
-      }
-    }
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,40 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_ADJUST_MEMORY_OPERANDS_MASKS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_ADJUST_MEMORY_OPERANDS_MASKS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A fuzzer pass to adjust the memory operand masks in memory access
-// instructions.
-class FuzzerPassAdjustMemoryOperandsMasks : public FuzzerPass {
- public:
-  FuzzerPassAdjustMemoryOperandsMasks(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAdjustMemoryOperandsMasks();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADJUST_MEMORY_OPERANDS_MASKS_H_

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

@@ -1,73 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_adjust_selection_controls.h"
-
-#include "source/fuzz/transformation_set_selection_control.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassAdjustSelectionControls::FuzzerPassAdjustSelectionControls(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassAdjustSelectionControls::~FuzzerPassAdjustSelectionControls() =
-    default;
-
-void FuzzerPassAdjustSelectionControls::Apply() {
-  // Consider every merge instruction in the module (via looking through all
-  // functions and blocks).
-  for (auto& function : *GetIRContext()->module()) {
-    for (auto& block : function) {
-      if (auto merge_inst = block.GetMergeInst()) {
-        // Ignore the instruction if it is not a selection merge.
-        if (merge_inst->opcode() != SpvOpSelectionMerge) {
-          continue;
-        }
-
-        // Choose randomly whether to change the selection control for this
-        // instruction.
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfAdjustingSelectionControl())) {
-          continue;
-        }
-
-        // The choices to change the selection control to are the set of valid
-        // controls, minus the current control.
-        std::vector<uint32_t> choices;
-        for (auto control :
-             {SpvSelectionControlMaskNone, SpvSelectionControlFlattenMask,
-              SpvSelectionControlDontFlattenMask}) {
-          if (control == merge_inst->GetSingleWordOperand(1)) {
-            continue;
-          }
-          choices.push_back(control);
-        }
-
-        // Apply the transformation and add it to the output transformation
-        // sequence.
-        TransformationSetSelectionControl transformation(
-            block.id(), choices[GetFuzzerContext()->RandomIndex(choices)]);
-        ApplyTransformation(transformation);
-      }
-    }
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,39 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_ADJUST_SELECTION_CONTROLS_
-#define SOURCE_FUZZ_FUZZER_PASS_ADJUST_SELECTION_CONTROLS_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A pass that adjusts the selection controls on OpSelectionMerge instructions.
-class FuzzerPassAdjustSelectionControls : public FuzzerPass {
- public:
-  FuzzerPassAdjustSelectionControls(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassAdjustSelectionControls() override;
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_ADJUST_SELECTION_CONTROLS_

+ 0 - 192
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp

@@ -1,192 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_apply_id_synonyms.h"
-
-#include "source/fuzz/data_descriptor.h"
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/id_use_descriptor.h"
-#include "source/fuzz/instruction_descriptor.h"
-#include "source/fuzz/transformation_composite_extract.h"
-#include "source/fuzz/transformation_compute_data_synonym_fact_closure.h"
-#include "source/fuzz/transformation_replace_id_with_synonym.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassApplyIdSynonyms::FuzzerPassApplyIdSynonyms(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassApplyIdSynonyms::~FuzzerPassApplyIdSynonyms() = default;
-
-void FuzzerPassApplyIdSynonyms::Apply() {
-  // Compute a closure of data synonym facts, to enrich the pool of synonyms
-  // that are available.
-  ApplyTransformation(TransformationComputeDataSynonymFactClosure(
-      GetFuzzerContext()
-          ->GetMaximumEquivalenceClassSizeForDataSynonymFactClosure()));
-
-  for (auto id_with_known_synonyms : GetTransformationContext()
-                                         ->GetFactManager()
-                                         ->GetIdsForWhichSynonymsAreKnown()) {
-    // 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 {
-          // 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 (const auto& use : uses) {
-      auto use_inst = use.first;
-      auto use_index = use.second;
-      auto block_containing_use = GetIRContext()->get_instr_block(use_inst);
-      // The use might not be in a block; e.g. it could be a decoration.
-      if (!block_containing_use) {
-        continue;
-      }
-      if (!GetFuzzerContext()->ChoosePercentage(
-              GetFuzzerContext()->GetChanceOfReplacingIdWithSynonym())) {
-        continue;
-      }
-      // |use_index| is the absolute index of the operand.  We require
-      // the index of the operand restricted to input operands only.
-      uint32_t use_in_operand_index =
-          fuzzerutil::InOperandIndexFromOperandIndex(*use_inst, use_index);
-      if (!TransformationReplaceIdWithSynonym::UseCanBeReplacedWithSynonym(
-              GetIRContext(), use_inst, use_in_operand_index)) {
-        continue;
-      }
-
-      std::vector<const protobufs::DataDescriptor*> synonyms_to_try;
-      for (const auto* data_descriptor :
-           GetTransformationContext()->GetFactManager()->GetSynonymsForId(
-               id_with_known_synonyms)) {
-        protobufs::DataDescriptor descriptor_for_this_id =
-            MakeDataDescriptor(id_with_known_synonyms, {});
-        if (DataDescriptorEquals()(data_descriptor, &descriptor_for_this_id)) {
-          // Exclude the fact that the id is synonymous with itself.
-          continue;
-        }
-
-        if (DataDescriptorsHaveCompatibleTypes(
-                use_inst->opcode(), use_in_operand_index,
-                descriptor_for_this_id, *data_descriptor)) {
-          synonyms_to_try.push_back(data_descriptor);
-        }
-      }
-      while (!synonyms_to_try.empty()) {
-        auto synonym_to_try =
-            GetFuzzerContext()->RemoveAtRandomIndex(&synonyms_to_try);
-
-        // If the synonym's |index_size| is zero, the synonym represents an id.
-        // Otherwise it represents some element of a composite structure, in
-        // which case we need to be able to add an extract instruction to get
-        // that element out.
-        if (synonym_to_try->index_size() > 0 &&
-            !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
-                                                          use_inst) &&
-            use_inst->opcode() != SpvOpPhi) {
-          // We cannot insert an extract before this instruction, so this
-          // synonym is no good.
-          continue;
-        }
-
-        if (!fuzzerutil::IdIsAvailableAtUse(GetIRContext(), use_inst,
-                                            use_in_operand_index,
-                                            synonym_to_try->object())) {
-          continue;
-        }
-
-        // We either replace the use with an id known to be synonymous (when
-        // the synonym's |index_size| is 0), or an id that will hold the result
-        // of extracting a synonym from a composite (when the synonym's
-        // |index_size| is > 0).
-        uint32_t id_with_which_to_replace_use;
-        if (synonym_to_try->index_size() == 0) {
-          id_with_which_to_replace_use = synonym_to_try->object();
-        } else {
-          id_with_which_to_replace_use = GetFuzzerContext()->GetFreshId();
-          opt::Instruction* instruction_to_insert_before = nullptr;
-
-          if (use_inst->opcode() != SpvOpPhi) {
-            instruction_to_insert_before = use_inst;
-          } else {
-            auto parent_block_id =
-                use_inst->GetSingleWordInOperand(use_in_operand_index + 1);
-            auto parent_block_instruction =
-                GetIRContext()->get_def_use_mgr()->GetDef(parent_block_id);
-            auto parent_block =
-                GetIRContext()->get_instr_block(parent_block_instruction);
-
-            instruction_to_insert_before = parent_block->GetMergeInst()
-                                               ? parent_block->GetMergeInst()
-                                               : parent_block->terminator();
-          }
-
-          assert(!GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
-                     synonym_to_try->object()) &&
-                 "Irrelevant ids can't participate in DataSynonym facts");
-          ApplyTransformation(TransformationCompositeExtract(
-              MakeInstructionDescriptor(GetIRContext(),
-                                        instruction_to_insert_before),
-              id_with_which_to_replace_use, synonym_to_try->object(),
-              fuzzerutil::RepeatedFieldToVector(synonym_to_try->index())));
-        }
-
-        ApplyTransformation(TransformationReplaceIdWithSynonym(
-            MakeIdUseDescriptorFromUse(GetIRContext(), use_inst,
-                                       use_in_operand_index),
-            id_with_which_to_replace_use));
-        break;
-      }
-    }
-  }
-}
-
-bool FuzzerPassApplyIdSynonyms::DataDescriptorsHaveCompatibleTypes(
-    SpvOp opcode, uint32_t use_in_operand_index,
-    const protobufs::DataDescriptor& dd1,
-    const protobufs::DataDescriptor& dd2) {
-  auto base_object_type_id_1 =
-      fuzzerutil::GetTypeId(GetIRContext(), dd1.object());
-  auto base_object_type_id_2 =
-      fuzzerutil::GetTypeId(GetIRContext(), dd2.object());
-  assert(base_object_type_id_1 && base_object_type_id_2 &&
-         "Data descriptors are invalid");
-
-  auto type_id_1 = fuzzerutil::WalkCompositeTypeIndices(
-      GetIRContext(), base_object_type_id_1, dd1.index());
-  auto type_id_2 = fuzzerutil::WalkCompositeTypeIndices(
-      GetIRContext(), base_object_type_id_2, dd2.index());
-  assert(type_id_1 && type_id_2 && "Data descriptors have invalid types");
-
-  return TransformationReplaceIdWithSynonym::TypesAreCompatible(
-      GetIRContext(), opcode, use_in_operand_index, type_id_1, type_id_2);
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,51 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_APPLY_ID_SYNONYMS_
-#define SOURCE_FUZZ_FUZZER_PASS_APPLY_ID_SYNONYMS_
-
-#include "source/fuzz/fuzzer_pass.h"
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A pass that replaces ids with other ids, or accesses into structures, that
-// are known to hold the same values.
-class FuzzerPassApplyIdSynonyms : public FuzzerPass {
- public:
-  FuzzerPassApplyIdSynonyms(opt::IRContext* ir_context,
-                            TransformationContext* transformation_context,
-                            FuzzerContext* fuzzer_context,
-                            protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassApplyIdSynonyms() override;
-
-  void Apply() override;
-
- private:
-  // Returns true if uses of |dd1| can be replaced with |dd2| and vice-versa
-  // with respect to the type. Concretely, returns true if |dd1| and |dd2| have
-  // the same type or both |dd1| and |dd2| are either a numerical or a vector
-  // type of integral components with possibly different signedness.
-  bool DataDescriptorsHaveCompatibleTypes(SpvOp opcode,
-                                          uint32_t use_in_operand_index,
-                                          const protobufs::DataDescriptor& dd1,
-                                          const protobufs::DataDescriptor& dd2);
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_APPLY_ID_SYNONYMS_

+ 0 - 385
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_construct_composites.cpp

@@ -1,385 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_construct_composites.h"
-
-#include <memory>
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_composite_construct.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassConstructComposites::FuzzerPassConstructComposites(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassConstructComposites::~FuzzerPassConstructComposites() = default;
-
-void FuzzerPassConstructComposites::Apply() {
-  // Gather up the ids of all composite types.
-  std::vector<uint32_t> composite_type_ids;
-  for (auto& inst : GetIRContext()->types_values()) {
-    if (fuzzerutil::IsCompositeType(
-            GetIRContext()->get_type_mgr()->GetType(inst.result_id()))) {
-      composite_type_ids.push_back(inst.result_id());
-    }
-  }
-
-  ForEachInstructionWithInstructionDescriptor(
-      [this, &composite_type_ids](
-          opt::Function* function, opt::BasicBlock* block,
-          opt::BasicBlock::iterator inst_it,
-          const protobufs::InstructionDescriptor& instruction_descriptor)
-          -> void {
-        // Check whether it is legitimate to insert a composite construction
-        // before the instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpCompositeConstruct, inst_it)) {
-          return;
-        }
-
-        // Randomly decide whether to try inserting an object copy here.
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfConstructingComposite())) {
-          return;
-        }
-
-        // For each instruction that is available at this program point (i.e. an
-        // instruction that is global or whose definition strictly dominates the
-        // program point) and suitable for making a synonym of, associate it
-        // with the id of its result type.
-        TypeIdToInstructions type_id_to_available_instructions;
-        auto available_instructions = FindAvailableInstructions(
-            function, block, inst_it,
-            [this](opt::IRContext* ir_context, opt::Instruction* inst) {
-              if (!inst->result_id() || !inst->type_id()) {
-                return false;
-              }
-
-              // If the id is irrelevant, we can use it since it will not
-              // participate in DataSynonym fact. Otherwise, we should be able
-              // to produce a synonym out of the id.
-              return GetTransformationContext()
-                         ->GetFactManager()
-                         ->IdIsIrrelevant(inst->result_id()) ||
-                     fuzzerutil::CanMakeSynonymOf(
-                         ir_context, *GetTransformationContext(), inst);
-            });
-        for (auto instruction : available_instructions) {
-          RecordAvailableInstruction(instruction,
-                                     &type_id_to_available_instructions);
-        }
-
-        // At this point, |composite_type_ids| captures all the composite types
-        // we could try to create, while |type_id_to_available_instructions|
-        // captures all the available result ids we might use, organized by
-        // type.
-
-        // Now we try to find a composite that we can construct.  We might not
-        // manage, if there is a paucity of available ingredients in the module
-        // (e.g. if our only available composite was a boolean vector and we had
-        // no instructions generating boolean result types available).
-        //
-        // If we succeed, |chosen_composite_type| will end up being non-zero,
-        // and |constructor_arguments| will end up giving us result ids suitable
-        // for constructing a composite of that type.  Otherwise these variables
-        // will remain 0 and null respectively.
-        uint32_t chosen_composite_type = 0;
-        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.
-        auto composites_to_try_constructing = composite_type_ids;
-        while (!composites_to_try_constructing.empty()) {
-          // Remove a composite type from the composite types left for us to
-          // try.
-          auto next_composite_to_try_constructing =
-              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_inst = GetIRContext()->get_def_use_mgr()->GetDef(
-              next_composite_to_try_constructing);
-          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.empty()) {
-            // We succeeded!  Note the composite type we finally settled on, and
-            // exit from the loop.
-            chosen_composite_type = next_composite_to_try_constructing;
-            break;
-          }
-        }
-
-        if (!chosen_composite_type) {
-          // We did not manage to make a composite; return 0 to indicate that no
-          // instructions were added.
-          assert(constructor_arguments.empty());
-          return;
-        }
-        assert(!constructor_arguments.empty());
-
-        // Make and apply a transformation.
-        ApplyTransformation(TransformationCompositeConstruct(
-            chosen_composite_type, constructor_arguments,
-            instruction_descriptor, GetFuzzerContext()->GetFreshId()));
-      });
-}
-
-void FuzzerPassConstructComposites::RecordAvailableInstruction(
-    opt::Instruction* inst,
-    TypeIdToInstructions* type_id_to_available_instructions) {
-  if (type_id_to_available_instructions->count(inst->type_id()) == 0) {
-    (*type_id_to_available_instructions)[inst->type_id()] = {};
-  }
-  type_id_to_available_instructions->at(inst->type_id()).push_back(inst);
-}
-
-std::vector<uint32_t>
-FuzzerPassConstructComposites::FindComponentsToConstructArray(
-    const opt::Instruction& array_type_instruction,
-    const TypeIdToInstructions& type_id_to_available_instructions) {
-  assert(array_type_instruction.opcode() == SpvOpTypeArray &&
-         "Precondition: instruction must be an array type.");
-
-  // Get the element type for the array.
-  auto element_type_id = array_type_instruction.GetSingleWordInOperand(0);
-
-  // Get all instructions at our disposal that compute something of this element
-  // type.
-  auto available_instructions =
-      type_id_to_available_instructions.find(element_type_id);
-
-  if (available_instructions == type_id_to_available_instructions.cend()) {
-    // 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 {};
-  }
-
-  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::vector<uint32_t>
-FuzzerPassConstructComposites::FindComponentsToConstructMatrix(
-    const opt::Instruction& matrix_type_instruction,
-    const TypeIdToInstructions& type_id_to_available_instructions) {
-  assert(matrix_type_instruction.opcode() == SpvOpTypeMatrix &&
-         "Precondition: instruction must be a matrix type.");
-
-  // Get the element type for the matrix.
-  auto element_type_id = matrix_type_instruction.GetSingleWordInOperand(0);
-
-  // Get all instructions at our disposal that compute something of this element
-  // type.
-  auto available_instructions =
-      type_id_to_available_instructions.find(element_type_id);
-
-  if (available_instructions == type_id_to_available_instructions.cend()) {
-    // 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 {};
-  }
-  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::vector<uint32_t>
-FuzzerPassConstructComposites::FindComponentsToConstructStruct(
-    const opt::Instruction& struct_type_instruction,
-    const TypeIdToInstructions& type_id_to_available_instructions) {
-  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 (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 =
-        type_id_to_available_instructions.find(element_type_id);
-    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 {};
-    }
-    result.push_back(available_instructions
-                         ->second[GetFuzzerContext()->RandomIndex(
-                             available_instructions->second)]
-                         ->result_id());
-  }
-  return result;
-}
-
-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_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
-  // type.  For example, if |vector_type| is vec4, the mapping will be:
-  //   { float -> 1, vec2 -> 2, vec3 -> 3 }
-  // The mapping will have missing entries if some of these types do not exist.
-
-  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.
-  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(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.
-    // For example, a module can declare vec4 without having declared vec2 or
-    // vec3.
-    if (smaller_vector_type_id) {
-      smaller_vector_type_id_to_width[smaller_vector_type_id] = width;
-    }
-  }
-
-  // Now we know the types that are available to us, we set about populating a
-  // vector of the right length.  We do this by deciding, with no order in mind,
-  // which instructions we will use to populate the vector, and subsequently
-  // randomly choosing an order.  This is to avoid biasing construction of
-  // vectors with smaller vectors to the left and scalars to the right.  That is
-  // a concern because, e.g. in the case of populating a vec4, if we populate
-  // the constructor instructions left-to-right, we can always choose a vec3 to
-  // construct the first three elements, but can only choose a vec3 to construct
-  // the last three elements if we chose a float to construct the first element
-  // (otherwise there will not be space left for a vec3).
-
-  uint32_t vector_slots_used = 0;
-  // The instructions we will use to construct the vector, in no particular
-  // order at this stage.
-  std::vector<opt::Instruction*> instructions_to_use;
-
-  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(element_count - 1, element_count - vector_slots_used)) {
-        continue;
-      }
-      auto available_instructions =
-          type_id_to_available_instructions.find(entry.first);
-      if (available_instructions == type_id_to_available_instructions.cend()) {
-        continue;
-      }
-      instructions_to_choose_from.insert(instructions_to_choose_from.end(),
-                                         available_instructions->second.begin(),
-                                         available_instructions->second.end());
-    }
-    if (instructions_to_choose_from.empty()) {
-      // We may get unlucky and find that there are not any instructions to
-      // choose from.  In this case we give up constructing a composite of this
-      // vector type.  It might be that we could construct the composite in
-      // 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 {};
-    }
-    auto instruction_to_use =
-        instructions_to_choose_from[GetFuzzerContext()->RandomIndex(
-            instructions_to_choose_from)];
-    instructions_to_use.push_back(instruction_to_use);
-    auto chosen_type =
-        GetIRContext()->get_type_mgr()->GetType(instruction_to_use->type_id());
-    if (chosen_type->AsVector()) {
-      assert(chosen_type->AsVector()->element_type() == element_type);
-      assert(chosen_type->AsVector()->element_count() < element_count);
-      assert(chosen_type->AsVector()->element_count() <=
-             element_count - vector_slots_used);
-      vector_slots_used += chosen_type->AsVector()->element_count();
-    } else {
-      assert(chosen_type == element_type);
-      vector_slots_used += 1;
-    }
-  }
-  assert(vector_slots_used == element_count);
-
-  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());
-    instructions_to_use.erase(instructions_to_use.begin() + index);
-  }
-  assert(result.size() > 1);
-  return result;
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 80
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_construct_composites.h

@@ -1,80 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_CONSTRUCT_COMPOSITES_H_
-#define SOURCE_FUZZ_FUZZER_PASS_CONSTRUCT_COMPOSITES_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-#include <map>
-#include <vector>
-
-namespace spvtools {
-namespace fuzz {
-
-// A fuzzer pass for constructing composite objects from smaller objects.
-class FuzzerPassConstructComposites : public FuzzerPass {
- public:
-  FuzzerPassConstructComposites(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassConstructComposites();
-
-  void Apply() override;
-
- private:
-  // Used to map a type id to relevant instructions whose result type matches
-  // the type id.
-  typedef std::map<uint32_t, std::vector<opt::Instruction*>>
-      TypeIdToInstructions;
-
-  // Considers all instructions that are available at |inst| - instructions
-  // whose results could be packed into a composite - and updates
-  // |type_id_to_available_instructions| so that each such instruction is
-  // associated with its the id of its result type.
-  void RecordAvailableInstruction(
-      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_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 FindComponentsToConstructArray, but for matrices.
-  std::vector<uint32_t> FindComponentsToConstructMatrix(
-      const opt::Instruction& matrix_type_instruction,
-      const TypeIdToInstructions& type_id_to_available_instructions);
-
-  // 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 FindComponentsToConstructArray, but for vectors.
-  std::vector<uint32_t> FindComponentsToConstructVector(
-      const opt::Instruction& vector_type_instruction,
-      const TypeIdToInstructions& type_id_to_available_instructions);
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_CONSTRUCT_COMPOSITES_H_

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

@@ -1,83 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_copy_objects.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
-#include "source/fuzz/transformation_add_synonym.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassCopyObjects::FuzzerPassCopyObjects(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassCopyObjects::~FuzzerPassCopyObjects() = default;
-
-void FuzzerPassCopyObjects::Apply() {
-  ForEachInstructionWithInstructionDescriptor(
-      [this](opt::Function* function, opt::BasicBlock* block,
-             opt::BasicBlock::iterator inst_it,
-             const protobufs::InstructionDescriptor& instruction_descriptor)
-          -> void {
-        assert(inst_it->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
-
-        // Check whether it is legitimate to insert a copy before this
-        // instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyObject,
-                                                          inst_it)) {
-          return;
-        }
-
-        // Randomly decide whether to try inserting an object copy here.
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfCopyingObject())) {
-          return;
-        }
-
-        const auto relevant_instructions = FindAvailableInstructions(
-            function, block, inst_it,
-            [this](opt::IRContext* ir_context, opt::Instruction* inst) {
-              return TransformationAddSynonym::IsInstructionValid(
-                  ir_context, *GetTransformationContext(), inst,
-                  protobufs::TransformationAddSynonym::COPY_OBJECT);
-            });
-
-        // At this point, |relevant_instructions| contains all the instructions
-        // we might think of copying.
-        if (relevant_instructions.empty()) {
-          return;
-        }
-
-        // Choose a copyable instruction at random, and create and apply an
-        // object copying transformation based on it.
-        ApplyTransformation(TransformationAddSynonym(
-            relevant_instructions[GetFuzzerContext()->RandomIndex(
-                                      relevant_instructions)]
-                ->result_id(),
-            protobufs::TransformationAddSynonym::COPY_OBJECT,
-            GetFuzzerContext()->GetFreshId(), instruction_descriptor));
-      });
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 39
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_copy_objects.h

@@ -1,39 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_COPY_OBJECTS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_COPY_OBJECTS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A fuzzer pass for adding adding copies of objects to the module.
-class FuzzerPassCopyObjects : public FuzzerPass {
- public:
-  FuzzerPassCopyObjects(opt::IRContext* ir_context,
-                        TransformationContext* transformation_context,
-                        FuzzerContext* fuzzer_context,
-                        protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassCopyObjects();
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_COPY_OBJECTS_H_

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

@@ -1,1258 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_donate_modules.h"
-
-#include <map>
-#include <queue>
-#include <set>
-
-#include "source/fuzz/call_graph.h"
-#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"
-#include "source/fuzz/transformation_add_global_variable.h"
-#include "source/fuzz/transformation_add_spec_constant_op.h"
-#include "source/fuzz/transformation_add_type_array.h"
-#include "source/fuzz/transformation_add_type_boolean.h"
-#include "source/fuzz/transformation_add_type_float.h"
-#include "source/fuzz/transformation_add_type_function.h"
-#include "source/fuzz/transformation_add_type_int.h"
-#include "source/fuzz/transformation_add_type_matrix.h"
-#include "source/fuzz/transformation_add_type_pointer.h"
-#include "source/fuzz/transformation_add_type_struct.h"
-#include "source/fuzz/transformation_add_type_vector.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassDonateModules::FuzzerPassDonateModules(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations,
-    const std::vector<fuzzerutil::ModuleSupplier>& donor_suppliers)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations),
-      donor_suppliers_(donor_suppliers) {}
-
-FuzzerPassDonateModules::~FuzzerPassDonateModules() = default;
-
-void FuzzerPassDonateModules::Apply() {
-  // If there are no donor suppliers, this fuzzer pass is a no-op.
-  if (donor_suppliers_.empty()) {
-    return;
-  }
-
-  // Donate at least one module, and probabilistically decide when to stop
-  // donating modules.
-  do {
-    // Choose a donor supplier at random, and get the module that it provides.
-    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(),
-               GetTransformationContext()->GetValidatorOptions()) &&
-           "The donor module must be valid");
-    // Donate the supplied module.
-    //
-    // Randomly decide whether to make the module livesafe (see
-    // FactFunctionIsLivesafe); doing so allows it to be used for live code
-    // injection but restricts its behaviour to allow this, and means that its
-    // functions cannot be transformed as if they were arbitrary dead code.
-    bool make_livesafe = GetFuzzerContext()->ChoosePercentage(
-        GetFuzzerContext()->ChanceOfMakingDonorLivesafe());
-    DonateSingleModule(donor_ir_context.get(), make_livesafe);
-  } while (GetFuzzerContext()->ChoosePercentage(
-      GetFuzzerContext()->GetChanceOfDonatingAdditionalModule()));
-}
-
-void FuzzerPassDonateModules::DonateSingleModule(
-    opt::IRContext* donor_ir_context, bool make_livesafe) {
-  // Check that the donated module has capabilities, supported by the recipient
-  // module.
-  for (const auto& capability_inst : donor_ir_context->capabilities()) {
-    auto capability =
-        static_cast<SpvCapability>(capability_inst.GetSingleWordInOperand(0));
-    if (!GetIRContext()->get_feature_mgr()->HasCapability(capability)) {
-      return;
-    }
-  }
-
-  // The ids used by the donor module may very well clash with ids defined in
-  // the recipient module.  Furthermore, some instructions defined in the donor
-  // module will be equivalent to instructions defined in the recipient module,
-  // and it is not always legal to re-declare equivalent instructions.  For
-  // example, OpTypeVoid cannot be declared twice.
-  //
-  // To handle this, we maintain a mapping from an id used in the donor module
-  // to the corresponding id that will be used by the donated code when it
-  // appears in the recipient module.
-  //
-  // This mapping is populated in two ways:
-  // (1) by mapping a donor instruction's result id to the id of some equivalent
-  //     existing instruction in the recipient (e.g. this has to be done for
-  //     OpTypeVoid)
-  // (2) by mapping a donor instruction's result id to a freshly chosen id that
-  //     is guaranteed to be different from any id already used by the recipient
-  //     (or from any id already chosen to handle a previous donor id)
-  std::map<uint32_t, uint32_t> original_id_to_donated_id;
-
-  HandleExternalInstructionImports(donor_ir_context,
-                                   &original_id_to_donated_id);
-  HandleTypesAndValues(donor_ir_context, &original_id_to_donated_id);
-  HandleFunctions(donor_ir_context, &original_id_to_donated_id, make_livesafe);
-
-  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3115) Handle some
-  //  kinds of decoration.
-}
-
-SpvStorageClass FuzzerPassDonateModules::AdaptStorageClass(
-    SpvStorageClass donor_storage_class) {
-  switch (donor_storage_class) {
-    case SpvStorageClassFunction:
-    case SpvStorageClassPrivate:
-    case SpvStorageClassWorkgroup:
-      // We leave these alone
-      return donor_storage_class;
-    case SpvStorageClassInput:
-    case SpvStorageClassOutput:
-    case SpvStorageClassUniform:
-    case SpvStorageClassUniformConstant:
-    case SpvStorageClassPushConstant:
-    case SpvStorageClassImage:
-    case SpvStorageClassStorageBuffer:
-      // We change these to Private
-      return SpvStorageClassPrivate;
-    default:
-      // Handle other cases on demand.
-      assert(false && "Currently unsupported storage class.");
-      return SpvStorageClassMax;
-  }
-}
-
-void FuzzerPassDonateModules::HandleExternalInstructionImports(
-    opt::IRContext* donor_ir_context,
-    std::map<uint32_t, uint32_t>* original_id_to_donated_id) {
-  // Consider every external instruction set import in the donor module.
-  for (auto& donor_import : donor_ir_context->module()->ext_inst_imports()) {
-    const auto& donor_import_name_words = donor_import.GetInOperand(0).words;
-    // Look for an identical import in the recipient module.
-    for (auto& existing_import : GetIRContext()->module()->ext_inst_imports()) {
-      const auto& existing_import_name_words =
-          existing_import.GetInOperand(0).words;
-      if (donor_import_name_words == existing_import_name_words) {
-        // A matching import has found.  Map the result id for the donor import
-        // to the id of the existing import, so that when donor instructions
-        // rely on the import they will be rewritten to use the existing import.
-        original_id_to_donated_id->insert(
-            {donor_import.result_id(), existing_import.result_id()});
-        break;
-      }
-    }
-    // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3116): At present
-    //  we do not handle donation of instruction imports, i.e. we do not allow
-    //  the donor to import instruction sets that the recipient did not already
-    //  import.  It might be a good idea to allow this, but it requires some
-    //  thought.
-    assert(original_id_to_donated_id->count(donor_import.result_id()) &&
-           "Donation of imports is not yet supported.");
-  }
-}
-
-void FuzzerPassDonateModules::HandleTypesAndValues(
-    opt::IRContext* donor_ir_context,
-    std::map<uint32_t, uint32_t>* original_id_to_donated_id) {
-  // Consider every type/global/constant/undef in the module.
-  for (auto& type_or_value : donor_ir_context->module()->types_values()) {
-    HandleTypeOrValue(type_or_value, original_id_to_donated_id);
-  }
-}
-
-void FuzzerPassDonateModules::HandleTypeOrValue(
-    const opt::Instruction& type_or_value,
-    std::map<uint32_t, uint32_t>* original_id_to_donated_id) {
-  // The type/value instruction generates a result id, and we need to associate
-  // the donor's result id with a new result id.  That new result id will either
-  // be the id of some existing instruction, or a fresh id.  This variable
-  // captures it.
-  uint32_t new_result_id;
-
-  // Decide how to handle each kind of instruction on a case-by-case basis.
-  //
-  // Because the donor module is required to be valid, when we encounter a
-  // type comprised of component types (e.g. an aggregate or pointer), we know
-  // that its component types will have been considered previously, and that
-  // |original_id_to_donated_id| will already contain an entry for them.
-  switch (type_or_value.opcode()) {
-    case SpvOpTypeImage:
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeSampler:
-      // We do not donate types and variables that relate to images and
-      // samplers, so we skip these types and subsequently skip anything that
-      // depends on them.
-      return;
-    case SpvOpTypeVoid: {
-      // Void has to exist already in order for us to have an entry point.
-      // Get the existing id of void.
-      opt::analysis::Void void_type;
-      new_result_id = GetIRContext()->get_type_mgr()->GetId(&void_type);
-      assert(new_result_id &&
-             "The module being transformed will always have 'void' type "
-             "declared.");
-    } break;
-    case SpvOpTypeBool: {
-      // Bool cannot be declared multiple times, so use its existing id if
-      // present, or add a declaration of Bool with a fresh id if not.
-      opt::analysis::Bool bool_type;
-      auto bool_type_id = GetIRContext()->get_type_mgr()->GetId(&bool_type);
-      if (bool_type_id) {
-        new_result_id = bool_type_id;
-      } else {
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        ApplyTransformation(TransformationAddTypeBoolean(new_result_id));
-      }
-    } break;
-    case SpvOpTypeInt: {
-      // Int cannot be declared multiple times with the same width and
-      // signedness, so check whether an existing identical Int type is
-      // present and use its id if so.  Otherwise add a declaration of the
-      // Int type used by the donor, with a fresh id.
-      const uint32_t width = type_or_value.GetSingleWordInOperand(0);
-      const bool is_signed =
-          static_cast<bool>(type_or_value.GetSingleWordInOperand(1));
-      opt::analysis::Integer int_type(width, is_signed);
-      auto int_type_id = GetIRContext()->get_type_mgr()->GetId(&int_type);
-      if (int_type_id) {
-        new_result_id = int_type_id;
-      } else {
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        ApplyTransformation(
-            TransformationAddTypeInt(new_result_id, width, is_signed));
-      }
-    } break;
-    case SpvOpTypeFloat: {
-      // Similar to SpvOpTypeInt.
-      const uint32_t width = type_or_value.GetSingleWordInOperand(0);
-      opt::analysis::Float float_type(width);
-      auto float_type_id = GetIRContext()->get_type_mgr()->GetId(&float_type);
-      if (float_type_id) {
-        new_result_id = float_type_id;
-      } else {
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        ApplyTransformation(TransformationAddTypeFloat(new_result_id, width));
-      }
-    } break;
-    case SpvOpTypeVector: {
-      // It is not legal to have two Vector type declarations with identical
-      // element types and element counts, so check whether an existing
-      // identical Vector type is present and use its id if so.  Otherwise add
-      // a declaration of the Vector type used by the donor, with a fresh id.
-
-      // When considering the vector's component type id, we look up the id
-      // use in the donor to find the id to which this has been remapped.
-      uint32_t component_type_id = original_id_to_donated_id->at(
-          type_or_value.GetSingleWordInOperand(0));
-      auto component_type =
-          GetIRContext()->get_type_mgr()->GetType(component_type_id);
-      assert(component_type && "The base type should be registered.");
-      auto component_count = type_or_value.GetSingleWordInOperand(1);
-      opt::analysis::Vector vector_type(component_type, component_count);
-      auto vector_type_id = GetIRContext()->get_type_mgr()->GetId(&vector_type);
-      if (vector_type_id) {
-        new_result_id = vector_type_id;
-      } else {
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        ApplyTransformation(TransformationAddTypeVector(
-            new_result_id, component_type_id, component_count));
-      }
-    } break;
-    case SpvOpTypeMatrix: {
-      // Similar to SpvOpTypeVector.
-      uint32_t column_type_id = original_id_to_donated_id->at(
-          type_or_value.GetSingleWordInOperand(0));
-      auto column_type =
-          GetIRContext()->get_type_mgr()->GetType(column_type_id);
-      assert(column_type && column_type->AsVector() &&
-             "The column type should be a registered vector type.");
-      auto column_count = type_or_value.GetSingleWordInOperand(1);
-      opt::analysis::Matrix matrix_type(column_type, column_count);
-      auto matrix_type_id = GetIRContext()->get_type_mgr()->GetId(&matrix_type);
-      if (matrix_type_id) {
-        new_result_id = matrix_type_id;
-      } else {
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        ApplyTransformation(TransformationAddTypeMatrix(
-            new_result_id, column_type_id, column_count));
-      }
-
-    } break;
-    case SpvOpTypeArray: {
-      // It is OK to have multiple structurally identical array types, so
-      // we go ahead and add a remapped version of the type declared by the
-      // donor.
-      uint32_t component_type_id = type_or_value.GetSingleWordInOperand(0);
-      if (!original_id_to_donated_id->count(component_type_id)) {
-        // We did not donate the component type of this array type, so we
-        // cannot donate the array type.
-        return;
-      }
-      new_result_id = GetFuzzerContext()->GetFreshId();
-      ApplyTransformation(TransformationAddTypeArray(
-          new_result_id, original_id_to_donated_id->at(component_type_id),
-          original_id_to_donated_id->at(
-              type_or_value.GetSingleWordInOperand(1))));
-    } break;
-    case SpvOpTypeRuntimeArray: {
-      // A runtime array is allowed as the final member of an SSBO.  During
-      // donation we turn runtime arrays into fixed-size arrays.  For dead
-      // code donations this is OK because the array is never indexed into at
-      // runtime, so it does not matter what its size is.  For live-safe code,
-      // all accesses are made in-bounds, so this is also OK.
-      //
-      // The special OpArrayLength instruction, which works on runtime arrays,
-      // is rewritten to yield the fixed length that is used for the array.
-
-      uint32_t component_type_id = type_or_value.GetSingleWordInOperand(0);
-      if (!original_id_to_donated_id->count(component_type_id)) {
-        // We did not donate the component type of this runtime array type, so
-        // we cannot donate it as a fixed-size array.
-        return;
-      }
-      new_result_id = GetFuzzerContext()->GetFreshId();
-      ApplyTransformation(TransformationAddTypeArray(
-          new_result_id, original_id_to_donated_id->at(component_type_id),
-          FindOrCreateIntegerConstant(
-              {GetFuzzerContext()->GetRandomSizeForNewArray()}, 32, false,
-              false)));
-    } break;
-    case SpvOpTypeStruct: {
-      // Similar to SpvOpTypeArray.
-      std::vector<uint32_t> member_type_ids;
-      for (uint32_t i = 0; i < type_or_value.NumInOperands(); i++) {
-        auto component_type_id = type_or_value.GetSingleWordInOperand(i);
-        if (!original_id_to_donated_id->count(component_type_id)) {
-          // We did not donate every member type for this struct type, so we
-          // cannot donate the struct type.
-          return;
-        }
-        member_type_ids.push_back(
-            original_id_to_donated_id->at(component_type_id));
-      }
-      new_result_id = GetFuzzerContext()->GetFreshId();
-      ApplyTransformation(
-          TransformationAddTypeStruct(new_result_id, member_type_ids));
-    } break;
-    case SpvOpTypePointer: {
-      // Similar to SpvOpTypeArray.
-      uint32_t pointee_type_id = type_or_value.GetSingleWordInOperand(1);
-      if (!original_id_to_donated_id->count(pointee_type_id)) {
-        // We did not donate the pointee type for this pointer type, so we
-        // cannot donate the pointer type.
-        return;
-      }
-      new_result_id = GetFuzzerContext()->GetFreshId();
-      ApplyTransformation(TransformationAddTypePointer(
-          new_result_id,
-          AdaptStorageClass(static_cast<SpvStorageClass>(
-              type_or_value.GetSingleWordInOperand(0))),
-          original_id_to_donated_id->at(pointee_type_id)));
-    } break;
-    case SpvOpTypeFunction: {
-      // It is not OK to have multiple function types that use identical ids
-      // for their return and parameter types.  We thus go through all
-      // existing function types to look for a match.  We do not use the
-      // type manager here because we want to regard two function types that
-      // are structurally identical but that differ with respect to the
-      // actual ids used for pointer types as different.
-      //
-      // Example:
-      //
-      // %1 = OpTypeVoid
-      // %2 = OpTypeInt 32 0
-      // %3 = OpTypePointer Function %2
-      // %4 = OpTypePointer Function %2
-      // %5 = OpTypeFunction %1 %3
-      // %6 = OpTypeFunction %1 %4
-      //
-      // We regard %5 and %6 as distinct function types here, even though
-      // they both have the form "uint32* -> void"
-
-      std::vector<uint32_t> return_and_parameter_types;
-      for (uint32_t i = 0; i < type_or_value.NumInOperands(); i++) {
-        uint32_t return_or_parameter_type =
-            type_or_value.GetSingleWordInOperand(i);
-        if (!original_id_to_donated_id->count(return_or_parameter_type)) {
-          // We did not donate every return/parameter type for this function
-          // type, so we cannot donate the function type.
-          return;
-        }
-        return_and_parameter_types.push_back(
-            original_id_to_donated_id->at(return_or_parameter_type));
-      }
-      uint32_t existing_function_id = fuzzerutil::FindFunctionType(
-          GetIRContext(), return_and_parameter_types);
-      if (existing_function_id) {
-        new_result_id = existing_function_id;
-      } else {
-        // No match was found, so add a remapped version of the function type
-        // to the module, with a fresh id.
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        std::vector<uint32_t> argument_type_ids;
-        for (uint32_t i = 1; i < type_or_value.NumInOperands(); i++) {
-          argument_type_ids.push_back(original_id_to_donated_id->at(
-              type_or_value.GetSingleWordInOperand(i)));
-        }
-        ApplyTransformation(TransformationAddTypeFunction(
-            new_result_id,
-            original_id_to_donated_id->at(
-                type_or_value.GetSingleWordInOperand(0)),
-            argument_type_ids));
-      }
-    } break;
-    case SpvOpSpecConstantOp: {
-      new_result_id = GetFuzzerContext()->GetFreshId();
-      auto type_id = original_id_to_donated_id->at(type_or_value.type_id());
-      auto opcode = static_cast<SpvOp>(type_or_value.GetSingleWordInOperand(0));
-
-      // Make sure we take into account |original_id_to_donated_id| when
-      // computing operands for OpSpecConstantOp.
-      opt::Instruction::OperandList operands;
-      for (uint32_t i = 1; i < type_or_value.NumInOperands(); ++i) {
-        const auto& operand = type_or_value.GetInOperand(i);
-        auto data =
-            operand.type == SPV_OPERAND_TYPE_ID
-                ? opt::Operand::OperandData{original_id_to_donated_id->at(
-                      operand.words[0])}
-                : operand.words;
-
-        operands.push_back({operand.type, std::move(data)});
-      }
-
-      ApplyTransformation(TransformationAddSpecConstantOp(
-          new_result_id, type_id, opcode, std::move(operands)));
-    } break;
-    case SpvOpSpecConstantTrue:
-    case SpvOpSpecConstantFalse:
-    case SpvOpConstantTrue:
-    case SpvOpConstantFalse: {
-      // It is OK to have duplicate definitions of True and False, so add
-      // these to the module, using a remapped Bool type.
-      new_result_id = GetFuzzerContext()->GetFreshId();
-      auto value = type_or_value.opcode() == SpvOpConstantTrue ||
-                   type_or_value.opcode() == SpvOpSpecConstantTrue;
-      ApplyTransformation(
-          TransformationAddConstantBoolean(new_result_id, value, false));
-    } break;
-    case SpvOpSpecConstant:
-    case SpvOpConstant: {
-      // It is OK to have duplicate constant definitions, so add this to the
-      // module using a remapped result type.
-      new_result_id = GetFuzzerContext()->GetFreshId();
-      std::vector<uint32_t> data_words;
-      type_or_value.ForEachInOperand([&data_words](const uint32_t* in_operand) {
-        data_words.push_back(*in_operand);
-      });
-      ApplyTransformation(TransformationAddConstantScalar(
-          new_result_id, original_id_to_donated_id->at(type_or_value.type_id()),
-          data_words, false));
-    } break;
-    case SpvOpSpecConstantComposite:
-    case SpvOpConstantComposite: {
-      assert(original_id_to_donated_id->count(type_or_value.type_id()) &&
-             "Composite types for which it is possible to create a constant "
-             "should have been donated.");
-
-      // It is OK to have duplicate constant composite definitions, so add
-      // this to the module using remapped versions of all consituent ids and
-      // the result type.
-      new_result_id = GetFuzzerContext()->GetFreshId();
-      std::vector<uint32_t> constituent_ids;
-      type_or_value.ForEachInId([&constituent_ids, &original_id_to_donated_id](
-                                    const uint32_t* constituent_id) {
-        assert(original_id_to_donated_id->count(*constituent_id) &&
-               "The constants used to construct this composite should "
-               "have been donated.");
-        constituent_ids.push_back(
-            original_id_to_donated_id->at(*constituent_id));
-      });
-      ApplyTransformation(TransformationAddConstantComposite(
-          new_result_id, original_id_to_donated_id->at(type_or_value.type_id()),
-          constituent_ids, false));
-    } 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.
-        return;
-      }
-
-      // 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: {
-      if (!original_id_to_donated_id->count(type_or_value.type_id())) {
-        // We did not donate the pointer type associated with this variable,
-        // so we cannot donate the variable.
-        return;
-      }
-
-      // This is a global variable that could have one of various storage
-      // classes.  However, we change all global variable pointer storage
-      // classes (such as Uniform, Input and Output) to private when donating
-      // pointer types, with the exception of the Workgroup storage class.
-      //
-      // Thus this variable's pointer type is guaranteed to have storage class
-      // Private or Workgroup.
-      //
-      // We add a global variable with either Private or Workgroup storage
-      // class, using remapped versions of the result type and initializer ids
-      // for the global variable in the donor.
-      //
-      // We regard the added variable as having an irrelevant value.  This
-      // means that future passes can add stores to the variable in any
-      // way they wish, and pass them as pointer parameters to functions
-      // without worrying about whether their data might get modified.
-      new_result_id = GetFuzzerContext()->GetFreshId();
-      uint32_t remapped_pointer_type =
-          original_id_to_donated_id->at(type_or_value.type_id());
-      uint32_t initializer_id;
-      SpvStorageClass storage_class =
-          static_cast<SpvStorageClass>(type_or_value.GetSingleWordInOperand(
-              0)) == SpvStorageClassWorkgroup
-              ? SpvStorageClassWorkgroup
-              : SpvStorageClassPrivate;
-      if (type_or_value.NumInOperands() == 1) {
-        // The variable did not have an initializer.  Initialize it to zero
-        // if it has Private storage class (to limit problems associated with
-        // uninitialized data), and leave it uninitialized if it has Workgroup
-        // storage class (as Workgroup variables cannot have initializers).
-
-        // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3275): we
-        //  could initialize Workgroup variables at the start of an entry
-        //  point, and should do so if their uninitialized nature proves
-        //  problematic.
-        initializer_id = storage_class == SpvStorageClassWorkgroup
-                             ? 0
-                             : FindOrCreateZeroConstant(
-                                   fuzzerutil::GetPointeeTypeIdFromPointerType(
-                                       GetIRContext(), remapped_pointer_type),
-                                   false);
-      } else {
-        // The variable already had an initializer; use its remapped id.
-        initializer_id = original_id_to_donated_id->at(
-            type_or_value.GetSingleWordInOperand(1));
-      }
-      ApplyTransformation(
-          TransformationAddGlobalVariable(new_result_id, remapped_pointer_type,
-                                          storage_class, initializer_id, true));
-    } break;
-    case SpvOpUndef: {
-      if (!original_id_to_donated_id->count(type_or_value.type_id())) {
-        // We did not donate the type associated with this undef, so we cannot
-        // donate the undef.
-        return;
-      }
-
-      // It is fine to have multiple Undef instructions of the same type, so
-      // we just add this to the recipient module.
-      new_result_id = GetFuzzerContext()->GetFreshId();
-      ApplyTransformation(TransformationAddGlobalUndef(
-          new_result_id,
-          original_id_to_donated_id->at(type_or_value.type_id())));
-    } break;
-    default: {
-      assert(0 && "Unknown type/value.");
-      new_result_id = 0;
-    } break;
-  }
-
-  // Update the id mapping to associate the instruction's result id with its
-  // corresponding id in the recipient.
-  original_id_to_donated_id->insert({type_or_value.result_id(), new_result_id});
-}
-
-void FuzzerPassDonateModules::HandleFunctions(
-    opt::IRContext* donor_ir_context,
-    std::map<uint32_t, uint32_t>* original_id_to_donated_id,
-    bool make_livesafe) {
-  // Get the ids of functions in the donor module, topologically sorted
-  // according to the donor's call graph.
-  auto topological_order =
-      GetFunctionsInCallGraphTopologicalOrder(donor_ir_context);
-
-  // Donate the functions in reverse topological order.  This ensures that a
-  // function gets donated before any function that depends on it.  This allows
-  // donation of the functions to be separated into a number of transformations,
-  // each adding one function, such that every prefix of transformations leaves
-  // the module valid.
-  for (auto function_id = topological_order.rbegin();
-       function_id != topological_order.rend(); ++function_id) {
-    // Find the function to be donated.
-    opt::Function* function_to_donate = nullptr;
-    for (auto& function : *donor_ir_context->module()) {
-      if (function.result_id() == *function_id) {
-        function_to_donate = &function;
-        break;
-      }
-    }
-    assert(function_to_donate && "Function to be donated was not found.");
-
-    if (!original_id_to_donated_id->count(
-            function_to_donate->DefInst().GetSingleWordInOperand(1))) {
-      // We were not able to donate this function's type, so we cannot donate
-      // the function.
-      continue;
-    }
-
-    // We will collect up protobuf messages representing the donor function's
-    // instructions here, and use them to create an AddFunction transformation.
-    std::vector<protobufs::Instruction> donated_instructions;
-
-    // This set tracks the ids of those instructions for which donation was
-    // completely skipped: neither the instruction nor a substitute for it was
-    // donated.
-    std::set<uint32_t> skipped_instructions;
-
-    // Consider every instruction of the donor function.
-    function_to_donate->ForEachInst(
-        [this, &donated_instructions, donor_ir_context,
-         &original_id_to_donated_id,
-         &skipped_instructions](const opt::Instruction* instruction) {
-          if (instruction->opcode() == SpvOpArrayLength) {
-            // We treat OpArrayLength specially.
-            HandleOpArrayLength(*instruction, original_id_to_donated_id,
-                                &donated_instructions);
-          } else if (!CanDonateInstruction(donor_ir_context, *instruction,
-                                           *original_id_to_donated_id,
-                                           skipped_instructions)) {
-            // This is an instruction that we cannot directly donate.
-            HandleDifficultInstruction(*instruction, original_id_to_donated_id,
-                                       &donated_instructions,
-                                       &skipped_instructions);
-          } else {
-            PrepareInstructionForDonation(*instruction, donor_ir_context,
-                                          original_id_to_donated_id,
-                                          &donated_instructions);
-          }
-        });
-
-    // If |make_livesafe| is true, try to add the function in a livesafe manner.
-    // Otherwise (if |make_lifesafe| is false or an attempt to make the function
-    // livesafe has failed), add the function in a non-livesafe manner.
-    if (!make_livesafe ||
-        !MaybeAddLivesafeFunction(*function_to_donate, donor_ir_context,
-                                  *original_id_to_donated_id,
-                                  donated_instructions)) {
-      ApplyTransformation(TransformationAddFunction(donated_instructions));
-    }
-  }
-}
-
-bool FuzzerPassDonateModules::CanDonateInstruction(
-    opt::IRContext* donor_ir_context, const opt::Instruction& instruction,
-    const std::map<uint32_t, uint32_t>& original_id_to_donated_id,
-    const std::set<uint32_t>& skipped_instructions) const {
-  if (instruction.type_id() &&
-      !original_id_to_donated_id.count(instruction.type_id())) {
-    // We could not donate the result type of this instruction, so we cannot
-    // donate the instruction.
-    return false;
-  }
-
-  // Now consider instructions we specifically want to skip because we do not
-  // yet support them.
-  switch (instruction.opcode()) {
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-      // We conservatively ignore all atomic instructions at present.
-      // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3276): Consider
-      //  being less conservative here.
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageFetch:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageRead:
-    case SpvOpImageWrite:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpImageSparseRead:
-    case SpvOpImageSampleFootprintNV:
-    case SpvOpImage:
-    case SpvOpImageQueryFormat:
-    case SpvOpImageQueryLevels:
-    case SpvOpImageQueryLod:
-    case SpvOpImageQueryOrder:
-    case SpvOpImageQuerySamples:
-    case SpvOpImageQuerySize:
-    case SpvOpImageQuerySizeLod:
-    case SpvOpSampledImage:
-      // We ignore all instructions related to accessing images, since we do not
-      // donate images.
-      return false;
-    case SpvOpLoad:
-      switch (donor_ir_context->get_def_use_mgr()
-                  ->GetDef(instruction.type_id())
-                  ->opcode()) {
-        case SpvOpTypeImage:
-        case SpvOpTypeSampledImage:
-        case SpvOpTypeSampler:
-          // Again, we ignore instructions that relate to accessing images.
-          return false;
-        default:
-          break;
-      }
-    default:
-      break;
-  }
-
-  // Examine each id input operand to the instruction.  If it turns out that we
-  // have skipped any of these operands then we cannot donate the instruction.
-  bool result = true;
-  instruction.WhileEachInId(
-      [donor_ir_context, &original_id_to_donated_id, &result,
-       &skipped_instructions](const uint32_t* in_id) -> bool {
-        if (!original_id_to_donated_id.count(*in_id)) {
-          // We do not have a mapped result id for this id operand.  That either
-          // means that it is a forward reference (which is OK), that we skipped
-          // the instruction that generated it (which is not OK), or that it is
-          // the id of a function or global value that we did not donate (which
-          // is not OK).  We check for the latter two cases.
-          if (skipped_instructions.count(*in_id) ||
-              // A function or global value does not have an associated basic
-              // block.
-              !donor_ir_context->get_instr_block(*in_id)) {
-            result = false;
-            return false;
-          }
-        }
-        return true;
-      });
-  return result;
-}
-
-bool FuzzerPassDonateModules::IsBasicType(
-    const opt::Instruction& instruction) const {
-  switch (instruction.opcode()) {
-    case SpvOpTypeArray:
-    case SpvOpTypeBool:
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeStruct:
-    case SpvOpTypeVector:
-      return true;
-    default:
-      return false;
-  }
-}
-
-std::vector<uint32_t>
-FuzzerPassDonateModules::GetFunctionsInCallGraphTopologicalOrder(
-    opt::IRContext* context) {
-  CallGraph call_graph(context);
-
-  // This is an implementation of Kahn’s algorithm for topological sorting.
-
-  // This is the sorted order of function ids that we will eventually return.
-  std::vector<uint32_t> result;
-
-  // Get a copy of the initial in-degrees of all functions.  The algorithm
-  // involves decrementing these values, hence why we work on a copy.
-  std::map<uint32_t, uint32_t> function_in_degree =
-      call_graph.GetFunctionInDegree();
-
-  // Populate a queue with all those function ids with in-degree zero.
-  std::queue<uint32_t> queue;
-  for (auto& entry : function_in_degree) {
-    if (entry.second == 0) {
-      queue.push(entry.first);
-    }
-  }
-
-  // Pop ids from the queue, adding them to the sorted order and decreasing the
-  // in-degrees of their successors.  A successor who's in-degree becomes zero
-  // gets added to the queue.
-  while (!queue.empty()) {
-    auto next = queue.front();
-    queue.pop();
-    result.push_back(next);
-    for (auto successor : call_graph.GetDirectCallees(next)) {
-      assert(function_in_degree.at(successor) > 0 &&
-             "The in-degree cannot be zero if the function is a successor.");
-      function_in_degree[successor] = function_in_degree.at(successor) - 1;
-      if (function_in_degree.at(successor) == 0) {
-        queue.push(successor);
-      }
-    }
-  }
-
-  assert(result.size() == function_in_degree.size() &&
-         "Every function should appear in the sort.");
-
-  return result;
-}
-
-void FuzzerPassDonateModules::HandleOpArrayLength(
-    const opt::Instruction& instruction,
-    std::map<uint32_t, uint32_t>* original_id_to_donated_id,
-    std::vector<protobufs::Instruction>* donated_instructions) const {
-  assert(instruction.opcode() == SpvOpArrayLength &&
-         "Precondition: instruction must be OpArrayLength.");
-  uint32_t donated_variable_id =
-      original_id_to_donated_id->at(instruction.GetSingleWordInOperand(0));
-  auto donated_variable_instruction =
-      GetIRContext()->get_def_use_mgr()->GetDef(donated_variable_id);
-  auto pointer_to_struct_instruction =
-      GetIRContext()->get_def_use_mgr()->GetDef(
-          donated_variable_instruction->type_id());
-  assert(pointer_to_struct_instruction->opcode() == SpvOpTypePointer &&
-         "Type of variable must be pointer.");
-  auto donated_struct_type_instruction =
-      GetIRContext()->get_def_use_mgr()->GetDef(
-          pointer_to_struct_instruction->GetSingleWordInOperand(1));
-  assert(donated_struct_type_instruction->opcode() == SpvOpTypeStruct &&
-         "Pointee type of pointer used by OpArrayLength must be struct.");
-  assert(donated_struct_type_instruction->NumInOperands() ==
-             instruction.GetSingleWordInOperand(1) + 1 &&
-         "OpArrayLength must refer to the final member of the given "
-         "struct.");
-  uint32_t fixed_size_array_type_id =
-      donated_struct_type_instruction->GetSingleWordInOperand(
-          donated_struct_type_instruction->NumInOperands() - 1);
-  auto fixed_size_array_type_instruction =
-      GetIRContext()->get_def_use_mgr()->GetDef(fixed_size_array_type_id);
-  assert(fixed_size_array_type_instruction->opcode() == SpvOpTypeArray &&
-         "The donated array type must be fixed-size.");
-  auto array_size_id =
-      fixed_size_array_type_instruction->GetSingleWordInOperand(1);
-
-  if (instruction.result_id() &&
-      !original_id_to_donated_id->count(instruction.result_id())) {
-    original_id_to_donated_id->insert(
-        {instruction.result_id(), GetFuzzerContext()->GetFreshId()});
-  }
-
-  donated_instructions->push_back(MakeInstructionMessage(
-      SpvOpCopyObject, original_id_to_donated_id->at(instruction.type_id()),
-      original_id_to_donated_id->at(instruction.result_id()),
-      opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {array_size_id}}})));
-}
-
-void FuzzerPassDonateModules::HandleDifficultInstruction(
-    const opt::Instruction& instruction,
-    std::map<uint32_t, uint32_t>* original_id_to_donated_id,
-    std::vector<protobufs::Instruction>* donated_instructions,
-    std::set<uint32_t>* skipped_instructions) {
-  if (!instruction.result_id()) {
-    // It does not generate a result id, so it can be ignored.
-    return;
-  }
-  if (!original_id_to_donated_id->count(instruction.type_id())) {
-    // We cannot handle this instruction's result type, so we need to skip it
-    // all together.
-    skipped_instructions->insert(instruction.result_id());
-    return;
-  }
-
-  // We now attempt to replace the instruction with an OpCopyObject.
-  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3278): We could do
-  //  something more refined here - we could check which operands to the
-  //  instruction could not be donated and replace those operands with
-  //  references to other ids (such as constants), so that we still get an
-  //  instruction with the opcode and easy-to-handle operands of the donor
-  //  instruction.
-  auto remapped_type_id = original_id_to_donated_id->at(instruction.type_id());
-  if (!IsBasicType(
-          *GetIRContext()->get_def_use_mgr()->GetDef(remapped_type_id))) {
-    // The instruction has a non-basic result type, so we cannot replace it with
-    // an object copy of a constant.  We thus skip it completely.
-    // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3279): We could
-    //  instead look for an available id of the right type and generate an
-    //  OpCopyObject of that id.
-    skipped_instructions->insert(instruction.result_id());
-    return;
-  }
-
-  // We are going to add an OpCopyObject instruction.  Add a mapping for the
-  // result id of the original instruction if does not already exist (it may
-  // exist in the case that it has been forward-referenced).
-  if (!original_id_to_donated_id->count(instruction.result_id())) {
-    original_id_to_donated_id->insert(
-        {instruction.result_id(), GetFuzzerContext()->GetFreshId()});
-  }
-
-  // We find or add a zero constant to the receiving module for the type in
-  // question, and add an OpCopyObject instruction that copies this zero.
-  //
-  // We mark the constant as irrelevant so that we can replace it with a
-  // more interesting value later.
-  auto zero_constant = FindOrCreateZeroConstant(remapped_type_id, true);
-  donated_instructions->push_back(MakeInstructionMessage(
-      SpvOpCopyObject, remapped_type_id,
-      original_id_to_donated_id->at(instruction.result_id()),
-      opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {zero_constant}}})));
-}
-
-void FuzzerPassDonateModules::PrepareInstructionForDonation(
-    const opt::Instruction& instruction, opt::IRContext* donor_ir_context,
-    std::map<uint32_t, uint32_t>* original_id_to_donated_id,
-    std::vector<protobufs::Instruction>* donated_instructions) {
-  // Get the instruction's input operands into donation-ready form,
-  // remapping any id uses in the process.
-  opt::Instruction::OperandList input_operands;
-
-  // Consider each input operand in turn.
-  for (uint32_t in_operand_index = 0;
-       in_operand_index < instruction.NumInOperands(); in_operand_index++) {
-    std::vector<uint32_t> operand_data;
-    const opt::Operand& in_operand = instruction.GetInOperand(in_operand_index);
-    // Check whether this operand is an id.
-    if (spvIsIdType(in_operand.type)) {
-      // This is an id operand - it consists of a single word of data,
-      // which needs to be remapped so that it is replaced with the
-      // donated form of the id.
-      auto operand_id = in_operand.words[0];
-      if (!original_id_to_donated_id->count(operand_id)) {
-        // This is a forward reference.  We will choose a corresponding
-        // donor id for the referenced id and update the mapping to
-        // reflect it.
-
-        // Keep release compilers happy because |donor_ir_context| is only used
-        // in this assertion.
-        (void)(donor_ir_context);
-        assert((donor_ir_context->get_def_use_mgr()
-                        ->GetDef(operand_id)
-                        ->opcode() == SpvOpLabel ||
-                instruction.opcode() == SpvOpPhi) &&
-               "Unsupported forward reference.");
-        original_id_to_donated_id->insert(
-            {operand_id, GetFuzzerContext()->GetFreshId()});
-      }
-      operand_data.push_back(original_id_to_donated_id->at(operand_id));
-    } else {
-      // For non-id operands, we just add each of the data words.
-      for (auto word : in_operand.words) {
-        operand_data.push_back(word);
-      }
-    }
-    input_operands.push_back({in_operand.type, operand_data});
-  }
-
-  if (instruction.opcode() == SpvOpVariable &&
-      instruction.NumInOperands() == 1) {
-    // This is an uninitialized local variable.  Initialize it to zero.
-    input_operands.push_back(
-        {SPV_OPERAND_TYPE_ID,
-         {FindOrCreateZeroConstant(
-             fuzzerutil::GetPointeeTypeIdFromPointerType(
-                 GetIRContext(),
-                 original_id_to_donated_id->at(instruction.type_id())),
-             false)}});
-  }
-
-  if (instruction.result_id() &&
-      !original_id_to_donated_id->count(instruction.result_id())) {
-    original_id_to_donated_id->insert(
-        {instruction.result_id(), GetFuzzerContext()->GetFreshId()});
-  }
-
-  // Remap the result type and result id (if present) of the
-  // instruction, and turn it into a protobuf message.
-  donated_instructions->push_back(MakeInstructionMessage(
-      instruction.opcode(),
-      instruction.type_id()
-          ? original_id_to_donated_id->at(instruction.type_id())
-          : 0,
-      instruction.result_id()
-          ? original_id_to_donated_id->at(instruction.result_id())
-          : 0,
-      input_operands));
-}
-
-bool FuzzerPassDonateModules::CreateLoopLimiterInfo(
-    opt::IRContext* donor_ir_context, const opt::BasicBlock& loop_header,
-    const std::map<uint32_t, uint32_t>& original_id_to_donated_id,
-    protobufs::LoopLimiterInfo* out) {
-  assert(loop_header.IsLoopHeader() && "|loop_header| is not a loop header");
-
-  // Grab the loop header's id, mapped to its donated value.
-  out->set_loop_header_id(original_id_to_donated_id.at(loop_header.id()));
-
-  // Get fresh ids that will be used to load the loop limiter, increment
-  // it, compare it with the loop limit, and an id for a new block that
-  // will contain the loop's original terminator.
-  out->set_load_id(GetFuzzerContext()->GetFreshId());
-  out->set_increment_id(GetFuzzerContext()->GetFreshId());
-  out->set_compare_id(GetFuzzerContext()->GetFreshId());
-  out->set_logical_op_id(GetFuzzerContext()->GetFreshId());
-
-  // We are creating a branch from the back-edge block to the merge block. Thus,
-  // if merge block has any OpPhi instructions, we might need to adjust
-  // them.
-
-  // Note that the loop might have an unreachable back-edge block. This means
-  // that the loop can't iterate, so we don't need to adjust anything.
-  const auto back_edge_block_id = TransformationAddFunction::GetBackEdgeBlockId(
-      donor_ir_context, loop_header.id());
-  if (!back_edge_block_id) {
-    return true;
-  }
-
-  auto* back_edge_block = donor_ir_context->cfg()->block(back_edge_block_id);
-  assert(back_edge_block && "|back_edge_block_id| is invalid");
-
-  const auto* merge_block =
-      donor_ir_context->cfg()->block(loop_header.MergeBlockId());
-  assert(merge_block && "Loop header has invalid merge block id");
-
-  // We don't need to adjust anything if there is already a branch from
-  // the back-edge block to the merge block.
-  if (back_edge_block->IsSuccessor(merge_block)) {
-    return true;
-  }
-
-  // Adjust OpPhi instructions in the |merge_block|.
-  for (const auto& inst : *merge_block) {
-    if (inst.opcode() != SpvOpPhi) {
-      break;
-    }
-
-    // There is no simple way to ensure that a chosen operand for the OpPhi
-    // instruction will never cause any problems (e.g. if we choose an
-    // integer id, it might have a zero value when we branch from the back
-    // edge block. This might cause a division by 0 later in the function.).
-    // Thus, we ignore possible problems and proceed as follows:
-    // - if any of the existing OpPhi operands dominates the back-edge
-    //   block - use it
-    // - if OpPhi has a basic type (see IsBasicType method) - create
-    //   a zero constant
-    // - otherwise, we can't add a livesafe function.
-    uint32_t suitable_operand_id = 0;
-    for (uint32_t i = 0; i < inst.NumInOperands(); i += 2) {
-      auto dependency_inst_id = inst.GetSingleWordInOperand(i);
-
-      if (fuzzerutil::IdIsAvailableBeforeInstruction(
-              donor_ir_context, back_edge_block->terminator(),
-              dependency_inst_id)) {
-        suitable_operand_id = original_id_to_donated_id.at(dependency_inst_id);
-        break;
-      }
-    }
-
-    if (suitable_operand_id == 0 &&
-        IsBasicType(
-            *donor_ir_context->get_def_use_mgr()->GetDef(inst.type_id()))) {
-      // We mark this constant as irrelevant so that we can replace it
-      // with more interesting value later.
-      suitable_operand_id = FindOrCreateZeroConstant(
-          original_id_to_donated_id.at(inst.type_id()), true);
-    }
-
-    if (suitable_operand_id == 0) {
-      return false;
-    }
-
-    out->add_phi_id(suitable_operand_id);
-  }
-
-  return true;
-}
-
-bool FuzzerPassDonateModules::MaybeAddLivesafeFunction(
-    const opt::Function& function_to_donate, opt::IRContext* donor_ir_context,
-    const std::map<uint32_t, uint32_t>& original_id_to_donated_id,
-    const std::vector<protobufs::Instruction>& donated_instructions) {
-  // Various types and constants must be in place for a function to be made
-  // live-safe.  Add them if not already present.
-  FindOrCreateBoolType();  // Needed for comparisons
-  FindOrCreatePointerToIntegerType(
-      32, false, SpvStorageClassFunction);  // Needed for adding loop limiters
-  FindOrCreateIntegerConstant({0}, 32, false,
-                              false);  // Needed for initializing loop limiters
-  FindOrCreateIntegerConstant({1}, 32, false,
-                              false);  // Needed for incrementing loop limiters
-
-  // Get a fresh id for the variable that will be used as a loop limiter.
-  const uint32_t loop_limiter_variable_id = GetFuzzerContext()->GetFreshId();
-  // Choose a random loop limit, and add the required constant to the
-  // module if not already there.
-  const uint32_t loop_limit = FindOrCreateIntegerConstant(
-      {GetFuzzerContext()->GetRandomLoopLimit()}, 32, false, false);
-
-  // Consider every loop header in the function to donate, and create a
-  // structure capturing the ids to be used for manipulating the loop
-  // limiter each time the loop is iterated.
-  std::vector<protobufs::LoopLimiterInfo> loop_limiters;
-  for (auto& block : function_to_donate) {
-    if (block.IsLoopHeader()) {
-      protobufs::LoopLimiterInfo loop_limiter;
-
-      if (!CreateLoopLimiterInfo(donor_ir_context, block,
-                                 original_id_to_donated_id, &loop_limiter)) {
-        return false;
-      }
-
-      loop_limiters.emplace_back(std::move(loop_limiter));
-    }
-  }
-
-  // Consider every access chain in the function to donate, and create a
-  // structure containing the ids necessary to clamp the access chain
-  // indices to be in-bounds.
-  std::vector<protobufs::AccessChainClampingInfo> access_chain_clamping_info;
-  for (auto& block : function_to_donate) {
-    for (auto& inst : block) {
-      switch (inst.opcode()) {
-        case SpvOpAccessChain:
-        case SpvOpInBoundsAccessChain: {
-          protobufs::AccessChainClampingInfo clamping_info;
-          clamping_info.set_access_chain_id(
-              original_id_to_donated_id.at(inst.result_id()));
-
-          auto base_object = donor_ir_context->get_def_use_mgr()->GetDef(
-              inst.GetSingleWordInOperand(0));
-          assert(base_object && "The base object must exist.");
-          auto pointer_type = donor_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 =
-              donor_ir_context->get_def_use_mgr()->GetDef(
-                  pointer_type->GetSingleWordInOperand(1));
-
-          // Walk the access chain, creating fresh ids to facilitate
-          // clamping each index.  For simplicity we do this for every
-          // index, even though constant indices will not end up being
-          // clamped.
-          for (uint32_t index = 1; index < inst.NumInOperands(); index++) {
-            auto compare_and_select_ids =
-                clamping_info.add_compare_and_select_ids();
-            compare_and_select_ids->set_first(GetFuzzerContext()->GetFreshId());
-            compare_and_select_ids->set_second(
-                GetFuzzerContext()->GetFreshId());
-
-            // Get the bound for the component being indexed into.
-            uint32_t bound;
-            if (should_be_composite_type->opcode() == SpvOpTypeRuntimeArray) {
-              // The donor is indexing into a runtime array.  We do not
-              // donate runtime arrays.  Instead, we donate a corresponding
-              // fixed-size array for every runtime array.  We should thus
-              // find that donor composite type's result id maps to a fixed-
-              // size array.
-              auto fixed_size_array_type =
-                  GetIRContext()->get_def_use_mgr()->GetDef(
-                      original_id_to_donated_id.at(
-                          should_be_composite_type->result_id()));
-              assert(fixed_size_array_type->opcode() == SpvOpTypeArray &&
-                     "A runtime array type in the donor should have been "
-                     "replaced by a fixed-sized array in the recipient.");
-              // The size of this fixed-size array is a suitable bound.
-              bound = fuzzerutil::GetBoundForCompositeIndex(
-                  *fixed_size_array_type, GetIRContext());
-            } else {
-              bound = fuzzerutil::GetBoundForCompositeIndex(
-                  *should_be_composite_type, donor_ir_context);
-            }
-            const uint32_t index_id = inst.GetSingleWordInOperand(index);
-            auto index_inst =
-                donor_ir_context->get_def_use_mgr()->GetDef(index_id);
-            auto index_type_inst = donor_ir_context->get_def_use_mgr()->GetDef(
-                index_inst->type_id());
-            assert(index_type_inst->opcode() == SpvOpTypeInt);
-            opt::analysis::Integer* index_int_type =
-                donor_ir_context->get_type_mgr()
-                    ->GetType(index_type_inst->result_id())
-                    ->AsInteger();
-            if (index_inst->opcode() != SpvOpConstant) {
-              // We will have to clamp this index, so we need a constant
-              // whose value is one less than the bound, to compare
-              // against and to use as the clamped value.
-              FindOrCreateIntegerConstant({bound - 1}, 32,
-                                          index_int_type->IsSigned(), false);
-            }
-            should_be_composite_type =
-                TransformationAddFunction::FollowCompositeIndex(
-                    donor_ir_context, *should_be_composite_type, index_id);
-          }
-          access_chain_clamping_info.push_back(clamping_info);
-          break;
-        }
-        default:
-          break;
-      }
-    }
-  }
-
-  // If |function_to_donate| has non-void return type and contains an
-  // OpKill/OpUnreachable instruction, then a value is needed in order to turn
-  // these into instructions of the form OpReturnValue %value_id.
-  uint32_t kill_unreachable_return_value_id = 0;
-  auto function_return_type_inst =
-      donor_ir_context->get_def_use_mgr()->GetDef(function_to_donate.type_id());
-  if (function_return_type_inst->opcode() != SpvOpTypeVoid &&
-      fuzzerutil::FunctionContainsOpKillOrUnreachable(function_to_donate)) {
-    kill_unreachable_return_value_id = FindOrCreateZeroConstant(
-        original_id_to_donated_id.at(function_return_type_inst->result_id()),
-        false);
-  }
-
-  // Add the function in a livesafe manner.
-  ApplyTransformation(TransformationAddFunction(
-      donated_instructions, loop_limiter_variable_id, loop_limit, loop_limiters,
-      kill_unreachable_return_value_id, access_chain_clamping_info));
-  return true;
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

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

@@ -1,170 +0,0 @@
-// Copyright (c) 2019 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_FUZZER_PASS_DONATE_MODULES_H_
-#define SOURCE_FUZZ_FUZZER_PASS_DONATE_MODULES_H_
-
-#include <vector>
-
-#include "source/fuzz/fuzzer_pass.h"
-#include "source/fuzz/fuzzer_util.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A fuzzer pass that randomly adds code from other SPIR-V modules to the module
-// being transformed.
-class FuzzerPassDonateModules : public FuzzerPass {
- public:
-  FuzzerPassDonateModules(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations,
-      const std::vector<fuzzerutil::ModuleSupplier>& donor_suppliers);
-
-  ~FuzzerPassDonateModules();
-
-  void Apply() override;
-
-  // Donates the global declarations and functions of |donor_ir_context| into
-  // the fuzzer pass's IR context.  |make_livesafe| dictates whether the
-  // functions of the donated module will be made livesafe (see
-  // FactFunctionIsLivesafe).
-  void DonateSingleModule(opt::IRContext* donor_ir_context, bool make_livesafe);
-
- private:
-  // Adapts a storage class coming from a donor module so that it will work
-  // in a recipient module, e.g. by changing Uniform to Private.
-  static SpvStorageClass AdaptStorageClass(SpvStorageClass donor_storage_class);
-
-  // Identifies all external instruction set imports in |donor_ir_context| and
-  // populates |original_id_to_donated_id| with a mapping from the donor's id
-  // for such an import to a corresponding import in the recipient.  Aborts if
-  // no such corresponding import is available.
-  void HandleExternalInstructionImports(
-      opt::IRContext* donor_ir_context,
-      std::map<uint32_t, uint32_t>* original_id_to_donated_id);
-
-  // Considers all types, globals, constants and undefs in |donor_ir_context|.
-  // For each instruction, uses |original_to_donated_id| to map its result id to
-  // either (1) the id of an existing identical instruction in the recipient, or
-  // (2) to a fresh id, in which case the instruction is also added to the
-  // recipient (with any operand ids that it uses being remapped via
-  // |original_id_to_donated_id|).
-  void HandleTypesAndValues(
-      opt::IRContext* donor_ir_context,
-      std::map<uint32_t, uint32_t>* original_id_to_donated_id);
-
-  // Helper method for HandleTypesAndValues, to handle a single type/value.
-  void HandleTypeOrValue(
-      const opt::Instruction& type_or_value,
-      std::map<uint32_t, uint32_t>* original_id_to_donated_id);
-
-  // Assumes that |donor_ir_context| does not exhibit recursion.  Considers the
-  // functions in |donor_ir_context|'s call graph in a reverse-topologically-
-  // sorted order (leaves-to-root), adding each function to the recipient
-  // module, rewritten to use fresh ids and using |original_id_to_donated_id| to
-  // remap ids.  The |make_livesafe| argument captures whether the functions in
-  // the module are required to be made livesafe before being added to the
-  // recipient.
-  void HandleFunctions(opt::IRContext* donor_ir_context,
-                       std::map<uint32_t, uint32_t>* original_id_to_donated_id,
-                       bool make_livesafe);
-
-  // During donation we will have to ignore some instructions, e.g. because they
-  // use opcodes that we cannot support or because they reference the ids of
-  // instructions that have not been donated.  This function encapsulates the
-  // logic for deciding which whether instruction |instruction| from
-  // |donor_ir_context| can be donated.
-  bool CanDonateInstruction(
-      opt::IRContext* donor_ir_context, const opt::Instruction& instruction,
-      const std::map<uint32_t, uint32_t>& original_id_to_donated_id,
-      const std::set<uint32_t>& skipped_instructions) const;
-
-  // We treat the OpArrayLength instruction specially.  In the donor shader this
-  // instruction yields the length of a runtime array that is the final member
-  // of a struct.  During donation, we will have converted the runtime array
-  // type, and the associated struct field, into a fixed-size array.
-  //
-  // Instead of donating this instruction, we turn it into an OpCopyObject
-  // instruction that copies the size of the fixed-size array.
-  void HandleOpArrayLength(
-      const opt::Instruction& instruction,
-      std::map<uint32_t, uint32_t>* original_id_to_donated_id,
-      std::vector<protobufs::Instruction>* donated_instructions) const;
-
-  // The instruction |instruction| is required to be an instruction that cannot
-  // be easily donated, either because it uses an unsupported opcode, has an
-  // unsupported result type, or uses id operands that could not be donated.
-  //
-  // If |instruction| generates a result id, the function attempts to add a
-  // substitute for |instruction| to |donated_instructions| that has the correct
-  // result type.  If this cannot be done, the instruction's result id is added
-  // to |skipped_instructions|.  The mapping from donor ids to recipient ids is
-  // managed by |original_id_to_donated_id|.
-  void HandleDifficultInstruction(
-      const opt::Instruction& instruction,
-      std::map<uint32_t, uint32_t>* original_id_to_donated_id,
-      std::vector<protobufs::Instruction>* donated_instructions,
-      std::set<uint32_t>* skipped_instructions);
-
-  // Adds an instruction based in |instruction| to |donated_instructions| in a
-  // form ready for donation.  The original instruction comes from
-  // |donor_ir_context|, and |original_id_to_donated_id| maps ids from
-  // |donor_ir_context| to corresponding ids in the recipient module.
-  void PrepareInstructionForDonation(
-      const opt::Instruction& instruction, opt::IRContext* donor_ir_context,
-      std::map<uint32_t, uint32_t>* original_id_to_donated_id,
-      std::vector<protobufs::Instruction>* donated_instructions);
-
-  // Tries to create a protobufs::LoopLimiterInfo given a loop header basic
-  // block. Returns true if successful and outputs loop limiter into the |out|
-  // variable. Otherwise, returns false. |out| contains an undefined value when
-  // this function returns false.
-  bool CreateLoopLimiterInfo(
-      opt::IRContext* donor_ir_context, const opt::BasicBlock& loop_header,
-      const std::map<uint32_t, uint32_t>& original_id_to_donated_id,
-      protobufs::LoopLimiterInfo* out);
-
-  // Requires that |donated_instructions| represents a prepared version of the
-  // instructions of |function_to_donate| (which comes from |donor_ir_context|)
-  // ready for donation, and |original_id_to_donated_id| maps ids from
-  // |donor_ir_context| to their corresponding ids in the recipient module.
-  //
-  // Attempts to add a livesafe version of the function, based on
-  // |donated_instructions|, to the recipient module. Returns true if the
-  // donation was successful, false otherwise.
-  bool MaybeAddLivesafeFunction(
-      const opt::Function& function_to_donate, opt::IRContext* donor_ir_context,
-      const std::map<uint32_t, uint32_t>& original_id_to_donated_id,
-      const std::vector<protobufs::Instruction>& donated_instructions);
-
-  // Returns true if and only if |instruction| is a scalar, vector, matrix,
-  // array or struct; i.e. it is not an opaque type.
-  bool IsBasicType(const opt::Instruction& instruction) const;
-
-  // Returns the ids of all functions in |context| in a topological order in
-  // relation to the call graph of |context|, which is assumed to be recursion-
-  // free.
-  static std::vector<uint32_t> GetFunctionsInCallGraphTopologicalOrder(
-      opt::IRContext* context);
-
-  // Functions that supply SPIR-V modules
-  std::vector<fuzzerutil::ModuleSupplier> donor_suppliers_;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_DONATE_MODULES_H_

+ 0 - 104
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_inline_functions.cpp

@@ -1,104 +0,0 @@
-// Copyright (c) 2020 André Perez Maselco
-//
-// 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/fuzzer_pass_inline_functions.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/instruction_descriptor.h"
-#include "source/fuzz/transformation_inline_function.h"
-#include "source/fuzz/transformation_split_block.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassInlineFunctions::FuzzerPassInlineFunctions(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassInlineFunctions::~FuzzerPassInlineFunctions() = default;
-
-void FuzzerPassInlineFunctions::Apply() {
-  // |function_call_instructions| are the instructions that will be inlined.
-  // First, they will be collected and then do the inlining in another loop.
-  // This avoids changing the module while it is being inspected.
-  std::vector<opt::Instruction*> function_call_instructions;
-
-  for (auto& function : *GetIRContext()->module()) {
-    for (auto& block : function) {
-      for (auto& instruction : block) {
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()->GetChanceOfInliningFunction())) {
-          continue;
-        }
-
-        // |instruction| must be suitable for inlining.
-        if (!TransformationInlineFunction::IsSuitableForInlining(
-                GetIRContext(), &instruction)) {
-          continue;
-        }
-
-        function_call_instructions.push_back(&instruction);
-      }
-    }
-  }
-
-  // Once the function calls have been collected, it's time to actually create
-  // and apply the inlining transformations.
-  for (auto& function_call_instruction : function_call_instructions) {
-    // If |function_call_instruction| is not the penultimate instruction in its
-    // block or its block termination instruction is not OpBranch, then try to
-    // split |function_call_block| such that the conditions are met.
-    auto* function_call_block =
-        GetIRContext()->get_instr_block(function_call_instruction);
-    if ((function_call_instruction != &*--function_call_block->tail() ||
-         function_call_block->terminator()->opcode() != SpvOpBranch) &&
-        !MaybeApplyTransformation(TransformationSplitBlock(
-            MakeInstructionDescriptor(GetIRContext(),
-                                      function_call_instruction->NextNode()),
-            GetFuzzerContext()->GetFreshId()))) {
-      continue;
-    }
-
-    auto* called_function = fuzzerutil::FindFunction(
-        GetIRContext(), function_call_instruction->GetSingleWordInOperand(0));
-
-    // Mapping the called function instructions.
-    std::map<uint32_t, uint32_t> result_id_map;
-    for (auto& called_function_block : *called_function) {
-      // The called function entry block label will not be inlined.
-      if (&called_function_block != &*called_function->entry()) {
-        result_id_map[called_function_block.GetLabelInst()->result_id()] =
-            GetFuzzerContext()->GetFreshId();
-      }
-
-      for (auto& instruction_to_inline : called_function_block) {
-        // The instructions are mapped to fresh ids.
-        if (instruction_to_inline.HasResultId()) {
-          result_id_map[instruction_to_inline.result_id()] =
-              GetFuzzerContext()->GetFreshId();
-        }
-      }
-    }
-
-    // Applies the inline function transformation.
-    ApplyTransformation(TransformationInlineFunction(
-        function_call_instruction->result_id(), result_id_map));
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 41
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_inline_functions.h

@@ -1,41 +0,0 @@
-// Copyright (c) 2020 André Perez Maselco
-//
-// 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_FUZZER_PASS_INLINE_FUNCTIONS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_INLINE_FUNCTIONS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Looks for OpFunctionCall instructions and randomly decides which ones to
-// inline. If the instructions of the called function are going to be inlined,
-// then a mapping, between their result ids and suitable ids, is done.
-class FuzzerPassInlineFunctions : public FuzzerPass {
- public:
-  FuzzerPassInlineFunctions(opt::IRContext* ir_context,
-                            TransformationContext* transformation_context,
-                            FuzzerContext* fuzzer_context,
-                            protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassInlineFunctions() override;
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_INLINE_FUNCTIONS_H_

+ 0 - 156
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.cpp

@@ -1,156 +0,0 @@
-// 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 "fuzzer_pass_interchange_signedness_of_integer_operands.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/id_use_descriptor.h"
-#include "source/fuzz/transformation_record_synonymous_constants.h"
-#include "source/fuzz/transformation_replace_id_with_synonym.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassInterchangeSignednessOfIntegerOperands::
-    FuzzerPassInterchangeSignednessOfIntegerOperands(
-        opt::IRContext* ir_context,
-        TransformationContext* transformation_context,
-        FuzzerContext* fuzzer_context,
-        protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassInterchangeSignednessOfIntegerOperands::
-    ~FuzzerPassInterchangeSignednessOfIntegerOperands() = default;
-
-void FuzzerPassInterchangeSignednessOfIntegerOperands::Apply() {
-  // Make vector keeping track of all the uses we want to replace.
-  // This is a vector of pairs, where the first element is an id use descriptor
-  // identifying the use of a constant id and the second is the id that should
-  // be used to replace it.
-  std::vector<std::pair<protobufs::IdUseDescriptor, uint32_t>> uses_to_replace;
-
-  for (auto constant : GetIRContext()->GetConstants()) {
-    uint32_t constant_id = constant->result_id();
-
-    // We want to record the synonymity of an integer constant with another
-    // constant with opposite signedness, and this can only be done if they are
-    // not irrelevant.
-    if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
-            constant_id)) {
-      continue;
-    }
-
-    uint32_t toggled_id =
-        FindOrCreateToggledIntegerConstant(constant->result_id());
-    if (!toggled_id) {
-      // Not an integer constant
-      continue;
-    }
-
-    assert(!GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
-               toggled_id) &&
-           "FindOrCreateToggledConstant can't produce an irrelevant id");
-
-    // Record synonymous constants
-    ApplyTransformation(
-        TransformationRecordSynonymousConstants(constant_id, toggled_id));
-
-    // Find all the uses of the constant and, for each, probabilistically
-    // decide whether to replace it.
-    GetIRContext()->get_def_use_mgr()->ForEachUse(
-        constant_id,
-        [this, toggled_id, &uses_to_replace](opt::Instruction* use_inst,
-                                             uint32_t use_index) -> void {
-          if (GetFuzzerContext()->ChoosePercentage(
-                  GetFuzzerContext()
-                      ->GetChanceOfInterchangingSignednessOfIntegerOperands())) {
-            MaybeAddUseToReplace(use_inst, use_index, toggled_id,
-                                 &uses_to_replace);
-          }
-        });
-  }
-
-  // Replace the ids if it is allowed.
-  for (auto use_to_replace : uses_to_replace) {
-    MaybeApplyTransformation(TransformationReplaceIdWithSynonym(
-        use_to_replace.first, use_to_replace.second));
-  }
-}
-
-uint32_t FuzzerPassInterchangeSignednessOfIntegerOperands::
-    FindOrCreateToggledIntegerConstant(uint32_t id) {
-  // |id| must not be a specialization constant because we do not know the value
-  // of specialization constants.
-  if (opt::IsSpecConstantInst(
-          GetIRContext()->get_def_use_mgr()->GetDef(id)->opcode())) {
-    return 0;
-  }
-
-  auto constant = GetIRContext()->get_constant_mgr()->FindDeclaredConstant(id);
-
-  // This pass only toggles integer constants.
-  if (!constant->AsIntConstant() &&
-      (!constant->AsVectorConstant() ||
-       !constant->AsVectorConstant()->component_type()->AsInteger())) {
-    return 0;
-  }
-
-  if (auto integer = constant->AsIntConstant()) {
-    auto type = integer->type()->AsInteger();
-
-    // Find or create and return the toggled constant.
-    return FindOrCreateIntegerConstant(std::vector<uint32_t>(integer->words()),
-                                       type->width(), !type->IsSigned(), false);
-  }
-
-  // The constant is an integer vector.
-
-  // Find the component type.
-  auto component_type =
-      constant->AsVectorConstant()->component_type()->AsInteger();
-
-  // Find or create the toggled component type.
-  uint32_t toggled_component_type = FindOrCreateIntegerType(
-      component_type->width(), !component_type->IsSigned());
-
-  // Get the information about the toggled components. We need to extract this
-  // information now because the analyses might be invalidated, which would make
-  // the constant and component_type variables invalid.
-  std::vector<std::vector<uint32_t>> component_words;
-
-  for (auto component : constant->AsVectorConstant()->GetComponents()) {
-    component_words.push_back(component->AsIntConstant()->words());
-  }
-  uint32_t width = component_type->width();
-  bool is_signed = !component_type->IsSigned();
-
-  std::vector<uint32_t> toggled_components;
-
-  // Find or create the toggled components.
-  for (auto words : component_words) {
-    toggled_components.push_back(
-        FindOrCreateIntegerConstant(words, width, is_signed, false));
-  }
-
-  // Find or create the required toggled vector type.
-  uint32_t toggled_type = FindOrCreateVectorType(
-      toggled_component_type, (uint32_t)toggled_components.size());
-
-  // Find or create and return the toggled vector constant.
-  return FindOrCreateCompositeConstant(toggled_components, toggled_type, false);
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 51
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.h

@@ -1,51 +0,0 @@
-// 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_FUZZER_PASS_INTERCHANGE_SIGNEDNESS_OF_INTEGER_OPERANDS_
-#define SOURCE_FUZZ_FUZZER_PASS_INTERCHANGE_SIGNEDNESS_OF_INTEGER_OPERANDS_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A pass that:
-// - Finds all the integer constant (scalar and vector) definitions in the
-//   module and adds the definitions of the integer with the same data words but
-//   opposite signedness. If the synonym is already in the module, it does not
-//   add a new one.
-// - For each use of an integer constant where its signedness does not matter,
-// decides whether to change it to the id of the toggled constant.
-class FuzzerPassInterchangeSignednessOfIntegerOperands : public FuzzerPass {
- public:
-  FuzzerPassInterchangeSignednessOfIntegerOperands(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassInterchangeSignednessOfIntegerOperands() override;
-
-  void Apply() override;
-
- private:
-  // Given the id of an integer constant (scalar or vector), it finds or creates
-  // the corresponding toggled constant (the integer with the same data words
-  // but opposite signedness). Returns the id of the toggled instruction if the
-  // constant is an integer scalar or vector, 0 otherwise.
-  uint32_t FindOrCreateToggledIntegerConstant(uint32_t id);
-};
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_INTERCHANGE_SIGNEDNESS_OF_INTEGER_OPERANDS_

+ 0 - 116
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_interchange_zero_like_constants.cpp

@@ -1,116 +0,0 @@
-// Copyright (c) 2020 Stefano Milizia
-// 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/fuzzer_pass_interchange_zero_like_constants.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/id_use_descriptor.h"
-#include "source/fuzz/transformation_record_synonymous_constants.h"
-#include "source/fuzz/transformation_replace_id_with_synonym.h"
-
-namespace spvtools {
-namespace fuzz {
-FuzzerPassInterchangeZeroLikeConstants::FuzzerPassInterchangeZeroLikeConstants(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassInterchangeZeroLikeConstants::
-    ~FuzzerPassInterchangeZeroLikeConstants() = default;
-
-uint32_t FuzzerPassInterchangeZeroLikeConstants::FindOrCreateToggledConstant(
-    opt::Instruction* declaration) {
-  // |declaration| must not be a specialization constant because we do not know
-  // the value of specialization constants.
-  if (opt::IsSpecConstantInst(declaration->opcode())) {
-    return 0;
-  }
-
-  auto constant = GetIRContext()->get_constant_mgr()->FindDeclaredConstant(
-      declaration->result_id());
-
-  // This pass only toggles zero-like constants
-  if (!constant->IsZero()) {
-    return 0;
-  }
-
-  if (constant->AsScalarConstant()) {
-    return FindOrCreateNullConstant(declaration->type_id());
-  } else if (constant->AsNullConstant()) {
-    // Add declaration of equivalent scalar constant
-    auto kind = constant->type()->kind();
-    if (kind == opt::analysis::Type::kBool ||
-        kind == opt::analysis::Type::kInteger ||
-        kind == opt::analysis::Type::kFloat) {
-      return FindOrCreateZeroConstant(declaration->type_id(), false);
-    }
-  }
-
-  return 0;
-}
-
-void FuzzerPassInterchangeZeroLikeConstants::Apply() {
-  // Make vector keeping track of all the uses we want to replace.
-  // This is a vector of pairs, where the first element is an id use descriptor
-  // identifying the use of a constant id and the second is the id that should
-  // be used to replace it.
-  std::vector<std::pair<protobufs::IdUseDescriptor, uint32_t>> uses_to_replace;
-
-  for (auto constant : GetIRContext()->GetConstants()) {
-    uint32_t constant_id = constant->result_id();
-    if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
-            constant_id)) {
-      continue;
-    }
-
-    uint32_t toggled_id = FindOrCreateToggledConstant(constant);
-    if (!toggled_id) {
-      // Not a zero-like constant
-      continue;
-    }
-
-    assert(!GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
-               toggled_id) &&
-           "FindOrCreateToggledConstant can't produce an irrelevant id");
-
-    // Record synonymous constants
-    ApplyTransformation(
-        TransformationRecordSynonymousConstants(constant_id, toggled_id));
-
-    // Find all the uses of the constant and, for each, probabilistically
-    // decide whether to replace it.
-    GetIRContext()->get_def_use_mgr()->ForEachUse(
-        constant_id,
-        [this, toggled_id, &uses_to_replace](opt::Instruction* use_inst,
-                                             uint32_t use_index) -> void {
-          if (GetFuzzerContext()->ChoosePercentage(
-                  GetFuzzerContext()
-                      ->GetChanceOfInterchangingZeroLikeConstants())) {
-            MaybeAddUseToReplace(use_inst, use_index, toggled_id,
-                                 &uses_to_replace);
-          }
-        });
-  }
-
-  // Replace the ids if it is allowed.
-  for (auto use_to_replace : uses_to_replace) {
-    MaybeApplyTransformation(TransformationReplaceIdWithSynonym(
-        use_to_replace.first, use_to_replace.second));
-  }
-}
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 53
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_interchange_zero_like_constants.h

@@ -1,53 +0,0 @@
-// Copyright (c) 2020 Stefano Milizia
-// 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_FUZZER_PASS_INTERCHANGE_ZERO_LIKE_CONSTANTS_
-#define SOURCE_FUZZ_FUZZER_PASS_INTERCHANGE_ZERO_LIKE_CONSTANTS_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// A pass that:
-// - Finds all the zero-like constant definitions in the module and adds the
-//   definitions of the corresponding synonym, recording the fact that they
-//   are synonymous. If the synonym is already in the module, it does not
-//   add a new one.
-// - For each use of a zero-like constant, decides whether to change it to the
-//   id of the toggled constant.
-class FuzzerPassInterchangeZeroLikeConstants : public FuzzerPass {
- public:
-  FuzzerPassInterchangeZeroLikeConstants(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassInterchangeZeroLikeConstants() override;
-
-  void Apply() override;
-
- private:
-  // Given the declaration of a zero-like constant, it finds or creates the
-  // corresponding toggled constant (a scalar constant of value 0 becomes a
-  // null constant of the same type and vice versa).
-  // Returns the id of the toggled instruction if the constant is zero-like,
-  // 0 otherwise.
-  uint32_t FindOrCreateToggledConstant(opt::Instruction* declaration);
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-#endif  // SOURCE_FUZZ_FUZZER_PASS_INTERCHANGE_ZERO_LIKE_CONSTANTS_

+ 0 - 52
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_invert_comparison_operators.cpp

@@ -1,52 +0,0 @@
-// Copyright (c) 2020 Vasyl Teliman
-//
-// 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/fuzzer_pass_invert_comparison_operators.h"
-
-#include "source/fuzz/fuzzer_context.h"
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/transformation_invert_comparison_operator.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassInvertComparisonOperators::FuzzerPassInvertComparisonOperators(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassInvertComparisonOperators::~FuzzerPassInvertComparisonOperators() =
-    default;
-
-void FuzzerPassInvertComparisonOperators::Apply() {
-  GetIRContext()->module()->ForEachInst([this](const opt::Instruction* inst) {
-    if (!TransformationInvertComparisonOperator::IsInversionSupported(
-            inst->opcode())) {
-      return;
-    }
-
-    if (!GetFuzzerContext()->ChoosePercentage(
-            GetFuzzerContext()->GetChanceOfInvertingComparisonOperators())) {
-      return;
-    }
-
-    ApplyTransformation(TransformationInvertComparisonOperator(
-        inst->result_id(), GetFuzzerContext()->GetFreshId()));
-  });
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 40
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_invert_comparison_operators.h

@@ -1,40 +0,0 @@
-// Copyright (c) 2020 Vasyl Teliman
-//
-// 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_FUZZER_PASS_INVERT_COMPARISON_OPERATORS_H_
-#define SOURCE_FUZZ_FUZZER_PASS_INVERT_COMPARISON_OPERATORS_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Iterates over different comparison operators in the module (>=, <, > etc.)
-// and randomly decides whether to invert each one or not.
-class FuzzerPassInvertComparisonOperators : public FuzzerPass {
- public:
-  FuzzerPassInvertComparisonOperators(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassInvertComparisonOperators() override;
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_INVERT_COMPARISON_OPERATORS_H_

+ 0 - 71
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp

@@ -1,71 +0,0 @@
-// Copyright (c) 2020 André Perez Maselco
-//
-// 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/fuzzer_pass_make_vector_operations_dynamic.h"
-
-#include "source/fuzz/fuzzer_util.h"
-#include "source/fuzz/instruction_descriptor.h"
-#include "source/fuzz/transformation_make_vector_operation_dynamic.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassMakeVectorOperationsDynamic::FuzzerPassMakeVectorOperationsDynamic(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassMakeVectorOperationsDynamic::
-    ~FuzzerPassMakeVectorOperationsDynamic() = default;
-
-void FuzzerPassMakeVectorOperationsDynamic::Apply() {
-  for (auto& function : *GetIRContext()->module()) {
-    for (auto& block : function) {
-      for (auto& instruction : block) {
-        // Randomly decide whether to try applying the transformation.
-        if (!GetFuzzerContext()->ChoosePercentage(
-                GetFuzzerContext()
-                    ->GetChanceOfMakingVectorOperationDynamic())) {
-          continue;
-        }
-
-        // |instruction| must be a vector operation.
-        if (!TransformationMakeVectorOperationDynamic::IsVectorOperation(
-                GetIRContext(), &instruction)) {
-          continue;
-        }
-
-        // Make sure |instruction| has only one indexing operand.
-        assert(instruction.NumInOperands() ==
-                   (instruction.opcode() == SpvOpCompositeExtract ? 2 : 3) &&
-               "FuzzerPassMakeVectorOperationsDynamic: the composite "
-               "instruction must have "
-               "only one indexing operand.");
-
-        // Applies the make vector operation dynamic transformation.
-        ApplyTransformation(TransformationMakeVectorOperationDynamic(
-            instruction.result_id(),
-            FindOrCreateIntegerConstant(
-                {instruction.GetSingleWordInOperand(
-                    instruction.opcode() == SpvOpCompositeExtract ? 1 : 2)},
-                32, GetFuzzerContext()->ChooseEven(), false)));
-      }
-    }
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

+ 0 - 40
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.h

@@ -1,40 +0,0 @@
-// Copyright (c) 2020 André Perez Maselco
-//
-// 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_FUZZER_PASS_MAKE_VECTOR_OPERATIONS_DYNAMIC_H_
-#define SOURCE_FUZZ_FUZZER_PASS_MAKE_VECTOR_OPERATIONS_DYNAMIC_H_
-
-#include "source/fuzz/fuzzer_pass.h"
-
-namespace spvtools {
-namespace fuzz {
-
-// Looks for OpCompositeExtract/Insert instructions on vectors, and replaces
-// them with OpVectorExtract/InsertDynamic.
-class FuzzerPassMakeVectorOperationsDynamic : public FuzzerPass {
- public:
-  FuzzerPassMakeVectorOperationsDynamic(
-      opt::IRContext* ir_context, TransformationContext* transformation_context,
-      FuzzerContext* fuzzer_context,
-      protobufs::TransformationSequence* transformations);
-
-  ~FuzzerPassMakeVectorOperationsDynamic() override;
-
-  void Apply() override;
-};
-
-}  // namespace fuzz
-}  // namespace spvtools
-
-#endif  // SOURCE_FUZZ_FUZZER_PASS_MAKE_VECTOR_OPERATIONS_DYNAMIC_H_

+ 0 - 63
3rdparty/spirv-tools/source/fuzz/fuzzer_pass_merge_blocks.cpp

@@ -1,63 +0,0 @@
-// Copyright (c) 2019 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/fuzzer_pass_merge_blocks.h"
-
-#include <vector>
-
-#include "source/fuzz/transformation_merge_blocks.h"
-
-namespace spvtools {
-namespace fuzz {
-
-FuzzerPassMergeBlocks::FuzzerPassMergeBlocks(
-    opt::IRContext* ir_context, TransformationContext* transformation_context,
-    FuzzerContext* fuzzer_context,
-    protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
-                 transformations) {}
-
-FuzzerPassMergeBlocks::~FuzzerPassMergeBlocks() = default;
-
-void FuzzerPassMergeBlocks::Apply() {
-  // First we populate a sequence of transformations that we might consider
-  // applying.
-  std::vector<TransformationMergeBlocks> potential_transformations;
-  // We do this by considering every block of every function.
-  for (auto& function : *GetIRContext()->module()) {
-    for (auto& block : function) {
-      // We probabilistically decide to ignore some blocks.
-      if (!GetFuzzerContext()->ChoosePercentage(
-              GetFuzzerContext()->GetChanceOfMergingBlocks())) {
-        continue;
-      }
-      // 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(),
-                                      *GetTransformationContext())) {
-        potential_transformations.push_back(transformation);
-      }
-    }
-  }
-
-  while (!potential_transformations.empty()) {
-    auto transformation =
-        GetFuzzerContext()->RemoveAtRandomIndex(&potential_transformations);
-    MaybeApplyTransformation(transformation);
-  }
-}
-
-}  // namespace fuzz
-}  // namespace spvtools

Некоторые файлы не были показаны из-за большого количества измененных файлов