aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-06-23 22:15:32 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-06-23 22:15:32 +0000
commit7902a7c9c7bfc5d00c20a0d52b54736f884cb9c8 (patch)
tree4e2ee1f3ee49bafef164576a1b78df38574dece0
parent1bcda7cb130bacf2b1cbe37d2209bed84e5bf1a8 (diff)
parent47bf8579daa75447135e50c739df6b590368262b (diff)
downloadspirv-tools-ndk-release-r23.tar.gz
Snap for 7485283 from 47bf8579daa75447135e50c739df6b590368262b to ndk-release-r23ndk-r23cndk-r23bndk-r23ndk-release-r23
Change-Id: Ib854f82534ecb1c35e4abba8020f21971d2a95f7
-rw-r--r--Android.mk1
-rw-r--r--BUILD.gn174
-rw-r--r--CHANGES23
-rw-r--r--DEPS6
-rw-r--r--docs/spirv-fuzz.md2
-rw-r--r--include/spirv-tools/libspirv.h6
-rw-r--r--include/spirv-tools/libspirv.hpp2
-rw-r--r--include/spirv-tools/optimizer.hpp9
-rw-r--r--kokoro/check-format/build.sh3
-rw-r--r--source/CMakeLists.txt2
-rw-r--r--source/fuzz/CMakeLists.txt2
-rw-r--r--source/fuzz/available_instructions.cpp191
-rw-r--r--source/fuzz/available_instructions.h111
-rw-r--r--source/fuzz/force_render_red.cpp4
-rw-r--r--source/fuzz/force_render_red.h2
-rw-r--r--source/fuzz/fuzzer.cpp458
-rw-r--r--source/fuzz/fuzzer.h120
-rw-r--r--source/fuzz/fuzzer_context.cpp17
-rw-r--r--source/fuzz/fuzzer_context.h25
-rw-r--r--source/fuzz/fuzzer_pass_add_access_chains.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_access_chains.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_composite_extract.cpp46
-rw-r--r--source/fuzz/fuzzer_pass_add_composite_extract.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_composite_inserts.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_composite_inserts.h1
-rw-r--r--source/fuzz/fuzzer_pass_add_composite_types.cpp6
-rw-r--r--source/fuzz/fuzzer_pass_add_composite_types.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_copy_memory.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_copy_memory.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_dead_blocks.cpp25
-rw-r--r--source/fuzz/fuzzer_pass_add_dead_blocks.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_dead_breaks.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_dead_breaks.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_dead_continues.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_dead_continues.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_equation_instructions.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_add_equation_instructions.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_function_calls.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_function_calls.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_global_variables.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_global_variables.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_image_sample_unused_components.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_add_image_sample_unused_components.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_loads.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_loads.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_local_variables.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_local_variables.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_loop_preheaders.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_loop_preheaders.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_loops_to_create_int_constant_synonyms.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_add_loops_to_create_int_constant_synonyms.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_add_no_contraction_decorations.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_opphi_synonyms.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_parameters.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_parameters.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_relaxed_decorations.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_relaxed_decorations.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_stores.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_stores.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_synonyms.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_add_synonyms.h2
-rw-r--r--source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.h2
-rw-r--r--source/fuzz/fuzzer_pass_adjust_branch_weights.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_adjust_branch_weights.h2
-rw-r--r--source/fuzz/fuzzer_pass_adjust_function_controls.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_adjust_function_controls.h2
-rw-r--r--source/fuzz/fuzzer_pass_adjust_loop_controls.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_adjust_loop_controls.h2
-rw-r--r--source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h2
-rw-r--r--source/fuzz/fuzzer_pass_adjust_selection_controls.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_adjust_selection_controls.h2
-rw-r--r--source/fuzz/fuzzer_pass_apply_id_synonyms.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_apply_id_synonyms.h2
-rw-r--r--source/fuzz/fuzzer_pass_construct_composites.cpp264
-rw-r--r--source/fuzz/fuzzer_pass_construct_composites.h19
-rw-r--r--source/fuzz/fuzzer_pass_copy_objects.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_copy_objects.h2
-rw-r--r--source/fuzz/fuzzer_pass_donate_modules.cpp11
-rw-r--r--source/fuzz/fuzzer_pass_donate_modules.h2
-rw-r--r--source/fuzz/fuzzer_pass_duplicate_regions_with_selections.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_duplicate_regions_with_selections.h2
-rw-r--r--source/fuzz/fuzzer_pass_expand_vector_reductions.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_expand_vector_reductions.h2
-rw-r--r--source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_flatten_conditional_branches.h2
-rw-r--r--source/fuzz/fuzzer_pass_inline_functions.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_inline_functions.h2
-rw-r--r--source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.cpp6
-rw-r--r--source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.h2
-rw-r--r--source/fuzz/fuzzer_pass_interchange_zero_like_constants.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_interchange_zero_like_constants.h2
-rw-r--r--source/fuzz/fuzzer_pass_invert_comparison_operators.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_invert_comparison_operators.h2
-rw-r--r--source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_make_vector_operations_dynamic.h2
-rw-r--r--source/fuzz/fuzzer_pass_merge_blocks.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_merge_blocks.h2
-rw-r--r--source/fuzz/fuzzer_pass_merge_function_returns.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_merge_function_returns.h2
-rw-r--r--source/fuzz/fuzzer_pass_mutate_pointers.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_mutate_pointers.h2
-rw-r--r--source/fuzz/fuzzer_pass_obfuscate_constants.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_obfuscate_constants.h2
-rw-r--r--source/fuzz/fuzzer_pass_outline_functions.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_outline_functions.h2
-rw-r--r--source/fuzz/fuzzer_pass_permute_blocks.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_permute_blocks.h2
-rw-r--r--source/fuzz/fuzzer_pass_permute_function_parameters.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_permute_function_parameters.h2
-rw-r--r--source/fuzz/fuzzer_pass_permute_instructions.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_permute_instructions.h2
-rw-r--r--source/fuzz/fuzzer_pass_permute_phi_operands.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_permute_phi_operands.h2
-rw-r--r--source/fuzz/fuzzer_pass_propagate_instructions_down.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_propagate_instructions_down.h2
-rw-r--r--source/fuzz/fuzzer_pass_propagate_instructions_up.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_propagate_instructions_up.h2
-rw-r--r--source/fuzz/fuzzer_pass_push_ids_through_variables.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_push_ids_through_variables.h2
-rw-r--r--source/fuzz/fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.h2
-rw-r--r--source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.h2
-rw-r--r--source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.h2
-rw-r--r--source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.h2
-rw-r--r--source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_replace_irrelevant_ids.h2
-rw-r--r--source/fuzz/fuzzer_pass_replace_linear_algebra_instructions.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_replace_linear_algebra_instructions.h2
-rw-r--r--source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.h2
-rw-r--r--source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.h2
-rw-r--r--source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.h2
-rw-r--r--source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_replace_parameter_with_global.h2
-rw-r--r--source/fuzz/fuzzer_pass_replace_params_with_struct.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_replace_params_with_struct.h2
-rw-r--r--source/fuzz/fuzzer_pass_split_blocks.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_split_blocks.h2
-rw-r--r--source/fuzz/fuzzer_pass_swap_commutable_operands.cpp2
-rw-r--r--source/fuzz/fuzzer_pass_swap_commutable_operands.h2
-rw-r--r--source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_swap_conditional_branch_operands.h2
-rw-r--r--source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h2
-rw-r--r--source/fuzz/fuzzer_pass_wrap_regions_in_selections.cpp3
-rw-r--r--source/fuzz/fuzzer_pass_wrap_regions_in_selections.h2
-rw-r--r--source/fuzz/fuzzer_util.cpp290
-rw-r--r--source/fuzz/fuzzer_util.h68
-rw-r--r--source/fuzz/instruction_descriptor.cpp55
-rw-r--r--source/fuzz/pass_management/repeated_pass_manager.cpp24
-rw-r--r--source/fuzz/pass_management/repeated_pass_manager.h16
-rw-r--r--source/fuzz/transformation_access_chain.cpp44
-rw-r--r--source/fuzz/transformation_access_chain.h2
-rw-r--r--source/fuzz/transformation_add_bit_instruction_synonym.cpp5
-rw-r--r--source/fuzz/transformation_add_bit_instruction_synonym.h2
-rw-r--r--source/fuzz/transformation_add_constant_boolean.cpp22
-rw-r--r--source/fuzz/transformation_add_constant_boolean.h2
-rw-r--r--source/fuzz/transformation_add_constant_composite.cpp20
-rw-r--r--source/fuzz/transformation_add_constant_composite.h2
-rw-r--r--source/fuzz/transformation_add_constant_null.cpp24
-rw-r--r--source/fuzz/transformation_add_constant_null.h6
-rw-r--r--source/fuzz/transformation_add_constant_scalar.cpp18
-rw-r--r--source/fuzz/transformation_add_constant_scalar.h2
-rw-r--r--source/fuzz/transformation_add_copy_memory.cpp49
-rw-r--r--source/fuzz/transformation_add_copy_memory.h2
-rw-r--r--source/fuzz/transformation_add_dead_block.cpp4
-rw-r--r--source/fuzz/transformation_add_dead_block.h2
-rw-r--r--source/fuzz/transformation_add_dead_break.cpp48
-rw-r--r--source/fuzz/transformation_add_dead_break.h11
-rw-r--r--source/fuzz/transformation_add_dead_continue.cpp56
-rw-r--r--source/fuzz/transformation_add_dead_continue.h11
-rw-r--r--source/fuzz/transformation_add_early_terminator_wrapper.cpp5
-rw-r--r--source/fuzz/transformation_add_early_terminator_wrapper.h2
-rw-r--r--source/fuzz/transformation_add_function.cpp4
-rw-r--r--source/fuzz/transformation_add_function.h2
-rw-r--r--source/fuzz/transformation_add_global_undef.cpp16
-rw-r--r--source/fuzz/transformation_add_global_undef.h2
-rw-r--r--source/fuzz/transformation_add_global_variable.cpp12
-rw-r--r--source/fuzz/transformation_add_global_variable.h2
-rw-r--r--source/fuzz/transformation_add_image_sample_unused_components.cpp5
-rw-r--r--source/fuzz/transformation_add_image_sample_unused_components.h2
-rw-r--r--source/fuzz/transformation_add_local_variable.cpp18
-rw-r--r--source/fuzz/transformation_add_local_variable.h2
-rw-r--r--source/fuzz/transformation_add_loop_preheader.cpp4
-rw-r--r--source/fuzz/transformation_add_loop_preheader.h2
-rw-r--r--source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp5
-rw-r--r--source/fuzz/transformation_add_loop_to_create_int_constant_synonym.h3
-rw-r--r--source/fuzz/transformation_add_no_contraction_decoration.cpp5
-rw-r--r--source/fuzz/transformation_add_no_contraction_decoration.h2
-rw-r--r--source/fuzz/transformation_add_opphi_synonym.cpp4
-rw-r--r--source/fuzz/transformation_add_opphi_synonym.h2
-rw-r--r--source/fuzz/transformation_add_parameter.cpp4
-rw-r--r--source/fuzz/transformation_add_parameter.h2
-rw-r--r--source/fuzz/transformation_add_relaxed_decoration.cpp5
-rw-r--r--source/fuzz/transformation_add_relaxed_decoration.h2
-rw-r--r--source/fuzz/transformation_add_synonym.cpp15
-rw-r--r--source/fuzz/transformation_add_type_array.cpp28
-rw-r--r--source/fuzz/transformation_add_type_array.h6
-rw-r--r--source/fuzz/transformation_add_type_boolean.cpp20
-rw-r--r--source/fuzz/transformation_add_type_boolean.h2
-rw-r--r--source/fuzz/transformation_add_type_float.cpp21
-rw-r--r--source/fuzz/transformation_add_type_float.h2
-rw-r--r--source/fuzz/transformation_add_type_function.cpp4
-rw-r--r--source/fuzz/transformation_add_type_function.h2
-rw-r--r--source/fuzz/transformation_add_type_int.cpp25
-rw-r--r--source/fuzz/transformation_add_type_int.h2
-rw-r--r--source/fuzz/transformation_add_type_matrix.cpp20
-rw-r--r--source/fuzz/transformation_add_type_matrix.h2
-rw-r--r--source/fuzz/transformation_add_type_pointer.cpp20
-rw-r--r--source/fuzz/transformation_add_type_pointer.h2
-rw-r--r--source/fuzz/transformation_add_type_struct.cpp50
-rw-r--r--source/fuzz/transformation_add_type_struct.h6
-rw-r--r--source/fuzz/transformation_add_type_vector.cpp35
-rw-r--r--source/fuzz/transformation_add_type_vector.h2
-rw-r--r--source/fuzz/transformation_adjust_branch_weights.cpp4
-rw-r--r--source/fuzz/transformation_adjust_branch_weights.h2
-rw-r--r--source/fuzz/transformation_composite_construct.cpp16
-rw-r--r--source/fuzz/transformation_composite_construct.h2
-rw-r--r--source/fuzz/transformation_composite_extract.cpp17
-rw-r--r--source/fuzz/transformation_composite_extract.h2
-rw-r--r--source/fuzz/transformation_composite_insert.cpp22
-rw-r--r--source/fuzz/transformation_composite_insert.h2
-rw-r--r--source/fuzz/transformation_compute_data_synonym_fact_closure.cpp5
-rw-r--r--source/fuzz/transformation_compute_data_synonym_fact_closure.h2
-rw-r--r--source/fuzz/transformation_duplicate_region_with_selection.cpp5
-rw-r--r--source/fuzz/transformation_duplicate_region_with_selection.h2
-rw-r--r--source/fuzz/transformation_equation_instruction.cpp14
-rw-r--r--source/fuzz/transformation_equation_instruction.h2
-rw-r--r--source/fuzz/transformation_expand_vector_reduction.cpp5
-rw-r--r--source/fuzz/transformation_expand_vector_reduction.h2
-rw-r--r--source/fuzz/transformation_flatten_conditional_branch.cpp8
-rw-r--r--source/fuzz/transformation_flatten_conditional_branch.h2
-rw-r--r--source/fuzz/transformation_function_call.cpp4
-rw-r--r--source/fuzz/transformation_function_call.h2
-rw-r--r--source/fuzz/transformation_inline_function.cpp4
-rw-r--r--source/fuzz/transformation_inline_function.h2
-rw-r--r--source/fuzz/transformation_load.cpp24
-rw-r--r--source/fuzz/transformation_load.h2
-rw-r--r--source/fuzz/transformation_make_vector_operation_dynamic.cpp5
-rw-r--r--source/fuzz/transformation_make_vector_operation_dynamic.h2
-rw-r--r--source/fuzz/transformation_merge_blocks.cpp4
-rw-r--r--source/fuzz/transformation_merge_blocks.h2
-rw-r--r--source/fuzz/transformation_merge_function_returns.cpp4
-rw-r--r--source/fuzz/transformation_merge_function_returns.h2
-rw-r--r--source/fuzz/transformation_move_block_down.cpp4
-rw-r--r--source/fuzz/transformation_move_block_down.h2
-rw-r--r--source/fuzz/transformation_move_instruction_down.cpp4
-rw-r--r--source/fuzz/transformation_move_instruction_down.h2
-rw-r--r--source/fuzz/transformation_mutate_pointer.cpp33
-rw-r--r--source/fuzz/transformation_mutate_pointer.h2
-rw-r--r--source/fuzz/transformation_outline_function.cpp4
-rw-r--r--source/fuzz/transformation_outline_function.h2
-rw-r--r--source/fuzz/transformation_permute_function_parameters.cpp5
-rw-r--r--source/fuzz/transformation_permute_function_parameters.h2
-rw-r--r--source/fuzz/transformation_permute_phi_operands.cpp10
-rw-r--r--source/fuzz/transformation_permute_phi_operands.h2
-rw-r--r--source/fuzz/transformation_propagate_instruction_down.cpp4
-rw-r--r--source/fuzz/transformation_propagate_instruction_down.h2
-rw-r--r--source/fuzz/transformation_propagate_instruction_up.cpp4
-rw-r--r--source/fuzz/transformation_propagate_instruction_up.h2
-rw-r--r--source/fuzz/transformation_push_id_through_variable.cpp49
-rw-r--r--source/fuzz/transformation_push_id_through_variable.h2
-rw-r--r--source/fuzz/transformation_record_synonymous_constants.cpp4
-rw-r--r--source/fuzz/transformation_record_synonymous_constants.h2
-rw-r--r--source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp5
-rw-r--r--source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.h3
-rw-r--r--source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp6
-rw-r--r--source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h2
-rw-r--r--source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp10
-rw-r--r--source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h9
-rw-r--r--source/fuzz/transformation_replace_constant_with_uniform.cpp30
-rw-r--r--source/fuzz/transformation_replace_constant_with_uniform.h2
-rw-r--r--source/fuzz/transformation_replace_copy_memory_with_load_store.cpp5
-rw-r--r--source/fuzz/transformation_replace_copy_memory_with_load_store.h2
-rw-r--r--source/fuzz/transformation_replace_copy_object_with_store_load.cpp48
-rw-r--r--source/fuzz/transformation_replace_copy_object_with_store_load.h2
-rw-r--r--source/fuzz/transformation_replace_id_with_synonym.cpp13
-rw-r--r--source/fuzz/transformation_replace_id_with_synonym.h2
-rw-r--r--source/fuzz/transformation_replace_irrelevant_id.cpp13
-rw-r--r--source/fuzz/transformation_replace_irrelevant_id.h2
-rw-r--r--source/fuzz/transformation_replace_linear_algebra_instruction.cpp5
-rw-r--r--source/fuzz/transformation_replace_linear_algebra_instruction.h2
-rw-r--r--source/fuzz/transformation_replace_load_store_with_copy_memory.cpp5
-rw-r--r--source/fuzz/transformation_replace_load_store_with_copy_memory.h2
-rw-r--r--source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp5
-rw-r--r--source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.h3
-rw-r--r--source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp5
-rw-r--r--source/fuzz/transformation_replace_opselect_with_conditional_branch.h3
-rw-r--r--source/fuzz/transformation_replace_parameter_with_global.cpp4
-rw-r--r--source/fuzz/transformation_replace_parameter_with_global.h2
-rw-r--r--source/fuzz/transformation_replace_params_with_struct.cpp4
-rw-r--r--source/fuzz/transformation_replace_params_with_struct.h2
-rw-r--r--source/fuzz/transformation_set_function_control.cpp4
-rw-r--r--source/fuzz/transformation_set_function_control.h2
-rw-r--r--source/fuzz/transformation_set_loop_control.cpp34
-rw-r--r--source/fuzz/transformation_set_loop_control.h2
-rw-r--r--source/fuzz/transformation_set_memory_operands_mask.cpp17
-rw-r--r--source/fuzz/transformation_set_memory_operands_mask.h2
-rw-r--r--source/fuzz/transformation_set_selection_control.cpp4
-rw-r--r--source/fuzz/transformation_set_selection_control.h2
-rw-r--r--source/fuzz/transformation_split_block.cpp27
-rw-r--r--source/fuzz/transformation_split_block.h2
-rw-r--r--source/fuzz/transformation_store.cpp26
-rw-r--r--source/fuzz/transformation_store.h2
-rw-r--r--source/fuzz/transformation_swap_commutable_operands.cpp5
-rw-r--r--source/fuzz/transformation_swap_commutable_operands.h2
-rw-r--r--source/fuzz/transformation_swap_conditional_branch_operands.cpp21
-rw-r--r--source/fuzz/transformation_swap_conditional_branch_operands.h2
-rw-r--r--source/fuzz/transformation_toggle_access_chain_instruction.cpp5
-rw-r--r--source/fuzz/transformation_toggle_access_chain_instruction.h2
-rw-r--r--source/fuzz/transformation_vector_shuffle.cpp17
-rw-r--r--source/fuzz/transformation_vector_shuffle.h2
-rw-r--r--source/fuzz/transformation_wrap_early_terminator_in_function.cpp5
-rw-r--r--source/fuzz/transformation_wrap_early_terminator_in_function.h2
-rw-r--r--source/fuzz/transformation_wrap_region_in_selection.cpp4
-rw-r--r--source/fuzz/transformation_wrap_region_in_selection.h2
-rw-r--r--source/opcode.cpp2
-rw-r--r--source/opt/CMakeLists.txt2
-rw-r--r--source/opt/code_sink.cpp2
-rw-r--r--source/opt/constants.h2
-rw-r--r--source/opt/folding_rules.cpp4
-rw-r--r--source/opt/inline_pass.h2
-rw-r--r--source/opt/interp_fixup_pass.cpp131
-rw-r--r--source/opt/interp_fixup_pass.h54
-rw-r--r--source/opt/iterator.h22
-rw-r--r--source/opt/mem_pass.h2
-rw-r--r--source/opt/optimizer.cpp10
-rw-r--r--source/opt/passes.h1
-rw-r--r--source/opt/scalar_replacement_pass.cpp7
-rw-r--r--source/opt/scalar_replacement_pass.h4
-rw-r--r--source/opt/type_manager.cpp4
-rw-r--r--source/opt/types.h2
-rw-r--r--source/reduce/reducer.cpp10
-rw-r--r--source/reduce/reducer.h6
-rw-r--r--source/val/basic_block.h9
-rw-r--r--source/val/validate.cpp1
-rw-r--r--source/val/validate_atomics.cpp276
-rw-r--r--source/val/validate_barriers.cpp6
-rw-r--r--source/val/validate_cfg.cpp17
-rw-r--r--source/val/validate_decorations.cpp2
-rw-r--r--source/val/validate_extensions.cpp15
-rw-r--r--source/val/validate_logicals.cpp2
-rw-r--r--source/val/validate_memory.cpp1
-rw-r--r--source/val/validate_memory_semantics.cpp15
-rw-r--r--source/val/validate_memory_semantics.h3
-rw-r--r--source/val/validate_misc.cpp41
-rw-r--r--source/val/validate_scopes.cpp50
-rw-r--r--source/val/validate_type.cpp4
-rw-r--r--source/val/validation_state.cpp28
-rw-r--r--test/binary_parse_test.cpp2
-rw-r--r--test/binary_to_text_test.cpp6
-rw-r--r--test/enum_string_mapping_test.cpp2
-rw-r--r--test/fuzz/CMakeLists.txt1
-rw-r--r--test/fuzz/available_instructions_test.cpp328
-rw-r--r--test/fuzz/fuzzer_pass_add_opphi_synonyms_test.cpp4
-rw-r--r--test/fuzz/fuzzer_pass_construct_composites_test.cpp8
-rw-r--r--test/fuzz/fuzzer_pass_donate_modules_test.cpp76
-rw-r--r--test/fuzz/fuzzer_pass_outline_functions_test.cpp16
-rw-r--r--test/fuzz/fuzzer_pass_test.cpp4
-rw-r--r--test/fuzz/fuzzer_replayer_test.cpp61
-rw-r--r--test/fuzz/fuzzer_shrinker_test.cpp57
-rw-r--r--test/fuzz/shrinker_test.cpp9
-rw-r--r--test/fuzz/transformation_add_bit_instruction_synonym_test.cpp82
-rw-r--r--test/fuzz/transformation_add_constant_boolean_test.cpp8
-rw-r--r--test/fuzz/transformation_add_constant_composite_test.cpp26
-rw-r--r--test/fuzz/transformation_add_constant_null_test.cpp18
-rw-r--r--test/fuzz/transformation_add_constant_scalar_test.cpp4
-rw-r--r--test/fuzz/transformation_add_global_undef_test.cpp13
-rw-r--r--test/fuzz/transformation_add_global_variable_test.cpp227
-rw-r--r--test/fuzz/transformation_add_local_variable_test.cpp4
-rw-r--r--test/fuzz/transformation_add_type_array_test.cpp29
-rw-r--r--test/fuzz/transformation_add_type_boolean_test.cpp4
-rw-r--r--test/fuzz/transformation_add_type_float_test.cpp12
-rw-r--r--test/fuzz/transformation_add_type_int_test.cpp6
-rw-r--r--test/fuzz/transformation_add_type_matrix_test.cpp17
-rw-r--r--test/fuzz/transformation_add_type_pointer_test.cpp20
-rw-r--r--test/fuzz/transformation_add_type_struct_test.cpp17
-rw-r--r--test/fuzz/transformation_add_type_vector_test.cpp17
-rw-r--r--test/fuzz/transformation_composite_construct_test.cpp11
-rw-r--r--test/fuzz/transformation_composite_extract_test.cpp8
-rw-r--r--test/fuzz/transformation_equation_instruction_test.cpp4
-rw-r--r--test/fuzz/transformation_flatten_conditional_branch_test.cpp32
-rw-r--r--test/fuzz/transformation_permute_phi_operands_test.cpp17
-rw-r--r--test/fuzz/transformation_push_id_through_variable_test.cpp19
-rw-r--r--test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp296
-rw-r--r--test/fuzz/transformation_replace_id_with_synonym_test.cpp8
-rw-r--r--test/fuzz/transformation_set_loop_control_test.cpp22
-rw-r--r--test/fuzz/transformation_set_memory_operands_mask_test.cpp687
-rw-r--r--test/fuzz/transformation_swap_conditional_branch_operands_test.cpp22
-rw-r--r--test/opt/CMakeLists.txt1
-rw-r--r--test/opt/aggressive_dead_code_elim_test.cpp5
-rw-r--r--test/opt/block_merge_test.cpp2
-rw-r--r--test/opt/dead_branch_elim_test.cpp4
-rw-r--r--test/opt/instruction_list_test.cpp2
-rw-r--r--test/opt/interp_fixup_test.cpp172
-rw-r--r--test/opt/scalar_replacement_test.cpp40
-rw-r--r--test/test_fixture.h2
-rw-r--r--test/text_to_binary.extension_test.cpp31
-rw-r--r--test/val/CMakeLists.txt2
-rw-r--r--test/val/val_atomics_test.cpp557
-rw-r--r--test/val/val_barriers_test.cpp100
-rw-r--r--test/val/val_builtins_test.cpp30
-rw-r--r--test/val/val_cfg_test.cpp26
-rw-r--r--test/val/val_decoration_test.cpp2
-rw-r--r--test/val/val_ext_inst_test.cpp128
-rw-r--r--test/val/val_extension_spv_khr_expect_assume.cpp310
-rw-r--r--test/val/val_extension_spv_khr_linkonce_odr.cpp100
-rw-r--r--test/val/val_id_test.cpp4
-rw-r--r--test/val/val_image_test.cpp45
-rw-r--r--test/val/val_limits_test.cpp4
-rw-r--r--test/val/val_misc_test.cpp24
-rw-r--r--test/val/val_state_test.cpp2
-rw-r--r--test/val/val_validation_state_test.cpp4
-rw-r--r--tools/as/as.cpp2
-rw-r--r--tools/cfg/cfg.cpp2
-rw-r--r--tools/dis/dis.cpp2
-rw-r--r--tools/fuzz/fuzz.cpp116
-rw-r--r--tools/io.h118
-rw-r--r--tools/link/linker.cpp2
-rw-r--r--tools/opt/opt.cpp2
-rw-r--r--tools/reduce/reduce.cpp2
-rw-r--r--tools/val/val.cpp2
-rwxr-xr-xutils/check_copyright.py3
-rwxr-xr-xutils/generate_grammar_tables.py4
-rw-r--r--utils/vscode/README.md12
-rw-r--r--utils/vscode/go.mod8
-rw-r--r--utils/vscode/go.sum4
-rw-r--r--utils/vscode/install.bat2
-rw-r--r--utils/vscode/spirv.json57
-rw-r--r--utils/vscode/src/langsvr.go25
-rw-r--r--utils/vscode/src/lsp/protocol/log.go2
-rw-r--r--utils/vscode/src/lsp/protocol/protocol.go2
-rw-r--r--utils/vscode/src/lsp/protocol/span.go3
-rw-r--r--utils/vscode/src/lsp/protocol/tsclient.go2
-rw-r--r--utils/vscode/src/lsp/protocol/tsserver.go2
-rw-r--r--utils/vscode/src/parser/parser.go2
-rwxr-xr-xutils/vscode/src/schema/schema.go2796
-rw-r--r--utils/vscode/src/tools/gen-grammar.go6
449 files changed, 8009 insertions, 3395 deletions
diff --git a/Android.mk b/Android.mk
index 1000f422..ef1cdff1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -122,6 +122,7 @@ SPVTOOLS_OPT_SRC_FILES := \
source/opt/instruction.cpp \
source/opt/instruction_list.cpp \
source/opt/instrument_pass.cpp \
+ source/opt/interp_fixup_pass.cpp \
source/opt/ir_context.cpp \
source/opt/ir_loader.cpp \
source/opt/licm_pass.cpp \
diff --git a/BUILD.gn b/BUILD.gn
index 845eb29e..19ee77ac 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -19,6 +19,7 @@ if (build_with_chromium) {
}
spirv_headers = spirv_tools_spirv_headers_dir
+spirv_is_winuwp = is_win && target_os == "winuwp"
template("spvtools_core_tables") {
assert(defined(invoker.version), "Need version in $target_name generation.")
@@ -32,13 +33,14 @@ template("spvtools_core_tables") {
"${spirv_headers}/include/spirv/$version/spirv.core.grammar.json"
core_insts_file = "${target_gen_dir}/core.insts-$version.inc"
operand_kinds_file = "${target_gen_dir}/operand.kinds-$version.inc"
- debuginfo_insts_file = "${spirv_headers}/include/spirv/unified1/extinst.debuginfo.grammar.json"
+ debuginfo_insts_file =
+ "${spirv_headers}/include/spirv/unified1/extinst.debuginfo.grammar.json"
cldebuginfo100_insts_file = "${spirv_headers}/include/spirv/unified1/extinst.opencl.debuginfo.100.grammar.json"
sources = [
+ cldebuginfo100_insts_file,
core_json_file,
debuginfo_insts_file,
- cldebuginfo100_insts_file,
]
outputs = [
core_insts_file,
@@ -69,7 +71,8 @@ template("spvtools_core_enums") {
core_json_file =
"${spirv_headers}/include/spirv/$version/spirv.core.grammar.json"
- debuginfo_insts_file = "${spirv_headers}/include/spirv/unified1/extinst.debuginfo.grammar.json"
+ debuginfo_insts_file =
+ "${spirv_headers}/include/spirv/unified1/extinst.debuginfo.grammar.json"
cldebuginfo100_insts_file = "${spirv_headers}/include/spirv/unified1/extinst.opencl.debuginfo.100.grammar.json"
extension_enum_file = "${target_gen_dir}/extension_enum.inc"
@@ -110,7 +113,8 @@ template("spvtools_glsl_tables") {
core_json_file =
"${spirv_headers}/include/spirv/$version/spirv.core.grammar.json"
glsl_json_file = "${spirv_headers}/include/spirv/${version}/extinst.glsl.std.450.grammar.json"
- debuginfo_insts_file = "${spirv_headers}/include/spirv/unified1/extinst.debuginfo.grammar.json"
+ debuginfo_insts_file =
+ "${spirv_headers}/include/spirv/unified1/extinst.debuginfo.grammar.json"
cldebuginfo100_insts_file = "${spirv_headers}/include/spirv/unified1/extinst.opencl.debuginfo.100.grammar.json"
glsl_insts_file = "${target_gen_dir}/glsl.std.450.insts.inc"
@@ -133,9 +137,7 @@ template("spvtools_glsl_tables") {
debuginfo_insts_file,
cldebuginfo100_insts_file,
]
- outputs = [
- glsl_insts_file,
- ]
+ outputs = [ glsl_insts_file ]
}
}
@@ -150,7 +152,8 @@ template("spvtools_opencl_tables") {
core_json_file =
"${spirv_headers}/include/spirv/$version/spirv.core.grammar.json"
opencl_json_file = "${spirv_headers}/include/spirv/${version}/extinst.opencl.std.100.grammar.json"
- debuginfo_insts_file = "${spirv_headers}/include/spirv/unified1/extinst.debuginfo.grammar.json"
+ debuginfo_insts_file =
+ "${spirv_headers}/include/spirv/unified1/extinst.debuginfo.grammar.json"
cldebuginfo100_insts_file = "${spirv_headers}/include/spirv/unified1/extinst.opencl.debuginfo.100.grammar.json"
opencl_insts_file = "${target_gen_dir}/opencl.std.insts.inc"
@@ -173,9 +176,7 @@ template("spvtools_opencl_tables") {
debuginfo_insts_file,
cldebuginfo100_insts_file,
]
- outputs = [
- opencl_insts_file,
- ]
+ outputs = [ opencl_insts_file ]
}
}
@@ -194,12 +195,8 @@ template("spvtools_language_header") {
"--extinst-output-path",
rebase_path(extinst_output_path, root_build_dir),
]
- inputs = [
- invoker.grammar_file,
- ]
- outputs = [
- "${extinst_output_path}",
- ]
+ inputs = [ invoker.grammar_file ]
+ outputs = [ "${extinst_output_path}" ]
}
}
@@ -210,7 +207,8 @@ template("spvtools_vendor_table") {
script = "utils/generate_grammar_tables.py"
name = invoker.name
- extinst_vendor_grammar = "${spirv_headers}/include/spirv/unified1/extinst.${name}.grammar.json"
+ extinst_vendor_grammar =
+ "${spirv_headers}/include/spirv/unified1/extinst.${name}.grammar.json"
extinst_file = "${target_gen_dir}/${name}.insts.inc"
args = [
@@ -219,14 +217,10 @@ template("spvtools_vendor_table") {
"--vendor-insts-output",
rebase_path(extinst_file, root_build_dir),
"--vendor-operand-kind-prefix",
- invoker.operand_kind_prefix
- ]
- inputs = [
- extinst_vendor_grammar,
- ]
- outputs = [
- extinst_file,
+ invoker.operand_kind_prefix,
]
+ inputs = [ extinst_vendor_grammar ]
+ outputs = [ extinst_file ]
}
}
@@ -237,12 +231,8 @@ action("spvtools_generators_inc") {
xml_file = "${spirv_headers}/include/spirv/spir-v.xml"
inc_file = "${target_gen_dir}/generators.inc"
- sources = [
- xml_file,
- ]
- outputs = [
- inc_file,
- ]
+ sources = [ xml_file ]
+ outputs = [ inc_file ]
args = [
"--xml",
rebase_path(xml_file, root_build_dir),
@@ -257,9 +247,7 @@ action("spvtools_build_version") {
src_dir = "."
inc_file = "${target_gen_dir}/build-version.inc"
- outputs = [
- inc_file,
- ]
+ outputs = [ inc_file ]
args = [
rebase_path(src_dir, root_build_dir),
rebase_path(inc_file, root_build_dir),
@@ -280,7 +268,8 @@ spvtools_opencl_tables("opencl1-0") {
}
spvtools_language_header("debuginfo") {
name = "DebugInfo"
- grammar_file = "${spirv_headers}/include/spirv/unified1/extinst.debuginfo.grammar.json"
+ grammar_file =
+ "${spirv_headers}/include/spirv/unified1/extinst.debuginfo.grammar.json"
}
spvtools_language_header("cldebuginfo100") {
name = "OpenCLDebugInfo100"
@@ -288,13 +277,34 @@ spvtools_language_header("cldebuginfo100") {
}
spvtools_vendor_tables = [
- ["spv-amd-shader-explicit-vertex-parameter", "...nil..."],
- ["spv-amd-shader-trinary-minmax", "...nil..."],
- ["spv-amd-gcn-shader", "...nil..."],
- ["spv-amd-shader-ballot", "...nil..."],
- ["debuginfo", "...nil..."],
- ["opencl.debuginfo.100", "CLDEBUG100_"],
- ["nonsemantic.clspvreflection", "...nil..."],
+ [
+ "spv-amd-shader-explicit-vertex-parameter",
+ "...nil...",
+ ],
+ [
+ "spv-amd-shader-trinary-minmax",
+ "...nil...",
+ ],
+ [
+ "spv-amd-gcn-shader",
+ "...nil...",
+ ],
+ [
+ "spv-amd-shader-ballot",
+ "...nil...",
+ ],
+ [
+ "debuginfo",
+ "...nil...",
+ ],
+ [
+ "opencl.debuginfo.100",
+ "CLDEBUG100_",
+ ],
+ [
+ "nonsemantic.clspvreflection",
+ "...nil...",
+ ],
]
foreach(table_def, spvtools_vendor_tables) {
@@ -317,11 +327,15 @@ config("spvtools_internal_config") {
configs = [ ":spvtools_public_config" ]
+ cflags = []
if (is_clang) {
- cflags = [
+ cflags += [
"-Wno-implicit-fallthrough",
"-Wno-newline-eof",
]
+ } else if (!is_win) {
+ # Work around a false-positive on a Skia GCC 10 builder.
+ cflags += [ "-Wno-format-truncation" ]
}
}
@@ -342,8 +356,8 @@ static_library("spvtools") {
":spvtools_core_tables_unified1",
":spvtools_generators_inc",
":spvtools_glsl_tables_glsl1-0",
- ":spvtools_language_header_debuginfo",
":spvtools_language_header_cldebuginfo100",
+ ":spvtools_language_header_debuginfo",
":spvtools_opencl_tables_opencl1-0",
]
foreach(table_def, spvtools_vendor_tables) {
@@ -486,9 +500,7 @@ static_library("spvtools_val") {
":spvtools_language_header_cldebuginfo100",
":spvtools_language_header_debuginfo",
]
- public_deps = [
- ":spvtools_headers",
- ]
+ public_deps = [ ":spvtools_headers" ]
if (build_with_chromium) {
configs -= [ "//build/config/compiler:chromium_code" ]
@@ -539,10 +551,10 @@ static_library("spvtools_opt") {
"source/opt/dead_insert_elim_pass.h",
"source/opt/dead_variable_elimination.cpp",
"source/opt/dead_variable_elimination.h",
- "source/opt/decoration_manager.cpp",
- "source/opt/decoration_manager.h",
"source/opt/debug_info_manager.cpp",
"source/opt/debug_info_manager.h",
+ "source/opt/decoration_manager.cpp",
+ "source/opt/decoration_manager.h",
"source/opt/def_use_manager.cpp",
"source/opt/def_use_manager.h",
"source/opt/desc_sroa.cpp",
@@ -598,6 +610,8 @@ static_library("spvtools_opt") {
"source/opt/instruction_list.h",
"source/opt/instrument_pass.cpp",
"source/opt/instrument_pass.h",
+ "source/opt/interp_fixup_pass.cpp",
+ "source/opt/interp_fixup_pass.h",
"source/opt/ir_builder.h",
"source/opt/ir_context.cpp",
"source/opt/ir_context.h",
@@ -709,9 +723,7 @@ static_library("spvtools_opt") {
":spvtools_language_header_debuginfo",
":spvtools_vendor_tables_spv-amd-shader-ballot",
]
- public_deps = [
- ":spvtools_headers",
- ]
+ public_deps = [ ":spvtools_headers" ]
if (build_with_chromium) {
configs -= [ "//build/config/compiler:chromium_code" ]
@@ -721,17 +733,13 @@ static_library("spvtools_opt") {
}
static_library("spvtools_link") {
- sources = [
- "source/link/linker.cpp",
- ]
+ sources = [ "source/link/linker.cpp" ]
deps = [
":spvtools",
":spvtools_opt",
":spvtools_val",
]
- public_deps = [
- ":spvtools_headers",
- ]
+ public_deps = [ ":spvtools_headers" ]
if (build_with_chromium) {
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
@@ -804,9 +812,7 @@ static_library("spvtools_reduce") {
":spvtools",
":spvtools_opt",
]
- public_deps = [
- ":spvtools_headers",
- ]
+ public_deps = [ ":spvtools_headers" ]
if (build_with_chromium) {
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
@@ -841,10 +847,10 @@ if (build_with_chromium) {
"test/comment_test.cpp",
"test/enum_set_test.cpp",
"test/enum_string_mapping_test.cpp",
+ "test/ext_inst.cldebug100_test.cpp",
"test/ext_inst.debuginfo_test.cpp",
"test/ext_inst.glsl_test.cpp",
"test/ext_inst.opencl_test.cpp",
- "test/ext_inst.cldebug100_test.cpp",
"test/fix_word_test.cpp",
"test/generator_magic_number_test.cpp",
"test/hex_float_test.cpp",
@@ -891,8 +897,8 @@ if (build_with_chromium) {
deps = [
":spvtools",
- ":spvtools_language_header_debuginfo",
":spvtools_language_header_cldebuginfo100",
+ ":spvtools_language_header_debuginfo",
":spvtools_val",
"//testing/gmock",
"//testing/gtest",
@@ -912,9 +918,7 @@ if (build_with_chromium) {
if (spirv_tools_standalone) {
group("fuzzers") {
testonly = true
- deps = [
- "test/fuzzers",
- ]
+ deps = [ "test/fuzzers" ]
}
}
@@ -923,16 +927,12 @@ source_set("spvtools_util_cli_consumer") {
"tools/util/cli_consumer.cpp",
"tools/util/cli_consumer.h",
]
- deps = [
- ":spvtools_headers",
- ]
+ deps = [ ":spvtools_headers" ]
configs += [ ":spvtools_internal_config" ]
}
source_set("spvtools_software_version") {
- sources = [
- "source/software_version.cpp",
- ]
+ sources = [ "source/software_version.cpp" ]
deps = [
":spvtools_build_version",
":spvtools_headers",
@@ -941,9 +941,7 @@ source_set("spvtools_software_version") {
}
executable("spirv-as") {
- sources = [
- "tools/as/as.cpp",
- ]
+ sources = [ "tools/as/as.cpp" ]
deps = [
":spvtools",
":spvtools_software_version",
@@ -952,9 +950,7 @@ executable("spirv-as") {
}
executable("spirv-dis") {
- sources = [
- "tools/dis/dis.cpp",
- ]
+ sources = [ "tools/dis/dis.cpp" ]
deps = [
":spvtools",
":spvtools_software_version",
@@ -963,9 +959,7 @@ executable("spirv-dis") {
}
executable("spirv-val") {
- sources = [
- "tools/val/val.cpp",
- ]
+ sources = [ "tools/val/val.cpp" ]
deps = [
":spvtools",
":spvtools_software_version",
@@ -989,9 +983,7 @@ executable("spirv-cfg") {
}
executable("spirv-opt") {
- sources = [
- "tools/opt/opt.cpp",
- ]
+ sources = [ "tools/opt/opt.cpp" ]
deps = [
":spvtools",
":spvtools_opt",
@@ -1003,9 +995,7 @@ executable("spirv-opt") {
}
executable("spirv-link") {
- sources = [
- "tools/link/linker.cpp",
- ]
+ sources = [ "tools/link/linker.cpp" ]
deps = [
":spvtools",
":spvtools_link",
@@ -1016,12 +1006,10 @@ executable("spirv-link") {
configs += [ ":spvtools_internal_config" ]
}
-if (!is_ios) {
- # iOS does not allow std::system calls which spirv-reduce requires
+if (!is_ios && !spirv_is_winuwp) {
+ # iOS and UWP do not allow std::system calls which spirv-reduce requires
executable("spirv-reduce") {
- sources = [
- "tools/reduce/reduce.cpp",
- ]
+ sources = [ "tools/reduce/reduce.cpp" ]
deps = [
":spvtools",
":spvtools_opt",
@@ -1043,7 +1031,7 @@ group("all_spirv_tools") {
":spirv-opt",
":spirv-val",
]
- if (!is_ios) {
+ if (!is_ios && !spirv_is_winuwp) {
deps += [ ":spirv-reduce" ]
}
}
diff --git a/CHANGES b/CHANGES
index 19eb18c4..2b2da982 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,7 +1,24 @@
Revision history for SPIRV-Tools
-v2021.0-dev 2021-02-16
- - Start SPIRV-Tools v2021.0-dev
+v2021.1 2021-04-19
+ - General
+ - Support SPV_KHR_linkonce_odr, SPV_KHR_expect_assume (#4161)
+ - Fixes for the vscode language server extension (#4150)
+ - Validator
+ - Add validation for SPV_EXT_shader_atomic_float_min_max (#4105)
+ - Add Vulkan Execution Scope checks (#4183)
+ - Vulkan 64-bit OpAtomicStore check (#4163)
+ - Optimizer
+ - Add interpolate legalization pass (#4220)
+ - Fuzz
+ - Various performance optimizations
+ - Do not add too many dead blocks (#4217)
+ - Add WGSL compatibility flag to context (#4193)
+ - Add persistent state to the fuzzer (#4137)
+ - Debug Info
+ - Instrumentation
+ - Linker
+ - Reduce
v2020.7 2021-02-16
- General
@@ -40,7 +57,7 @@ v2020.7 2021-02-16
- Add last Position VUID (#4052)
- Allow forward pointer to be used in types generally (#4044)
- Optimizer
- - Mark module as modified if convert-to-half removes decorations. (#4127)
+ - Mark module as modified if convert-to-half removes decorations (#4127)
- Fix binding number calculation in desc sroa (#4095)
- Run DCE when SPV_KHR_shader_clock is used (#4049)
- Debug Info
diff --git a/DEPS b/DEPS
index 75581c5a..65aebf5a 100644
--- a/DEPS
+++ b/DEPS
@@ -4,9 +4,9 @@ vars = {
'github': 'https://github.com',
'effcee_revision': '2ec8f8738118cc483b67c04a759fee53496c5659',
- 'googletest_revision': '3af06fe1664d30f98de1e78c53a7087e842a2547',
- 're2_revision': 'ca11026a032ce2a3de4b3c389ee53d2bdc8794d6',
- 'spirv_headers_revision': 'faa570afbc91ac73d594d787486bcf8f2df1ace0',
+ 'googletest_revision': 'b7d472f1225c5a64943821d8483fecb469d3f382',
+ 're2_revision': 'f8e389f3acdc2517562924239e2a188037393683',
+ 'spirv_headers_revision': 'bcf55210f13a4fa3c3d0963b509ff1070e434c79',
}
deps = {
diff --git a/docs/spirv-fuzz.md b/docs/spirv-fuzz.md
index e5439e3c..5716b35e 100644
--- a/docs/spirv-fuzz.md
+++ b/docs/spirv-fuzz.md
@@ -53,7 +53,7 @@ See `transformation_set_selection_control.h` for an example.
The `IsApplicable` method should have a comment in the header file describing the conditions for applicability in simple terms. These conditions should be implemented in the body of this method in the `.cpp` file.
-In the case of `TransformationSetSelectionControl`, `IsApplicable` involves checking that `block_id` is indeed the id of a block that has an `OpSelectoinMerge` instruction, and that `selection_control` is a valid selection mask.
+In the case of `TransformationSetSelectionControl`, `IsApplicable` involves checking that `block_id` is indeed the id of a block that has an `OpSelectionMerge` instruction, and that `selection_control` is a valid selection mask.
The `Apply` method should have a comment in the header file summarising the result of applying the transformation. It should be implemented in the `.cpp` file, and you should assume that `IsApplicable` holds whenever `Apply` is invoked.
diff --git a/include/spirv-tools/libspirv.h b/include/spirv-tools/libspirv.h
index 658c4dd5..8b30dcba 100644
--- a/include/spirv-tools/libspirv.h
+++ b/include/spirv-tools/libspirv.h
@@ -588,6 +588,8 @@ SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetRelaxLogicalPointer(
// 3) Pointers that are actaul parameters on function calls do not have to point
// to the same type pointed as the formal parameter. The types just need to
// logically match.
+// 4) GLSLstd450 Interpolate* instructions can have a load of an interpolant
+// for a first argument.
SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetBeforeHlslLegalization(
spv_validator_options options, bool val);
@@ -671,7 +673,7 @@ SPIRV_TOOLS_EXPORT void spvOptimizerOptionsSetPreserveSpecConstants(
// Creates a reducer options object with default options. Returns a valid
// options object. The object remains valid until it is passed into
// |spvReducerOptionsDestroy|.
-SPIRV_TOOLS_EXPORT spv_reducer_options spvReducerOptionsCreate();
+SPIRV_TOOLS_EXPORT spv_reducer_options spvReducerOptionsCreate(void);
// Destroys the given reducer options object.
SPIRV_TOOLS_EXPORT void spvReducerOptionsDestroy(spv_reducer_options options);
@@ -698,7 +700,7 @@ SPIRV_TOOLS_EXPORT void spvReducerOptionsSetTargetFunction(
// Creates a fuzzer options object with default options. Returns a valid
// options object. The object remains valid until it is passed into
// |spvFuzzerOptionsDestroy|.
-SPIRV_TOOLS_EXPORT spv_fuzzer_options spvFuzzerOptionsCreate();
+SPIRV_TOOLS_EXPORT spv_fuzzer_options spvFuzzerOptionsCreate(void);
// Destroys the given fuzzer options object.
SPIRV_TOOLS_EXPORT void spvFuzzerOptionsDestroy(spv_fuzzer_options options);
diff --git a/include/spirv-tools/libspirv.hpp b/include/spirv-tools/libspirv.hpp
index e7e7fc7a..0c31a182 100644
--- a/include/spirv-tools/libspirv.hpp
+++ b/include/spirv-tools/libspirv.hpp
@@ -136,6 +136,8 @@ class ValidatorOptions {
// 3) Pointers that are actaul parameters on function calls do not have to
// point to the same type pointed as the formal parameter. The types just
// need to logically match.
+ // 4) GLSLstd450 Interpolate* instructions can have a load of an interpolant
+ // for a first argument.
void SetBeforeHlslLegalization(bool val) {
spvValidatorOptionsSetBeforeHlslLegalization(options_, val);
}
diff --git a/include/spirv-tools/optimizer.hpp b/include/spirv-tools/optimizer.hpp
index 1683d077..e8b5b698 100644
--- a/include/spirv-tools/optimizer.hpp
+++ b/include/spirv-tools/optimizer.hpp
@@ -838,6 +838,15 @@ Optimizer::PassToken CreateWrapOpKillPass();
// capabilities.
Optimizer::PassToken CreateAmdExtToKhrPass();
+// Replaces the internal version of GLSLstd450 InterpolateAt* extended
+// instructions with the externally valid version. The internal version allows
+// an OpLoad of the interpolant for the first argument. This pass removes the
+// OpLoad and replaces it with its pointer. glslang and possibly other
+// frontends will create the internal version for HLSL. This pass will be part
+// of HLSL legalization and should be called after interpolants have been
+// propagated into their final positions.
+Optimizer::PassToken CreateInterpolateFixupPass();
+
} // namespace spvtools
#endif // INCLUDE_SPIRV_TOOLS_OPTIMIZER_HPP_
diff --git a/kokoro/check-format/build.sh b/kokoro/check-format/build.sh
index 0c4b8d1c..8a5df9a8 100644
--- a/kokoro/check-format/build.sh
+++ b/kokoro/check-format/build.sh
@@ -35,7 +35,8 @@ git clone https://github.com/google/googletest external/googletest
cd external && cd googletest && git reset --hard 1fb1bb23bb8418dc73a5a9a82bbed31dc610fec7 && cd .. && cd ..
git clone --depth=1 https://github.com/google/effcee external/effcee
git clone --depth=1 https://github.com/google/re2 external/re2
-curl -L http://llvm.org/svn/llvm-project/cfe/trunk/tools/clang-format/clang-format-diff.py -o utils/clang-format-diff.py;
+# The --fail flag causes the command to fail on HTTP error response codes, like 404.
+curl -L --fail https://raw.githubusercontent.com/llvm/llvm-project/main/clang/tools/clang-format/clang-format-diff.py -o utils/clang-format-diff.py
echo $(date): Check formatting...
./utils/check_code_format.sh;
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 65087f2c..8247f6f8 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -359,7 +359,7 @@ function(spirv_tools_default_target_options target)
)
set_property(TARGET ${target} PROPERTY FOLDER "SPIRV-Tools libraries")
spvtools_check_symbol_exports(${target})
- add_dependencies(${target} core_tables enum_string_mapping extinst_tables)
+ add_dependencies(${target} spirv-tools-build-version core_tables enum_string_mapping extinst_tables)
endfunction()
# Always build ${SPIRV_TOOLS}-shared. This is expected distro packages, and
diff --git a/source/fuzz/CMakeLists.txt b/source/fuzz/CMakeLists.txt
index d3aa9f1e..804fcf07 100644
--- a/source/fuzz/CMakeLists.txt
+++ b/source/fuzz/CMakeLists.txt
@@ -37,6 +37,7 @@ if(SPIRV_BUILD_FUZZER)
set(SPIRV_TOOLS_FUZZ_SOURCES
added_function_reducer.h
+ available_instructions.h
call_graph.h
comparator_deep_blocks_first.h
counter_overflow_id_source.h
@@ -229,6 +230,7 @@ if(SPIRV_BUILD_FUZZER)
${CMAKE_CURRENT_BINARY_DIR}/protobufs/spvtoolsfuzz.pb.h
added_function_reducer.cpp
+ available_instructions.cpp
call_graph.cpp
counter_overflow_id_source.cpp
data_descriptor.cpp
diff --git a/source/fuzz/available_instructions.cpp b/source/fuzz/available_instructions.cpp
new file mode 100644
index 00000000..e25ed900
--- /dev/null
+++ b/source/fuzz/available_instructions.cpp
@@ -0,0 +1,191 @@
+// Copyright (c) 2021 Alastair F. Donaldson
+//
+// 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/available_instructions.h"
+#include "source/fuzz/fuzzer_util.h"
+
+namespace spvtools {
+namespace fuzz {
+
+AvailableInstructions::AvailableInstructions(
+ opt::IRContext* ir_context,
+ const std::function<bool(opt::IRContext*, opt::Instruction*)>& predicate)
+ : ir_context_(ir_context) {
+ // Consider all global declarations
+ for (auto& global : ir_context->module()->types_values()) {
+ if (predicate(ir_context, &global)) {
+ available_globals_.push_back(&global);
+ }
+ }
+
+ // Consider every function
+ for (auto& function : *ir_context->module()) {
+ // Identify those function parameters that satisfy the predicate.
+ std::vector<opt::Instruction*> available_params_for_function;
+ function.ForEachParam(
+ [&predicate, ir_context,
+ &available_params_for_function](opt::Instruction* param) {
+ if (predicate(ir_context, param)) {
+ available_params_for_function.push_back(param);
+ }
+ });
+
+ // Consider every reachable block in the function.
+ auto dominator_analysis = ir_context->GetDominatorAnalysis(&function);
+ for (auto& block : function) {
+ if (!fuzzerutil::BlockIsReachableInItsFunction(ir_context, &block)) {
+ // The block is not reachable.
+ continue;
+ }
+ if (&block == &*function.begin()) {
+ // The function entry block is special: only the relevant globals and
+ // function parameters are available at its entry point.
+ num_available_at_block_entry_.insert(
+ {&block,
+ static_cast<uint32_t>(available_params_for_function.size() +
+ available_globals_.size())});
+ } else {
+ // |block| is not the entry block and is reachable, so it must have an
+ // immediate dominator. The number of instructions available on entry to
+ // |block| is thus the number of instructions available on entry to the
+ // immediate dominator + the number of instructions generated_by_block
+ // by the immediate dominator.
+ auto immediate_dominator =
+ dominator_analysis->ImmediateDominator(&block);
+ assert(immediate_dominator != nullptr &&
+ "The block is reachable so should have an immediate dominator.");
+ assert(generated_by_block_.count(immediate_dominator) != 0 &&
+ "Immediate dominator should have already been processed.");
+ assert(num_available_at_block_entry_.count(immediate_dominator) != 0 &&
+ "Immediate dominator should have already been processed.");
+ num_available_at_block_entry_.insert(
+ {&block,
+ static_cast<uint32_t>(
+ generated_by_block_.at(immediate_dominator).size()) +
+ num_available_at_block_entry_.at(immediate_dominator)});
+ }
+ // Now consider each instruction in the block.
+ std::vector<opt::Instruction*> generated_by_block;
+ for (auto& inst : block) {
+ assert(num_available_at_block_entry_.count(&block) != 0 &&
+ "Block should have already been processed.");
+ // The number of available instructions before |inst| is the number
+ // available at the start of the block + the number of relevant
+ // instructions generated by the block so far.
+ num_available_before_instruction_.insert(
+ {&inst, num_available_at_block_entry_.at(&block) +
+ static_cast<uint32_t>(generated_by_block.size())});
+ if (predicate(ir_context, &inst)) {
+ // This instruction satisfies the predicate, so note that it is
+ // generated by |block|.
+ generated_by_block.push_back(&inst);
+ }
+ }
+ generated_by_block_.emplace(&block, std::move(generated_by_block));
+ }
+ available_params_.emplace(&function,
+ std::move(available_params_for_function));
+ }
+}
+
+AvailableInstructions::AvailableBeforeInstruction
+AvailableInstructions::GetAvailableBeforeInstruction(
+ opt::Instruction* inst) const {
+ assert(num_available_before_instruction_.count(inst) != 0 &&
+ "Availability can only be queried for reachable instructions.");
+ return {*this, inst};
+}
+
+AvailableInstructions::AvailableBeforeInstruction::AvailableBeforeInstruction(
+ const AvailableInstructions& available_instructions, opt::Instruction* inst)
+ : available_instructions_(available_instructions), inst_(inst) {}
+
+uint32_t AvailableInstructions::AvailableBeforeInstruction::size() const {
+ return available_instructions_.num_available_before_instruction_.at(inst_);
+}
+
+bool AvailableInstructions::AvailableBeforeInstruction::empty() const {
+ return size() == 0;
+}
+
+opt::Instruction* AvailableInstructions::AvailableBeforeInstruction::operator[](
+ uint32_t index) const {
+ assert(index < size() && "Index out of bounds.");
+
+ // First, check the cache to see whether we can return the available
+ // instruction in constant time.
+ auto cached_result = index_cache.find(index);
+ if (cached_result != index_cache.end()) {
+ return cached_result->second;
+ }
+
+ // Next check whether the index falls into the global region.
+ if (index < available_instructions_.available_globals_.size()) {
+ auto result = available_instructions_.available_globals_[index];
+ index_cache.insert({index, result});
+ return result;
+ }
+
+ auto block = available_instructions_.ir_context_->get_instr_block(inst_);
+ auto function = block->GetParent();
+
+ // Next check whether the index falls into the available instructions that
+ // correspond to function parameters.
+ if (index <
+ available_instructions_.available_globals_.size() +
+ available_instructions_.available_params_.at(function).size()) {
+ auto result = available_instructions_.available_params_.at(
+ function)[index - available_instructions_.available_globals_.size()];
+ index_cache.insert({index, result});
+ return result;
+ }
+
+ auto dominator_analysis =
+ available_instructions_.ir_context_->GetDominatorAnalysis(function);
+
+ // Now the expensive part (which is why we have the cache): walk the dominator
+ // tree backwards starting from the block containing |inst_| until we get to
+ // the block in which the instruction corresponding to |index| exists.
+ for (auto* ancestor = block; true;
+ ancestor = dominator_analysis->ImmediateDominator(ancestor)) {
+ uint32_t num_available_at_ancestor_entry =
+ available_instructions_.num_available_at_block_entry_.at(ancestor);
+ if (index_cache.count(num_available_at_ancestor_entry) == 0) {
+ // This is the first time we have traversed this block, so we populate the
+ // cache with the index of each instruction, so that if a future index
+ // query relates to indices associated with this block we can return the
+ // result in constant time.
+ auto& generated_by_ancestor =
+ available_instructions_.generated_by_block_.at(ancestor);
+ for (uint32_t local_index = 0; local_index < generated_by_ancestor.size();
+ local_index++) {
+ index_cache.insert({num_available_at_ancestor_entry + local_index,
+ generated_by_ancestor[local_index]});
+ }
+ }
+ if (index >= num_available_at_ancestor_entry) {
+ // This block contains the instruction we want, so by now it will be in
+ // the cache.
+ return index_cache.at(index);
+ }
+ assert(ancestor != &*function->begin() &&
+ "By construction we should find a block associated with the index.");
+ }
+
+ assert(false && "Unreachable.");
+ return nullptr;
+}
+
+} // namespace fuzz
+} // namespace spvtools
diff --git a/source/fuzz/available_instructions.h b/source/fuzz/available_instructions.h
new file mode 100644
index 00000000..5c0b4175
--- /dev/null
+++ b/source/fuzz/available_instructions.h
@@ -0,0 +1,111 @@
+// Copyright (c) 2021 Alastair F. Donaldson
+//
+// 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_AVAILABLE_INSTRUCTIONS_H_
+#define SOURCE_FUZZ_AVAILABLE_INSTRUCTIONS_H_
+
+#include <unordered_map>
+#include <vector>
+
+#include "source/opt/instruction.h"
+#include "source/opt/ir_context.h"
+
+namespace spvtools {
+namespace fuzz {
+
+// A class for allowing efficient querying of the instruction that satisfy a
+// particular predicate that are available before a given instruction.
+// Availability information is only computed for instructions in *reachable*
+// basic blocks.
+class AvailableInstructions {
+ public:
+ // The outer class captures availability information for a whole module, and
+ // each instance of this inner class captures availability for a particular
+ // instruction.
+ class AvailableBeforeInstruction {
+ public:
+ AvailableBeforeInstruction(
+ const AvailableInstructions& available_instructions,
+ opt::Instruction* inst);
+
+ // Returns the number of instructions that are available before the
+ // instruction associated with this class.
+ uint32_t size() const;
+
+ // Returns true if and only if |size()| is 0.
+ bool empty() const;
+
+ // Requires |index| < |size()|. Returns the ith available instruction.
+ opt::Instruction* operator[](uint32_t index) const;
+
+ private:
+ // A references to an instance of the outer class.
+ const AvailableInstructions& available_instructions_;
+
+ // The instruction for which availability information is captured.
+ opt::Instruction* inst_;
+
+ // A cache to improve the efficiency of the [] operator. The [] operator
+ // requires walking the instruction's dominator tree to find an instruction
+ // at a particular index, which is a linear time operation. By inserting all
+ // instructions that are traversed during this search into a cache, future
+ // lookups will take constant time unless they require traversing the
+ // dominator tree more deeply.
+ mutable std::unordered_map<uint32_t, opt::Instruction*> index_cache;
+ };
+
+ // Constructs availability instructions for |ir_context|, where instructions
+ // are only available if they satisfy |predicate|.
+ AvailableInstructions(
+ opt::IRContext* ir_context,
+ const std::function<bool(opt::IRContext*, opt::Instruction*)>& predicate);
+
+ // Yields instruction availability for |inst|.
+ AvailableBeforeInstruction GetAvailableBeforeInstruction(
+ opt::Instruction* inst) const;
+
+ private:
+ // The module in which all instructions are contained.
+ opt::IRContext* ir_context_;
+
+ // The global instructions that satisfy the predicate.
+ std::vector<opt::Instruction*> available_globals_;
+
+ // Per function, the parameters that satisfy the predicate.
+ std::unordered_map<opt::Function*, std::vector<opt::Instruction*>>
+ available_params_;
+
+ // The number of instructions that satisfy the predicate and that are
+ // available at the entry to a block. For the entry block of a function this
+ // is the number of available globals + the number of available function
+ // parameters. For any other block it is the number of available instructions
+ // for the blocks immediate dominator + the number of instructions generated
+ // by the immediate dominator.
+ std::unordered_map<opt::BasicBlock*, uint32_t> num_available_at_block_entry_;
+
+ // For each block this records those instructions in the block that satisfy
+ // the predicate.
+ std::unordered_map<opt::BasicBlock*, std::vector<opt::Instruction*>>
+ generated_by_block_;
+
+ // For each instruction this records how many instructions satisfying the
+ // predicate are available before the instruction.
+ std::unordered_map<opt::Instruction*, uint32_t>
+ num_available_before_instruction_;
+};
+
+} // namespace fuzz
+} // namespace spvtools
+
+#endif // SOURCE_FUZZ_AVAILABLE_INSTRUCTIONS_H_
diff --git a/source/fuzz/force_render_red.cpp b/source/fuzz/force_render_red.cpp
index fd0587a3..3267487a 100644
--- a/source/fuzz/force_render_red.cpp
+++ b/source/fuzz/force_render_red.cpp
@@ -19,12 +19,10 @@
#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 {
@@ -160,8 +158,8 @@ 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,
+ const MessageConsumer& message_consumer,
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, {},
diff --git a/source/fuzz/force_render_red.h b/source/fuzz/force_render_red.h
index b51c72b4..5b8eab1b 100644
--- a/source/fuzz/force_render_red.h
+++ b/source/fuzz/force_render_red.h
@@ -41,7 +41,7 @@ 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);
+ const MessageConsumer& message_consumer, std::vector<uint32_t>* binary_out);
} // namespace fuzz
} // namespace spvtools
diff --git a/source/fuzz/fuzzer.cpp b/source/fuzz/fuzzer.cpp
index 40da4974..9d1af752 100644
--- a/source/fuzz/fuzzer.cpp
+++ b/source/fuzz/fuzzer.cpp
@@ -17,9 +17,7 @@
#include <cassert>
#include <memory>
#include <numeric>
-#include <sstream>
-#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_bit_instruction_synonyms.h"
@@ -91,9 +89,6 @@
#include "source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h"
#include "source/fuzz/fuzzer_pass_wrap_regions_in_selections.h"
#include "source/fuzz/pass_management/repeated_pass_manager.h"
-#include "source/fuzz/pass_management/repeated_pass_manager_looped_with_recommendations.h"
-#include "source/fuzz/pass_management/repeated_pass_manager_random_with_recommendations.h"
-#include "source/fuzz/pass_management/repeated_pass_manager_simple.h"
#include "source/fuzz/pass_management/repeated_pass_recommender_standard.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation_context.h"
@@ -104,35 +99,147 @@
namespace spvtools {
namespace fuzz {
-namespace {
-const uint32_t kIdBoundGap = 100;
-
-} // namespace
-
-Fuzzer::Fuzzer(spv_target_env target_env, MessageConsumer consumer,
- const std::vector<uint32_t>& binary_in,
- const protobufs::FactSequence& initial_facts,
+Fuzzer::Fuzzer(std::unique_ptr<opt::IRContext> ir_context,
+ std::unique_ptr<TransformationContext> transformation_context,
+ std::unique_ptr<FuzzerContext> fuzzer_context,
+ MessageConsumer consumer,
const std::vector<fuzzerutil::ModuleSupplier>& donor_suppliers,
- std::unique_ptr<RandomGenerator> random_generator,
bool enable_all_passes,
RepeatedPassStrategy repeated_pass_strategy,
bool validate_after_each_fuzzer_pass,
spv_validator_options validator_options)
- : target_env_(target_env),
- consumer_(std::move(consumer)),
- binary_in_(binary_in),
- initial_facts_(initial_facts),
- donor_suppliers_(donor_suppliers),
- random_generator_(std::move(random_generator)),
+ : consumer_(std::move(consumer)),
enable_all_passes_(enable_all_passes),
- repeated_pass_strategy_(repeated_pass_strategy),
validate_after_each_fuzzer_pass_(validate_after_each_fuzzer_pass),
validator_options_(validator_options),
num_repeated_passes_applied_(0),
- ir_context_(nullptr),
- fuzzer_context_(nullptr),
- transformation_context_(nullptr),
- transformation_sequence_out_() {}
+ is_valid_(true),
+ ir_context_(std::move(ir_context)),
+ transformation_context_(std::move(transformation_context)),
+ fuzzer_context_(std::move(fuzzer_context)),
+ transformation_sequence_out_(),
+ pass_instances_(),
+ repeated_pass_recommender_(nullptr),
+ repeated_pass_manager_(nullptr),
+ final_passes_() {
+ assert(ir_context_ && "IRContext is not initialized");
+ assert(fuzzer_context_ && "FuzzerContext is not initialized");
+ assert(transformation_context_ && "TransformationContext is not initialized");
+ assert(fuzzerutil::IsValidAndWellFormed(ir_context_.get(), validator_options_,
+ consumer_) &&
+ "IRContext is invalid");
+
+ // The following passes are likely to be very useful: many other passes
+ // introduce synonyms, irrelevant ids and constants that these passes can work
+ // with. We thus enable them with high probability.
+ MaybeAddRepeatedPass<FuzzerPassObfuscateConstants>(90, &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassApplyIdSynonyms>(90, &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassReplaceIrrelevantIds>(90, &pass_instances_);
+
+ do {
+ // Each call to MaybeAddRepeatedPass randomly decides whether the given pass
+ // should be enabled, and adds an instance of the pass to |pass_instances|
+ // if it is enabled.
+ MaybeAddRepeatedPass<FuzzerPassAddAccessChains>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddBitInstructionSynonyms>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddCompositeExtract>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddCompositeInserts>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddCompositeTypes>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddCopyMemory>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddDeadBlocks>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddDeadBreaks>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddDeadContinues>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddEquationInstructions>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddFunctionCalls>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddGlobalVariables>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddImageSampleUnusedComponents>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddLoads>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddLocalVariables>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddLoopPreheaders>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddLoopsToCreateIntConstantSynonyms>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddOpPhiSynonyms>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddParameters>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddRelaxedDecorations>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddStores>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddSynonyms>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassAddVectorShuffleInstructions>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassConstructComposites>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassCopyObjects>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassDonateModules>(&pass_instances_,
+ donor_suppliers);
+ MaybeAddRepeatedPass<FuzzerPassDuplicateRegionsWithSelections>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassExpandVectorReductions>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassFlattenConditionalBranches>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassInlineFunctions>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassInvertComparisonOperators>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassMakeVectorOperationsDynamic>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassMergeBlocks>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassMergeFunctionReturns>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassMutatePointers>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassOutlineFunctions>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassPermuteBlocks>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassPermuteFunctionParameters>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassPermuteInstructions>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassPropagateInstructionsDown>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassPropagateInstructionsUp>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassPushIdsThroughVariables>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassReplaceAddsSubsMulsWithCarryingExtended>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassReplaceBranchesFromDeadBlocksWithExits>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassReplaceCopyMemoriesWithLoadsStores>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassReplaceCopyObjectsWithStoresLoads>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassReplaceLoadsStoresWithCopyMemories>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassReplaceParameterWithGlobal>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassReplaceLinearAlgebraInstructions>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassReplaceOpPhiIdsFromDeadPredecessors>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassReplaceOpSelectsWithConditionalBranches>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassReplaceParamsWithStruct>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassSplitBlocks>(&pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassSwapBranchConditionalOperands>(
+ &pass_instances_);
+ MaybeAddRepeatedPass<FuzzerPassWrapRegionsInSelections>(&pass_instances_);
+ // There is a theoretical possibility that no pass instances were created
+ // until now; loop again if so.
+ } while (pass_instances_.GetPasses().empty());
+
+ repeated_pass_recommender_ = MakeUnique<RepeatedPassRecommenderStandard>(
+ &pass_instances_, fuzzer_context_.get());
+ repeated_pass_manager_ = RepeatedPassManager::Create(
+ repeated_pass_strategy, fuzzer_context_.get(), &pass_instances_,
+ repeated_pass_recommender_.get());
+
+ MaybeAddFinalPass<FuzzerPassAdjustBranchWeights>(&final_passes_);
+ MaybeAddFinalPass<FuzzerPassAdjustFunctionControls>(&final_passes_);
+ MaybeAddFinalPass<FuzzerPassAdjustLoopControls>(&final_passes_);
+ MaybeAddFinalPass<FuzzerPassAdjustMemoryOperandsMasks>(&final_passes_);
+ MaybeAddFinalPass<FuzzerPassAdjustSelectionControls>(&final_passes_);
+ MaybeAddFinalPass<FuzzerPassAddNoContractionDecorations>(&final_passes_);
+ if (!fuzzer_context_->IsWgslCompatible()) {
+ // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/4214):
+ // this is disabled temporarily due to some issues in the Tint compiler.
+ // Enable it back when the issues are resolved.
+ MaybeAddFinalPass<FuzzerPassInterchangeSignednessOfIntegerOperands>(
+ &final_passes_);
+ }
+ MaybeAddFinalPass<FuzzerPassInterchangeZeroLikeConstants>(&final_passes_);
+ MaybeAddFinalPass<FuzzerPassPermutePhiOperands>(&final_passes_);
+ MaybeAddFinalPass<FuzzerPassSwapCommutableOperands>(&final_passes_);
+ MaybeAddFinalPass<FuzzerPassToggleAccessChainInstruction>(&final_passes_);
+}
Fuzzer::~Fuzzer() = default;
@@ -165,240 +272,107 @@ bool Fuzzer::ApplyPassAndCheckValidity(FuzzerPass* pass) const {
consumer_);
}
-Fuzzer::FuzzerResult Fuzzer::Run() {
- // Check compatibility between the library version being linked with and the
- // header files being used.
- GOOGLE_PROTOBUF_VERIFY_VERSION;
+opt::IRContext* Fuzzer::GetIRContext() { return ir_context_.get(); }
- assert(ir_context_ == nullptr && fuzzer_context_ == nullptr &&
- transformation_context_ == nullptr &&
- transformation_sequence_out_.transformation_size() == 0 &&
- "'Run' must not be invoked more than once.");
-
- 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,
- std::vector<uint32_t>(), protobufs::TransformationSequence()};
- }
-
- // 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,
- std::vector<uint32_t>(), protobufs::TransformationSequence()};
- }
-
- // Build the module from the input binary.
- ir_context_ =
- BuildModule(target_env_, consumer_, binary_in_.data(), binary_in_.size());
- assert(ir_context_);
-
- // 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;
- fuzzer_context_ =
- MakeUnique<FuzzerContext>(random_generator_.get(), minimum_fresh_id);
-
- transformation_context_ = MakeUnique<TransformationContext>(
- MakeUnique<FactManager>(ir_context_.get()), validator_options_);
- transformation_context_->GetFactManager()->AddInitialFacts(consumer_,
- initial_facts_);
+const protobufs::TransformationSequence& Fuzzer::GetTransformationSequence()
+ const {
+ return transformation_sequence_out_;
+}
- RepeatedPassInstances pass_instances{};
+Fuzzer::Result Fuzzer::Run(uint32_t num_of_transformations_to_apply) {
+ assert(is_valid_ && "The module was invalidated during the previous fuzzing");
- // The following passes are likely to be very useful: many other passes
- // introduce synonyms, irrelevant ids and constants that these passes can work
- // with. We thus enable them with high probability.
- MaybeAddRepeatedPass<FuzzerPassObfuscateConstants>(90, &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassApplyIdSynonyms>(90, &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassReplaceIrrelevantIds>(90, &pass_instances);
+ const auto initial_num_of_transformations =
+ static_cast<uint32_t>(transformation_sequence_out_.transformation_size());
+ auto status = Status::kComplete;
do {
- // Each call to MaybeAddRepeatedPass randomly decides whether the given pass
- // should be enabled, and adds an instance of the pass to |pass_instances|
- // if it is enabled.
- MaybeAddRepeatedPass<FuzzerPassAddAccessChains>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddBitInstructionSynonyms>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddCompositeExtract>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddCompositeInserts>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddCompositeTypes>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddCopyMemory>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddDeadBlocks>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddDeadBreaks>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddDeadContinues>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddEquationInstructions>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddFunctionCalls>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddGlobalVariables>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddImageSampleUnusedComponents>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddLoads>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddLocalVariables>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddLoopPreheaders>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddLoopsToCreateIntConstantSynonyms>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddOpPhiSynonyms>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddParameters>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddRelaxedDecorations>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddStores>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddSynonyms>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassAddVectorShuffleInstructions>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassConstructComposites>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassCopyObjects>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassDonateModules>(&pass_instances,
- donor_suppliers_);
- MaybeAddRepeatedPass<FuzzerPassDuplicateRegionsWithSelections>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassExpandVectorReductions>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassFlattenConditionalBranches>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassInlineFunctions>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassInvertComparisonOperators>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassMakeVectorOperationsDynamic>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassMergeBlocks>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassMergeFunctionReturns>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassMutatePointers>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassOutlineFunctions>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassPermuteBlocks>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassPermuteFunctionParameters>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassPermuteInstructions>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassPropagateInstructionsDown>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassPropagateInstructionsUp>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassPushIdsThroughVariables>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassReplaceAddsSubsMulsWithCarryingExtended>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassReplaceBranchesFromDeadBlocksWithExits>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassReplaceCopyMemoriesWithLoadsStores>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassReplaceCopyObjectsWithStoresLoads>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassReplaceLoadsStoresWithCopyMemories>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassReplaceParameterWithGlobal>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassReplaceLinearAlgebraInstructions>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassReplaceOpPhiIdsFromDeadPredecessors>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassReplaceOpSelectsWithConditionalBranches>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassReplaceParamsWithStruct>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassSplitBlocks>(&pass_instances);
- MaybeAddRepeatedPass<FuzzerPassSwapBranchConditionalOperands>(
- &pass_instances);
- MaybeAddRepeatedPass<FuzzerPassWrapRegionsInSelections>(&pass_instances);
- // There is a theoretical possibility that no pass instances were created
- // until now; loop again if so.
- } while (pass_instances.GetPasses().empty());
-
- RepeatedPassRecommenderStandard pass_recommender(&pass_instances,
- fuzzer_context_.get());
+ if (!ApplyPassAndCheckValidity(
+ repeated_pass_manager_->ChoosePass(transformation_sequence_out_))) {
+ status = Status::kFuzzerPassLedToInvalidModule;
+ break;
+ }
- std::unique_ptr<RepeatedPassManager> repeated_pass_manager = nullptr;
- switch (repeated_pass_strategy_) {
- case RepeatedPassStrategy::kSimple:
- repeated_pass_manager = MakeUnique<RepeatedPassManagerSimple>(
- fuzzer_context_.get(), &pass_instances);
+ // Check that the module is small enough.
+ if (ir_context_->module()->id_bound() >=
+ fuzzer_context_->GetIdBoundLimit()) {
+ status = Status::kModuleTooBig;
break;
- case RepeatedPassStrategy::kLoopedWithRecommendations:
- repeated_pass_manager =
- MakeUnique<RepeatedPassManagerLoopedWithRecommendations>(
- fuzzer_context_.get(), &pass_instances, &pass_recommender);
+ }
+
+ auto transformations_applied_so_far = static_cast<uint32_t>(
+ transformation_sequence_out_.transformation_size());
+ assert(transformations_applied_so_far >= initial_num_of_transformations &&
+ "Number of transformations cannot decrease");
+
+ // Check if we've already applied the maximum number of transformations.
+ if (transformations_applied_so_far >=
+ fuzzer_context_->GetTransformationLimit()) {
+ status = Status::kTransformationLimitReached;
break;
- case RepeatedPassStrategy::kRandomWithRecommendations:
- repeated_pass_manager =
- MakeUnique<RepeatedPassManagerRandomWithRecommendations>(
- fuzzer_context_.get(), &pass_instances, &pass_recommender);
+ }
+
+ // Check that we've not got stuck (this can happen if the only available
+ // fuzzer passes are not able to apply any transformations, or can only
+ // apply very few transformations).
+ if (num_repeated_passes_applied_ >=
+ fuzzer_context_->GetTransformationLimit()) {
+ status = Status::kFuzzerStuck;
break;
- }
+ }
- do {
- if (!ApplyPassAndCheckValidity(
- repeated_pass_manager->ChoosePass(transformation_sequence_out_))) {
- return {Fuzzer::FuzzerResultStatus::kFuzzerPassLedToInvalidModule,
- std::vector<uint32_t>(), protobufs::TransformationSequence()};
+ // Check whether we've exceeded the number of transformations we can apply
+ // in a single call to this method.
+ if (num_of_transformations_to_apply != 0 &&
+ transformations_applied_so_far - initial_num_of_transformations >=
+ num_of_transformations_to_apply) {
+ status = Status::kComplete;
+ break;
}
- } while (ShouldContinueFuzzing());
- // 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;
- MaybeAddFinalPass<FuzzerPassAdjustBranchWeights>(&final_passes);
- MaybeAddFinalPass<FuzzerPassAdjustFunctionControls>(&final_passes);
- MaybeAddFinalPass<FuzzerPassAdjustLoopControls>(&final_passes);
- MaybeAddFinalPass<FuzzerPassAdjustMemoryOperandsMasks>(&final_passes);
- MaybeAddFinalPass<FuzzerPassAdjustSelectionControls>(&final_passes);
- MaybeAddFinalPass<FuzzerPassAddNoContractionDecorations>(&final_passes);
- MaybeAddFinalPass<FuzzerPassInterchangeSignednessOfIntegerOperands>(
- &final_passes);
- MaybeAddFinalPass<FuzzerPassInterchangeZeroLikeConstants>(&final_passes);
- MaybeAddFinalPass<FuzzerPassPermutePhiOperands>(&final_passes);
- MaybeAddFinalPass<FuzzerPassSwapCommutableOperands>(&final_passes);
- MaybeAddFinalPass<FuzzerPassToggleAccessChainInstruction>(&final_passes);
- for (auto& pass : final_passes) {
- if (!ApplyPassAndCheckValidity(pass.get())) {
- return {Fuzzer::FuzzerResultStatus::kFuzzerPassLedToInvalidModule,
- std::vector<uint32_t>(), protobufs::TransformationSequence()};
+ } while (ShouldContinueRepeatedPasses(num_of_transformations_to_apply == 0));
+
+ if (status != Status::kFuzzerPassLedToInvalidModule) {
+ // We apply this transformations despite the fact that we might exceed
+ // |num_of_transformations_to_apply|. This is not a problem for us since
+ // these fuzzer passes are relatively simple yet might trigger some bugs.
+ for (auto& pass : final_passes_) {
+ if (!ApplyPassAndCheckValidity(pass.get())) {
+ status = Status::kFuzzerPassLedToInvalidModule;
+ break;
+ }
}
}
- // Encode the module as a binary.
- std::vector<uint32_t> binary_out;
- ir_context_->module()->ToBinary(&binary_out, false);
- return {Fuzzer::FuzzerResultStatus::kComplete, std::move(binary_out),
- std::move(transformation_sequence_out_)};
+ is_valid_ = status != Status::kFuzzerPassLedToInvalidModule;
+ return {status, static_cast<uint32_t>(
+ transformation_sequence_out_.transformation_size()) !=
+ initial_num_of_transformations};
}
-bool Fuzzer::ShouldContinueFuzzing() {
- // There's a risk that fuzzing could get stuck, if none of the enabled fuzzer
- // passes are able to apply any transformations. To guard against this we
- // count the number of times some repeated pass has been applied and ensure
- // that fuzzing stops if the number of repeated passes hits the limit on the
- // number of transformations that can be applied.
- assert(
- num_repeated_passes_applied_ <=
- fuzzer_context_->GetTransformationLimit() &&
- "The number of repeated passes applied must not exceed its upper limit.");
- if (ir_context_->module()->id_bound() >= fuzzer_context_->GetIdBoundLimit()) {
- return false;
- }
- if (num_repeated_passes_applied_ ==
- fuzzer_context_->GetTransformationLimit()) {
- // Stop because fuzzing has got stuck.
- return false;
- }
- auto transformations_applied_so_far =
- static_cast<uint32_t>(transformation_sequence_out_.transformation_size());
- if (transformations_applied_so_far >=
- fuzzer_context_->GetTransformationLimit()) {
- // Stop because we have reached the transformation limit.
- return false;
- }
- // If we have applied T transformations so far, and the limit on the number of
- // transformations to apply is L (where T < L), the chance that we will
- // continue fuzzing is:
- //
- // 1 - T/(2*L)
- //
- // That is, the chance of continuing decreases as more transformations are
- // applied. Using 2*L instead of L increases the number of transformations
- // that are applied on average.
- auto chance_of_continuing = static_cast<uint32_t>(
- 100.0 * (1.0 - (static_cast<double>(transformations_applied_so_far) /
- (2.0 * static_cast<double>(
- fuzzer_context_->GetTransformationLimit())))));
- if (!fuzzer_context_->ChoosePercentage(chance_of_continuing)) {
- // We have probabilistically decided to stop.
- return false;
+bool Fuzzer::ShouldContinueRepeatedPasses(
+ bool continue_fuzzing_probabilistically) {
+ if (continue_fuzzing_probabilistically) {
+ // If we have applied T transformations so far, and the limit on the number
+ // of transformations to apply is L (where T < L), the chance that we will
+ // continue fuzzing is:
+ //
+ // 1 - T/(2*L)
+ //
+ // That is, the chance of continuing decreases as more transformations are
+ // applied. Using 2*L instead of L increases the number of transformations
+ // that are applied on average.
+ auto transformations_applied_so_far = static_cast<uint32_t>(
+ transformation_sequence_out_.transformation_size());
+ auto chance_of_continuing = static_cast<uint32_t>(
+ 100.0 *
+ (1.0 - (static_cast<double>(transformations_applied_so_far) /
+ (2.0 * static_cast<double>(
+ fuzzer_context_->GetTransformationLimit())))));
+ if (!fuzzer_context_->ChoosePercentage(chance_of_continuing)) {
+ // We have probabilistically decided to stop.
+ return false;
+ }
}
// Continue fuzzing!
num_repeated_passes_applied_++;
diff --git a/source/fuzz/fuzzer.h b/source/fuzz/fuzzer.h
index 774457f5..1e7d6860 100644
--- a/source/fuzz/fuzzer.h
+++ b/source/fuzz/fuzzer.h
@@ -23,6 +23,7 @@
#include "source/fuzz/fuzzer_pass.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/pass_management/repeated_pass_instances.h"
+#include "source/fuzz/pass_management/repeated_pass_manager.h"
#include "source/fuzz/pass_management/repeated_pass_recommender.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/random_generator.h"
@@ -37,33 +38,28 @@ namespace fuzz {
class Fuzzer {
public:
// Possible statuses that can result from running the fuzzer.
- enum class FuzzerResultStatus {
+ enum class Status {
kComplete,
- kFailedToCreateSpirvToolsInterface,
+ kModuleTooBig,
+ kTransformationLimitReached,
+ kFuzzerStuck,
kFuzzerPassLedToInvalidModule,
- kInitialBinaryInvalid,
};
- struct FuzzerResult {
- FuzzerResultStatus status;
- std::vector<uint32_t> transformed_binary;
- protobufs::TransformationSequence applied_transformations;
- };
+ struct Result {
+ // Status of the fuzzing session.
+ Status status;
- // Each field of this enum corresponds to an available repeated pass
- // strategy, and is used to decide which kind of RepeatedPassManager object
- // to create.
- enum class RepeatedPassStrategy {
- kSimple,
- kRandomWithRecommendations,
- kLoopedWithRecommendations
+ // Equals to true if new transformations were applied during the previous
+ // fuzzing session.
+ bool is_changed;
};
- Fuzzer(spv_target_env target_env, MessageConsumer consumer,
- const std::vector<uint32_t>& binary_in,
- const protobufs::FactSequence& initial_facts,
+ Fuzzer(std::unique_ptr<opt::IRContext> ir_context,
+ std::unique_ptr<TransformationContext> transformation_context,
+ std::unique_ptr<FuzzerContext> fuzzer_context,
+ MessageConsumer consumer,
const std::vector<fuzzerutil::ModuleSupplier>& donor_suppliers,
- std::unique_ptr<RandomGenerator> random_generator,
bool enable_all_passes, RepeatedPassStrategy repeated_pass_strategy,
bool validate_after_each_fuzzer_pass,
spv_validator_options validator_options);
@@ -76,15 +72,23 @@ class Fuzzer {
~Fuzzer();
- // Transforms |binary_in_| 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_|. On success,
- // returns a successful result status together with the transformed binary and
- // the sequence of transformations that were applied. Otherwise, returns an
- // appropriate result status together with an empty binary and empty
- // transformation sequence.
- FuzzerResult Run();
+ // Transforms |ir_context_| by running a number of randomized fuzzer passes.
+ // Initial facts about the input binary and the context in which it will be
+ // executed are provided with |transformation_context_|.
+ // |num_of_transformations| is equal to the maximum number of transformations
+ // applied in a single call to this method. This parameter is ignored if its
+ // value is equal to 0. Because fuzzing cannot stop mid way through a fuzzer
+ // pass, fuzzing will stop after the fuzzer pass that exceeds
+ // |num_of_transformations| has completed, so that the total number of
+ // transformations may be somewhat larger than this number.
+ Result Run(uint32_t num_of_transformations_to_apply);
+
+ // Returns the current IR context. It may be invalid if the Run method
+ // returned Status::kFuzzerPassLedToInvalidModule previously.
+ opt::IRContext* GetIRContext();
+
+ // Returns the sequence of applied transformations.
+ const protobufs::TransformationSequence& GetTransformationSequence() const;
private:
// A convenience method to add a repeated fuzzer pass to |pass_instances| with
@@ -119,7 +123,9 @@ class Fuzzer {
// Decides whether to apply more repeated passes. The probability decreases as
// the number of transformations that have been applied increases.
- bool ShouldContinueFuzzing();
+ // The described probability is only applied if
+ // |continue_fuzzing_probabilistically| is true.
+ bool ShouldContinueRepeatedPasses(bool continue_fuzzing_probabilistically);
// Applies |pass|, which must be a pass constructed with |ir_context|.
// If |validate_after_each_fuzzer_pass_| is not set, true is always returned.
@@ -128,57 +134,59 @@ class Fuzzer {
// instruction has a distinct unique id.
bool ApplyPassAndCheckValidity(FuzzerPass* pass) const;
- // Target environment.
- const spv_target_env target_env_;
-
// Message consumer that will be invoked once for each message communicated
// from the library.
- MessageConsumer consumer_;
-
- // The initial binary to which fuzzing should be applied.
- const std::vector<uint32_t>& binary_in_;
-
- // Initial facts known to hold in advance of applying any transformations.
- const protobufs::FactSequence& initial_facts_;
-
- // A source of modules whose contents can be donated into the module being
- // fuzzed.
- const std::vector<fuzzerutil::ModuleSupplier>& donor_suppliers_;
-
- // Random number generator to control decision making during fuzzing.
- std::unique_ptr<RandomGenerator> random_generator_;
+ const MessageConsumer consumer_;
// Determines whether all passes should be enabled, vs. having passes be
// probabilistically enabled.
- bool enable_all_passes_;
-
- // Controls which type of RepeatedPassManager object to create.
- RepeatedPassStrategy repeated_pass_strategy_;
+ const bool enable_all_passes_;
// Determines whether the validator should be invoked after every fuzzer pass.
- bool validate_after_each_fuzzer_pass_;
+ const bool validate_after_each_fuzzer_pass_;
// Options to control validation.
- spv_validator_options validator_options_;
+ const spv_validator_options validator_options_;
// The number of repeated fuzzer passes that have been applied is kept track
// of, in order to enforce a hard limit on the number of times such passes
// can be applied.
uint32_t num_repeated_passes_applied_;
+ // We use this to determine whether we can continue fuzzing incrementally
+ // since the previous call to the Run method could've returned
+ // kFuzzerPassLedToInvalidModule.
+ bool is_valid_;
+
// Intermediate representation for the module being fuzzed, which gets
// mutated as fuzzing proceeds.
std::unique_ptr<opt::IRContext> ir_context_;
+ // Contextual information that is required in order to apply
+ // transformations.
+ std::unique_ptr<TransformationContext> transformation_context_;
+
// Provides probabilities that control the fuzzing process.
std::unique_ptr<FuzzerContext> fuzzer_context_;
- // Contextual information that is required in order to apply transformations.
- std::unique_ptr<TransformationContext> transformation_context_;
-
- // The sequence of transformations that have been applied during fuzzing. It
+ // The sequence of transformations that have been applied during fuzzing. It
// is initially empty and grows as fuzzer passes are applied.
protobufs::TransformationSequence transformation_sequence_out_;
+
+ // This object contains instances of all fuzzer passes that will participate
+ // in the fuzzing.
+ RepeatedPassInstances pass_instances_;
+
+ // This object defines the recommendation logic for fuzzer passes.
+ std::unique_ptr<RepeatedPassRecommender> repeated_pass_recommender_;
+
+ // This object manager a list of fuzzer pass and their available
+ // recommendations.
+ std::unique_ptr<RepeatedPassManager> repeated_pass_manager_;
+
+ // 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_;
};
} // namespace fuzz
diff --git a/source/fuzz/fuzzer_context.cpp b/source/fuzz/fuzzer_context.cpp
index 47bf4e25..ef93e719 100644
--- a/source/fuzz/fuzzer_context.cpp
+++ b/source/fuzz/fuzzer_context.cpp
@@ -21,6 +21,12 @@ namespace fuzz {
namespace {
+// An offset between the the module's id bound and the minimum fresh id.
+//
+// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2541): consider
+// the case where the maximum id bound is reached.
+const uint32_t kIdBoundGap = 100;
+
// Limits to help control the overall fuzzing process and rein in individual
// fuzzer passes.
const uint32_t kIdBoundLimit = 50000;
@@ -177,10 +183,11 @@ const std::function<bool(uint32_t, RandomGenerator*)>
} // namespace
-FuzzerContext::FuzzerContext(RandomGenerator* random_generator,
- uint32_t min_fresh_id)
- : random_generator_(random_generator),
+FuzzerContext::FuzzerContext(std::unique_ptr<RandomGenerator> random_generator,
+ uint32_t min_fresh_id, bool is_wgsl_compatible)
+ : random_generator_(std::move(random_generator)),
next_fresh_id_(min_fresh_id),
+ is_wgsl_compatible_(is_wgsl_compatible),
max_equivalence_class_size_for_data_synonym_fact_closure_(
kDefaultMaxEquivalenceClassSizeForDataSynonymFactClosure),
max_loop_control_partial_count_(kDefaultMaxLoopControlPartialCount),
@@ -403,5 +410,9 @@ uint32_t FuzzerContext::GetTransformationLimit() const {
return kTransformationLimit;
}
+uint32_t FuzzerContext::GetMinFreshId(opt::IRContext* ir_context) {
+ return ir_context->module()->id_bound() + kIdBoundGap;
+}
+
} // namespace fuzz
} // namespace spvtools
diff --git a/source/fuzz/fuzzer_context.h b/source/fuzz/fuzzer_context.h
index 8c510418..40fd8783 100644
--- a/source/fuzz/fuzzer_context.h
+++ b/source/fuzz/fuzzer_context.h
@@ -21,6 +21,7 @@
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/random_generator.h"
#include "source/opt/function.h"
+#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
@@ -32,7 +33,8 @@ 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(std::unique_ptr<RandomGenerator> random_generator,
+ uint32_t min_fresh_id, bool is_wgsl_compatible);
~FuzzerContext();
@@ -64,7 +66,7 @@ class FuzzerContext {
}
// Randomly shuffles a |sequence| between |lo| and |hi| indices inclusively.
- // |lo| and |hi| must be valid indices to the |sequence|
+ // |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;
@@ -89,7 +91,7 @@ class FuzzerContext {
}
}
- // Ramdomly shuffles a |sequence|
+ // Randomly shuffles a |sequence|.
template <typename T>
void Shuffle(std::vector<T>* sequence) const {
if (!sequence->empty()) {
@@ -102,7 +104,7 @@ class FuzzerContext {
uint32_t GetFreshId();
// Returns a vector of |count| fresh ids.
- std::vector<uint32_t> GetFreshIds(const uint32_t count);
+ std::vector<uint32_t> GetFreshIds(uint32_t count);
// A suggested limit on the id bound for the module being fuzzed. This is
// useful for deciding when to stop the overall fuzzing process. Furthermore,
@@ -115,6 +117,14 @@ class FuzzerContext {
// fuzzer passes.
uint32_t GetTransformationLimit() const;
+ // Returns the minimum fresh id that can be used given the |ir_context|.
+ static uint32_t GetMinFreshId(opt::IRContext* ir_context);
+
+ // Returns true if all transformations should be compatible with WGSL.
+ bool IsWgslCompatible() const {
+ return is_wgsl_compatible_;
+ }
+
// Probabilities associated with applying various transformations.
// Keep them in alphabetical order.
uint32_t GetChanceOfAcceptingRepeatedPassRecommendation() const {
@@ -442,15 +452,18 @@ class FuzzerContext {
return random_generator_->RandomUint32(max_unused_component_count) + 1;
}
bool GoDeeperInConstantObfuscation(uint32_t depth) {
- return go_deeper_in_constant_obfuscation_(depth, random_generator_);
+ return go_deeper_in_constant_obfuscation_(depth, random_generator_.get());
}
private:
// The source of randomness.
- RandomGenerator* random_generator_;
+ std::unique_ptr<RandomGenerator> random_generator_;
// The next fresh id to be issued.
uint32_t next_fresh_id_;
+ // True if all transformations should be compatible with WGSL spec.
+ bool is_wgsl_compatible_;
+
// Probabilities associated with applying various transformations.
// Keep them in alphabetical order.
uint32_t chance_of_accepting_repeated_pass_recommendation_;
diff --git a/source/fuzz/fuzzer_pass_add_access_chains.cpp b/source/fuzz/fuzzer_pass_add_access_chains.cpp
index 11155f23..c498642c 100644
--- a/source/fuzz/fuzzer_pass_add_access_chains.cpp
+++ b/source/fuzz/fuzzer_pass_add_access_chains.cpp
@@ -27,8 +27,6 @@ FuzzerPassAddAccessChains::FuzzerPassAddAccessChains(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddAccessChains::~FuzzerPassAddAccessChains() = default;
-
void FuzzerPassAddAccessChains::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
diff --git a/source/fuzz/fuzzer_pass_add_access_chains.h b/source/fuzz/fuzzer_pass_add_access_chains.h
index 8649296f..e80c2c6c 100644
--- a/source/fuzz/fuzzer_pass_add_access_chains.h
+++ b/source/fuzz/fuzzer_pass_add_access_chains.h
@@ -30,8 +30,6 @@ class FuzzerPassAddAccessChains : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddAccessChains();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.cpp b/source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.cpp
index 7b9ac4e2..b2edc194 100644
--- a/source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.cpp
+++ b/source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.cpp
@@ -28,9 +28,6 @@ FuzzerPassAddBitInstructionSynonyms::FuzzerPassAddBitInstructionSynonyms(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddBitInstructionSynonyms::~FuzzerPassAddBitInstructionSynonyms() =
- default;
-
void FuzzerPassAddBitInstructionSynonyms::Apply() {
for (auto& function : *GetIRContext()->module()) {
for (auto& block : function) {
diff --git a/source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.h b/source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.h
index 0194425d..28f95779 100644
--- a/source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.h
+++ b/source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.h
@@ -30,8 +30,6 @@ class FuzzerPassAddBitInstructionSynonyms : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddBitInstructionSynonyms();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_composite_extract.cpp b/source/fuzz/fuzzer_pass_add_composite_extract.cpp
index 132a49da..19f99024 100644
--- a/source/fuzz/fuzzer_pass_add_composite_extract.cpp
+++ b/source/fuzz/fuzzer_pass_add_composite_extract.cpp
@@ -14,6 +14,7 @@
#include "source/fuzz/fuzzer_pass_add_composite_extract.h"
+#include "source/fuzz/available_instructions.h"
#include "source/fuzz/fuzzer_context.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/instruction_descriptor.h"
@@ -29,8 +30,6 @@ FuzzerPassAddCompositeExtract::FuzzerPassAddCompositeExtract(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddCompositeExtract::~FuzzerPassAddCompositeExtract() = default;
-
void FuzzerPassAddCompositeExtract::Apply() {
std::vector<const protobufs::DataDescriptor*> composite_synonyms;
for (const auto* dd :
@@ -41,14 +40,16 @@ void FuzzerPassAddCompositeExtract::Apply() {
}
}
- // We don't want to invalidate the module every time we apply this
- // transformation since rebuilding DominatorAnalysis can be expensive, so we
- // collect up the transformations we wish to apply and apply them all later.
- std::vector<TransformationCompositeExtract> transformations;
+ AvailableInstructions available_composites(
+ GetIRContext(), [](opt::IRContext* ir_context, opt::Instruction* inst) {
+ return inst->type_id() && inst->result_id() &&
+ fuzzerutil::IsCompositeType(
+ ir_context->get_type_mgr()->GetType(inst->type_id()));
+ });
ForEachInstructionWithInstructionDescriptor(
- [this, &composite_synonyms, &transformations](
- opt::Function* function, opt::BasicBlock* block,
+ [this, &available_composites, &composite_synonyms](
+ opt::Function* /*unused*/, opt::BasicBlock* /*unused*/,
opt::BasicBlock::iterator inst_it,
const protobufs::InstructionDescriptor& instruction_descriptor) {
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
@@ -61,14 +62,6 @@ void FuzzerPassAddCompositeExtract::Apply() {
return;
}
- auto available_composites = FindAvailableInstructions(
- function, block, inst_it,
- [](opt::IRContext* ir_context, opt::Instruction* inst) {
- return inst->type_id() && inst->result_id() &&
- fuzzerutil::IsCompositeType(
- ir_context->get_type_mgr()->GetType(inst->type_id()));
- });
-
std::vector<const protobufs::DataDescriptor*> available_synonyms;
for (const auto* dd : composite_synonyms) {
if (fuzzerutil::IdIsAvailableBeforeInstruction(
@@ -77,18 +70,21 @@ void FuzzerPassAddCompositeExtract::Apply() {
}
}
- if (available_synonyms.empty() && available_composites.empty()) {
+ auto candidate_composites =
+ available_composites.GetAvailableBeforeInstruction(&*inst_it);
+
+ if (available_synonyms.empty() && candidate_composites.empty()) {
return;
}
uint32_t composite_id = 0;
std::vector<uint32_t> indices;
- if (available_synonyms.empty() || (!available_composites.empty() &&
+ if (available_synonyms.empty() || (!candidate_composites.empty() &&
GetFuzzerContext()->ChooseEven())) {
const auto* inst =
- available_composites[GetFuzzerContext()->RandomIndex(
- available_composites)];
+ candidate_composites[GetFuzzerContext()->RandomIndex(
+ candidate_composites)];
composite_id = inst->result_id();
auto type_id = inst->type_id();
@@ -153,14 +149,10 @@ void FuzzerPassAddCompositeExtract::Apply() {
assert(composite_id != 0 && !indices.empty() &&
"Composite object should have been chosen correctly");
- transformations.emplace_back(instruction_descriptor,
- GetFuzzerContext()->GetFreshId(),
- composite_id, indices);
+ ApplyTransformation(TransformationCompositeExtract(
+ instruction_descriptor, GetFuzzerContext()->GetFreshId(),
+ composite_id, indices));
});
-
- for (const auto& transformation : transformations) {
- ApplyTransformation(transformation);
- }
}
} // namespace fuzz
diff --git a/source/fuzz/fuzzer_pass_add_composite_extract.h b/source/fuzz/fuzzer_pass_add_composite_extract.h
index 8bcb825f..32ac190a 100644
--- a/source/fuzz/fuzzer_pass_add_composite_extract.h
+++ b/source/fuzz/fuzzer_pass_add_composite_extract.h
@@ -29,8 +29,6 @@ class FuzzerPassAddCompositeExtract : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddCompositeExtract() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_composite_inserts.cpp b/source/fuzz/fuzzer_pass_add_composite_inserts.cpp
index e58c754c..cf314d30 100644
--- a/source/fuzz/fuzzer_pass_add_composite_inserts.cpp
+++ b/source/fuzz/fuzzer_pass_add_composite_inserts.cpp
@@ -29,8 +29,6 @@ FuzzerPassAddCompositeInserts::FuzzerPassAddCompositeInserts(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddCompositeInserts::~FuzzerPassAddCompositeInserts() = default;
-
void FuzzerPassAddCompositeInserts::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
diff --git a/source/fuzz/fuzzer_pass_add_composite_inserts.h b/source/fuzz/fuzzer_pass_add_composite_inserts.h
index c4f51034..4d511f6c 100644
--- a/source/fuzz/fuzzer_pass_add_composite_inserts.h
+++ b/source/fuzz/fuzzer_pass_add_composite_inserts.h
@@ -29,7 +29,6 @@ class FuzzerPassAddCompositeInserts : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddCompositeInserts();
void Apply() override;
// Checks if any component of a composite is a pointer.
diff --git a/source/fuzz/fuzzer_pass_add_composite_types.cpp b/source/fuzz/fuzzer_pass_add_composite_types.cpp
index c4d8d1c9..3dfbd690 100644
--- a/source/fuzz/fuzzer_pass_add_composite_types.cpp
+++ b/source/fuzz/fuzzer_pass_add_composite_types.cpp
@@ -28,8 +28,6 @@ FuzzerPassAddCompositeTypes::FuzzerPassAddCompositeTypes(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddCompositeTypes::~FuzzerPassAddCompositeTypes() = default;
-
void FuzzerPassAddCompositeTypes::Apply() {
MaybeAddMissingVectorTypes();
MaybeAddMissingMatrixTypes();
@@ -125,7 +123,9 @@ uint32_t FuzzerPassAddCompositeTypes::ChooseScalarOrCompositeType() {
break;
case SpvOpTypeStruct: {
if (!fuzzerutil::MembersHaveBuiltInDecoration(GetIRContext(),
- inst.result_id())) {
+ inst.result_id()) &&
+ !fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(),
+ inst.result_id())) {
candidates.push_back(inst.result_id());
}
} break;
diff --git a/source/fuzz/fuzzer_pass_add_composite_types.h b/source/fuzz/fuzzer_pass_add_composite_types.h
index 87bc0ff3..89d48f8a 100644
--- a/source/fuzz/fuzzer_pass_add_composite_types.h
+++ b/source/fuzz/fuzzer_pass_add_composite_types.h
@@ -29,8 +29,6 @@ class FuzzerPassAddCompositeTypes : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddCompositeTypes();
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_pass_add_copy_memory.cpp b/source/fuzz/fuzzer_pass_add_copy_memory.cpp
index d98619c2..b654927f 100644
--- a/source/fuzz/fuzzer_pass_add_copy_memory.cpp
+++ b/source/fuzz/fuzzer_pass_add_copy_memory.cpp
@@ -29,8 +29,6 @@ FuzzerPassAddCopyMemory::FuzzerPassAddCopyMemory(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddCopyMemory::~FuzzerPassAddCopyMemory() = default;
-
void FuzzerPassAddCopyMemory::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
diff --git a/source/fuzz/fuzzer_pass_add_copy_memory.h b/source/fuzz/fuzzer_pass_add_copy_memory.h
index 321e4a1d..0f7db0c7 100644
--- a/source/fuzz/fuzzer_pass_add_copy_memory.h
+++ b/source/fuzz/fuzzer_pass_add_copy_memory.h
@@ -29,8 +29,6 @@ class FuzzerPassAddCopyMemory : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddCopyMemory() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_dead_blocks.cpp b/source/fuzz/fuzzer_pass_add_dead_blocks.cpp
index 84ed1fb9..8c166a20 100644
--- a/source/fuzz/fuzzer_pass_add_dead_blocks.cpp
+++ b/source/fuzz/fuzzer_pass_add_dead_blocks.cpp
@@ -14,12 +14,20 @@
#include "source/fuzz/fuzzer_pass_add_dead_blocks.h"
+#include <algorithm>
+
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/transformation_add_dead_block.h"
namespace spvtools {
namespace fuzz {
+namespace {
+
+const size_t kMaxTransformationsInOnePass = 100U;
+
+} // namespace
+
FuzzerPassAddDeadBlocks::FuzzerPassAddDeadBlocks(
opt::IRContext* ir_context, TransformationContext* transformation_context,
FuzzerContext* fuzzer_context,
@@ -27,8 +35,6 @@ FuzzerPassAddDeadBlocks::FuzzerPassAddDeadBlocks(
: 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
@@ -57,9 +63,18 @@ void FuzzerPassAddDeadBlocks::Apply() {
GetFuzzerContext()->GetFreshId(), block.id(), condition_value));
}
}
- // Apply all those transformations that are in fact applicable.
- for (auto& transformation : candidate_transformations) {
- MaybeApplyTransformation(transformation);
+ // Applying transformations can be expensive as each transformation requires
+ // dominator information and also invalidates dominator information. We thus
+ // limit the number of transformations that one application of this fuzzer
+ // pass can apply. We choose to do this after identifying all the
+ // transformations that we *might* want to apply, rather than breaking the
+ // above loops once the limit is reached, to avoid biasing towards
+ // transformations that target early parts of the module.
+ GetFuzzerContext()->Shuffle(&candidate_transformations);
+ for (size_t i = 0; i < std::min(kMaxTransformationsInOnePass,
+ candidate_transformations.size());
+ i++) {
+ MaybeApplyTransformation(candidate_transformations[i]);
}
}
diff --git a/source/fuzz/fuzzer_pass_add_dead_blocks.h b/source/fuzz/fuzzer_pass_add_dead_blocks.h
index d78f0883..a87c05c3 100644
--- a/source/fuzz/fuzzer_pass_add_dead_blocks.h
+++ b/source/fuzz/fuzzer_pass_add_dead_blocks.h
@@ -29,8 +29,6 @@ class FuzzerPassAddDeadBlocks : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddDeadBlocks();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_dead_breaks.cpp b/source/fuzz/fuzzer_pass_add_dead_breaks.cpp
index e726c63e..0c18da90 100644
--- a/source/fuzz/fuzzer_pass_add_dead_breaks.cpp
+++ b/source/fuzz/fuzzer_pass_add_dead_breaks.cpp
@@ -28,8 +28,6 @@ FuzzerPassAddDeadBreaks::FuzzerPassAddDeadBreaks(
: 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;
diff --git a/source/fuzz/fuzzer_pass_add_dead_breaks.h b/source/fuzz/fuzzer_pass_add_dead_breaks.h
index c379eed5..d1086fc4 100644
--- a/source/fuzz/fuzzer_pass_add_dead_breaks.h
+++ b/source/fuzz/fuzzer_pass_add_dead_breaks.h
@@ -28,8 +28,6 @@ class FuzzerPassAddDeadBreaks : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddDeadBreaks();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_dead_continues.cpp b/source/fuzz/fuzzer_pass_add_dead_continues.cpp
index 24617ae3..1ab40b73 100644
--- a/source/fuzz/fuzzer_pass_add_dead_continues.cpp
+++ b/source/fuzz/fuzzer_pass_add_dead_continues.cpp
@@ -28,8 +28,6 @@ FuzzerPassAddDeadContinues::FuzzerPassAddDeadContinues(
: 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()) {
diff --git a/source/fuzz/fuzzer_pass_add_dead_continues.h b/source/fuzz/fuzzer_pass_add_dead_continues.h
index b2acb935..bf0009e4 100644
--- a/source/fuzz/fuzzer_pass_add_dead_continues.h
+++ b/source/fuzz/fuzzer_pass_add_dead_continues.h
@@ -28,8 +28,6 @@ class FuzzerPassAddDeadContinues : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddDeadContinues();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_equation_instructions.cpp b/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
index 6376c9fc..15554b7a 100644
--- a/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
+++ b/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
@@ -49,9 +49,6 @@ FuzzerPassAddEquationInstructions::FuzzerPassAddEquationInstructions(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddEquationInstructions::~FuzzerPassAddEquationInstructions() =
- default;
-
void FuzzerPassAddEquationInstructions::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
diff --git a/source/fuzz/fuzzer_pass_add_equation_instructions.h b/source/fuzz/fuzzer_pass_add_equation_instructions.h
index 9ce581eb..dbec5bac 100644
--- a/source/fuzz/fuzzer_pass_add_equation_instructions.h
+++ b/source/fuzz/fuzzer_pass_add_equation_instructions.h
@@ -31,8 +31,6 @@ class FuzzerPassAddEquationInstructions : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddEquationInstructions();
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_pass_add_function_calls.cpp b/source/fuzz/fuzzer_pass_add_function_calls.cpp
index 74005579..2240696b 100644
--- a/source/fuzz/fuzzer_pass_add_function_calls.cpp
+++ b/source/fuzz/fuzzer_pass_add_function_calls.cpp
@@ -30,8 +30,6 @@ FuzzerPassAddFunctionCalls::FuzzerPassAddFunctionCalls(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddFunctionCalls::~FuzzerPassAddFunctionCalls() = default;
-
void FuzzerPassAddFunctionCalls::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
diff --git a/source/fuzz/fuzzer_pass_add_function_calls.h b/source/fuzz/fuzzer_pass_add_function_calls.h
index 4ed87911..081510c1 100644
--- a/source/fuzz/fuzzer_pass_add_function_calls.h
+++ b/source/fuzz/fuzzer_pass_add_function_calls.h
@@ -29,8 +29,6 @@ class FuzzerPassAddFunctionCalls : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddFunctionCalls();
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_pass_add_global_variables.cpp b/source/fuzz/fuzzer_pass_add_global_variables.cpp
index 9a45a374..06797413 100644
--- a/source/fuzz/fuzzer_pass_add_global_variables.cpp
+++ b/source/fuzz/fuzzer_pass_add_global_variables.cpp
@@ -27,8 +27,6 @@ FuzzerPassAddGlobalVariables::FuzzerPassAddGlobalVariables(
: 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()) {
diff --git a/source/fuzz/fuzzer_pass_add_global_variables.h b/source/fuzz/fuzzer_pass_add_global_variables.h
index a907d360..3745c5c3 100644
--- a/source/fuzz/fuzzer_pass_add_global_variables.h
+++ b/source/fuzz/fuzzer_pass_add_global_variables.h
@@ -29,8 +29,6 @@ class FuzzerPassAddGlobalVariables : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddGlobalVariables();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_image_sample_unused_components.cpp b/source/fuzz/fuzzer_pass_add_image_sample_unused_components.cpp
index 3095bb6e..c10db720 100644
--- a/source/fuzz/fuzzer_pass_add_image_sample_unused_components.cpp
+++ b/source/fuzz/fuzzer_pass_add_image_sample_unused_components.cpp
@@ -31,9 +31,6 @@ FuzzerPassAddImageSampleUnusedComponents::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddImageSampleUnusedComponents::
- ~FuzzerPassAddImageSampleUnusedComponents() = default;
-
void FuzzerPassAddImageSampleUnusedComponents::Apply() {
// SPIR-V module to help understand the transformation.
//
diff --git a/source/fuzz/fuzzer_pass_add_image_sample_unused_components.h b/source/fuzz/fuzzer_pass_add_image_sample_unused_components.h
index 26374c32..f5dea8bf 100644
--- a/source/fuzz/fuzzer_pass_add_image_sample_unused_components.h
+++ b/source/fuzz/fuzzer_pass_add_image_sample_unused_components.h
@@ -30,8 +30,6 @@ class FuzzerPassAddImageSampleUnusedComponents : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddImageSampleUnusedComponents();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_loads.cpp b/source/fuzz/fuzzer_pass_add_loads.cpp
index 256255bc..2e50da26 100644
--- a/source/fuzz/fuzzer_pass_add_loads.cpp
+++ b/source/fuzz/fuzzer_pass_add_loads.cpp
@@ -27,8 +27,6 @@ FuzzerPassAddLoads::FuzzerPassAddLoads(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddLoads::~FuzzerPassAddLoads() = default;
-
void FuzzerPassAddLoads::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
diff --git a/source/fuzz/fuzzer_pass_add_loads.h b/source/fuzz/fuzzer_pass_add_loads.h
index c4d5b27e..3913c624 100644
--- a/source/fuzz/fuzzer_pass_add_loads.h
+++ b/source/fuzz/fuzzer_pass_add_loads.h
@@ -28,8 +28,6 @@ class FuzzerPassAddLoads : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddLoads();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_local_variables.cpp b/source/fuzz/fuzzer_pass_add_local_variables.cpp
index ef8b5d0e..a50b0b07 100644
--- a/source/fuzz/fuzzer_pass_add_local_variables.cpp
+++ b/source/fuzz/fuzzer_pass_add_local_variables.cpp
@@ -28,8 +28,6 @@ FuzzerPassAddLocalVariables::FuzzerPassAddLocalVariables(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddLocalVariables::~FuzzerPassAddLocalVariables() = default;
-
void FuzzerPassAddLocalVariables::Apply() {
auto basic_type_ids_and_pointers =
GetAvailableBasicTypesAndPointers(SpvStorageClassFunction);
diff --git a/source/fuzz/fuzzer_pass_add_local_variables.h b/source/fuzz/fuzzer_pass_add_local_variables.h
index 08d26d8c..d73dae29 100644
--- a/source/fuzz/fuzzer_pass_add_local_variables.h
+++ b/source/fuzz/fuzzer_pass_add_local_variables.h
@@ -29,8 +29,6 @@ class FuzzerPassAddLocalVariables : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddLocalVariables();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_loop_preheaders.cpp b/source/fuzz/fuzzer_pass_add_loop_preheaders.cpp
index bdc31513..1cfed866 100644
--- a/source/fuzz/fuzzer_pass_add_loop_preheaders.cpp
+++ b/source/fuzz/fuzzer_pass_add_loop_preheaders.cpp
@@ -27,8 +27,6 @@ FuzzerPassAddLoopPreheaders::FuzzerPassAddLoopPreheaders(
: 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.
diff --git a/source/fuzz/fuzzer_pass_add_loop_preheaders.h b/source/fuzz/fuzzer_pass_add_loop_preheaders.h
index a8350567..8ac2dac8 100644
--- a/source/fuzz/fuzzer_pass_add_loop_preheaders.h
+++ b/source/fuzz/fuzzer_pass_add_loop_preheaders.h
@@ -32,8 +32,6 @@ class FuzzerPassAddLoopPreheaders : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddLoopPreheaders();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_loops_to_create_int_constant_synonyms.cpp b/source/fuzz/fuzzer_pass_add_loops_to_create_int_constant_synonyms.cpp
index 31a57798..69e0697f 100644
--- a/source/fuzz/fuzzer_pass_add_loops_to_create_int_constant_synonyms.cpp
+++ b/source/fuzz/fuzzer_pass_add_loops_to_create_int_constant_synonyms.cpp
@@ -33,9 +33,6 @@ FuzzerPassAddLoopsToCreateIntConstantSynonyms::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddLoopsToCreateIntConstantSynonyms::
- ~FuzzerPassAddLoopsToCreateIntConstantSynonyms() = default;
-
void FuzzerPassAddLoopsToCreateIntConstantSynonyms::Apply() {
std::vector<uint32_t> constants;
diff --git a/source/fuzz/fuzzer_pass_add_loops_to_create_int_constant_synonyms.h b/source/fuzz/fuzzer_pass_add_loops_to_create_int_constant_synonyms.h
index ee98c4e7..2eacef5f 100644
--- a/source/fuzz/fuzzer_pass_add_loops_to_create_int_constant_synonyms.h
+++ b/source/fuzz/fuzzer_pass_add_loops_to_create_int_constant_synonyms.h
@@ -30,8 +30,6 @@ class FuzzerPassAddLoopsToCreateIntConstantSynonyms : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddLoopsToCreateIntConstantSynonyms();
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp b/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp
index 09627d09..d0753100 100644
--- a/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp
+++ b/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp
@@ -26,9 +26,6 @@ FuzzerPassAddNoContractionDecorations::FuzzerPassAddNoContractionDecorations(
: 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()) {
diff --git a/source/fuzz/fuzzer_pass_add_no_contraction_decorations.h b/source/fuzz/fuzzer_pass_add_no_contraction_decorations.h
index c0c1e09d..74212d87 100644
--- a/source/fuzz/fuzzer_pass_add_no_contraction_decorations.h
+++ b/source/fuzz/fuzzer_pass_add_no_contraction_decorations.h
@@ -28,8 +28,6 @@ class FuzzerPassAddNoContractionDecorations : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddNoContractionDecorations() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp b/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp
index 2b339ca0..be6e7ea1 100644
--- a/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp
+++ b/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp
@@ -27,8 +27,6 @@ FuzzerPassAddOpPhiSynonyms::FuzzerPassAddOpPhiSynonyms(
: 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.
diff --git a/source/fuzz/fuzzer_pass_add_opphi_synonyms.h b/source/fuzz/fuzzer_pass_add_opphi_synonyms.h
index 6c7d7522..9077118e 100644
--- a/source/fuzz/fuzzer_pass_add_opphi_synonyms.h
+++ b/source/fuzz/fuzzer_pass_add_opphi_synonyms.h
@@ -30,8 +30,6 @@ class FuzzerPassAddOpPhiSynonyms : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddOpPhiSynonyms() override;
-
void Apply() override;
// Computes the equivalence classes for the non-pointer and non-irrelevant ids
diff --git a/source/fuzz/fuzzer_pass_add_parameters.cpp b/source/fuzz/fuzzer_pass_add_parameters.cpp
index 35532e90..784653d8 100644
--- a/source/fuzz/fuzzer_pass_add_parameters.cpp
+++ b/source/fuzz/fuzzer_pass_add_parameters.cpp
@@ -29,8 +29,6 @@ FuzzerPassAddParameters::FuzzerPassAddParameters(
: 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;
diff --git a/source/fuzz/fuzzer_pass_add_parameters.h b/source/fuzz/fuzzer_pass_add_parameters.h
index f1261ae5..47dde390 100644
--- a/source/fuzz/fuzzer_pass_add_parameters.h
+++ b/source/fuzz/fuzzer_pass_add_parameters.h
@@ -32,8 +32,6 @@ class FuzzerPassAddParameters : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddParameters() override;
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_pass_add_relaxed_decorations.cpp b/source/fuzz/fuzzer_pass_add_relaxed_decorations.cpp
index a2497df7..58c6d1b2 100644
--- a/source/fuzz/fuzzer_pass_add_relaxed_decorations.cpp
+++ b/source/fuzz/fuzzer_pass_add_relaxed_decorations.cpp
@@ -26,8 +26,6 @@ FuzzerPassAddRelaxedDecorations::FuzzerPassAddRelaxedDecorations(
: 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()) {
diff --git a/source/fuzz/fuzzer_pass_add_relaxed_decorations.h b/source/fuzz/fuzzer_pass_add_relaxed_decorations.h
index 897b8216..723c4a0a 100644
--- a/source/fuzz/fuzzer_pass_add_relaxed_decorations.h
+++ b/source/fuzz/fuzzer_pass_add_relaxed_decorations.h
@@ -28,8 +28,6 @@ class FuzzerPassAddRelaxedDecorations : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddRelaxedDecorations() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_stores.cpp b/source/fuzz/fuzzer_pass_add_stores.cpp
index 46efc643..f89428d3 100644
--- a/source/fuzz/fuzzer_pass_add_stores.cpp
+++ b/source/fuzz/fuzzer_pass_add_stores.cpp
@@ -27,8 +27,6 @@ FuzzerPassAddStores::FuzzerPassAddStores(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddStores::~FuzzerPassAddStores() = default;
-
void FuzzerPassAddStores::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
diff --git a/source/fuzz/fuzzer_pass_add_stores.h b/source/fuzz/fuzzer_pass_add_stores.h
index 55ec67f2..9519c385 100644
--- a/source/fuzz/fuzzer_pass_add_stores.h
+++ b/source/fuzz/fuzzer_pass_add_stores.h
@@ -30,8 +30,6 @@ class FuzzerPassAddStores : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddStores();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_synonyms.cpp b/source/fuzz/fuzzer_pass_add_synonyms.cpp
index 2fa07000..2a85e52c 100644
--- a/source/fuzz/fuzzer_pass_add_synonyms.cpp
+++ b/source/fuzz/fuzzer_pass_add_synonyms.cpp
@@ -29,8 +29,6 @@ FuzzerPassAddSynonyms::FuzzerPassAddSynonyms(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddSynonyms::~FuzzerPassAddSynonyms() = default;
-
void FuzzerPassAddSynonyms::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
diff --git a/source/fuzz/fuzzer_pass_add_synonyms.h b/source/fuzz/fuzzer_pass_add_synonyms.h
index dcfb9389..ccf4a886 100644
--- a/source/fuzz/fuzzer_pass_add_synonyms.h
+++ b/source/fuzz/fuzzer_pass_add_synonyms.h
@@ -29,8 +29,6 @@ class FuzzerPassAddSynonyms : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddSynonyms() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp b/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp
index 453448ba..e2eaaa0a 100644
--- a/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp
+++ b/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp
@@ -28,9 +28,6 @@ FuzzerPassAddVectorShuffleInstructions::FuzzerPassAddVectorShuffleInstructions(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAddVectorShuffleInstructions::
- ~FuzzerPassAddVectorShuffleInstructions() = default;
-
void FuzzerPassAddVectorShuffleInstructions::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
diff --git a/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.h b/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.h
index 99b9f244..c5af374c 100644
--- a/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.h
+++ b/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.h
@@ -28,8 +28,6 @@ class FuzzerPassAddVectorShuffleInstructions : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAddVectorShuffleInstructions();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp b/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp
index 1d6d4347..3c4f3803 100644
--- a/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp
+++ b/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp
@@ -28,8 +28,6 @@ FuzzerPassAdjustBranchWeights::FuzzerPassAdjustBranchWeights(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassAdjustBranchWeights::~FuzzerPassAdjustBranchWeights() = default;
-
void FuzzerPassAdjustBranchWeights::Apply() {
// For all OpBranchConditional instructions,
// randomly applies the transformation.
diff --git a/source/fuzz/fuzzer_pass_adjust_branch_weights.h b/source/fuzz/fuzzer_pass_adjust_branch_weights.h
index 5b2b33f1..de2f33d3 100644
--- a/source/fuzz/fuzzer_pass_adjust_branch_weights.h
+++ b/source/fuzz/fuzzer_pass_adjust_branch_weights.h
@@ -30,8 +30,6 @@ class FuzzerPassAdjustBranchWeights : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAdjustBranchWeights();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_adjust_function_controls.cpp b/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
index aa62d2f8..b38bd212 100644
--- a/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
+++ b/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
@@ -26,8 +26,6 @@ FuzzerPassAdjustFunctionControls::FuzzerPassAdjustFunctionControls(
: 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()) {
diff --git a/source/fuzz/fuzzer_pass_adjust_function_controls.h b/source/fuzz/fuzzer_pass_adjust_function_controls.h
index 5fdbe432..5ef32a18 100644
--- a/source/fuzz/fuzzer_pass_adjust_function_controls.h
+++ b/source/fuzz/fuzzer_pass_adjust_function_controls.h
@@ -28,8 +28,6 @@ class FuzzerPassAdjustFunctionControls : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAdjustFunctionControls() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp b/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
index f7addffe..0f7cf037 100644
--- a/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
+++ b/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
@@ -26,8 +26,6 @@ FuzzerPassAdjustLoopControls::FuzzerPassAdjustLoopControls(
: 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).
diff --git a/source/fuzz/fuzzer_pass_adjust_loop_controls.h b/source/fuzz/fuzzer_pass_adjust_loop_controls.h
index f133b2d1..4ca670b7 100644
--- a/source/fuzz/fuzzer_pass_adjust_loop_controls.h
+++ b/source/fuzz/fuzzer_pass_adjust_loop_controls.h
@@ -28,8 +28,6 @@ class FuzzerPassAdjustLoopControls : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAdjustLoopControls() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp b/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
index 68f0ca7e..778d43ff 100644
--- a/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
+++ b/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
@@ -27,9 +27,6 @@ FuzzerPassAdjustMemoryOperandsMasks::FuzzerPassAdjustMemoryOperandsMasks(
: 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()) {
diff --git a/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h b/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h
index 699dcb5a..a068b8dd 100644
--- a/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h
+++ b/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h
@@ -29,8 +29,6 @@ class FuzzerPassAdjustMemoryOperandsMasks : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAdjustMemoryOperandsMasks();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp b/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
index 83b1854e..d9b4e293 100644
--- a/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
+++ b/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
@@ -26,9 +26,6 @@ FuzzerPassAdjustSelectionControls::FuzzerPassAdjustSelectionControls(
: 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).
diff --git a/source/fuzz/fuzzer_pass_adjust_selection_controls.h b/source/fuzz/fuzzer_pass_adjust_selection_controls.h
index 910b40d6..6931f942 100644
--- a/source/fuzz/fuzzer_pass_adjust_selection_controls.h
+++ b/source/fuzz/fuzzer_pass_adjust_selection_controls.h
@@ -28,8 +28,6 @@ class FuzzerPassAdjustSelectionControls : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassAdjustSelectionControls() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp b/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
index 38553d25..71208313 100644
--- a/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
+++ b/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
@@ -32,8 +32,6 @@ FuzzerPassApplyIdSynonyms::FuzzerPassApplyIdSynonyms(
: 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.
diff --git a/source/fuzz/fuzzer_pass_apply_id_synonyms.h b/source/fuzz/fuzzer_pass_apply_id_synonyms.h
index 5deac105..b402b509 100644
--- a/source/fuzz/fuzzer_pass_apply_id_synonyms.h
+++ b/source/fuzz/fuzzer_pass_apply_id_synonyms.h
@@ -30,8 +30,6 @@ class FuzzerPassApplyIdSynonyms : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassApplyIdSynonyms() override;
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_pass_construct_composites.cpp b/source/fuzz/fuzzer_pass_construct_composites.cpp
index 584fa1a9..1a174cf1 100644
--- a/source/fuzz/fuzzer_pass_construct_composites.cpp
+++ b/source/fuzz/fuzzer_pass_construct_composites.cpp
@@ -16,6 +16,7 @@
#include <memory>
+#include "source/fuzz/available_instructions.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/transformation_composite_construct.h"
@@ -29,8 +30,6 @@ FuzzerPassConstructComposites::FuzzerPassConstructComposites(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassConstructComposites::~FuzzerPassConstructComposites() = default;
-
void FuzzerPassConstructComposites::Apply() {
// Gather up the ids of all composite types, but skip block-/buffer
// block-decorated struct types.
@@ -44,12 +43,40 @@ void FuzzerPassConstructComposites::Apply() {
}
}
+ if (composite_type_ids.empty()) {
+ // There are no composite types, so this fuzzer pass cannot do anything.
+ return;
+ }
+
+ AvailableInstructions available_composite_constituents(
+ GetIRContext(),
+ [this](opt::IRContext* ir_context, opt::Instruction* inst) -> bool {
+ 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);
+ });
+
ForEachInstructionWithInstructionDescriptor(
- [this, &composite_type_ids](
- opt::Function* function, opt::BasicBlock* block,
+ [this, &available_composite_constituents, &composite_type_ids](
+ opt::Function* /*unused*/, opt::BasicBlock* /*unused*/,
opt::BasicBlock::iterator inst_it,
const protobufs::InstructionDescriptor& instruction_descriptor)
-> void {
+ // Randomly decide whether to try inserting a composite construction
+ // here.
+ if (!GetFuzzerContext()->ChoosePercentage(
+ GetFuzzerContext()->GetChanceOfConstructingComposite())) {
+ return;
+ }
+
// Check whether it is legitimate to insert a composite construction
// before the instruction.
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
@@ -57,36 +84,21 @@ void FuzzerPassConstructComposites::Apply() {
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);
+ auto available_instructions =
+ available_composite_constituents.GetAvailableBeforeInstruction(
+ &*inst_it);
+ for (uint32_t available_instruction_index = 0;
+ available_instruction_index < available_instructions.size();
+ available_instruction_index++) {
+ opt::Instruction* inst =
+ available_instructions[available_instruction_index];
+ type_id_to_available_instructions[inst->type_id()].push_back(
+ inst->result_id());
}
// At this point, |composite_type_ids| captures all the composite types
@@ -94,68 +106,41 @@ void FuzzerPassConstructComposites::Apply() {
// 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;
+ // Now we choose a composite type to construct, building it from
+ // available constituent components and using zero constants if suitable
+ // components are not available.
- // 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;
+ std::vector<uint32_t> constructor_arguments;
+ uint32_t chosen_composite_type =
+ composite_type_ids[GetFuzzerContext()->RandomIndex(
+ composite_type_ids)];
+
+ // 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(chosen_composite_type);
+ 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 (!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());
@@ -166,15 +151,6 @@ void FuzzerPassConstructComposites::Apply() {
});
}
-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,
@@ -190,13 +166,6 @@ FuzzerPassConstructComposites::FindComponentsToConstructArray(
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()
@@ -205,10 +174,14 @@ FuzzerPassConstructComposites::FindComponentsToConstructArray(
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());
+ if (available_instructions == type_id_to_available_instructions.cend()) {
+ // No suitable instructions are available, so use a zero constant
+ result.push_back(FindOrCreateZeroConstant(element_type_id, true));
+ } else {
+ result.push_back(
+ available_instructions->second[GetFuzzerContext()->RandomIndex(
+ available_instructions->second)]);
+ }
}
return result;
}
@@ -228,19 +201,17 @@ FuzzerPassConstructComposites::FindComponentsToConstructMatrix(
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());
+ if (available_instructions == type_id_to_available_instructions.cend()) {
+ // No suitable components are available, so use a zero constant.
+ result.push_back(FindOrCreateZeroConstant(element_type_id, true));
+ } else {
+ result.push_back(
+ available_instructions->second[GetFuzzerContext()->RandomIndex(
+ available_instructions->second)]);
+ }
}
return result;
}
@@ -263,14 +234,14 @@ FuzzerPassConstructComposites::FindComponentsToConstructStruct(
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 {};
+ // No suitable component is available for this element type, so use a zero
+ // constant.
+ result.push_back(FindOrCreateZeroConstant(element_type_id, true));
+ } else {
+ result.push_back(
+ available_instructions->second[GetFuzzerContext()->RandomIndex(
+ available_instructions->second)]);
}
- result.push_back(available_instructions
- ->second[GetFuzzerContext()->RandomIndex(
- available_instructions->second)]
- ->result_id());
}
return result;
}
@@ -325,12 +296,13 @@ FuzzerPassConstructComposites::FindComponentsToConstructVector(
// (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;
+
+ // The instructions result ids we will use to construct the vector, in no
+ // particular order at this stage.
+ std::vector<uint32_t> result;
while (vector_slots_used < element_count) {
- std::vector<opt::Instruction*> instructions_to_choose_from;
+ std::vector<uint32_t> 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)) {
@@ -345,19 +317,16 @@ FuzzerPassConstructComposites::FindComponentsToConstructVector(
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);
+ // If there are no instructions to choose from then use a zero constant,
+ // otherwise select one of the instructions at random.
+ uint32_t id_of_instruction_to_use =
+ instructions_to_choose_from.empty()
+ ? FindOrCreateZeroConstant(element_type_id, true)
+ : instructions_to_choose_from[GetFuzzerContext()->RandomIndex(
+ instructions_to_choose_from)];
+ opt::Instruction* instruction_to_use =
+ GetIRContext()->get_def_use_mgr()->GetDef(id_of_instruction_to_use);
+ result.push_back(instruction_to_use->result_id());
auto chosen_type =
GetIRContext()->get_type_mgr()->GetType(instruction_to_use->type_id());
if (chosen_type->AsVector()) {
@@ -373,14 +342,7 @@ FuzzerPassConstructComposites::FindComponentsToConstructVector(
}
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);
+ GetFuzzerContext()->Shuffle(&result);
return result;
}
diff --git a/source/fuzz/fuzzer_pass_construct_composites.h b/source/fuzz/fuzzer_pass_construct_composites.h
index c140bded..333ac931 100644
--- a/source/fuzz/fuzzer_pass_construct_composites.h
+++ b/source/fuzz/fuzzer_pass_construct_composites.h
@@ -15,7 +15,7 @@
#ifndef SOURCE_FUZZ_FUZZER_PASS_CONSTRUCT_COMPOSITES_H_
#define SOURCE_FUZZ_FUZZER_PASS_CONSTRUCT_COMPOSITES_H_
-#include <map>
+#include <unordered_map>
#include <vector>
#include "source/fuzz/fuzzer_pass.h"
@@ -31,23 +31,12 @@ class FuzzerPassConstructComposites : public FuzzerPass {
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);
+ // Used to map a type id to the ids of relevant instructions of the type.
+ using TypeIdToInstructions =
+ std::unordered_map<uint32_t, std::vector<uint32_t>>;
// Requires that |array_type_instruction| has opcode OpTypeArray.
// Attempts to find suitable instruction result ids from the values of
diff --git a/source/fuzz/fuzzer_pass_copy_objects.cpp b/source/fuzz/fuzzer_pass_copy_objects.cpp
index 9f7bbd63..09b5368a 100644
--- a/source/fuzz/fuzzer_pass_copy_objects.cpp
+++ b/source/fuzz/fuzzer_pass_copy_objects.cpp
@@ -28,8 +28,6 @@ FuzzerPassCopyObjects::FuzzerPassCopyObjects(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassCopyObjects::~FuzzerPassCopyObjects() = default;
-
void FuzzerPassCopyObjects::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
diff --git a/source/fuzz/fuzzer_pass_copy_objects.h b/source/fuzz/fuzzer_pass_copy_objects.h
index 8de382e7..461cd979 100644
--- a/source/fuzz/fuzzer_pass_copy_objects.h
+++ b/source/fuzz/fuzzer_pass_copy_objects.h
@@ -28,8 +28,6 @@ class FuzzerPassCopyObjects : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassCopyObjects();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_donate_modules.cpp b/source/fuzz/fuzzer_pass_donate_modules.cpp
index 4cd48045..2f2ed50a 100644
--- a/source/fuzz/fuzzer_pass_donate_modules.cpp
+++ b/source/fuzz/fuzzer_pass_donate_modules.cpp
@@ -50,8 +50,6 @@ FuzzerPassDonateModules::FuzzerPassDonateModules(
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()) {
@@ -1202,11 +1200,14 @@ bool FuzzerPassDonateModules::MaybeAddLivesafeFunction(
false);
}
- // Add the function in a livesafe manner.
- ApplyTransformation(TransformationAddFunction(
+ // Try to add the function in a livesafe manner. This may fail due to edge
+ // cases, e.g. where adding loop limiters changes dominance such that the
+ // module becomes invalid. It would be ideal to handle all such edge cases,
+ // but as they are rare it is more pragmatic to bail out of making the
+ // function livesafe if the transformation's precondition fails to hold.
+ return MaybeApplyTransformation(TransformationAddFunction(
donated_instructions, loop_limiter_variable_id, loop_limit, loop_limiters,
kill_unreachable_return_value_id, access_chain_clamping_info));
- return true;
}
} // namespace fuzz
diff --git a/source/fuzz/fuzzer_pass_donate_modules.h b/source/fuzz/fuzzer_pass_donate_modules.h
index 0424cece..1581a8a4 100644
--- a/source/fuzz/fuzzer_pass_donate_modules.h
+++ b/source/fuzz/fuzzer_pass_donate_modules.h
@@ -33,8 +33,6 @@ class FuzzerPassDonateModules : public FuzzerPass {
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
diff --git a/source/fuzz/fuzzer_pass_duplicate_regions_with_selections.cpp b/source/fuzz/fuzzer_pass_duplicate_regions_with_selections.cpp
index 1651a9d5..e08d65b1 100644
--- a/source/fuzz/fuzzer_pass_duplicate_regions_with_selections.cpp
+++ b/source/fuzz/fuzzer_pass_duplicate_regions_with_selections.cpp
@@ -29,9 +29,6 @@ FuzzerPassDuplicateRegionsWithSelections::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassDuplicateRegionsWithSelections::
- ~FuzzerPassDuplicateRegionsWithSelections() = default;
-
void FuzzerPassDuplicateRegionsWithSelections::Apply() {
// Iterate over all of the functions in the module.
for (auto& function : *GetIRContext()->module()) {
diff --git a/source/fuzz/fuzzer_pass_duplicate_regions_with_selections.h b/source/fuzz/fuzzer_pass_duplicate_regions_with_selections.h
index 3fae6983..7cb1197d 100644
--- a/source/fuzz/fuzzer_pass_duplicate_regions_with_selections.h
+++ b/source/fuzz/fuzzer_pass_duplicate_regions_with_selections.h
@@ -31,8 +31,6 @@ class FuzzerPassDuplicateRegionsWithSelections : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassDuplicateRegionsWithSelections() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_expand_vector_reductions.cpp b/source/fuzz/fuzzer_pass_expand_vector_reductions.cpp
index 1416fe0b..e25dcbc3 100644
--- a/source/fuzz/fuzzer_pass_expand_vector_reductions.cpp
+++ b/source/fuzz/fuzzer_pass_expand_vector_reductions.cpp
@@ -28,8 +28,6 @@ FuzzerPassExpandVectorReductions::FuzzerPassExpandVectorReductions(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassExpandVectorReductions::~FuzzerPassExpandVectorReductions() = default;
-
void FuzzerPassExpandVectorReductions::Apply() {
for (auto& function : *GetIRContext()->module()) {
for (auto& block : function) {
diff --git a/source/fuzz/fuzzer_pass_expand_vector_reductions.h b/source/fuzz/fuzzer_pass_expand_vector_reductions.h
index ae3238b6..ed0225df 100644
--- a/source/fuzz/fuzzer_pass_expand_vector_reductions.h
+++ b/source/fuzz/fuzzer_pass_expand_vector_reductions.h
@@ -30,8 +30,6 @@ class FuzzerPassExpandVectorReductions : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassExpandVectorReductions();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp b/source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp
index 1e21aa50..84da7a74 100644
--- a/source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp
+++ b/source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp
@@ -30,9 +30,6 @@ FuzzerPassFlattenConditionalBranches::FuzzerPassFlattenConditionalBranches(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassFlattenConditionalBranches::~FuzzerPassFlattenConditionalBranches() =
- default;
-
void FuzzerPassFlattenConditionalBranches::Apply() {
for (auto& function : *GetIRContext()->module()) {
// Get all the selection headers that we want to flatten. We need to collect
diff --git a/source/fuzz/fuzzer_pass_flatten_conditional_branches.h b/source/fuzz/fuzzer_pass_flatten_conditional_branches.h
index 76f7782c..e7d7dc36 100644
--- a/source/fuzz/fuzzer_pass_flatten_conditional_branches.h
+++ b/source/fuzz/fuzzer_pass_flatten_conditional_branches.h
@@ -27,8 +27,6 @@ class FuzzerPassFlattenConditionalBranches : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassFlattenConditionalBranches() override;
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_pass_inline_functions.cpp b/source/fuzz/fuzzer_pass_inline_functions.cpp
index 90160d83..405afd8b 100644
--- a/source/fuzz/fuzzer_pass_inline_functions.cpp
+++ b/source/fuzz/fuzzer_pass_inline_functions.cpp
@@ -29,8 +29,6 @@ FuzzerPassInlineFunctions::FuzzerPassInlineFunctions(
: 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.
diff --git a/source/fuzz/fuzzer_pass_inline_functions.h b/source/fuzz/fuzzer_pass_inline_functions.h
index 37295d1c..a6ed8cad 100644
--- a/source/fuzz/fuzzer_pass_inline_functions.h
+++ b/source/fuzz/fuzzer_pass_inline_functions.h
@@ -30,8 +30,6 @@ class FuzzerPassInlineFunctions : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassInlineFunctions() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.cpp b/source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.cpp
index 0e40b496..675cae9a 100644
--- a/source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.cpp
+++ b/source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.cpp
@@ -31,10 +31,10 @@ FuzzerPassInterchangeSignednessOfIntegerOperands::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassInterchangeSignednessOfIntegerOperands::
- ~FuzzerPassInterchangeSignednessOfIntegerOperands() = default;
-
void FuzzerPassInterchangeSignednessOfIntegerOperands::Apply() {
+ assert(!GetFuzzerContext()->IsWgslCompatible() &&
+ "Cannot interchange signedness in WGSL");
+
// 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
diff --git a/source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.h b/source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.h
index 06882f47..11b8fb6e 100644
--- a/source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.h
+++ b/source/fuzz/fuzzer_pass_interchange_signedness_of_integer_operands.h
@@ -34,8 +34,6 @@ class FuzzerPassInterchangeSignednessOfIntegerOperands : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassInterchangeSignednessOfIntegerOperands() override;
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_pass_interchange_zero_like_constants.cpp b/source/fuzz/fuzzer_pass_interchange_zero_like_constants.cpp
index 20575e11..5d0a2223 100644
--- a/source/fuzz/fuzzer_pass_interchange_zero_like_constants.cpp
+++ b/source/fuzz/fuzzer_pass_interchange_zero_like_constants.cpp
@@ -29,9 +29,6 @@ FuzzerPassInterchangeZeroLikeConstants::FuzzerPassInterchangeZeroLikeConstants(
: 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
diff --git a/source/fuzz/fuzzer_pass_interchange_zero_like_constants.h b/source/fuzz/fuzzer_pass_interchange_zero_like_constants.h
index ef0f7655..012f03d3 100644
--- a/source/fuzz/fuzzer_pass_interchange_zero_like_constants.h
+++ b/source/fuzz/fuzzer_pass_interchange_zero_like_constants.h
@@ -35,8 +35,6 @@ class FuzzerPassInterchangeZeroLikeConstants : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassInterchangeZeroLikeConstants() override;
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_pass_invert_comparison_operators.cpp b/source/fuzz/fuzzer_pass_invert_comparison_operators.cpp
index de4ff1de..542748e9 100644
--- a/source/fuzz/fuzzer_pass_invert_comparison_operators.cpp
+++ b/source/fuzz/fuzzer_pass_invert_comparison_operators.cpp
@@ -28,9 +28,6 @@ FuzzerPassInvertComparisonOperators::FuzzerPassInvertComparisonOperators(
: 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(
diff --git a/source/fuzz/fuzzer_pass_invert_comparison_operators.h b/source/fuzz/fuzzer_pass_invert_comparison_operators.h
index 9c80bbbb..5f015c28 100644
--- a/source/fuzz/fuzzer_pass_invert_comparison_operators.h
+++ b/source/fuzz/fuzzer_pass_invert_comparison_operators.h
@@ -29,8 +29,6 @@ class FuzzerPassInvertComparisonOperators : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassInvertComparisonOperators() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp b/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp
index f4f2a802..7bf07a49 100644
--- a/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp
+++ b/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp
@@ -28,9 +28,6 @@ FuzzerPassMakeVectorOperationsDynamic::FuzzerPassMakeVectorOperationsDynamic(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassMakeVectorOperationsDynamic::
- ~FuzzerPassMakeVectorOperationsDynamic() = default;
-
void FuzzerPassMakeVectorOperationsDynamic::Apply() {
for (auto& function : *GetIRContext()->module()) {
for (auto& block : function) {
diff --git a/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.h b/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.h
index dd51cde7..da27825a 100644
--- a/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.h
+++ b/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.h
@@ -29,8 +29,6 @@ class FuzzerPassMakeVectorOperationsDynamic : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassMakeVectorOperationsDynamic() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_merge_blocks.cpp b/source/fuzz/fuzzer_pass_merge_blocks.cpp
index e66fc444..a8ec784c 100644
--- a/source/fuzz/fuzzer_pass_merge_blocks.cpp
+++ b/source/fuzz/fuzzer_pass_merge_blocks.cpp
@@ -28,8 +28,6 @@ FuzzerPassMergeBlocks::FuzzerPassMergeBlocks(
: 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.
diff --git a/source/fuzz/fuzzer_pass_merge_blocks.h b/source/fuzz/fuzzer_pass_merge_blocks.h
index 1a6c2c27..66cf4c64 100644
--- a/source/fuzz/fuzzer_pass_merge_blocks.h
+++ b/source/fuzz/fuzzer_pass_merge_blocks.h
@@ -28,8 +28,6 @@ class FuzzerPassMergeBlocks : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassMergeBlocks();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_merge_function_returns.cpp b/source/fuzz/fuzzer_pass_merge_function_returns.cpp
index fc9c74d0..70fa8200 100644
--- a/source/fuzz/fuzzer_pass_merge_function_returns.cpp
+++ b/source/fuzz/fuzzer_pass_merge_function_returns.cpp
@@ -30,8 +30,6 @@ FuzzerPassMergeFunctionReturns::FuzzerPassMergeFunctionReturns(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassMergeFunctionReturns::~FuzzerPassMergeFunctionReturns() = default;
-
void FuzzerPassMergeFunctionReturns::Apply() {
// The pass might add new functions to the module (due to wrapping early
// terminator instructions in function calls), so we record the functions that
diff --git a/source/fuzz/fuzzer_pass_merge_function_returns.h b/source/fuzz/fuzzer_pass_merge_function_returns.h
index 3b5a668f..ddd2c9dc 100644
--- a/source/fuzz/fuzzer_pass_merge_function_returns.h
+++ b/source/fuzz/fuzzer_pass_merge_function_returns.h
@@ -33,8 +33,6 @@ class FuzzerPassMergeFunctionReturns : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassMergeFunctionReturns();
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_pass_mutate_pointers.cpp b/source/fuzz/fuzzer_pass_mutate_pointers.cpp
index 89f5f5c0..f021a978 100644
--- a/source/fuzz/fuzzer_pass_mutate_pointers.cpp
+++ b/source/fuzz/fuzzer_pass_mutate_pointers.cpp
@@ -28,8 +28,6 @@ FuzzerPassMutatePointers::FuzzerPassMutatePointers(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassMutatePointers::~FuzzerPassMutatePointers() = default;
-
void FuzzerPassMutatePointers::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
diff --git a/source/fuzz/fuzzer_pass_mutate_pointers.h b/source/fuzz/fuzzer_pass_mutate_pointers.h
index f77523ef..5ef6a2ab 100644
--- a/source/fuzz/fuzzer_pass_mutate_pointers.h
+++ b/source/fuzz/fuzzer_pass_mutate_pointers.h
@@ -28,8 +28,6 @@ class FuzzerPassMutatePointers : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassMutatePointers() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_obfuscate_constants.cpp b/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
index d87662ee..32318e89 100644
--- a/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
+++ b/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
@@ -34,8 +34,6 @@ FuzzerPassObfuscateConstants::FuzzerPassObfuscateConstants(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassObfuscateConstants::~FuzzerPassObfuscateConstants() = default;
-
void FuzzerPassObfuscateConstants::ObfuscateBoolConstantViaConstantPair(
uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use,
const std::vector<SpvOp>& greater_than_opcodes,
diff --git a/source/fuzz/fuzzer_pass_obfuscate_constants.h b/source/fuzz/fuzzer_pass_obfuscate_constants.h
index d48b37f6..82b1092c 100644
--- a/source/fuzz/fuzzer_pass_obfuscate_constants.h
+++ b/source/fuzz/fuzzer_pass_obfuscate_constants.h
@@ -32,8 +32,6 @@ class FuzzerPassObfuscateConstants : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassObfuscateConstants() override;
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_pass_outline_functions.cpp b/source/fuzz/fuzzer_pass_outline_functions.cpp
index 42101256..bfde61f7 100644
--- a/source/fuzz/fuzzer_pass_outline_functions.cpp
+++ b/source/fuzz/fuzzer_pass_outline_functions.cpp
@@ -31,8 +31,6 @@ FuzzerPassOutlineFunctions::FuzzerPassOutlineFunctions(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassOutlineFunctions::~FuzzerPassOutlineFunctions() = default;
-
void FuzzerPassOutlineFunctions::Apply() {
std::vector<opt::Function*> original_functions;
for (auto& function : *GetIRContext()->module()) {
diff --git a/source/fuzz/fuzzer_pass_outline_functions.h b/source/fuzz/fuzzer_pass_outline_functions.h
index 02022aa7..45e52ff4 100644
--- a/source/fuzz/fuzzer_pass_outline_functions.h
+++ b/source/fuzz/fuzzer_pass_outline_functions.h
@@ -29,8 +29,6 @@ class FuzzerPassOutlineFunctions : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassOutlineFunctions();
-
void Apply() override;
// Returns a block suitable to be an entry block for a region that can be
diff --git a/source/fuzz/fuzzer_pass_permute_blocks.cpp b/source/fuzz/fuzzer_pass_permute_blocks.cpp
index 24c16fbb..769c49f0 100644
--- a/source/fuzz/fuzzer_pass_permute_blocks.cpp
+++ b/source/fuzz/fuzzer_pass_permute_blocks.cpp
@@ -26,8 +26,6 @@ FuzzerPassPermuteBlocks::FuzzerPassPermuteBlocks(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassPermuteBlocks::~FuzzerPassPermuteBlocks() = default;
-
void FuzzerPassPermuteBlocks::Apply() {
// For now we do something very simple: we randomly decide whether to move a
// block, and for each block that we do move, we push it down as far as we
diff --git a/source/fuzz/fuzzer_pass_permute_blocks.h b/source/fuzz/fuzzer_pass_permute_blocks.h
index e5a672cb..e40178e6 100644
--- a/source/fuzz/fuzzer_pass_permute_blocks.h
+++ b/source/fuzz/fuzzer_pass_permute_blocks.h
@@ -29,8 +29,6 @@ class FuzzerPassPermuteBlocks : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassPermuteBlocks() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_permute_function_parameters.cpp b/source/fuzz/fuzzer_pass_permute_function_parameters.cpp
index de6b03f3..9a61bea0 100644
--- a/source/fuzz/fuzzer_pass_permute_function_parameters.cpp
+++ b/source/fuzz/fuzzer_pass_permute_function_parameters.cpp
@@ -32,9 +32,6 @@ FuzzerPassPermuteFunctionParameters::FuzzerPassPermuteFunctionParameters(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassPermuteFunctionParameters::~FuzzerPassPermuteFunctionParameters() =
- default;
-
void FuzzerPassPermuteFunctionParameters::Apply() {
for (const auto& function : *GetIRContext()->module()) {
uint32_t function_id = function.result_id();
diff --git a/source/fuzz/fuzzer_pass_permute_function_parameters.h b/source/fuzz/fuzzer_pass_permute_function_parameters.h
index bc1031cb..a4bf2ca5 100644
--- a/source/fuzz/fuzzer_pass_permute_function_parameters.h
+++ b/source/fuzz/fuzzer_pass_permute_function_parameters.h
@@ -34,8 +34,6 @@ class FuzzerPassPermuteFunctionParameters : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassPermuteFunctionParameters() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_permute_instructions.cpp b/source/fuzz/fuzzer_pass_permute_instructions.cpp
index 6867053c..f17e0187 100644
--- a/source/fuzz/fuzzer_pass_permute_instructions.cpp
+++ b/source/fuzz/fuzzer_pass_permute_instructions.cpp
@@ -29,8 +29,6 @@ FuzzerPassPermuteInstructions::FuzzerPassPermuteInstructions(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassPermuteInstructions::~FuzzerPassPermuteInstructions() = default;
-
void FuzzerPassPermuteInstructions::Apply() {
// We are iterating over all instructions in all basic blocks.
for (auto& function : *GetIRContext()->module()) {
diff --git a/source/fuzz/fuzzer_pass_permute_instructions.h b/source/fuzz/fuzzer_pass_permute_instructions.h
index e02ddfae..027101dd 100644
--- a/source/fuzz/fuzzer_pass_permute_instructions.h
+++ b/source/fuzz/fuzzer_pass_permute_instructions.h
@@ -29,8 +29,6 @@ class FuzzerPassPermuteInstructions : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassPermuteInstructions() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_permute_phi_operands.cpp b/source/fuzz/fuzzer_pass_permute_phi_operands.cpp
index c379c535..f2cc5231 100644
--- a/source/fuzz/fuzzer_pass_permute_phi_operands.cpp
+++ b/source/fuzz/fuzzer_pass_permute_phi_operands.cpp
@@ -32,8 +32,6 @@ FuzzerPassPermutePhiOperands::FuzzerPassPermutePhiOperands(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassPermutePhiOperands::~FuzzerPassPermutePhiOperands() = default;
-
void FuzzerPassPermutePhiOperands::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* /*unused*/, opt::BasicBlock* /*unused*/,
diff --git a/source/fuzz/fuzzer_pass_permute_phi_operands.h b/source/fuzz/fuzzer_pass_permute_phi_operands.h
index 974c2c1e..79999562 100644
--- a/source/fuzz/fuzzer_pass_permute_phi_operands.h
+++ b/source/fuzz/fuzzer_pass_permute_phi_operands.h
@@ -29,8 +29,6 @@ class FuzzerPassPermutePhiOperands : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassPermutePhiOperands() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_propagate_instructions_down.cpp b/source/fuzz/fuzzer_pass_propagate_instructions_down.cpp
index 7a115aec..af27a5da 100644
--- a/source/fuzz/fuzzer_pass_propagate_instructions_down.cpp
+++ b/source/fuzz/fuzzer_pass_propagate_instructions_down.cpp
@@ -27,9 +27,6 @@ FuzzerPassPropagateInstructionsDown::FuzzerPassPropagateInstructionsDown(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassPropagateInstructionsDown::~FuzzerPassPropagateInstructionsDown() =
- default;
-
void FuzzerPassPropagateInstructionsDown::Apply() {
for (const auto& function : *GetIRContext()->module()) {
std::vector<const opt::BasicBlock*> reachable_blocks;
diff --git a/source/fuzz/fuzzer_pass_propagate_instructions_down.h b/source/fuzz/fuzzer_pass_propagate_instructions_down.h
index 536bf000..a2a0aac8 100644
--- a/source/fuzz/fuzzer_pass_propagate_instructions_down.h
+++ b/source/fuzz/fuzzer_pass_propagate_instructions_down.h
@@ -28,8 +28,6 @@ class FuzzerPassPropagateInstructionsDown : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassPropagateInstructionsDown() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_propagate_instructions_up.cpp b/source/fuzz/fuzzer_pass_propagate_instructions_up.cpp
index 16ec680e..8cd7437b 100644
--- a/source/fuzz/fuzzer_pass_propagate_instructions_up.cpp
+++ b/source/fuzz/fuzzer_pass_propagate_instructions_up.cpp
@@ -29,9 +29,6 @@ FuzzerPassPropagateInstructionsUp::FuzzerPassPropagateInstructionsUp(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassPropagateInstructionsUp::~FuzzerPassPropagateInstructionsUp() =
- default;
-
void FuzzerPassPropagateInstructionsUp::Apply() {
for (const auto& function : *GetIRContext()->module()) {
for (const auto& block : function) {
diff --git a/source/fuzz/fuzzer_pass_propagate_instructions_up.h b/source/fuzz/fuzzer_pass_propagate_instructions_up.h
index d915b31e..b89be48d 100644
--- a/source/fuzz/fuzzer_pass_propagate_instructions_up.h
+++ b/source/fuzz/fuzzer_pass_propagate_instructions_up.h
@@ -29,8 +29,6 @@ class FuzzerPassPropagateInstructionsUp : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassPropagateInstructionsUp() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp b/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
index 8d9acaa0..54e589c9 100644
--- a/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
+++ b/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
@@ -28,9 +28,6 @@ FuzzerPassPushIdsThroughVariables::FuzzerPassPushIdsThroughVariables(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassPushIdsThroughVariables::~FuzzerPassPushIdsThroughVariables() =
- default;
-
void FuzzerPassPushIdsThroughVariables::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
diff --git a/source/fuzz/fuzzer_pass_push_ids_through_variables.h b/source/fuzz/fuzzer_pass_push_ids_through_variables.h
index 3ad54042..53008ee2 100644
--- a/source/fuzz/fuzzer_pass_push_ids_through_variables.h
+++ b/source/fuzz/fuzzer_pass_push_ids_through_variables.h
@@ -30,8 +30,6 @@ class FuzzerPassPushIdsThroughVariables : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassPushIdsThroughVariables() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.cpp b/source/fuzz/fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.cpp
index 139dc6e2..8a83d3bc 100644
--- a/source/fuzz/fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.cpp
+++ b/source/fuzz/fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.cpp
@@ -33,9 +33,6 @@ FuzzerPassReplaceAddsSubsMulsWithCarryingExtended::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassReplaceAddsSubsMulsWithCarryingExtended::
- ~FuzzerPassReplaceAddsSubsMulsWithCarryingExtended() = default;
-
void FuzzerPassReplaceAddsSubsMulsWithCarryingExtended::Apply() {
std::vector<opt::Instruction> instructions_for_transformation;
for (auto& function : *GetIRContext()->module()) {
diff --git a/source/fuzz/fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.h b/source/fuzz/fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.h
index dd39e6b0..0e29a6c6 100644
--- a/source/fuzz/fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.h
+++ b/source/fuzz/fuzzer_pass_replace_adds_subs_muls_with_carrying_extended.h
@@ -31,8 +31,6 @@ class FuzzerPassReplaceAddsSubsMulsWithCarryingExtended : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassReplaceAddsSubsMulsWithCarryingExtended() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp b/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp
index e6bebead..a516f3d4 100644
--- a/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp
+++ b/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp
@@ -32,9 +32,6 @@ FuzzerPassReplaceBranchesFromDeadBlocksWithExits::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassReplaceBranchesFromDeadBlocksWithExits::
- ~FuzzerPassReplaceBranchesFromDeadBlocksWithExits() = default;
-
void FuzzerPassReplaceBranchesFromDeadBlocksWithExits::Apply() {
// OpKill can only be used as a terminator in a function that is guaranteed
// to be executed with the Fragment execution model. We conservatively only
diff --git a/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.h b/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.h
index 62164b32..ab7e00e5 100644
--- a/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.h
+++ b/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.h
@@ -30,8 +30,6 @@ class FuzzerPassReplaceBranchesFromDeadBlocksWithExits : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassReplaceBranchesFromDeadBlocksWithExits() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp b/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp
index 68471466..f17339a9 100644
--- a/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp
+++ b/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp
@@ -30,9 +30,6 @@ FuzzerPassReplaceCopyMemoriesWithLoadsStores::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassReplaceCopyMemoriesWithLoadsStores::
- ~FuzzerPassReplaceCopyMemoriesWithLoadsStores() = default;
-
void FuzzerPassReplaceCopyMemoriesWithLoadsStores::Apply() {
GetIRContext()->module()->ForEachInst([this](opt::Instruction* instruction) {
// Randomly decide whether to replace the OpCopyMemory.
diff --git a/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.h b/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.h
index 9c24ac73..cffe1cb9 100644
--- a/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.h
+++ b/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.h
@@ -30,8 +30,6 @@ class FuzzerPassReplaceCopyMemoriesWithLoadsStores : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassReplaceCopyMemoriesWithLoadsStores() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp b/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp
index e3729245..24f2255b 100644
--- a/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp
+++ b/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp
@@ -30,9 +30,6 @@ FuzzerPassReplaceCopyObjectsWithStoresLoads::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassReplaceCopyObjectsWithStoresLoads::
- ~FuzzerPassReplaceCopyObjectsWithStoresLoads() = default;
-
void FuzzerPassReplaceCopyObjectsWithStoresLoads::Apply() {
GetIRContext()->module()->ForEachInst([this](opt::Instruction* instruction) {
// Randomly decide whether to replace OpCopyObject.
diff --git a/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.h b/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.h
index ae03a450..e7b11ce1 100644
--- a/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.h
+++ b/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.h
@@ -30,8 +30,6 @@ class FuzzerPassReplaceCopyObjectsWithStoresLoads : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassReplaceCopyObjectsWithStoresLoads() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp b/source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp
index 432addbc..7e9d7baa 100644
--- a/source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp
+++ b/source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp
@@ -31,8 +31,6 @@ FuzzerPassReplaceIrrelevantIds::FuzzerPassReplaceIrrelevantIds(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassReplaceIrrelevantIds::~FuzzerPassReplaceIrrelevantIds() = default;
-
void FuzzerPassReplaceIrrelevantIds::Apply() {
// Keep track of the irrelevant ids. This includes all the ids that are
// irrelevant according to the fact manager and that are still present in the
diff --git a/source/fuzz/fuzzer_pass_replace_irrelevant_ids.h b/source/fuzz/fuzzer_pass_replace_irrelevant_ids.h
index ab3f01d1..1dc6b5d3 100644
--- a/source/fuzz/fuzzer_pass_replace_irrelevant_ids.h
+++ b/source/fuzz/fuzzer_pass_replace_irrelevant_ids.h
@@ -30,8 +30,6 @@ class FuzzerPassReplaceIrrelevantIds : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassReplaceIrrelevantIds();
-
void Apply() override;
};
} // namespace fuzz
diff --git a/source/fuzz/fuzzer_pass_replace_linear_algebra_instructions.cpp b/source/fuzz/fuzzer_pass_replace_linear_algebra_instructions.cpp
index c3e65789..0890c2fe 100644
--- a/source/fuzz/fuzzer_pass_replace_linear_algebra_instructions.cpp
+++ b/source/fuzz/fuzzer_pass_replace_linear_algebra_instructions.cpp
@@ -30,9 +30,6 @@ FuzzerPassReplaceLinearAlgebraInstructions::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassReplaceLinearAlgebraInstructions::
- ~FuzzerPassReplaceLinearAlgebraInstructions() = default;
-
void FuzzerPassReplaceLinearAlgebraInstructions::Apply() {
// For each instruction, checks whether it is a linear algebra instruction. In
// this case, the transformation is randomly applied.
diff --git a/source/fuzz/fuzzer_pass_replace_linear_algebra_instructions.h b/source/fuzz/fuzzer_pass_replace_linear_algebra_instructions.h
index 2c6126cd..5d2f2042 100644
--- a/source/fuzz/fuzzer_pass_replace_linear_algebra_instructions.h
+++ b/source/fuzz/fuzzer_pass_replace_linear_algebra_instructions.h
@@ -29,8 +29,6 @@ class FuzzerPassReplaceLinearAlgebraInstructions : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassReplaceLinearAlgebraInstructions();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp b/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp
index 7690ac41..f2cf80fa 100644
--- a/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp
+++ b/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp
@@ -31,9 +31,6 @@ FuzzerPassReplaceLoadsStoresWithCopyMemories::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassReplaceLoadsStoresWithCopyMemories::
- ~FuzzerPassReplaceLoadsStoresWithCopyMemories() = default;
-
void FuzzerPassReplaceLoadsStoresWithCopyMemories::Apply() {
// We look for matching pairs of instructions OpLoad and
// OpStore within the same block. Potential instructions OpLoad to be matched
diff --git a/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.h b/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.h
index 67871db2..f30fc2b7 100644
--- a/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.h
+++ b/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.h
@@ -30,8 +30,6 @@ class FuzzerPassReplaceLoadsStoresWithCopyMemories : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassReplaceLoadsStoresWithCopyMemories() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp b/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp
index 433cf744..b0a3d57c 100644
--- a/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp
+++ b/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp
@@ -28,9 +28,6 @@ FuzzerPassReplaceOpPhiIdsFromDeadPredecessors::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassReplaceOpPhiIdsFromDeadPredecessors::
- ~FuzzerPassReplaceOpPhiIdsFromDeadPredecessors() = default;
-
void FuzzerPassReplaceOpPhiIdsFromDeadPredecessors::Apply() {
// Keep a vector of the transformations to apply.
std::vector<TransformationReplaceOpPhiIdFromDeadPredecessor> transformations;
diff --git a/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.h b/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.h
index 972c5f9d..a2bc1886 100644
--- a/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.h
+++ b/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.h
@@ -29,8 +29,6 @@ class FuzzerPassReplaceOpPhiIdsFromDeadPredecessors : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassReplaceOpPhiIdsFromDeadPredecessors();
-
void Apply() override;
};
} // namespace fuzz
diff --git a/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp b/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp
index c3db0ef1..10bb90ad 100644
--- a/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp
+++ b/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp
@@ -31,9 +31,6 @@ FuzzerPassReplaceOpSelectsWithConditionalBranches::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassReplaceOpSelectsWithConditionalBranches::
- ~FuzzerPassReplaceOpSelectsWithConditionalBranches() = default;
-
void FuzzerPassReplaceOpSelectsWithConditionalBranches::Apply() {
// Keep track of the instructions that we want to replace. We need to collect
// them in a vector, since it's not safe to modify the module while iterating
diff --git a/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.h b/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.h
index 04c6cc6d..ec743890 100644
--- a/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.h
+++ b/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.h
@@ -29,8 +29,6 @@ class FuzzerPassReplaceOpSelectsWithConditionalBranches : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassReplaceOpSelectsWithConditionalBranches() override;
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp b/source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp
index 6b3a63ba..5c256bb0 100644
--- a/source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp
+++ b/source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp
@@ -31,9 +31,6 @@ FuzzerPassReplaceParameterWithGlobal::FuzzerPassReplaceParameterWithGlobal(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassReplaceParameterWithGlobal::~FuzzerPassReplaceParameterWithGlobal() =
- default;
-
void FuzzerPassReplaceParameterWithGlobal::Apply() {
for (const auto& function : *GetIRContext()->module()) {
if (fuzzerutil::FunctionIsEntryPoint(GetIRContext(),
diff --git a/source/fuzz/fuzzer_pass_replace_parameter_with_global.h b/source/fuzz/fuzzer_pass_replace_parameter_with_global.h
index 25011bdc..2ae49469 100644
--- a/source/fuzz/fuzzer_pass_replace_parameter_with_global.h
+++ b/source/fuzz/fuzzer_pass_replace_parameter_with_global.h
@@ -29,8 +29,6 @@ class FuzzerPassReplaceParameterWithGlobal : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassReplaceParameterWithGlobal() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_replace_params_with_struct.cpp b/source/fuzz/fuzzer_pass_replace_params_with_struct.cpp
index 0e0610f7..c045e19f 100644
--- a/source/fuzz/fuzzer_pass_replace_params_with_struct.cpp
+++ b/source/fuzz/fuzzer_pass_replace_params_with_struct.cpp
@@ -31,9 +31,6 @@ FuzzerPassReplaceParamsWithStruct::FuzzerPassReplaceParamsWithStruct(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassReplaceParamsWithStruct::~FuzzerPassReplaceParamsWithStruct() =
- default;
-
void FuzzerPassReplaceParamsWithStruct::Apply() {
for (const auto& function : *GetIRContext()->module()) {
auto params =
diff --git a/source/fuzz/fuzzer_pass_replace_params_with_struct.h b/source/fuzz/fuzzer_pass_replace_params_with_struct.h
index ed1aa6b5..f17f5207 100644
--- a/source/fuzz/fuzzer_pass_replace_params_with_struct.h
+++ b/source/fuzz/fuzzer_pass_replace_params_with_struct.h
@@ -29,8 +29,6 @@ class FuzzerPassReplaceParamsWithStruct : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassReplaceParamsWithStruct() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_split_blocks.cpp b/source/fuzz/fuzzer_pass_split_blocks.cpp
index 481cd960..7b493559 100644
--- a/source/fuzz/fuzzer_pass_split_blocks.cpp
+++ b/source/fuzz/fuzzer_pass_split_blocks.cpp
@@ -29,8 +29,6 @@ FuzzerPassSplitBlocks::FuzzerPassSplitBlocks(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassSplitBlocks::~FuzzerPassSplitBlocks() = default;
-
void FuzzerPassSplitBlocks::Apply() {
// Gather up pointers to all the blocks in the module. We are then able to
// iterate over these pointers and split the blocks to which they point;
diff --git a/source/fuzz/fuzzer_pass_split_blocks.h b/source/fuzz/fuzzer_pass_split_blocks.h
index 0ece48a0..58f10ddb 100644
--- a/source/fuzz/fuzzer_pass_split_blocks.h
+++ b/source/fuzz/fuzzer_pass_split_blocks.h
@@ -29,8 +29,6 @@ class FuzzerPassSplitBlocks : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassSplitBlocks() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp b/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp
index 321e8efd..27fadd17 100644
--- a/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp
+++ b/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp
@@ -28,8 +28,6 @@ FuzzerPassSwapCommutableOperands::FuzzerPassSwapCommutableOperands(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassSwapCommutableOperands::~FuzzerPassSwapCommutableOperands() = default;
-
void FuzzerPassSwapCommutableOperands::Apply() {
auto context = GetIRContext();
// Iterates over the module's instructions and checks whether it is
diff --git a/source/fuzz/fuzzer_pass_swap_commutable_operands.h b/source/fuzz/fuzzer_pass_swap_commutable_operands.h
index 74d937d8..93de1728 100644
--- a/source/fuzz/fuzzer_pass_swap_commutable_operands.h
+++ b/source/fuzz/fuzzer_pass_swap_commutable_operands.h
@@ -30,8 +30,6 @@ class FuzzerPassSwapCommutableOperands : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassSwapCommutableOperands();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp b/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp
index 9433a61f..b145b3bc 100644
--- a/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp
+++ b/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp
@@ -31,9 +31,6 @@ FuzzerPassSwapBranchConditionalOperands::
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassSwapBranchConditionalOperands::
- ~FuzzerPassSwapBranchConditionalOperands() = default;
-
void FuzzerPassSwapBranchConditionalOperands::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* /*unused*/, opt::BasicBlock* /*unused*/,
diff --git a/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.h b/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.h
index f84f3ba4..0137f38b 100644
--- a/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.h
+++ b/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.h
@@ -29,8 +29,6 @@ class FuzzerPassSwapBranchConditionalOperands : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassSwapBranchConditionalOperands() override;
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp b/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
index 4f26cba3..e5afd9ee 100644
--- a/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
+++ b/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
@@ -28,9 +28,6 @@ FuzzerPassToggleAccessChainInstruction::FuzzerPassToggleAccessChainInstruction(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassToggleAccessChainInstruction::
- ~FuzzerPassToggleAccessChainInstruction() = default;
-
void FuzzerPassToggleAccessChainInstruction::Apply() {
auto context = GetIRContext();
// Iterates over the module's instructions and checks whether it is
diff --git a/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h b/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h
index d77c7cbe..ff2f5d45 100644
--- a/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h
+++ b/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h
@@ -29,8 +29,6 @@ class FuzzerPassToggleAccessChainInstruction : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassToggleAccessChainInstruction();
-
void Apply() override;
};
diff --git a/source/fuzz/fuzzer_pass_wrap_regions_in_selections.cpp b/source/fuzz/fuzzer_pass_wrap_regions_in_selections.cpp
index e6cdca41..66bbcd81 100644
--- a/source/fuzz/fuzzer_pass_wrap_regions_in_selections.cpp
+++ b/source/fuzz/fuzzer_pass_wrap_regions_in_selections.cpp
@@ -29,9 +29,6 @@ FuzzerPassWrapRegionsInSelections::FuzzerPassWrapRegionsInSelections(
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
-FuzzerPassWrapRegionsInSelections::~FuzzerPassWrapRegionsInSelections() =
- default;
-
void FuzzerPassWrapRegionsInSelections::Apply() {
for (auto& function : *GetIRContext()->module()) {
if (!GetFuzzerContext()->ChoosePercentage(
diff --git a/source/fuzz/fuzzer_pass_wrap_regions_in_selections.h b/source/fuzz/fuzzer_pass_wrap_regions_in_selections.h
index eb28d208..822c308f 100644
--- a/source/fuzz/fuzzer_pass_wrap_regions_in_selections.h
+++ b/source/fuzz/fuzzer_pass_wrap_regions_in_selections.h
@@ -29,8 +29,6 @@ class FuzzerPassWrapRegionsInSelections : public FuzzerPass {
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
- ~FuzzerPassWrapRegionsInSelections() override;
-
void Apply() override;
private:
diff --git a/source/fuzz/fuzzer_util.cpp b/source/fuzz/fuzzer_util.cpp
index 8c14db4b..aa0d30e2 100644
--- a/source/fuzz/fuzzer_util.cpp
+++ b/source/fuzz/fuzzer_util.cpp
@@ -25,6 +25,25 @@ namespace fuzz {
namespace fuzzerutil {
namespace {
+// A utility class that uses RAII to change and restore the terminator
+// instruction of the |block|.
+class ChangeTerminatorRAII {
+ public:
+ explicit ChangeTerminatorRAII(opt::BasicBlock* block,
+ opt::Instruction new_terminator)
+ : block_(block), old_terminator_(std::move(*block->terminator())) {
+ *block_->terminator() = std::move(new_terminator);
+ }
+
+ ~ChangeTerminatorRAII() {
+ *block_->terminator() = std::move(old_terminator_);
+ }
+
+ private:
+ opt::BasicBlock* block_;
+ opt::Instruction old_terminator_;
+};
+
uint32_t MaybeGetOpConstant(opt::IRContext* ir_context,
const TransformationContext& transformation_context,
const std::vector<uint32_t>& words,
@@ -47,6 +66,34 @@ const spvtools::MessageConsumer kSilentMessageConsumer =
[](spv_message_level_t, const char*, const spv_position_t&,
const char*) -> void {};
+bool BuildIRContext(spv_target_env target_env,
+ const spvtools::MessageConsumer& message_consumer,
+ const std::vector<uint32_t>& binary_in,
+ spv_validator_options validator_options,
+ std::unique_ptr<spvtools::opt::IRContext>* ir_context) {
+ SpirvTools tools(target_env);
+ tools.SetMessageConsumer(message_consumer);
+ 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.data(), 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.
+ auto result = BuildModule(target_env, message_consumer, binary_in.data(),
+ binary_in.size());
+ assert(result && "IRContext must be valid");
+ *ir_context = std::move(result);
+ return true;
+}
+
bool IsFreshId(opt::IRContext* context, uint32_t id) {
return !context->get_def_use_mgr()->GetDef(id);
}
@@ -135,35 +182,46 @@ bool PhiIdsOkForNewEdge(
return true;
}
-void AddUnreachableEdgeAndUpdateOpPhis(
- opt::IRContext* context, opt::BasicBlock* bb_from, opt::BasicBlock* bb_to,
- uint32_t bool_id,
- const google::protobuf::RepeatedField<google::protobuf::uint32>& phi_ids) {
- assert(PhiIdsOkForNewEdge(context, bb_from, bb_to, phi_ids) &&
- "Precondition on phi_ids is not satisfied");
+opt::Instruction CreateUnreachableEdgeInstruction(opt::IRContext* ir_context,
+ uint32_t bb_from_id,
+ uint32_t bb_to_id,
+ uint32_t bool_id) {
+ const auto* bb_from = MaybeFindBlock(ir_context, bb_from_id);
+ assert(bb_from && "|bb_from_id| is invalid");
+ assert(MaybeFindBlock(ir_context, bb_to_id) && "|bb_to_id| is invalid");
assert(bb_from->terminator()->opcode() == SpvOpBranch &&
"Precondition on terminator of bb_from is not satisfied");
// Get the id of the boolean constant to be used as the condition.
- auto condition_inst = context->get_def_use_mgr()->GetDef(bool_id);
+ auto condition_inst = ir_context->get_def_use_mgr()->GetDef(bool_id);
assert(condition_inst &&
(condition_inst->opcode() == SpvOpConstantTrue ||
condition_inst->opcode() == SpvOpConstantFalse) &&
"|bool_id| is invalid");
auto condition_value = condition_inst->opcode() == SpvOpConstantTrue;
-
- const bool from_to_edge_already_exists = bb_from->IsSuccessor(bb_to);
- auto successor = bb_from->terminator()->GetSingleWordInOperand(0);
+ auto successor_id = bb_from->terminator()->GetSingleWordInOperand(0);
// Add the dead branch, by turning OpBranch into OpBranchConditional, and
// ordering the targets depending on whether the given boolean corresponds to
// true or false.
- bb_from->terminator()->SetOpcode(SpvOpBranchConditional);
- bb_from->terminator()->SetInOperands(
+ return opt::Instruction(
+ ir_context, SpvOpBranchConditional, 0, 0,
{{SPV_OPERAND_TYPE_ID, {bool_id}},
- {SPV_OPERAND_TYPE_ID, {condition_value ? successor : bb_to->id()}},
- {SPV_OPERAND_TYPE_ID, {condition_value ? bb_to->id() : successor}}});
+ {SPV_OPERAND_TYPE_ID, {condition_value ? successor_id : bb_to_id}},
+ {SPV_OPERAND_TYPE_ID, {condition_value ? bb_to_id : successor_id}}});
+}
+
+void AddUnreachableEdgeAndUpdateOpPhis(
+ opt::IRContext* context, opt::BasicBlock* bb_from, opt::BasicBlock* bb_to,
+ uint32_t bool_id,
+ const google::protobuf::RepeatedField<google::protobuf::uint32>& phi_ids) {
+ assert(PhiIdsOkForNewEdge(context, bb_from, bb_to, phi_ids) &&
+ "Precondition on phi_ids is not satisfied");
+
+ const bool from_to_edge_already_exists = bb_from->IsSuccessor(bb_to);
+ *bb_from->terminator() = CreateUnreachableEdgeInstruction(
+ context, bb_from->id(), bb_to->id(), bool_id);
// Update OpPhi instructions in the target block if this branch adds a
// previously non-existent edge from source to target.
@@ -410,7 +468,7 @@ bool IsValid(const opt::IRContext* context,
std::vector<uint32_t> binary;
context->module()->ToBinary(&binary, false);
SpirvTools tools(context->grammar().target_env());
- tools.SetMessageConsumer(consumer);
+ tools.SetMessageConsumer(std::move(consumer));
return tools.Validate(binary.data(), binary.size(), validator_options);
}
@@ -747,14 +805,15 @@ bool IsNullConstantSupported(const opt::analysis::Type& type) {
bool GlobalVariablesMustBeDeclaredInEntryPointInterfaces(
const opt::IRContext* ir_context) {
- // TODO(afd): We capture the universal environments for which this requirement
- // holds. The check should be refined on demand for other target
- // environments.
+ // TODO(afd): We capture the environments for which this requirement holds.
+ // The check should be refined on demand for other target environments.
switch (ir_context->grammar().target_env()) {
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_UNIVERSAL_1_1:
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_UNIVERSAL_1_3:
+ case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_VULKAN_1_1:
return false;
default:
return true;
@@ -778,9 +837,10 @@ void AddVariableIdToEntryPointInterfaces(opt::IRContext* context, uint32_t id) {
}
}
-void AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
- uint32_t type_id, SpvStorageClass storage_class,
- uint32_t initializer_id) {
+opt::Instruction* AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
+ uint32_t type_id,
+ SpvStorageClass storage_class,
+ uint32_t initializer_id) {
// Check various preconditions.
assert(result_id != 0 && "Result id can't be 0");
@@ -815,16 +875,20 @@ void AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
operands.push_back({SPV_OPERAND_TYPE_ID, {initializer_id}});
}
- context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- context, SpvOpVariable, type_id, result_id, std::move(operands)));
+ auto new_instruction = MakeUnique<opt::Instruction>(
+ context, SpvOpVariable, type_id, result_id, std::move(operands));
+ auto result = new_instruction.get();
+ context->module()->AddGlobalValue(std::move(new_instruction));
AddVariableIdToEntryPointInterfaces(context, result_id);
UpdateModuleIdBound(context, result_id);
+
+ return result;
}
-void AddLocalVariable(opt::IRContext* context, uint32_t result_id,
- uint32_t type_id, uint32_t function_id,
- uint32_t initializer_id) {
+opt::Instruction* AddLocalVariable(opt::IRContext* context, uint32_t result_id,
+ uint32_t type_id, uint32_t function_id,
+ uint32_t initializer_id) {
// Check various preconditions.
assert(result_id != 0 && "Result id can't be 0");
@@ -845,13 +909,17 @@ void AddLocalVariable(opt::IRContext* context, uint32_t result_id,
auto* function = FindFunction(context, function_id);
assert(function && "Function id is invalid");
- function->begin()->begin()->InsertBefore(MakeUnique<opt::Instruction>(
+ auto new_instruction = MakeUnique<opt::Instruction>(
context, SpvOpVariable, type_id, result_id,
opt::Instruction::OperandList{
{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}},
- {SPV_OPERAND_TYPE_ID, {initializer_id}}}));
+ {SPV_OPERAND_TYPE_ID, {initializer_id}}});
+ auto result = new_instruction.get();
+ function->begin()->begin()->InsertBefore(std::move(new_instruction));
UpdateModuleIdBound(context, result_id);
+
+ return result;
}
bool HasDuplicates(const std::vector<uint32_t>& arr) {
@@ -1355,74 +1423,6 @@ uint32_t MaybeGetBoolConstant(
return 0;
}
-void AddIntegerType(opt::IRContext* ir_context, uint32_t result_id,
- uint32_t width, bool is_signed) {
- ir_context->module()->AddType(MakeUnique<opt::Instruction>(
- ir_context, SpvOpTypeInt, 0, result_id,
- opt::Instruction::OperandList{
- {SPV_OPERAND_TYPE_LITERAL_INTEGER, {width}},
- {SPV_OPERAND_TYPE_LITERAL_INTEGER, {is_signed ? 1u : 0u}}}));
-
- UpdateModuleIdBound(ir_context, result_id);
-}
-
-void AddFloatType(opt::IRContext* ir_context, uint32_t result_id,
- uint32_t width) {
- ir_context->module()->AddType(MakeUnique<opt::Instruction>(
- ir_context, SpvOpTypeFloat, 0, result_id,
- opt::Instruction::OperandList{
- {SPV_OPERAND_TYPE_LITERAL_INTEGER, {width}}}));
-
- UpdateModuleIdBound(ir_context, result_id);
-}
-
-void AddVectorType(opt::IRContext* ir_context, uint32_t result_id,
- uint32_t component_type_id, uint32_t element_count) {
- const auto* component_type =
- ir_context->get_type_mgr()->GetType(component_type_id);
- (void)component_type; // Make compiler happy in release mode.
- assert(component_type &&
- (component_type->AsInteger() || component_type->AsFloat() ||
- component_type->AsBool()) &&
- "|component_type_id| is invalid");
- assert(element_count >= 2 && element_count <= 4 &&
- "Precondition: component count must be in range [2, 4].");
- ir_context->module()->AddType(MakeUnique<opt::Instruction>(
- ir_context, SpvOpTypeVector, 0, result_id,
- opt::Instruction::OperandList{
- {SPV_OPERAND_TYPE_ID, {component_type_id}},
- {SPV_OPERAND_TYPE_LITERAL_INTEGER, {element_count}}}));
-
- UpdateModuleIdBound(ir_context, result_id);
-}
-
-void AddStructType(opt::IRContext* ir_context, uint32_t result_id,
- const std::vector<uint32_t>& component_type_ids) {
- opt::Instruction::OperandList operands;
- operands.reserve(component_type_ids.size());
-
- for (auto type_id : component_type_ids) {
- const auto* type = ir_context->get_type_mgr()->GetType(type_id);
- (void)type; // Make compiler happy in release mode.
- assert(type && !type->AsFunction() && "Component's type id is invalid");
-
- if (type->AsStruct()) {
- // From the spec for the BuiltIn decoration:
- // - When applied to a structure-type member, that structure type cannot
- // be contained as a member of another structure type.
- assert(!MembersHaveBuiltInDecoration(ir_context, type_id) &&
- "A member struct has BuiltIn members");
- }
-
- operands.push_back({SPV_OPERAND_TYPE_ID, {type_id}});
- }
-
- ir_context->AddType(MakeUnique<opt::Instruction>(
- ir_context, SpvOpTypeStruct, 0, result_id, std::move(operands)));
-
- UpdateModuleIdBound(ir_context, result_id);
-}
-
std::vector<uint32_t> IntToWords(uint64_t value, uint32_t width,
bool is_signed) {
assert(width <= 64 && "The bit width should not be more than 64 bits");
@@ -1827,6 +1827,104 @@ std::set<uint32_t> GetReachableReturnBlocks(opt::IRContext* ir_context,
return result;
}
+bool NewTerminatorPreservesDominationRules(opt::IRContext* ir_context,
+ uint32_t block_id,
+ opt::Instruction new_terminator) {
+ auto* mutated_block = MaybeFindBlock(ir_context, block_id);
+ assert(mutated_block && "|block_id| is invalid");
+
+ ChangeTerminatorRAII change_terminator_raii(mutated_block,
+ std::move(new_terminator));
+ opt::DominatorAnalysis dominator_analysis;
+ dominator_analysis.InitializeTree(*ir_context->cfg(),
+ mutated_block->GetParent());
+
+ // Check that each dominator appears before each dominated block.
+ std::unordered_map<uint32_t, size_t> positions;
+ for (const auto& block : *mutated_block->GetParent()) {
+ positions[block.id()] = positions.size();
+ }
+
+ std::queue<uint32_t> q({mutated_block->GetParent()->begin()->id()});
+ std::unordered_set<uint32_t> visited;
+ while (!q.empty()) {
+ auto block = q.front();
+ q.pop();
+ visited.insert(block);
+
+ auto success = ir_context->cfg()->block(block)->WhileEachSuccessorLabel(
+ [&positions, &visited, &dominator_analysis, block, &q](uint32_t id) {
+ if (id == block) {
+ // Handle the case when loop header and continue target are the same
+ // block.
+ return true;
+ }
+
+ if (dominator_analysis.Dominates(block, id) &&
+ positions[block] > positions[id]) {
+ // |block| dominates |id| but appears after |id| - violates
+ // domination rules.
+ return false;
+ }
+
+ if (!visited.count(id)) {
+ q.push(id);
+ }
+
+ return true;
+ });
+
+ if (!success) {
+ return false;
+ }
+ }
+
+ // For each instruction in the |block->GetParent()| function check whether
+ // all its dependencies satisfy domination rules (i.e. all id operands
+ // dominate that instruction).
+ for (const auto& block : *mutated_block->GetParent()) {
+ if (!dominator_analysis.IsReachable(&block)) {
+ // If some block is not reachable then we don't need to worry about the
+ // preservation of domination rules for its instructions.
+ continue;
+ }
+
+ for (const auto& inst : block) {
+ for (uint32_t i = 0; i < inst.NumInOperands();
+ i += inst.opcode() == SpvOpPhi ? 2 : 1) {
+ const auto& operand = inst.GetInOperand(i);
+ if (!spvIsInIdType(operand.type)) {
+ continue;
+ }
+
+ if (MaybeFindBlock(ir_context, operand.words[0])) {
+ // Ignore operands that refer to OpLabel instructions.
+ continue;
+ }
+
+ const auto* dependency_block =
+ ir_context->get_instr_block(operand.words[0]);
+ if (!dependency_block) {
+ // A global instruction always dominates all instructions in any
+ // function.
+ continue;
+ }
+
+ auto domination_target_id = inst.opcode() == SpvOpPhi
+ ? inst.GetSingleWordInOperand(i + 1)
+ : block.id();
+
+ if (!dominator_analysis.Dominates(dependency_block->id(),
+ domination_target_id)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
} // namespace fuzzerutil
} // namespace fuzz
} // namespace spvtools
diff --git a/source/fuzz/fuzzer_util.h b/source/fuzz/fuzzer_util.h
index 4e6ec36e..fcbf1c65 100644
--- a/source/fuzz/fuzzer_util.h
+++ b/source/fuzz/fuzzer_util.h
@@ -38,6 +38,15 @@ extern const spvtools::MessageConsumer kSilentMessageConsumer;
// Function type that produces a SPIR-V module.
using ModuleSupplier = std::function<std::unique_ptr<opt::IRContext>()>;
+// Builds a new opt::IRContext object. Returns true if successful and changes
+// the |ir_context| parameter. Otherwise (if any errors occur), returns false
+// and |ir_context| remains unchanged.
+bool BuildIRContext(spv_target_env target_env,
+ const spvtools::MessageConsumer& message_consumer,
+ const std::vector<uint32_t>& binary_in,
+ spv_validator_options validator_options,
+ std::unique_ptr<spvtools::opt::IRContext>* ir_context);
+
// Returns true if and only if the module does not define the given id.
bool IsFreshId(opt::IRContext* context, uint32_t id);
@@ -59,6 +68,16 @@ bool PhiIdsOkForNewEdge(
opt::IRContext* context, opt::BasicBlock* bb_from, opt::BasicBlock* bb_to,
const google::protobuf::RepeatedField<google::protobuf::uint32>& phi_ids);
+// Returns an OpBranchConditional instruction that will create an unreachable
+// branch from |bb_from_id| to |bb_to_id|. |bool_id| must be a result id of
+// either OpConstantTrue or OpConstantFalse. Based on the opcode of |bool_id|,
+// operands of the returned instruction will be positioned in a way that the
+// branch from |bb_from_id| to |bb_to_id| is always unreachable.
+opt::Instruction CreateUnreachableEdgeInstruction(opt::IRContext* ir_context,
+ uint32_t bb_from_id,
+ uint32_t bb_to_id,
+ uint32_t bool_id);
+
// Requires that |bool_id| is a valid result id of either OpConstantTrue or
// OpConstantFalse, that PhiIdsOkForNewEdge(context, bb_from, bb_to, phi_ids)
// holds, and that bb_from ends with "OpBranch %some_block". Turns OpBranch
@@ -284,9 +303,12 @@ void AddVariableIdToEntryPointInterfaces(opt::IRContext* context, uint32_t id);
// - |initializer_id| must be 0 if |storage_class| is Workgroup, and otherwise
// may either be 0 or the id of a constant whose type is the pointee type of
// |type_id|.
-void AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
- uint32_t type_id, SpvStorageClass storage_class,
- uint32_t initializer_id);
+//
+// Returns a pointer to the new global variable instruction.
+opt::Instruction* AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
+ uint32_t type_id,
+ SpvStorageClass storage_class,
+ uint32_t initializer_id);
// Adds an instruction to the start of |function_id|, of the form:
// |result_id| = OpVariable |type_id| Function |initializer_id|.
@@ -296,9 +318,11 @@ void AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
// - |initializer_id| must be the id of a constant with the same type as the
// pointer's pointee type.
// - |function_id| must be the id of a function.
-void AddLocalVariable(opt::IRContext* context, uint32_t result_id,
- uint32_t type_id, uint32_t function_id,
- uint32_t initializer_id);
+//
+// Returns a pointer to the new local variable instruction.
+opt::Instruction* AddLocalVariable(opt::IRContext* context, uint32_t result_id,
+ uint32_t type_id, uint32_t function_id,
+ uint32_t initializer_id);
// Returns true if the vector |arr| has duplicates.
bool HasDuplicates(const std::vector<uint32_t>& arr);
@@ -476,30 +500,6 @@ uint32_t MaybeGetBoolConstant(
const TransformationContext& transformation_context, bool value,
bool is_irrelevant);
-// Creates a new OpTypeInt instruction in the module. Updates module's id bound
-// to accommodate for |result_id|.
-void AddIntegerType(opt::IRContext* ir_context, uint32_t result_id,
- uint32_t width, bool is_signed);
-
-// Creates a new OpTypeFloat instruction in the module. Updates module's id
-// bound to accommodate for |result_id|.
-void AddFloatType(opt::IRContext* ir_context, uint32_t result_id,
- uint32_t width);
-
-// Creates a new OpTypeVector instruction in the module. |component_type_id|
-// must be a valid result id of an OpTypeInt, OpTypeFloat or OpTypeBool
-// instruction in the module. |element_count| must be in the range [2, 4].
-// Updates module's id bound to accommodate for |result_id|.
-void AddVectorType(opt::IRContext* ir_context, uint32_t result_id,
- uint32_t component_type_id, uint32_t element_count);
-
-// Creates a new OpTypeStruct instruction in the module. Updates module's id
-// bound to accommodate for |result_id|. |component_type_ids| may not contain
-// a result id of an OpTypeFunction. if |component_type_ids| contains a result
-// of an OpTypeStruct instruction, that struct may not have BuiltIn members.
-void AddStructType(opt::IRContext* ir_context, uint32_t result_id,
- const std::vector<uint32_t>& component_type_ids);
-
// Returns a vector of words representing the integer |value|, only considering
// the last |width| bits. The last |width| bits are sign-extended if the value
// is signed, zero-extended if it is unsigned.
@@ -588,6 +588,14 @@ bool InstructionHasNoSideEffects(const opt::Instruction& instruction);
std::set<uint32_t> GetReachableReturnBlocks(opt::IRContext* ir_context,
uint32_t function_id);
+// Returns true if changing terminator instruction to |new_terminator| in the
+// basic block with id |block_id| preserves domination rules and valid block
+// order (i.e. dominator must always appear before dominated in the CFG).
+// Returns false otherwise.
+bool NewTerminatorPreservesDominationRules(opt::IRContext* ir_context,
+ uint32_t block_id,
+ opt::Instruction new_terminator);
+
} // namespace fuzzerutil
} // namespace fuzz
} // namespace spvtools
diff --git a/source/fuzz/instruction_descriptor.cpp b/source/fuzz/instruction_descriptor.cpp
index c0cc5e52..fb1ff765 100644
--- a/source/fuzz/instruction_descriptor.cpp
+++ b/source/fuzz/instruction_descriptor.cpp
@@ -20,37 +20,32 @@ namespace fuzz {
opt::Instruction* FindInstruction(
const protobufs::InstructionDescriptor& instruction_descriptor,
spvtools::opt::IRContext* context) {
- for (auto& function : *context->module()) {
- for (auto& block : function) {
- bool found_base =
- block.id() == instruction_descriptor.base_instruction_result_id();
- uint32_t num_ignored = 0;
- for (auto& instruction : block) {
- if (instruction.HasResultId() &&
- instruction.result_id() ==
- instruction_descriptor.base_instruction_result_id()) {
- assert(!found_base &&
- "It should not be possible to find the base instruction "
- "multiple times.");
- found_base = true;
- assert(num_ignored == 0 &&
- "The skipped instruction count should only be incremented "
- "after the instruction base has been found.");
- }
- if (found_base &&
- instruction.opcode() ==
- instruction_descriptor.target_instruction_opcode()) {
- if (num_ignored == instruction_descriptor.num_opcodes_to_ignore()) {
- return &instruction;
- }
- num_ignored++;
- }
- }
- if (found_base) {
- // We found the base instruction, but did not find the target
- // instruction in the same block.
- return nullptr;
+ auto block = context->get_instr_block(
+ instruction_descriptor.base_instruction_result_id());
+ if (block == nullptr) {
+ return nullptr;
+ }
+ bool found_base =
+ block->id() == instruction_descriptor.base_instruction_result_id();
+ uint32_t num_ignored = 0;
+ for (auto& instruction : *block) {
+ if (instruction.HasResultId() &&
+ instruction.result_id() ==
+ instruction_descriptor.base_instruction_result_id()) {
+ assert(!found_base &&
+ "It should not be possible to find the base instruction "
+ "multiple times.");
+ found_base = true;
+ assert(num_ignored == 0 &&
+ "The skipped instruction count should only be incremented "
+ "after the instruction base has been found.");
+ }
+ if (found_base && instruction.opcode() ==
+ instruction_descriptor.target_instruction_opcode()) {
+ if (num_ignored == instruction_descriptor.num_opcodes_to_ignore()) {
+ return &instruction;
}
+ num_ignored++;
}
}
return nullptr;
diff --git a/source/fuzz/pass_management/repeated_pass_manager.cpp b/source/fuzz/pass_management/repeated_pass_manager.cpp
index 032f2645..ec443733 100644
--- a/source/fuzz/pass_management/repeated_pass_manager.cpp
+++ b/source/fuzz/pass_management/repeated_pass_manager.cpp
@@ -14,6 +14,10 @@
#include "source/fuzz/pass_management/repeated_pass_manager.h"
+#include "source/fuzz/pass_management/repeated_pass_manager_looped_with_recommendations.h"
+#include "source/fuzz/pass_management/repeated_pass_manager_random_with_recommendations.h"
+#include "source/fuzz/pass_management/repeated_pass_manager_simple.h"
+
namespace spvtools {
namespace fuzz {
@@ -23,5 +27,25 @@ RepeatedPassManager::RepeatedPassManager(FuzzerContext* fuzzer_context,
RepeatedPassManager::~RepeatedPassManager() = default;
+std::unique_ptr<RepeatedPassManager> RepeatedPassManager::Create(
+ RepeatedPassStrategy strategy, FuzzerContext* fuzzer_context,
+ RepeatedPassInstances* pass_instances,
+ RepeatedPassRecommender* pass_recommender) {
+ switch (strategy) {
+ case RepeatedPassStrategy::kSimple:
+ return MakeUnique<RepeatedPassManagerSimple>(fuzzer_context,
+ pass_instances);
+ case RepeatedPassStrategy::kLoopedWithRecommendations:
+ return MakeUnique<RepeatedPassManagerLoopedWithRecommendations>(
+ fuzzer_context, pass_instances, pass_recommender);
+ case RepeatedPassStrategy::kRandomWithRecommendations:
+ return MakeUnique<RepeatedPassManagerRandomWithRecommendations>(
+ fuzzer_context, pass_instances, pass_recommender);
+ }
+
+ assert(false && "Unreachable");
+ return nullptr;
+}
+
} // namespace fuzz
} // namespace spvtools
diff --git a/source/fuzz/pass_management/repeated_pass_manager.h b/source/fuzz/pass_management/repeated_pass_manager.h
index 1c231792..1e6ae3e4 100644
--- a/source/fuzz/pass_management/repeated_pass_manager.h
+++ b/source/fuzz/pass_management/repeated_pass_manager.h
@@ -18,11 +18,21 @@
#include "source/fuzz/fuzzer_context.h"
#include "source/fuzz/fuzzer_pass.h"
#include "source/fuzz/pass_management/repeated_pass_instances.h"
+#include "source/fuzz/pass_management/repeated_pass_recommender.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
namespace spvtools {
namespace fuzz {
+// Each field of this enum corresponds to an available repeated pass
+// strategy, and is used to decide which kind of RepeatedPassManager object
+// to create.
+enum class RepeatedPassStrategy {
+ kSimple,
+ kRandomWithRecommendations,
+ kLoopedWithRecommendations
+};
+
// An interface to encapsulate the manner in which the sequence of repeated
// passes that are applied during fuzzing is chosen. An implementation of this
// interface could, for example, keep track of the history of passes that have
@@ -40,6 +50,12 @@ class RepeatedPassManager {
virtual FuzzerPass* ChoosePass(
const protobufs::TransformationSequence& applied_transformations) = 0;
+ // Creates a corresponding RepeatedPassManager based on the |strategy|.
+ static std::unique_ptr<RepeatedPassManager> Create(
+ RepeatedPassStrategy strategy, FuzzerContext* fuzzer_context,
+ RepeatedPassInstances* pass_instances,
+ RepeatedPassRecommender* pass_recommender);
+
protected:
FuzzerContext* GetFuzzerContext() { return fuzzer_context_; }
diff --git a/source/fuzz/transformation_access_chain.cpp b/source/fuzz/transformation_access_chain.cpp
index daf73d63..97d4e041 100644
--- a/source/fuzz/transformation_access_chain.cpp
+++ b/source/fuzz/transformation_access_chain.cpp
@@ -23,8 +23,8 @@ namespace spvtools {
namespace fuzz {
TransformationAccessChain::TransformationAccessChain(
- const spvtools::fuzz::protobufs::TransformationAccessChain& message)
- : message_(message) {}
+ protobufs::TransformationAccessChain message)
+ : message_(std::move(message)) {}
TransformationAccessChain::TransformationAccessChain(
uint32_t fresh_id, uint32_t pointer_id,
@@ -228,6 +228,11 @@ void TransformationAccessChain::Apply(
uint32_t id_pairs_used = 0;
+ opt::Instruction* instruction_to_insert_before =
+ FindInstruction(message_.instruction_to_insert_before(), ir_context);
+ opt::BasicBlock* enclosing_block =
+ ir_context->get_instr_block(instruction_to_insert_before);
+
// Go through the index ids in turn.
for (auto index_id : message_.index_id()) {
uint32_t index_value;
@@ -280,29 +285,37 @@ void TransformationAccessChain::Apply(
// Clamp the integer and add the corresponding instructions in the module
// if |add_clamping_instructions| is set.
- auto instruction_to_insert_before =
- FindInstruction(message_.instruction_to_insert_before(), ir_context);
// Compare the index with the bound via an instruction of the form:
// %fresh_ids.first = OpULessThanEqual %bool %int_id %bound_minus_one.
fuzzerutil::UpdateModuleIdBound(ir_context, fresh_ids.first());
- instruction_to_insert_before->InsertBefore(MakeUnique<opt::Instruction>(
+ auto comparison_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpULessThanEqual, bool_type_id, fresh_ids.first(),
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {index_instruction->result_id()}},
- {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}})));
+ {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}}));
+ auto comparison_instruction_ptr = comparison_instruction.get();
+ instruction_to_insert_before->InsertBefore(
+ std::move(comparison_instruction));
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(
+ comparison_instruction_ptr);
+ ir_context->set_instr_block(comparison_instruction_ptr, enclosing_block);
// Select the index if in-bounds, otherwise one less than the bound:
// %fresh_ids.second = OpSelect %int_type %fresh_ids.first %int_id
// %bound_minus_one
fuzzerutil::UpdateModuleIdBound(ir_context, fresh_ids.second());
- instruction_to_insert_before->InsertBefore(MakeUnique<opt::Instruction>(
+ auto select_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpSelect, int_type_inst->result_id(),
fresh_ids.second(),
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {fresh_ids.first()}},
{SPV_OPERAND_TYPE_ID, {index_instruction->result_id()}},
- {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}})));
+ {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}}));
+ auto select_instruction_ptr = select_instruction.get();
+ instruction_to_insert_before->InsertBefore(std::move(select_instruction));
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(select_instruction_ptr);
+ ir_context->set_instr_block(select_instruction_ptr, enclosing_block);
new_index_id = fresh_ids.second();
@@ -326,13 +339,14 @@ void TransformationAccessChain::Apply(
// Add the access chain instruction to the module, and update the module's
// id bound.
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- FindInstruction(message_.instruction_to_insert_before(), ir_context)
- ->InsertBefore(MakeUnique<opt::Instruction>(
- ir_context, SpvOpAccessChain, result_type, message_.fresh_id(),
- operands));
-
- // Conservatively invalidate all analyses.
- ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+ auto access_chain_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpAccessChain, result_type, message_.fresh_id(), operands);
+ auto access_chain_instruction_ptr = access_chain_instruction.get();
+ instruction_to_insert_before->InsertBefore(
+ std::move(access_chain_instruction));
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(
+ access_chain_instruction_ptr);
+ ir_context->set_instr_block(access_chain_instruction_ptr, enclosing_block);
// If the base pointer's pointee value was irrelevant, the same is true of
// the pointee value of the result of this access chain.
diff --git a/source/fuzz/transformation_access_chain.h b/source/fuzz/transformation_access_chain.h
index 02cdc329..5582de39 100644
--- a/source/fuzz/transformation_access_chain.h
+++ b/source/fuzz/transformation_access_chain.h
@@ -28,7 +28,7 @@ namespace fuzz {
class TransformationAccessChain : public Transformation {
public:
explicit TransformationAccessChain(
- const protobufs::TransformationAccessChain& message);
+ protobufs::TransformationAccessChain message);
TransformationAccessChain(
uint32_t fresh_id, uint32_t pointer_id,
diff --git a/source/fuzz/transformation_add_bit_instruction_synonym.cpp b/source/fuzz/transformation_add_bit_instruction_synonym.cpp
index 6cdfdfb6..d232e13a 100644
--- a/source/fuzz/transformation_add_bit_instruction_synonym.cpp
+++ b/source/fuzz/transformation_add_bit_instruction_synonym.cpp
@@ -21,9 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddBitInstructionSynonym::TransformationAddBitInstructionSynonym(
- const spvtools::fuzz::protobufs::TransformationAddBitInstructionSynonym&
- message)
- : message_(message) {}
+ protobufs::TransformationAddBitInstructionSynonym message)
+ : message_(std::move(message)) {}
TransformationAddBitInstructionSynonym::TransformationAddBitInstructionSynonym(
const uint32_t instruction_result_id,
diff --git a/source/fuzz/transformation_add_bit_instruction_synonym.h b/source/fuzz/transformation_add_bit_instruction_synonym.h
index ed1a0af5..ad9d32d9 100644
--- a/source/fuzz/transformation_add_bit_instruction_synonym.h
+++ b/source/fuzz/transformation_add_bit_instruction_synonym.h
@@ -103,7 +103,7 @@ namespace fuzz {
class TransformationAddBitInstructionSynonym : public Transformation {
public:
explicit TransformationAddBitInstructionSynonym(
- const protobufs::TransformationAddBitInstructionSynonym& message);
+ protobufs::TransformationAddBitInstructionSynonym message);
TransformationAddBitInstructionSynonym(
const uint32_t instruction_result_id,
diff --git a/source/fuzz/transformation_add_constant_boolean.cpp b/source/fuzz/transformation_add_constant_boolean.cpp
index 937fdbcc..39354325 100644
--- a/source/fuzz/transformation_add_constant_boolean.cpp
+++ b/source/fuzz/transformation_add_constant_boolean.cpp
@@ -21,8 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddConstantBoolean::TransformationAddConstantBoolean(
- const protobufs::TransformationAddConstantBoolean& message)
- : message_(message) {}
+ protobufs::TransformationAddConstantBoolean message)
+ : message_(std::move(message)) {}
TransformationAddConstantBoolean::TransformationAddConstantBoolean(
uint32_t fresh_id, bool is_true, bool is_irrelevant) {
@@ -42,14 +42,18 @@ void TransformationAddConstantBoolean::Apply(
TransformationContext* transformation_context) const {
// Add the boolean constant to the module, ensuring the module's id bound is
// high enough.
+ auto new_instruction = MakeUnique<opt::Instruction>(
+ ir_context, message_.is_true() ? SpvOpConstantTrue : SpvOpConstantFalse,
+ fuzzerutil::MaybeGetBoolType(ir_context), message_.fresh_id(),
+ opt::Instruction::OperandList());
+ auto new_instruction_ptr = new_instruction.get();
+ ir_context->module()->AddGlobalValue(std::move(new_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- ir_context->module()->AddGlobalValue(
- message_.is_true() ? SpvOpConstantTrue : SpvOpConstantFalse,
- message_.fresh_id(), fuzzerutil::MaybeGetBoolType(ir_context));
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+
+ // Inform the def-use manager about the new instruction. Invalidate the
+ // constant manager as we have added a new constant.
+ ir_context->get_def_use_mgr()->AnalyzeInstDef(new_instruction_ptr);
+ ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisConstants);
if (message_.is_irrelevant()) {
transformation_context->GetFactManager()->AddFactIdIsIrrelevant(
diff --git a/source/fuzz/transformation_add_constant_boolean.h b/source/fuzz/transformation_add_constant_boolean.h
index d1d04efd..7f31471c 100644
--- a/source/fuzz/transformation_add_constant_boolean.h
+++ b/source/fuzz/transformation_add_constant_boolean.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddConstantBoolean : public Transformation {
public:
explicit TransformationAddConstantBoolean(
- const protobufs::TransformationAddConstantBoolean& message);
+ protobufs::TransformationAddConstantBoolean message);
TransformationAddConstantBoolean(uint32_t fresh_id, bool is_true,
bool is_irrelevant);
diff --git a/source/fuzz/transformation_add_constant_composite.cpp b/source/fuzz/transformation_add_constant_composite.cpp
index 02603210..e6cd5a96 100644
--- a/source/fuzz/transformation_add_constant_composite.cpp
+++ b/source/fuzz/transformation_add_constant_composite.cpp
@@ -22,9 +22,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddConstantComposite::TransformationAddConstantComposite(
- const spvtools::fuzz::protobufs::TransformationAddConstantComposite&
- message)
- : message_(message) {}
+ spvtools::fuzz::protobufs::TransformationAddConstantComposite message)
+ : message_(std::move(message)) {}
TransformationAddConstantComposite::TransformationAddConstantComposite(
uint32_t fresh_id, uint32_t type_id,
@@ -120,14 +119,17 @@ void TransformationAddConstantComposite::Apply(
for (auto constituent_id : message_.constituent_id()) {
in_operands.push_back({SPV_OPERAND_TYPE_ID, {constituent_id}});
}
- ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ auto new_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpConstantComposite, message_.type_id(),
- message_.fresh_id(), in_operands));
+ message_.fresh_id(), in_operands);
+ auto new_instruction_ptr = new_instruction.get();
+ ir_context->module()->AddGlobalValue(std::move(new_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+
+ // Inform the def-use manager of the new instruction. Invalidate the constant
+ // manager as we have added a new constant.
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction_ptr);
+ ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisConstants);
if (message_.is_irrelevant()) {
transformation_context->GetFactManager()->AddFactIdIsIrrelevant(
diff --git a/source/fuzz/transformation_add_constant_composite.h b/source/fuzz/transformation_add_constant_composite.h
index 9e9222dc..94e7a927 100644
--- a/source/fuzz/transformation_add_constant_composite.h
+++ b/source/fuzz/transformation_add_constant_composite.h
@@ -28,7 +28,7 @@ namespace fuzz {
class TransformationAddConstantComposite : public Transformation {
public:
explicit TransformationAddConstantComposite(
- const protobufs::TransformationAddConstantComposite& message);
+ protobufs::TransformationAddConstantComposite message);
TransformationAddConstantComposite(
uint32_t fresh_id, uint32_t type_id,
diff --git a/source/fuzz/transformation_add_constant_null.cpp b/source/fuzz/transformation_add_constant_null.cpp
index 3c66ab10..32544e6d 100644
--- a/source/fuzz/transformation_add_constant_null.cpp
+++ b/source/fuzz/transformation_add_constant_null.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddConstantNull::TransformationAddConstantNull(
- const spvtools::fuzz::protobufs::TransformationAddConstantNull& message)
- : message_(message) {}
+ spvtools::fuzz::protobufs::TransformationAddConstantNull message)
+ : message_(std::move(message)) {}
TransformationAddConstantNull::TransformationAddConstantNull(uint32_t fresh_id,
uint32_t type_id) {
@@ -46,14 +46,18 @@ bool TransformationAddConstantNull::IsApplicable(
}
void TransformationAddConstantNull::Apply(
- opt::IRContext* context, TransformationContext* /*unused*/) const {
- context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
- context, SpvOpConstantNull, message_.type_id(), message_.fresh_id(),
- opt::Instruction::OperandList()));
- fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+ opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
+ auto new_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpConstantNull, message_.type_id(), message_.fresh_id(),
+ opt::Instruction::OperandList());
+ auto new_instruction_ptr = new_instruction.get();
+ ir_context->module()->AddGlobalValue(std::move(new_instruction));
+ fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+
+ // Inform the def-use manager about the new instruction. Invalidate the
+ // constant manager as we have added a new constant.
+ ir_context->get_def_use_mgr()->AnalyzeInstDef(new_instruction_ptr);
+ ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisConstants);
}
protobufs::Transformation TransformationAddConstantNull::ToMessage() const {
diff --git a/source/fuzz/transformation_add_constant_null.h b/source/fuzz/transformation_add_constant_null.h
index bd08b1da..bb1d1b7c 100644
--- a/source/fuzz/transformation_add_constant_null.h
+++ b/source/fuzz/transformation_add_constant_null.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddConstantNull : public Transformation {
public:
explicit TransformationAddConstantNull(
- const protobufs::TransformationAddConstantNull& message);
+ protobufs::TransformationAddConstantNull message);
TransformationAddConstantNull(uint32_t fresh_id, uint32_t type_id);
@@ -34,12 +34,12 @@ class TransformationAddConstantNull : public Transformation {
// - |message_.type_id| must be the id of a type for which it is acceptable
// to create a null constant
bool IsApplicable(
- opt::IRContext* context,
+ opt::IRContext* ir_context,
const TransformationContext& transformation_context) const override;
// Adds an OpConstantNull instruction to the module, with |message_.type_id|
// as its type. The instruction has result id |message_.fresh_id|.
- void Apply(opt::IRContext* context,
+ void Apply(opt::IRContext* ir_context,
TransformationContext* transformation_context) const override;
std::unordered_set<uint32_t> GetFreshIds() const override;
diff --git a/source/fuzz/transformation_add_constant_scalar.cpp b/source/fuzz/transformation_add_constant_scalar.cpp
index 9a6642a9..a2d95fb6 100644
--- a/source/fuzz/transformation_add_constant_scalar.cpp
+++ b/source/fuzz/transformation_add_constant_scalar.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddConstantScalar::TransformationAddConstantScalar(
- const spvtools::fuzz::protobufs::TransformationAddConstantScalar& message)
- : message_(message) {}
+ spvtools::fuzz::protobufs::TransformationAddConstantScalar message)
+ : message_(std::move(message)) {}
TransformationAddConstantScalar::TransformationAddConstantScalar(
uint32_t fresh_id, uint32_t type_id, const std::vector<uint32_t>& words,
@@ -64,19 +64,21 @@ bool TransformationAddConstantScalar::IsApplicable(
void TransformationAddConstantScalar::Apply(
opt::IRContext* ir_context,
TransformationContext* transformation_context) const {
- ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ auto new_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpConstant, message_.type_id(), message_.fresh_id(),
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_LITERAL_INTEGER,
std::vector<uint32_t>(message_.word().begin(),
- message_.word().end())}})));
+ message_.word().end())}}));
+ auto new_instruction_ptr = new_instruction.get();
+ ir_context->module()->AddGlobalValue(std::move(new_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ // Inform the def-use manager about the new instruction. Invalidate the
+ // constant manager as we have added a new constant.
+ ir_context->get_def_use_mgr()->AnalyzeInstDef(new_instruction_ptr);
+ ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisConstants);
if (message_.is_irrelevant()) {
transformation_context->GetFactManager()->AddFactIdIsIrrelevant(
diff --git a/source/fuzz/transformation_add_constant_scalar.h b/source/fuzz/transformation_add_constant_scalar.h
index 3f23907c..adb07355 100644
--- a/source/fuzz/transformation_add_constant_scalar.h
+++ b/source/fuzz/transformation_add_constant_scalar.h
@@ -28,7 +28,7 @@ namespace fuzz {
class TransformationAddConstantScalar : public Transformation {
public:
explicit TransformationAddConstantScalar(
- const protobufs::TransformationAddConstantScalar& message);
+ protobufs::TransformationAddConstantScalar message);
TransformationAddConstantScalar(uint32_t fresh_id, uint32_t type_id,
const std::vector<uint32_t>& words,
diff --git a/source/fuzz/transformation_add_copy_memory.cpp b/source/fuzz/transformation_add_copy_memory.cpp
index 44bb9c57..5eb4bdc0 100644
--- a/source/fuzz/transformation_add_copy_memory.cpp
+++ b/source/fuzz/transformation_add_copy_memory.cpp
@@ -22,8 +22,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddCopyMemory::TransformationAddCopyMemory(
- const protobufs::TransformationAddCopyMemory& message)
- : message_(message) {}
+ protobufs::TransformationAddCopyMemory message)
+ : message_(std::move(message)) {}
TransformationAddCopyMemory::TransformationAddCopyMemory(
const protobufs::InstructionDescriptor& instruction_descriptor,
@@ -99,15 +99,8 @@ void TransformationAddCopyMemory::Apply(
auto* insert_before_inst =
FindInstruction(message_.instruction_descriptor(), ir_context);
assert(insert_before_inst);
-
- auto insert_before_iter = fuzzerutil::GetIteratorForInstruction(
- ir_context->get_instr_block(insert_before_inst), insert_before_inst);
-
- insert_before_iter.InsertBefore(MakeUnique<opt::Instruction>(
- ir_context, SpvOpCopyMemory, 0, 0,
- opt::Instruction::OperandList{
- {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}},
- {SPV_OPERAND_TYPE_ID, {message_.source_id()}}}));
+ opt::BasicBlock* enclosing_block =
+ ir_context->get_instr_block(insert_before_inst);
// Add global or local variable to copy memory into.
auto storage_class = static_cast<SpvStorageClass>(message_.storage_class());
@@ -118,23 +111,35 @@ void TransformationAddCopyMemory::Apply(
storage_class);
if (storage_class == SpvStorageClassPrivate) {
- fuzzerutil::AddGlobalVariable(ir_context, message_.fresh_id(), type_id,
- storage_class, message_.initializer_id());
+ opt::Instruction* new_global =
+ fuzzerutil::AddGlobalVariable(ir_context, message_.fresh_id(), type_id,
+ storage_class, message_.initializer_id());
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_global);
} else {
assert(storage_class == SpvStorageClassFunction &&
"Storage class can be either Private or Function");
- fuzzerutil::AddLocalVariable(ir_context, message_.fresh_id(), type_id,
- ir_context->get_instr_block(insert_before_inst)
- ->GetParent()
- ->result_id(),
- message_.initializer_id());
+ opt::Function* enclosing_function = enclosing_block->GetParent();
+ opt::Instruction* new_local = fuzzerutil::AddLocalVariable(
+ ir_context, message_.fresh_id(), type_id,
+ enclosing_function->result_id(), message_.initializer_id());
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_local);
+ ir_context->set_instr_block(new_local, &*enclosing_function->entry());
}
- fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+ auto insert_before_iter = fuzzerutil::GetIteratorForInstruction(
+ enclosing_block, insert_before_inst);
+
+ auto new_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpCopyMemory, 0, 0,
+ opt::Instruction::OperandList{
+ {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}},
+ {SPV_OPERAND_TYPE_ID, {message_.source_id()}}});
+ auto new_instruction_ptr = new_instruction.get();
+ insert_before_iter.InsertBefore(std::move(new_instruction));
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction_ptr);
+ ir_context->set_instr_block(new_instruction_ptr, enclosing_block);
- // Make sure our changes are analyzed
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
// Even though the copy memory instruction will - at least temporarily - lead
// to the destination and source pointers referring to identical values, this
diff --git a/source/fuzz/transformation_add_copy_memory.h b/source/fuzz/transformation_add_copy_memory.h
index cc42f1e2..b25652fd 100644
--- a/source/fuzz/transformation_add_copy_memory.h
+++ b/source/fuzz/transformation_add_copy_memory.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddCopyMemory : public Transformation {
public:
explicit TransformationAddCopyMemory(
- const protobufs::TransformationAddCopyMemory& message);
+ protobufs::TransformationAddCopyMemory message);
TransformationAddCopyMemory(
const protobufs::InstructionDescriptor& instruction_descriptor,
diff --git a/source/fuzz/transformation_add_dead_block.cpp b/source/fuzz/transformation_add_dead_block.cpp
index 5dce3569..82e8cd8f 100644
--- a/source/fuzz/transformation_add_dead_block.cpp
+++ b/source/fuzz/transformation_add_dead_block.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddDeadBlock::TransformationAddDeadBlock(
- const spvtools::fuzz::protobufs::TransformationAddDeadBlock& message)
- : message_(message) {}
+ protobufs::TransformationAddDeadBlock message)
+ : message_(std::move(message)) {}
TransformationAddDeadBlock::TransformationAddDeadBlock(uint32_t fresh_id,
uint32_t existing_block,
diff --git a/source/fuzz/transformation_add_dead_block.h b/source/fuzz/transformation_add_dead_block.h
index 50af6b0b..d8b3c2ae 100644
--- a/source/fuzz/transformation_add_dead_block.h
+++ b/source/fuzz/transformation_add_dead_block.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddDeadBlock : public Transformation {
public:
explicit TransformationAddDeadBlock(
- const protobufs::TransformationAddDeadBlock& message);
+ protobufs::TransformationAddDeadBlock message);
TransformationAddDeadBlock(uint32_t fresh_id, uint32_t existing_block,
bool condition_value);
diff --git a/source/fuzz/transformation_add_dead_break.cpp b/source/fuzz/transformation_add_dead_break.cpp
index bc938d40..ad46ce7f 100644
--- a/source/fuzz/transformation_add_dead_break.cpp
+++ b/source/fuzz/transformation_add_dead_break.cpp
@@ -24,8 +24,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddDeadBreak::TransformationAddDeadBreak(
- const spvtools::fuzz::protobufs::TransformationAddDeadBreak& message)
- : message_(message) {}
+ protobufs::TransformationAddDeadBreak message)
+ : message_(std::move(message)) {}
TransformationAddDeadBreak::TransformationAddDeadBreak(
uint32_t from_block, uint32_t to_block, bool break_condition_value,
@@ -112,9 +112,10 @@ bool TransformationAddDeadBreak::IsApplicable(
const TransformationContext& transformation_context) const {
// First, we check that a constant with the same value as
// |message_.break_condition_value| is present.
- if (!fuzzerutil::MaybeGetBoolConstant(ir_context, transformation_context,
- message_.break_condition_value(),
- false)) {
+ const auto bool_id =
+ fuzzerutil::MaybeGetBoolConstant(ir_context, transformation_context,
+ message_.break_condition_value(), false);
+ if (!bool_id) {
// The required constant is not present, so the transformation cannot be
// applied.
return false;
@@ -171,25 +172,23 @@ bool TransformationAddDeadBreak::IsApplicable(
}
// Adding the dead break is only valid if SPIR-V rules related to dominance
- // hold. Rather than checking these rules explicitly, we defer to the
- // validator. We make a clone of the module, apply the transformation to the
- // clone, and check whether the transformed clone is valid.
- //
- // In principle some of the above checks could be removed, with more reliance
- // being places on the validator. This should be revisited if we are sure
- // the validator is complete with respect to checking structured control flow
- // rules.
- auto cloned_context = fuzzerutil::CloneIRContext(ir_context);
- ApplyImpl(cloned_context.get(), transformation_context);
- return fuzzerutil::IsValid(cloned_context.get(),
- transformation_context.GetValidatorOptions(),
- fuzzerutil::kSilentMessageConsumer);
+ // hold.
+ return fuzzerutil::NewTerminatorPreservesDominationRules(
+ ir_context, message_.from_block(),
+ fuzzerutil::CreateUnreachableEdgeInstruction(
+ ir_context, message_.from_block(), message_.to_block(), bool_id));
}
void TransformationAddDeadBreak::Apply(
opt::IRContext* ir_context,
TransformationContext* transformation_context) const {
- ApplyImpl(ir_context, *transformation_context);
+ fuzzerutil::AddUnreachableEdgeAndUpdateOpPhis(
+ ir_context, ir_context->cfg()->block(message_.from_block()),
+ ir_context->cfg()->block(message_.to_block()),
+ fuzzerutil::MaybeGetBoolConstant(ir_context, *transformation_context,
+ message_.break_condition_value(), false),
+ message_.phi_id());
+
// Invalidate all analyses
ir_context->InvalidateAnalysesExceptFor(
opt::IRContext::Analysis::kAnalysisNone);
@@ -201,17 +200,6 @@ protobufs::Transformation TransformationAddDeadBreak::ToMessage() const {
return result;
}
-void TransformationAddDeadBreak::ApplyImpl(
- spvtools::opt::IRContext* ir_context,
- const TransformationContext& transformation_context) const {
- fuzzerutil::AddUnreachableEdgeAndUpdateOpPhis(
- ir_context, ir_context->cfg()->block(message_.from_block()),
- ir_context->cfg()->block(message_.to_block()),
- fuzzerutil::MaybeGetBoolConstant(ir_context, transformation_context,
- message_.break_condition_value(), false),
- message_.phi_id());
-}
-
std::unordered_set<uint32_t> TransformationAddDeadBreak::GetFreshIds() const {
return std::unordered_set<uint32_t>();
}
diff --git a/source/fuzz/transformation_add_dead_break.h b/source/fuzz/transformation_add_dead_break.h
index afb8dc7b..8c1ab4a4 100644
--- a/source/fuzz/transformation_add_dead_break.h
+++ b/source/fuzz/transformation_add_dead_break.h
@@ -28,7 +28,7 @@ namespace fuzz {
class TransformationAddDeadBreak : public Transformation {
public:
explicit TransformationAddDeadBreak(
- const protobufs::TransformationAddDeadBreak& message);
+ protobufs::TransformationAddDeadBreak message);
TransformationAddDeadBreak(uint32_t from_block, uint32_t to_block,
bool break_condition_value,
@@ -71,15 +71,6 @@ class TransformationAddDeadBreak : public Transformation {
bool AddingBreakRespectsStructuredControlFlow(opt::IRContext* ir_context,
opt::BasicBlock* bb_from) const;
- // Used by 'Apply' to actually apply the transformation to the module of
- // interest, and by 'IsApplicable' to do a dry-run of the transformation on a
- // cloned module, in order to check that the transformation leads to a valid
- // module. This is only invoked by 'IsApplicable' after certain basic
- // applicability checks have been made, ensuring that the invocation of this
- // method is legal.
- void ApplyImpl(opt::IRContext* ir_context,
- const TransformationContext& transformation_context) const;
-
protobufs::TransformationAddDeadBreak message_;
};
diff --git a/source/fuzz/transformation_add_dead_continue.cpp b/source/fuzz/transformation_add_dead_continue.cpp
index 18b3c39f..be6294e8 100644
--- a/source/fuzz/transformation_add_dead_continue.cpp
+++ b/source/fuzz/transformation_add_dead_continue.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddDeadContinue::TransformationAddDeadContinue(
- const spvtools::fuzz::protobufs::TransformationAddDeadContinue& message)
- : message_(message) {}
+ protobufs::TransformationAddDeadContinue message)
+ : message_(std::move(message)) {}
TransformationAddDeadContinue::TransformationAddDeadContinue(
uint32_t from_block, bool continue_condition_value,
@@ -38,9 +38,10 @@ bool TransformationAddDeadContinue::IsApplicable(
const TransformationContext& transformation_context) const {
// First, we check that a constant with the same value as
// |message_.continue_condition_value| is present.
- if (!fuzzerutil::MaybeGetBoolConstant(ir_context, transformation_context,
- message_.continue_condition_value(),
- false)) {
+ const auto bool_id = fuzzerutil::MaybeGetBoolConstant(
+ ir_context, transformation_context, message_.continue_condition_value(),
+ false);
+ if (!bool_id) {
// The required constant is not present, so the transformation cannot be
// applied.
return false;
@@ -111,39 +112,16 @@ bool TransformationAddDeadContinue::IsApplicable(
}
// Adding the dead break is only valid if SPIR-V rules related to dominance
- // hold. Rather than checking these rules explicitly, we defer to the
- // validator. We make a clone of the module, apply the transformation to the
- // clone, and check whether the transformed clone is valid.
- //
- // In principle some of the above checks could be removed, with more reliance
- // being placed on the validator. This should be revisited if we are sure
- // the validator is complete with respect to checking structured control flow
- // rules.
- auto cloned_context = fuzzerutil::CloneIRContext(ir_context);
- ApplyImpl(cloned_context.get(), transformation_context);
- return fuzzerutil::IsValid(cloned_context.get(),
- transformation_context.GetValidatorOptions(),
- fuzzerutil::kSilentMessageConsumer);
+ // hold.
+ return fuzzerutil::NewTerminatorPreservesDominationRules(
+ ir_context, message_.from_block(),
+ fuzzerutil::CreateUnreachableEdgeInstruction(
+ ir_context, message_.from_block(), continue_block, bool_id));
}
void TransformationAddDeadContinue::Apply(
opt::IRContext* ir_context,
TransformationContext* transformation_context) const {
- ApplyImpl(ir_context, *transformation_context);
- // Invalidate all analyses
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
-}
-
-protobufs::Transformation TransformationAddDeadContinue::ToMessage() const {
- protobufs::Transformation result;
- *result.mutable_add_dead_continue() = message_;
- return result;
-}
-
-void TransformationAddDeadContinue::ApplyImpl(
- spvtools::opt::IRContext* ir_context,
- const TransformationContext& transformation_context) const {
auto bb_from = ir_context->cfg()->block(message_.from_block());
auto continue_block =
bb_from->IsLoopHeader()
@@ -153,10 +131,20 @@ void TransformationAddDeadContinue::ApplyImpl(
assert(continue_block && "message_.from_block must be in a loop.");
fuzzerutil::AddUnreachableEdgeAndUpdateOpPhis(
ir_context, bb_from, ir_context->cfg()->block(continue_block),
- fuzzerutil::MaybeGetBoolConstant(ir_context, transformation_context,
+ fuzzerutil::MaybeGetBoolConstant(ir_context, *transformation_context,
message_.continue_condition_value(),
false),
message_.phi_id());
+
+ // Invalidate all analyses
+ ir_context->InvalidateAnalysesExceptFor(
+ opt::IRContext::Analysis::kAnalysisNone);
+}
+
+protobufs::Transformation TransformationAddDeadContinue::ToMessage() const {
+ protobufs::Transformation result;
+ *result.mutable_add_dead_continue() = message_;
+ return result;
}
std::unordered_set<uint32_t> TransformationAddDeadContinue::GetFreshIds()
diff --git a/source/fuzz/transformation_add_dead_continue.h b/source/fuzz/transformation_add_dead_continue.h
index 27527e78..9463aebc 100644
--- a/source/fuzz/transformation_add_dead_continue.h
+++ b/source/fuzz/transformation_add_dead_continue.h
@@ -28,7 +28,7 @@ namespace fuzz {
class TransformationAddDeadContinue : public Transformation {
public:
explicit TransformationAddDeadContinue(
- const protobufs::TransformationAddDeadContinue& message);
+ protobufs::TransformationAddDeadContinue message);
TransformationAddDeadContinue(uint32_t from_block,
bool continue_condition_value,
@@ -68,15 +68,6 @@ class TransformationAddDeadContinue : public Transformation {
protobufs::Transformation ToMessage() const override;
private:
- // Used by 'Apply' to actually apply the transformation to the module of
- // interest, and by 'IsApplicable' to do a dry-run of the transformation on a
- // cloned module, in order to check that the transformation leads to a valid
- // module. This is only invoked by 'IsApplicable' after certain basic
- // applicability checks have been made, ensuring that the invocation of this
- // method is legal.
- void ApplyImpl(opt::IRContext* ir_context,
- const TransformationContext& transformation_context) const;
-
protobufs::TransformationAddDeadContinue message_;
};
diff --git a/source/fuzz/transformation_add_early_terminator_wrapper.cpp b/source/fuzz/transformation_add_early_terminator_wrapper.cpp
index 9f86070f..547398aa 100644
--- a/source/fuzz/transformation_add_early_terminator_wrapper.cpp
+++ b/source/fuzz/transformation_add_early_terminator_wrapper.cpp
@@ -22,9 +22,8 @@ namespace fuzz {
TransformationAddEarlyTerminatorWrapper::
TransformationAddEarlyTerminatorWrapper(
- const spvtools::fuzz::protobufs::
- TransformationAddEarlyTerminatorWrapper& message)
- : message_(message) {}
+ protobufs::TransformationAddEarlyTerminatorWrapper message)
+ : message_(std::move(message)) {}
TransformationAddEarlyTerminatorWrapper::
TransformationAddEarlyTerminatorWrapper(uint32_t function_fresh_id,
diff --git a/source/fuzz/transformation_add_early_terminator_wrapper.h b/source/fuzz/transformation_add_early_terminator_wrapper.h
index 273037e5..97cc527c 100644
--- a/source/fuzz/transformation_add_early_terminator_wrapper.h
+++ b/source/fuzz/transformation_add_early_terminator_wrapper.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddEarlyTerminatorWrapper : public Transformation {
public:
explicit TransformationAddEarlyTerminatorWrapper(
- const protobufs::TransformationAddEarlyTerminatorWrapper& message);
+ protobufs::TransformationAddEarlyTerminatorWrapper message);
TransformationAddEarlyTerminatorWrapper(uint32_t function_fresh_id,
uint32_t label_fresh_id,
diff --git a/source/fuzz/transformation_add_function.cpp b/source/fuzz/transformation_add_function.cpp
index 9799373d..06cd6572 100644
--- a/source/fuzz/transformation_add_function.cpp
+++ b/source/fuzz/transformation_add_function.cpp
@@ -21,8 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddFunction::TransformationAddFunction(
- const spvtools::fuzz::protobufs::TransformationAddFunction& message)
- : message_(message) {}
+ protobufs::TransformationAddFunction message)
+ : message_(std::move(message)) {}
TransformationAddFunction::TransformationAddFunction(
const std::vector<protobufs::Instruction>& instructions) {
diff --git a/source/fuzz/transformation_add_function.h b/source/fuzz/transformation_add_function.h
index e5381d14..c41eee33 100644
--- a/source/fuzz/transformation_add_function.h
+++ b/source/fuzz/transformation_add_function.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddFunction : public Transformation {
public:
explicit TransformationAddFunction(
- const protobufs::TransformationAddFunction& message);
+ protobufs::TransformationAddFunction message);
// Creates a transformation to add a non live-safe function.
explicit TransformationAddFunction(
diff --git a/source/fuzz/transformation_add_global_undef.cpp b/source/fuzz/transformation_add_global_undef.cpp
index 7a90b821..eb390ea0 100644
--- a/source/fuzz/transformation_add_global_undef.cpp
+++ b/source/fuzz/transformation_add_global_undef.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddGlobalUndef::TransformationAddGlobalUndef(
- const spvtools::fuzz::protobufs::TransformationAddGlobalUndef& message)
- : message_(message) {}
+ spvtools::fuzz::protobufs::TransformationAddGlobalUndef message)
+ : message_(std::move(message)) {}
TransformationAddGlobalUndef::TransformationAddGlobalUndef(uint32_t fresh_id,
uint32_t type_id) {
@@ -42,14 +42,14 @@ bool TransformationAddGlobalUndef::IsApplicable(
void TransformationAddGlobalUndef::Apply(
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
- ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+ auto new_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpUndef, message_.type_id(), message_.fresh_id(),
- opt::Instruction::OperandList()));
+ opt::Instruction::OperandList());
+ auto new_instruction_ptr = new_instruction.get();
+ ir_context->module()->AddGlobalValue(std::move(new_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ // Inform the def-use manager about the new instruction.
+ ir_context->get_def_use_mgr()->AnalyzeInstDef(new_instruction_ptr);
}
protobufs::Transformation TransformationAddGlobalUndef::ToMessage() const {
diff --git a/source/fuzz/transformation_add_global_undef.h b/source/fuzz/transformation_add_global_undef.h
index 717dc9ad..37542c3f 100644
--- a/source/fuzz/transformation_add_global_undef.h
+++ b/source/fuzz/transformation_add_global_undef.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddGlobalUndef : public Transformation {
public:
explicit TransformationAddGlobalUndef(
- const protobufs::TransformationAddGlobalUndef& message);
+ protobufs::TransformationAddGlobalUndef message);
TransformationAddGlobalUndef(uint32_t fresh_id, uint32_t type_id);
diff --git a/source/fuzz/transformation_add_global_variable.cpp b/source/fuzz/transformation_add_global_variable.cpp
index dd04e48a..814d01b3 100644
--- a/source/fuzz/transformation_add_global_variable.cpp
+++ b/source/fuzz/transformation_add_global_variable.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddGlobalVariable::TransformationAddGlobalVariable(
- const spvtools::fuzz::protobufs::TransformationAddGlobalVariable& message)
- : message_(message) {}
+ spvtools::fuzz::protobufs::TransformationAddGlobalVariable message)
+ : message_(std::move(message)) {}
TransformationAddGlobalVariable::TransformationAddGlobalVariable(
uint32_t fresh_id, uint32_t type_id, SpvStorageClass storage_class,
@@ -93,15 +93,13 @@ bool TransformationAddGlobalVariable::IsApplicable(
void TransformationAddGlobalVariable::Apply(
opt::IRContext* ir_context,
TransformationContext* transformation_context) const {
- fuzzerutil::AddGlobalVariable(
+ opt::Instruction* new_instruction = fuzzerutil::AddGlobalVariable(
ir_context, message_.fresh_id(), message_.type_id(),
static_cast<SpvStorageClass>(message_.storage_class()),
message_.initializer_id());
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ // Inform the def-use manager about the new instruction.
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction);
if (message_.value_is_irrelevant()) {
transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
diff --git a/source/fuzz/transformation_add_global_variable.h b/source/fuzz/transformation_add_global_variable.h
index 8d46edb7..d74d48a2 100644
--- a/source/fuzz/transformation_add_global_variable.h
+++ b/source/fuzz/transformation_add_global_variable.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddGlobalVariable : public Transformation {
public:
explicit TransformationAddGlobalVariable(
- const protobufs::TransformationAddGlobalVariable& message);
+ protobufs::TransformationAddGlobalVariable message);
TransformationAddGlobalVariable(uint32_t fresh_id, uint32_t type_id,
SpvStorageClass storage_class,
diff --git a/source/fuzz/transformation_add_image_sample_unused_components.cpp b/source/fuzz/transformation_add_image_sample_unused_components.cpp
index ab48f0b6..1ead82bc 100644
--- a/source/fuzz/transformation_add_image_sample_unused_components.cpp
+++ b/source/fuzz/transformation_add_image_sample_unused_components.cpp
@@ -22,9 +22,8 @@ namespace fuzz {
TransformationAddImageSampleUnusedComponents::
TransformationAddImageSampleUnusedComponents(
- const spvtools::fuzz::protobufs::
- TransformationAddImageSampleUnusedComponents& message)
- : message_(message) {}
+ protobufs::TransformationAddImageSampleUnusedComponents message)
+ : message_(std::move(message)) {}
TransformationAddImageSampleUnusedComponents::
TransformationAddImageSampleUnusedComponents(
diff --git a/source/fuzz/transformation_add_image_sample_unused_components.h b/source/fuzz/transformation_add_image_sample_unused_components.h
index 7486c760..7b13f9f6 100644
--- a/source/fuzz/transformation_add_image_sample_unused_components.h
+++ b/source/fuzz/transformation_add_image_sample_unused_components.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddImageSampleUnusedComponents : public Transformation {
public:
explicit TransformationAddImageSampleUnusedComponents(
- const protobufs::TransformationAddImageSampleUnusedComponents& message);
+ protobufs::TransformationAddImageSampleUnusedComponents message);
TransformationAddImageSampleUnusedComponents(
uint32_t coordinate_with_unused_components_id,
diff --git a/source/fuzz/transformation_add_local_variable.cpp b/source/fuzz/transformation_add_local_variable.cpp
index 0a7a3dac..21768d22 100644
--- a/source/fuzz/transformation_add_local_variable.cpp
+++ b/source/fuzz/transformation_add_local_variable.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddLocalVariable::TransformationAddLocalVariable(
- const spvtools::fuzz::protobufs::TransformationAddLocalVariable& message)
- : message_(message) {}
+ spvtools::fuzz::protobufs::TransformationAddLocalVariable message)
+ : message_(std::move(message)) {}
TransformationAddLocalVariable::TransformationAddLocalVariable(
uint32_t fresh_id, uint32_t type_id, uint32_t function_id,
@@ -70,11 +70,17 @@ bool TransformationAddLocalVariable::IsApplicable(
void TransformationAddLocalVariable::Apply(
opt::IRContext* ir_context,
TransformationContext* transformation_context) const {
- fuzzerutil::AddLocalVariable(ir_context, message_.fresh_id(),
- message_.type_id(), message_.function_id(),
- message_.initializer_id());
+ opt::Instruction* new_instruction = fuzzerutil::AddLocalVariable(
+ ir_context, message_.fresh_id(), message_.type_id(),
+ message_.function_id(), message_.initializer_id());
- ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+ // Inform the def-use manager about the new instruction.
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction);
+ ir_context->set_instr_block(
+ new_instruction,
+ fuzzerutil::FindFunction(ir_context, message_.function_id())
+ ->entry()
+ .get());
if (message_.value_is_irrelevant()) {
transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
diff --git a/source/fuzz/transformation_add_local_variable.h b/source/fuzz/transformation_add_local_variable.h
index 963079f5..b008a1c0 100644
--- a/source/fuzz/transformation_add_local_variable.h
+++ b/source/fuzz/transformation_add_local_variable.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddLocalVariable : public Transformation {
public:
explicit TransformationAddLocalVariable(
- const protobufs::TransformationAddLocalVariable& message);
+ protobufs::TransformationAddLocalVariable message);
TransformationAddLocalVariable(uint32_t fresh_id, uint32_t type_id,
uint32_t function_id, uint32_t initializer_id,
diff --git a/source/fuzz/transformation_add_loop_preheader.cpp b/source/fuzz/transformation_add_loop_preheader.cpp
index 3d50fa92..71ab18da 100644
--- a/source/fuzz/transformation_add_loop_preheader.cpp
+++ b/source/fuzz/transformation_add_loop_preheader.cpp
@@ -20,8 +20,8 @@
namespace spvtools {
namespace fuzz {
TransformationAddLoopPreheader::TransformationAddLoopPreheader(
- const protobufs::TransformationAddLoopPreheader& message)
- : message_(message) {}
+ protobufs::TransformationAddLoopPreheader message)
+ : message_(std::move(message)) {}
TransformationAddLoopPreheader::TransformationAddLoopPreheader(
uint32_t loop_header_block, uint32_t fresh_id,
diff --git a/source/fuzz/transformation_add_loop_preheader.h b/source/fuzz/transformation_add_loop_preheader.h
index 05448f3f..9d2c565f 100644
--- a/source/fuzz/transformation_add_loop_preheader.h
+++ b/source/fuzz/transformation_add_loop_preheader.h
@@ -23,7 +23,7 @@ namespace fuzz {
class TransformationAddLoopPreheader : public Transformation {
public:
explicit TransformationAddLoopPreheader(
- const protobufs::TransformationAddLoopPreheader& message);
+ protobufs::TransformationAddLoopPreheader message);
TransformationAddLoopPreheader(uint32_t loop_header_block, uint32_t fresh_id,
std::vector<uint32_t> phi_id);
diff --git a/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp b/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp
index 45d3fc85..657fafa4 100644
--- a/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp
+++ b/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp
@@ -23,9 +23,8 @@ uint32_t kMaxNumOfIterations = 32;
TransformationAddLoopToCreateIntConstantSynonym::
TransformationAddLoopToCreateIntConstantSynonym(
- const protobufs::TransformationAddLoopToCreateIntConstantSynonym&
- message)
- : message_(message) {}
+ protobufs::TransformationAddLoopToCreateIntConstantSynonym message)
+ : message_(std::move(message)) {}
TransformationAddLoopToCreateIntConstantSynonym::
TransformationAddLoopToCreateIntConstantSynonym(
diff --git a/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.h b/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.h
index 67c3bcd2..a6dfe63a 100644
--- a/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.h
+++ b/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.h
@@ -22,8 +22,7 @@ namespace fuzz {
class TransformationAddLoopToCreateIntConstantSynonym : public Transformation {
public:
explicit TransformationAddLoopToCreateIntConstantSynonym(
- const protobufs::TransformationAddLoopToCreateIntConstantSynonym&
- message);
+ protobufs::TransformationAddLoopToCreateIntConstantSynonym message);
TransformationAddLoopToCreateIntConstantSynonym(
uint32_t constant_id, uint32_t initial_val_id, uint32_t step_val_id,
diff --git a/source/fuzz/transformation_add_no_contraction_decoration.cpp b/source/fuzz/transformation_add_no_contraction_decoration.cpp
index 29a871df..992a216b 100644
--- a/source/fuzz/transformation_add_no_contraction_decoration.cpp
+++ b/source/fuzz/transformation_add_no_contraction_decoration.cpp
@@ -21,9 +21,8 @@ namespace fuzz {
TransformationAddNoContractionDecoration::
TransformationAddNoContractionDecoration(
- const spvtools::fuzz::protobufs::
- TransformationAddNoContractionDecoration& message)
- : message_(message) {}
+ protobufs::TransformationAddNoContractionDecoration message)
+ : message_(std::move(message)) {}
TransformationAddNoContractionDecoration::
TransformationAddNoContractionDecoration(uint32_t result_id) {
diff --git a/source/fuzz/transformation_add_no_contraction_decoration.h b/source/fuzz/transformation_add_no_contraction_decoration.h
index f5a34e81..2f78d429 100644
--- a/source/fuzz/transformation_add_no_contraction_decoration.h
+++ b/source/fuzz/transformation_add_no_contraction_decoration.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddNoContractionDecoration : public Transformation {
public:
explicit TransformationAddNoContractionDecoration(
- const protobufs::TransformationAddNoContractionDecoration& message);
+ protobufs::TransformationAddNoContractionDecoration message);
explicit TransformationAddNoContractionDecoration(uint32_t fresh_id);
diff --git a/source/fuzz/transformation_add_opphi_synonym.cpp b/source/fuzz/transformation_add_opphi_synonym.cpp
index 227c4338..3c4698a7 100644
--- a/source/fuzz/transformation_add_opphi_synonym.cpp
+++ b/source/fuzz/transformation_add_opphi_synonym.cpp
@@ -19,8 +19,8 @@
namespace spvtools {
namespace fuzz {
TransformationAddOpPhiSynonym::TransformationAddOpPhiSynonym(
- const protobufs::TransformationAddOpPhiSynonym& message)
- : message_(message) {}
+ protobufs::TransformationAddOpPhiSynonym message)
+ : message_(std::move(message)) {}
TransformationAddOpPhiSynonym::TransformationAddOpPhiSynonym(
uint32_t block_id, const std::map<uint32_t, uint32_t>& preds_to_ids,
diff --git a/source/fuzz/transformation_add_opphi_synonym.h b/source/fuzz/transformation_add_opphi_synonym.h
index 3b68abee..39ebea89 100644
--- a/source/fuzz/transformation_add_opphi_synonym.h
+++ b/source/fuzz/transformation_add_opphi_synonym.h
@@ -22,7 +22,7 @@ namespace fuzz {
class TransformationAddOpPhiSynonym : public Transformation {
public:
explicit TransformationAddOpPhiSynonym(
- const protobufs::TransformationAddOpPhiSynonym& message);
+ protobufs::TransformationAddOpPhiSynonym message);
TransformationAddOpPhiSynonym(
uint32_t block_id, const std::map<uint32_t, uint32_t>& preds_to_ids,
diff --git a/source/fuzz/transformation_add_parameter.cpp b/source/fuzz/transformation_add_parameter.cpp
index 9ed0bfb4..48de3e83 100644
--- a/source/fuzz/transformation_add_parameter.cpp
+++ b/source/fuzz/transformation_add_parameter.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddParameter::TransformationAddParameter(
- const protobufs::TransformationAddParameter& message)
- : message_(message) {}
+ protobufs::TransformationAddParameter message)
+ : message_(std::move(message)) {}
TransformationAddParameter::TransformationAddParameter(
uint32_t function_id, uint32_t parameter_fresh_id,
diff --git a/source/fuzz/transformation_add_parameter.h b/source/fuzz/transformation_add_parameter.h
index a33521da..0bc096e7 100644
--- a/source/fuzz/transformation_add_parameter.h
+++ b/source/fuzz/transformation_add_parameter.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddParameter : public Transformation {
public:
explicit TransformationAddParameter(
- const protobufs::TransformationAddParameter& message);
+ protobufs::TransformationAddParameter message);
TransformationAddParameter(uint32_t function_id, uint32_t parameter_fresh_id,
uint32_t parameter_type_id,
diff --git a/source/fuzz/transformation_add_relaxed_decoration.cpp b/source/fuzz/transformation_add_relaxed_decoration.cpp
index 7b513053..b66a1a83 100644
--- a/source/fuzz/transformation_add_relaxed_decoration.cpp
+++ b/source/fuzz/transformation_add_relaxed_decoration.cpp
@@ -20,9 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddRelaxedDecoration::TransformationAddRelaxedDecoration(
- const spvtools::fuzz::protobufs::TransformationAddRelaxedDecoration&
- message)
- : message_(message) {}
+ protobufs::TransformationAddRelaxedDecoration message)
+ : message_(std::move(message)) {}
TransformationAddRelaxedDecoration::TransformationAddRelaxedDecoration(
uint32_t result_id) {
diff --git a/source/fuzz/transformation_add_relaxed_decoration.h b/source/fuzz/transformation_add_relaxed_decoration.h
index 3f8bf3ed..c0163497 100644
--- a/source/fuzz/transformation_add_relaxed_decoration.h
+++ b/source/fuzz/transformation_add_relaxed_decoration.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddRelaxedDecoration : public Transformation {
public:
explicit TransformationAddRelaxedDecoration(
- const protobufs::TransformationAddRelaxedDecoration& message);
+ protobufs::TransformationAddRelaxedDecoration message);
explicit TransformationAddRelaxedDecoration(uint32_t fresh_id);
diff --git a/source/fuzz/transformation_add_synonym.cpp b/source/fuzz/transformation_add_synonym.cpp
index a516916b..40768e2e 100644
--- a/source/fuzz/transformation_add_synonym.cpp
+++ b/source/fuzz/transformation_add_synonym.cpp
@@ -102,14 +102,19 @@ void TransformationAddSynonym::Apply(
opt::IRContext* ir_context,
TransformationContext* transformation_context) const {
// Add a synonymous instruction.
- FindInstruction(message_.insert_before(), ir_context)
- ->InsertBefore(
- MakeSynonymousInstruction(ir_context, *transformation_context));
+ auto new_instruction =
+ MakeSynonymousInstruction(ir_context, *transformation_context);
+ auto new_instruction_ptr = new_instruction.get();
+ auto insert_before = FindInstruction(message_.insert_before(), ir_context);
+ insert_before->InsertBefore(std::move(new_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.synonym_fresh_id());
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ // Inform the def-use manager about the new instruction and record its basic
+ // block.
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction_ptr);
+ ir_context->set_instr_block(new_instruction_ptr,
+ ir_context->get_instr_block(insert_before));
// Propagate PointeeValueIsIrrelevant fact.
const auto* new_synonym_type = ir_context->get_type_mgr()->GetType(
diff --git a/source/fuzz/transformation_add_type_array.cpp b/source/fuzz/transformation_add_type_array.cpp
index c9f6a87a..45bc8dfe 100644
--- a/source/fuzz/transformation_add_type_array.cpp
+++ b/source/fuzz/transformation_add_type_array.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddTypeArray::TransformationAddTypeArray(
- const spvtools::fuzz::protobufs::TransformationAddTypeArray& message)
- : message_(message) {}
+ protobufs::TransformationAddTypeArray message)
+ : message_(std::move(message)) {}
TransformationAddTypeArray::TransformationAddTypeArray(uint32_t fresh_id,
uint32_t element_type_id,
@@ -39,9 +39,11 @@ bool TransformationAddTypeArray::IsApplicable(
}
auto element_type =
ir_context->get_type_mgr()->GetType(message_.element_type_id());
- if (!element_type || element_type->AsFunction()) {
- // The element type id either does not refer to a type, or refers to a
- // function type; both are illegal.
+ if (!element_type || element_type->AsFunction() ||
+ fuzzerutil::HasBlockOrBufferBlockDecoration(ir_context,
+ message_.element_type_id())) {
+ // The element type id either does not refer to a type, refers to a function
+ // type, or refers to a block-decorated struct. These cases are all illegal.
return false;
}
auto constant =
@@ -69,13 +71,17 @@ void TransformationAddTypeArray::Apply(
opt::Instruction::OperandList in_operands;
in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.element_type_id()}});
in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.size_id()}});
- ir_context->module()->AddType(MakeUnique<opt::Instruction>(
- ir_context, SpvOpTypeArray, 0, message_.fresh_id(), in_operands));
+ auto type_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpTypeArray, 0, message_.fresh_id(), in_operands);
+ auto type_instruction_ptr = type_instruction.get();
+ ir_context->module()->AddType(std::move(type_instruction));
+
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+
+ // Inform the def use manager that there is a new definition. Invalidate the
+ // type manager since we have added a new type.
+ ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
+ ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeArray::ToMessage() const {
diff --git a/source/fuzz/transformation_add_type_array.h b/source/fuzz/transformation_add_type_array.h
index ebefc237..3162497a 100644
--- a/source/fuzz/transformation_add_type_array.h
+++ b/source/fuzz/transformation_add_type_array.h
@@ -26,15 +26,17 @@ namespace fuzz {
class TransformationAddTypeArray : public Transformation {
public:
explicit TransformationAddTypeArray(
- const protobufs::TransformationAddTypeArray& message);
+ protobufs::TransformationAddTypeArray message);
TransformationAddTypeArray(uint32_t fresh_id, uint32_t element_type_id,
uint32_t size_id);
// - |message_.fresh_id| must be fresh
// - |message_.element_type_id| must be the id of a non-function type
+ // - |message_.member_type_id| must not be the result id of an OpTypeStruct
+ // instruction that has the Block or BufferBlock decoration
// - |message_.size_id| must be the id of a 32-bit integer constant that is
- // positive when interpreted as signed.
+ // positive when interpreted as signed
bool IsApplicable(
opt::IRContext* ir_context,
const TransformationContext& transformation_context) const override;
diff --git a/source/fuzz/transformation_add_type_boolean.cpp b/source/fuzz/transformation_add_type_boolean.cpp
index ebbfabc8..30ff43e2 100644
--- a/source/fuzz/transformation_add_type_boolean.cpp
+++ b/source/fuzz/transformation_add_type_boolean.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddTypeBoolean::TransformationAddTypeBoolean(
- const spvtools::fuzz::protobufs::TransformationAddTypeBoolean& message)
- : message_(message) {}
+ protobufs::TransformationAddTypeBoolean message)
+ : message_(std::move(message)) {}
TransformationAddTypeBoolean::TransformationAddTypeBoolean(uint32_t fresh_id) {
message_.set_fresh_id(fresh_id);
@@ -42,13 +42,17 @@ bool TransformationAddTypeBoolean::IsApplicable(
void TransformationAddTypeBoolean::Apply(
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
opt::Instruction::OperandList empty_operands;
- ir_context->module()->AddType(MakeUnique<opt::Instruction>(
- ir_context, SpvOpTypeBool, 0, message_.fresh_id(), empty_operands));
+ auto type_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpTypeBool, 0, message_.fresh_id(), empty_operands);
+ auto type_instruction_ptr = type_instruction.get();
+ ir_context->module()->AddType(std::move(type_instruction));
+
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+
+ // Inform the def use manager that there is a new definition. Invalidate the
+ // type manager since we have added a new type.
+ ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
+ ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeBoolean::ToMessage() const {
diff --git a/source/fuzz/transformation_add_type_boolean.h b/source/fuzz/transformation_add_type_boolean.h
index 25c92727..ee640153 100644
--- a/source/fuzz/transformation_add_type_boolean.h
+++ b/source/fuzz/transformation_add_type_boolean.h
@@ -25,7 +25,7 @@ namespace fuzz {
class TransformationAddTypeBoolean : public Transformation {
public:
explicit TransformationAddTypeBoolean(
- const protobufs::TransformationAddTypeBoolean& message);
+ protobufs::TransformationAddTypeBoolean message);
explicit TransformationAddTypeBoolean(uint32_t fresh_id);
diff --git a/source/fuzz/transformation_add_type_float.cpp b/source/fuzz/transformation_add_type_float.cpp
index da3f3e4e..1b88b25c 100644
--- a/source/fuzz/transformation_add_type_float.cpp
+++ b/source/fuzz/transformation_add_type_float.cpp
@@ -26,8 +26,8 @@ TransformationAddTypeFloat::TransformationAddTypeFloat(uint32_t fresh_id,
}
TransformationAddTypeFloat::TransformationAddTypeFloat(
- const spvtools::fuzz::protobufs::TransformationAddTypeFloat& message)
- : message_(message) {}
+ protobufs::TransformationAddTypeFloat message)
+ : message_(std::move(message)) {}
bool TransformationAddTypeFloat::IsApplicable(
opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
@@ -65,11 +65,18 @@ bool TransformationAddTypeFloat::IsApplicable(
void TransformationAddTypeFloat::Apply(
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
- fuzzerutil::AddFloatType(ir_context, message_.fresh_id(), message_.width());
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ auto type_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpTypeFloat, 0, message_.fresh_id(),
+ opt::Instruction::OperandList{
+ {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.width()}}});
+ auto type_instruction_ptr = type_instruction.get();
+ ir_context->module()->AddType(std::move(type_instruction));
+ fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+
+ // Inform the def use manager that there is a new definition, and invalidate
+ // the type manager since we have added a new type.
+ ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
+ ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeFloat::ToMessage() const {
diff --git a/source/fuzz/transformation_add_type_float.h b/source/fuzz/transformation_add_type_float.h
index 30cd0fc6..e049d9a0 100644
--- a/source/fuzz/transformation_add_type_float.h
+++ b/source/fuzz/transformation_add_type_float.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddTypeFloat : public Transformation {
public:
explicit TransformationAddTypeFloat(
- const protobufs::TransformationAddTypeFloat& message);
+ protobufs::TransformationAddTypeFloat message);
TransformationAddTypeFloat(uint32_t fresh_id, uint32_t width);
diff --git a/source/fuzz/transformation_add_type_function.cpp b/source/fuzz/transformation_add_type_function.cpp
index b6cddfc0..e96067f2 100644
--- a/source/fuzz/transformation_add_type_function.cpp
+++ b/source/fuzz/transformation_add_type_function.cpp
@@ -22,8 +22,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddTypeFunction::TransformationAddTypeFunction(
- const spvtools::fuzz::protobufs::TransformationAddTypeFunction& message)
- : message_(message) {}
+ protobufs::TransformationAddTypeFunction message)
+ : message_(std::move(message)) {}
TransformationAddTypeFunction::TransformationAddTypeFunction(
uint32_t fresh_id, uint32_t return_type_id,
diff --git a/source/fuzz/transformation_add_type_function.h b/source/fuzz/transformation_add_type_function.h
index 59ded2b3..71044579 100644
--- a/source/fuzz/transformation_add_type_function.h
+++ b/source/fuzz/transformation_add_type_function.h
@@ -28,7 +28,7 @@ namespace fuzz {
class TransformationAddTypeFunction : public Transformation {
public:
explicit TransformationAddTypeFunction(
- const protobufs::TransformationAddTypeFunction& message);
+ protobufs::TransformationAddTypeFunction message);
TransformationAddTypeFunction(uint32_t fresh_id, uint32_t return_type_id,
const std::vector<uint32_t>& argument_type_ids);
diff --git a/source/fuzz/transformation_add_type_int.cpp b/source/fuzz/transformation_add_type_int.cpp
index 253ea15b..d4ef9819 100644
--- a/source/fuzz/transformation_add_type_int.cpp
+++ b/source/fuzz/transformation_add_type_int.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddTypeInt::TransformationAddTypeInt(
- const spvtools::fuzz::protobufs::TransformationAddTypeInt& message)
- : message_(message) {}
+ protobufs::TransformationAddTypeInt message)
+ : message_(std::move(message)) {}
TransformationAddTypeInt::TransformationAddTypeInt(uint32_t fresh_id,
uint32_t width,
@@ -74,12 +74,21 @@ bool TransformationAddTypeInt::IsApplicable(
void TransformationAddTypeInt::Apply(opt::IRContext* ir_context,
TransformationContext* /*unused*/) const {
- fuzzerutil::AddIntegerType(ir_context, message_.fresh_id(), message_.width(),
- message_.is_signed());
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ auto type_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpTypeInt, 0, message_.fresh_id(),
+ opt::Instruction::OperandList{
+ {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.width()}},
+ {SPV_OPERAND_TYPE_LITERAL_INTEGER,
+ {message_.is_signed() ? 1u : 0u}}});
+ auto type_instruction_ptr = type_instruction.get();
+ ir_context->module()->AddType(std::move(type_instruction));
+
+ fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+
+ // Inform the def use manager that there is a new definition. Invalidate the
+ // type manager since we have added a new type.
+ ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
+ ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeInt::ToMessage() const {
diff --git a/source/fuzz/transformation_add_type_int.h b/source/fuzz/transformation_add_type_int.h
index 20c90ca4..dc67b7dc 100644
--- a/source/fuzz/transformation_add_type_int.h
+++ b/source/fuzz/transformation_add_type_int.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddTypeInt : public Transformation {
public:
explicit TransformationAddTypeInt(
- const protobufs::TransformationAddTypeInt& message);
+ protobufs::TransformationAddTypeInt message);
TransformationAddTypeInt(uint32_t fresh_id, uint32_t width, bool is_signed);
diff --git a/source/fuzz/transformation_add_type_matrix.cpp b/source/fuzz/transformation_add_type_matrix.cpp
index cecebb41..b574b01b 100644
--- a/source/fuzz/transformation_add_type_matrix.cpp
+++ b/source/fuzz/transformation_add_type_matrix.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddTypeMatrix::TransformationAddTypeMatrix(
- const spvtools::fuzz::protobufs::TransformationAddTypeMatrix& message)
- : message_(message) {}
+ protobufs::TransformationAddTypeMatrix message)
+ : message_(std::move(message)) {}
TransformationAddTypeMatrix::TransformationAddTypeMatrix(
uint32_t fresh_id, uint32_t column_type_id, uint32_t column_count) {
@@ -52,13 +52,17 @@ void TransformationAddTypeMatrix::Apply(
in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.column_type_id()}});
in_operands.push_back(
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.column_count()}});
- ir_context->module()->AddType(MakeUnique<opt::Instruction>(
- ir_context, SpvOpTypeMatrix, 0, message_.fresh_id(), in_operands));
+ auto type_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpTypeMatrix, 0, message_.fresh_id(), in_operands);
+ auto type_instruction_ptr = type_instruction.get();
+ ir_context->module()->AddType(std::move(type_instruction));
+
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+
+ // Inform the def use manager that there is a new definition. Invalidate the
+ // type manager since we have added a new type.
+ ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
+ ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeMatrix::ToMessage() const {
diff --git a/source/fuzz/transformation_add_type_matrix.h b/source/fuzz/transformation_add_type_matrix.h
index f1d41656..b4788b1b 100644
--- a/source/fuzz/transformation_add_type_matrix.h
+++ b/source/fuzz/transformation_add_type_matrix.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddTypeMatrix : public Transformation {
public:
explicit TransformationAddTypeMatrix(
- const protobufs::TransformationAddTypeMatrix& message);
+ protobufs::TransformationAddTypeMatrix message);
TransformationAddTypeMatrix(uint32_t fresh_id, uint32_t column_type_id,
uint32_t column_count);
diff --git a/source/fuzz/transformation_add_type_pointer.cpp b/source/fuzz/transformation_add_type_pointer.cpp
index f74768d6..c6c3945b 100644
--- a/source/fuzz/transformation_add_type_pointer.cpp
+++ b/source/fuzz/transformation_add_type_pointer.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddTypePointer::TransformationAddTypePointer(
- const spvtools::fuzz::protobufs::TransformationAddTypePointer& message)
- : message_(message) {}
+ protobufs::TransformationAddTypePointer message)
+ : message_(std::move(message)) {}
TransformationAddTypePointer::TransformationAddTypePointer(
uint32_t fresh_id, SpvStorageClass storage_class, uint32_t base_type_id) {
@@ -47,13 +47,17 @@ void TransformationAddTypePointer::Apply(
opt::Instruction::OperandList in_operands = {
{SPV_OPERAND_TYPE_STORAGE_CLASS, {message_.storage_class()}},
{SPV_OPERAND_TYPE_ID, {message_.base_type_id()}}};
- ir_context->module()->AddType(MakeUnique<opt::Instruction>(
- ir_context, SpvOpTypePointer, 0, message_.fresh_id(), in_operands));
+ auto type_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpTypePointer, 0, message_.fresh_id(), in_operands);
+ auto type_instruction_ptr = type_instruction.get();
+ ir_context->module()->AddType(std::move(type_instruction));
+
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+
+ // Inform the def use manager that there is a new definition. Invalidate the
+ // type manager since we have added a new type.
+ ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
+ ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypePointer::ToMessage() const {
diff --git a/source/fuzz/transformation_add_type_pointer.h b/source/fuzz/transformation_add_type_pointer.h
index 3f686e97..8468c14d 100644
--- a/source/fuzz/transformation_add_type_pointer.h
+++ b/source/fuzz/transformation_add_type_pointer.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddTypePointer : public Transformation {
public:
explicit TransformationAddTypePointer(
- const protobufs::TransformationAddTypePointer& message);
+ protobufs::TransformationAddTypePointer message);
TransformationAddTypePointer(uint32_t fresh_id, SpvStorageClass storage_class,
uint32_t base_type_id);
diff --git a/source/fuzz/transformation_add_type_struct.cpp b/source/fuzz/transformation_add_type_struct.cpp
index b20ffb00..d7f0711e 100644
--- a/source/fuzz/transformation_add_type_struct.cpp
+++ b/source/fuzz/transformation_add_type_struct.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddTypeStruct::TransformationAddTypeStruct(
- const spvtools::fuzz::protobufs::TransformationAddTypeStruct& message)
- : message_(message) {}
+ protobufs::TransformationAddTypeStruct message)
+ : message_(std::move(message)) {}
TransformationAddTypeStruct::TransformationAddTypeStruct(
uint32_t fresh_id, const std::vector<uint32_t>& member_type_ids) {
@@ -39,9 +39,11 @@ bool TransformationAddTypeStruct::IsApplicable(
}
for (auto member_type : message_.member_type_id()) {
auto type = ir_context->get_type_mgr()->GetType(member_type);
- if (!type || type->AsFunction()) {
- // The member type id either does not refer to a type, or refers to a
- // function type; both are illegal.
+ if (!type || type->AsFunction() ||
+ fuzzerutil::HasBlockOrBufferBlockDecoration(ir_context, member_type)) {
+ // The member type id either does not refer to a type, refers to a
+ // function type, or refers to a block-decorated struct. These cases are
+ // all illegal.
return false;
}
@@ -58,14 +60,36 @@ bool TransformationAddTypeStruct::IsApplicable(
void TransformationAddTypeStruct::Apply(
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
- fuzzerutil::AddStructType(
- ir_context, message_.fresh_id(),
- std::vector<uint32_t>(message_.member_type_id().begin(),
- message_.member_type_id().end()));
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ opt::Instruction::OperandList operands;
+ operands.reserve(message_.member_type_id().size());
+
+ for (auto type_id : message_.member_type_id()) {
+ const auto* type = ir_context->get_type_mgr()->GetType(type_id);
+ (void)type; // Make compiler happy in release mode.
+ assert(type && !type->AsFunction() && "Component's type id is invalid");
+
+ if (type->AsStruct()) {
+ // From the spec for the BuiltIn decoration:
+ // - When applied to a structure-type member, that structure type cannot
+ // be contained as a member of another structure type.
+ assert(!fuzzerutil::MembersHaveBuiltInDecoration(ir_context, type_id) &&
+ "A member struct has BuiltIn members");
+ }
+
+ operands.push_back({SPV_OPERAND_TYPE_ID, {type_id}});
+ }
+
+ auto type_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpTypeStruct, 0, message_.fresh_id(), std::move(operands));
+ auto type_instruction_ptr = type_instruction.get();
+ ir_context->AddType(std::move(type_instruction));
+
+ fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+
+ // Inform the def use manager that there is a new definition. Invalidate the
+ // type manager since we have added a new type.
+ ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
+ ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeStruct::ToMessage() const {
diff --git a/source/fuzz/transformation_add_type_struct.h b/source/fuzz/transformation_add_type_struct.h
index 94be42ad..6a8dce7c 100644
--- a/source/fuzz/transformation_add_type_struct.h
+++ b/source/fuzz/transformation_add_type_struct.h
@@ -28,7 +28,7 @@ namespace fuzz {
class TransformationAddTypeStruct : public Transformation {
public:
explicit TransformationAddTypeStruct(
- const protobufs::TransformationAddTypeStruct& message);
+ protobufs::TransformationAddTypeStruct message);
TransformationAddTypeStruct(uint32_t fresh_id,
const std::vector<uint32_t>& component_type_ids);
@@ -37,7 +37,9 @@ class TransformationAddTypeStruct : public Transformation {
// - |message_.member_type_id| must be a sequence of non-function type ids
// - |message_.member_type_id| may not contain a result id of an OpTypeStruct
// instruction with BuiltIn members (i.e. members of the struct are
- // decorated via OpMemberDecorate with BuiltIn decoration).
+ // decorated via OpMemberDecorate with BuiltIn decoration)
+ // - |message_.member_type_id| may not contain a result id of an OpTypeStruct
+ // instruction that has the Block or BufferBlock decoration
bool IsApplicable(
opt::IRContext* ir_context,
const TransformationContext& transformation_context) const override;
diff --git a/source/fuzz/transformation_add_type_vector.cpp b/source/fuzz/transformation_add_type_vector.cpp
index a3b0010e..4da0ff01 100644
--- a/source/fuzz/transformation_add_type_vector.cpp
+++ b/source/fuzz/transformation_add_type_vector.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationAddTypeVector::TransformationAddTypeVector(
- const spvtools::fuzz::protobufs::TransformationAddTypeVector& message)
- : message_(message) {}
+ protobufs::TransformationAddTypeVector message)
+ : message_(std::move(message)) {}
TransformationAddTypeVector::TransformationAddTypeVector(
uint32_t fresh_id, uint32_t component_type_id, uint32_t component_count) {
@@ -46,13 +46,30 @@ bool TransformationAddTypeVector::IsApplicable(
void TransformationAddTypeVector::Apply(
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
- fuzzerutil::AddVectorType(ir_context, message_.fresh_id(),
- message_.component_type_id(),
- message_.component_count());
- // We have added an instruction to the module, so need to be careful about the
- // validity of existing analyses.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ const auto* component_type =
+ ir_context->get_type_mgr()->GetType(message_.component_type_id());
+ (void)component_type; // Make compiler happy in release mode.
+ assert(component_type &&
+ (component_type->AsInteger() || component_type->AsFloat() ||
+ component_type->AsBool()) &&
+ "|component_type_id| is invalid");
+ assert(message_.component_count() >= 2 && message_.component_count() <= 4 &&
+ "Precondition: component count must be in range [2, 4].");
+
+ auto type_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpTypeVector, 0, message_.fresh_id(),
+ opt::Instruction::OperandList{
+ {SPV_OPERAND_TYPE_ID, {message_.component_type_id()}},
+ {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.component_count()}}});
+ auto type_instruction_ptr = type_instruction.get();
+ ir_context->module()->AddType(std::move(type_instruction));
+
+ fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+
+ // Inform the def use manager that there is a new definition. Invalidate the
+ // type manager since we have added a new type.
+ ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
+ ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeVector::ToMessage() const {
diff --git a/source/fuzz/transformation_add_type_vector.h b/source/fuzz/transformation_add_type_vector.h
index c25d565d..43460ce4 100644
--- a/source/fuzz/transformation_add_type_vector.h
+++ b/source/fuzz/transformation_add_type_vector.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAddTypeVector : public Transformation {
public:
explicit TransformationAddTypeVector(
- const protobufs::TransformationAddTypeVector& message);
+ protobufs::TransformationAddTypeVector message);
TransformationAddTypeVector(uint32_t fresh_id, uint32_t component_type_id,
uint32_t component_count);
diff --git a/source/fuzz/transformation_adjust_branch_weights.cpp b/source/fuzz/transformation_adjust_branch_weights.cpp
index 8b74ed37..21fef258 100644
--- a/source/fuzz/transformation_adjust_branch_weights.cpp
+++ b/source/fuzz/transformation_adjust_branch_weights.cpp
@@ -28,8 +28,8 @@ const uint32_t kBranchWeightForFalseLabelIndex = 4;
} // namespace
TransformationAdjustBranchWeights::TransformationAdjustBranchWeights(
- const spvtools::fuzz::protobufs::TransformationAdjustBranchWeights& message)
- : message_(message) {}
+ protobufs::TransformationAdjustBranchWeights message)
+ : message_(std::move(message)) {}
TransformationAdjustBranchWeights::TransformationAdjustBranchWeights(
const protobufs::InstructionDescriptor& instruction_descriptor,
diff --git a/source/fuzz/transformation_adjust_branch_weights.h b/source/fuzz/transformation_adjust_branch_weights.h
index 4d451a5a..41eceeb5 100644
--- a/source/fuzz/transformation_adjust_branch_weights.h
+++ b/source/fuzz/transformation_adjust_branch_weights.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationAdjustBranchWeights : public Transformation {
public:
explicit TransformationAdjustBranchWeights(
- const protobufs::TransformationAdjustBranchWeights& message);
+ protobufs::TransformationAdjustBranchWeights message);
TransformationAdjustBranchWeights(
const protobufs::InstructionDescriptor& instruction_descriptor,
diff --git a/source/fuzz/transformation_composite_construct.cpp b/source/fuzz/transformation_composite_construct.cpp
index f0de1aeb..0cd2308b 100644
--- a/source/fuzz/transformation_composite_construct.cpp
+++ b/source/fuzz/transformation_composite_construct.cpp
@@ -23,8 +23,8 @@ namespace spvtools {
namespace fuzz {
TransformationCompositeConstruct::TransformationCompositeConstruct(
- const protobufs::TransformationCompositeConstruct& message)
- : message_(message) {}
+ protobufs::TransformationCompositeConstruct message)
+ : message_(std::move(message)) {}
TransformationCompositeConstruct::TransformationCompositeConstruct(
uint32_t composite_type_id, std::vector<uint32_t> component,
@@ -120,12 +120,18 @@ void TransformationCompositeConstruct::Apply(
}
// Insert an OpCompositeConstruct instruction.
- insert_before.InsertBefore(MakeUnique<opt::Instruction>(
+ auto new_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpCompositeConstruct, message_.composite_type_id(),
- message_.fresh_id(), in_operands));
+ message_.fresh_id(), in_operands);
+ auto new_instruction_ptr = new_instruction.get();
+ insert_before.InsertBefore(std::move(new_instruction));
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction_ptr);
+ ir_context->set_instr_block(new_instruction_ptr, destination_block);
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+
+ // No analyses need to be invalidated since the transformation is local to a
+ // block and the def-use and instruction-to-block mappings have been updated.
AddDataSynonymFacts(ir_context, transformation_context);
}
diff --git a/source/fuzz/transformation_composite_construct.h b/source/fuzz/transformation_composite_construct.h
index 3a3e43c4..cc44a612 100644
--- a/source/fuzz/transformation_composite_construct.h
+++ b/source/fuzz/transformation_composite_construct.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationCompositeConstruct : public Transformation {
public:
explicit TransformationCompositeConstruct(
- const protobufs::TransformationCompositeConstruct& message);
+ protobufs::TransformationCompositeConstruct message);
TransformationCompositeConstruct(
uint32_t composite_type_id, std::vector<uint32_t> component,
diff --git a/source/fuzz/transformation_composite_extract.cpp b/source/fuzz/transformation_composite_extract.cpp
index 2aff02fb..647cd74e 100644
--- a/source/fuzz/transformation_composite_extract.cpp
+++ b/source/fuzz/transformation_composite_extract.cpp
@@ -24,8 +24,8 @@ namespace spvtools {
namespace fuzz {
TransformationCompositeExtract::TransformationCompositeExtract(
- const spvtools::fuzz::protobufs::TransformationCompositeExtract& message)
- : message_(message) {}
+ protobufs::TransformationCompositeExtract message)
+ : message_(std::move(message)) {}
TransformationCompositeExtract::TransformationCompositeExtract(
const protobufs::InstructionDescriptor& instruction_to_insert_before,
@@ -89,15 +89,20 @@ void TransformationCompositeExtract::Apply(
auto extracted_type = fuzzerutil::WalkCompositeTypeIndices(
ir_context, composite_instruction->type_id(), message_.index());
- FindInstruction(message_.instruction_to_insert_before(), ir_context)
- ->InsertBefore(MakeUnique<opt::Instruction>(
+ auto insert_before =
+ FindInstruction(message_.instruction_to_insert_before(), ir_context);
+ opt::Instruction* new_instruction =
+ insert_before->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpCompositeExtract, extracted_type,
message_.fresh_id(), extract_operands));
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction);
+ ir_context->set_instr_block(new_instruction,
+ ir_context->get_instr_block(insert_before));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ // No analyses need to be invalidated since the transformation is local to a
+ // block and the def-use and instruction-to-block mappings have been updated.
AddDataSynonymFacts(ir_context, transformation_context);
}
diff --git a/source/fuzz/transformation_composite_extract.h b/source/fuzz/transformation_composite_extract.h
index 0f5348a8..0682a61c 100644
--- a/source/fuzz/transformation_composite_extract.h
+++ b/source/fuzz/transformation_composite_extract.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationCompositeExtract : public Transformation {
public:
explicit TransformationCompositeExtract(
- const protobufs::TransformationCompositeExtract& message);
+ protobufs::TransformationCompositeExtract message);
TransformationCompositeExtract(
const protobufs::InstructionDescriptor& instruction_to_insert_before,
diff --git a/source/fuzz/transformation_composite_insert.cpp b/source/fuzz/transformation_composite_insert.cpp
index cc681415..14c3a1b0 100644
--- a/source/fuzz/transformation_composite_insert.cpp
+++ b/source/fuzz/transformation_composite_insert.cpp
@@ -22,8 +22,8 @@ namespace spvtools {
namespace fuzz {
TransformationCompositeInsert::TransformationCompositeInsert(
- const spvtools::fuzz::protobufs::TransformationCompositeInsert& message)
- : message_(message) {}
+ protobufs::TransformationCompositeInsert message)
+ : message_(std::move(message)) {}
TransformationCompositeInsert::TransformationCompositeInsert(
const protobufs::InstructionDescriptor& instruction_to_insert_before,
@@ -124,15 +124,21 @@ void TransformationCompositeInsert::Apply(
auto composite_type_id =
fuzzerutil::GetTypeId(ir_context, message_.composite_id());
- FindInstruction(message_.instruction_to_insert_before(), ir_context)
- ->InsertBefore(MakeUnique<opt::Instruction>(
- ir_context, SpvOpCompositeInsert, composite_type_id,
- message_.fresh_id(), std::move(in_operands)));
+ auto insert_before =
+ FindInstruction(message_.instruction_to_insert_before(), ir_context);
+ auto new_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpCompositeInsert, composite_type_id, message_.fresh_id(),
+ std::move(in_operands));
+ auto new_instruction_ptr = new_instruction.get();
+ insert_before->InsertBefore(std::move(new_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- // We have modified the module so most analyzes are now invalid.
- ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+ // Inform the def-use manager about the new instruction and record its basic
+ // block.
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction_ptr);
+ ir_context->set_instr_block(new_instruction_ptr,
+ ir_context->get_instr_block(insert_before));
// Add data synonym facts that arise from the insertion.
AddDataSynonymFacts(ir_context, transformation_context);
diff --git a/source/fuzz/transformation_composite_insert.h b/source/fuzz/transformation_composite_insert.h
index f2290142..413d41f1 100644
--- a/source/fuzz/transformation_composite_insert.h
+++ b/source/fuzz/transformation_composite_insert.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationCompositeInsert : public Transformation {
public:
explicit TransformationCompositeInsert(
- const protobufs::TransformationCompositeInsert& message);
+ protobufs::TransformationCompositeInsert message);
TransformationCompositeInsert(
const protobufs::InstructionDescriptor& instruction_to_insert_before,
diff --git a/source/fuzz/transformation_compute_data_synonym_fact_closure.cpp b/source/fuzz/transformation_compute_data_synonym_fact_closure.cpp
index f7270526..7ae9df82 100644
--- a/source/fuzz/transformation_compute_data_synonym_fact_closure.cpp
+++ b/source/fuzz/transformation_compute_data_synonym_fact_closure.cpp
@@ -19,9 +19,8 @@ namespace fuzz {
TransformationComputeDataSynonymFactClosure::
TransformationComputeDataSynonymFactClosure(
- const spvtools::fuzz::protobufs::
- TransformationComputeDataSynonymFactClosure& message)
- : message_(message) {}
+ protobufs::TransformationComputeDataSynonymFactClosure message)
+ : message_(std::move(message)) {}
TransformationComputeDataSynonymFactClosure::
TransformationComputeDataSynonymFactClosure(
diff --git a/source/fuzz/transformation_compute_data_synonym_fact_closure.h b/source/fuzz/transformation_compute_data_synonym_fact_closure.h
index dedabe23..c61b26ec 100644
--- a/source/fuzz/transformation_compute_data_synonym_fact_closure.h
+++ b/source/fuzz/transformation_compute_data_synonym_fact_closure.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationComputeDataSynonymFactClosure : public Transformation {
public:
explicit TransformationComputeDataSynonymFactClosure(
- const protobufs::TransformationComputeDataSynonymFactClosure& message);
+ protobufs::TransformationComputeDataSynonymFactClosure message);
explicit TransformationComputeDataSynonymFactClosure(
uint32_t maximum_equivalence_class_size);
diff --git a/source/fuzz/transformation_duplicate_region_with_selection.cpp b/source/fuzz/transformation_duplicate_region_with_selection.cpp
index 2ac6259d..dee1207f 100644
--- a/source/fuzz/transformation_duplicate_region_with_selection.cpp
+++ b/source/fuzz/transformation_duplicate_region_with_selection.cpp
@@ -21,9 +21,8 @@ namespace fuzz {
TransformationDuplicateRegionWithSelection::
TransformationDuplicateRegionWithSelection(
- const spvtools::fuzz::protobufs::
- TransformationDuplicateRegionWithSelection& message)
- : message_(message) {}
+ protobufs::TransformationDuplicateRegionWithSelection message)
+ : message_(std::move(message)) {}
TransformationDuplicateRegionWithSelection::
TransformationDuplicateRegionWithSelection(
diff --git a/source/fuzz/transformation_duplicate_region_with_selection.h b/source/fuzz/transformation_duplicate_region_with_selection.h
index a2b9a433..30e3c373 100644
--- a/source/fuzz/transformation_duplicate_region_with_selection.h
+++ b/source/fuzz/transformation_duplicate_region_with_selection.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationDuplicateRegionWithSelection : public Transformation {
public:
explicit TransformationDuplicateRegionWithSelection(
- const protobufs::TransformationDuplicateRegionWithSelection& message);
+ protobufs::TransformationDuplicateRegionWithSelection message);
explicit TransformationDuplicateRegionWithSelection(
uint32_t new_entry_fresh_id, uint32_t condition_id,
diff --git a/source/fuzz/transformation_equation_instruction.cpp b/source/fuzz/transformation_equation_instruction.cpp
index 32e83518..1e5dae97 100644
--- a/source/fuzz/transformation_equation_instruction.cpp
+++ b/source/fuzz/transformation_equation_instruction.cpp
@@ -21,8 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationEquationInstruction::TransformationEquationInstruction(
- const spvtools::fuzz::protobufs::TransformationEquationInstruction& message)
- : message_(message) {}
+ protobufs::TransformationEquationInstruction message)
+ : message_(std::move(message)) {}
TransformationEquationInstruction::TransformationEquationInstruction(
uint32_t fresh_id, SpvOp opcode, const std::vector<uint32_t>& in_operand_id,
@@ -84,13 +84,17 @@ void TransformationEquationInstruction::Apply(
rhs_id.push_back(id);
}
- FindInstruction(message_.instruction_to_insert_before(), ir_context)
- ->InsertBefore(MakeUnique<opt::Instruction>(
+ auto insert_before =
+ FindInstruction(message_.instruction_to_insert_before(), ir_context);
+ opt::Instruction* new_instruction =
+ insert_before->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, static_cast<SpvOp>(message_.opcode()),
MaybeGetResultTypeId(ir_context), message_.fresh_id(),
std::move(in_operands)));
- ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction);
+ ir_context->set_instr_block(new_instruction,
+ ir_context->get_instr_block(insert_before));
// Add an equation fact as long as the result id is not irrelevant (it could
// be if we are inserting into a dead block).
diff --git a/source/fuzz/transformation_equation_instruction.h b/source/fuzz/transformation_equation_instruction.h
index 4afc85fb..ae32a1a2 100644
--- a/source/fuzz/transformation_equation_instruction.h
+++ b/source/fuzz/transformation_equation_instruction.h
@@ -28,7 +28,7 @@ namespace fuzz {
class TransformationEquationInstruction : public Transformation {
public:
explicit TransformationEquationInstruction(
- const protobufs::TransformationEquationInstruction& message);
+ protobufs::TransformationEquationInstruction message);
TransformationEquationInstruction(
uint32_t fresh_id, SpvOp opcode,
diff --git a/source/fuzz/transformation_expand_vector_reduction.cpp b/source/fuzz/transformation_expand_vector_reduction.cpp
index 640aea25..99387066 100644
--- a/source/fuzz/transformation_expand_vector_reduction.cpp
+++ b/source/fuzz/transformation_expand_vector_reduction.cpp
@@ -21,9 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationExpandVectorReduction::TransformationExpandVectorReduction(
- const spvtools::fuzz::protobufs::TransformationExpandVectorReduction&
- message)
- : message_(message) {}
+ protobufs::TransformationExpandVectorReduction message)
+ : message_(std::move(message)) {}
TransformationExpandVectorReduction::TransformationExpandVectorReduction(
const uint32_t instruction_result_id,
diff --git a/source/fuzz/transformation_expand_vector_reduction.h b/source/fuzz/transformation_expand_vector_reduction.h
index e4cc9539..6ee2cefa 100644
--- a/source/fuzz/transformation_expand_vector_reduction.h
+++ b/source/fuzz/transformation_expand_vector_reduction.h
@@ -70,7 +70,7 @@ namespace fuzz {
class TransformationExpandVectorReduction : public Transformation {
public:
explicit TransformationExpandVectorReduction(
- const protobufs::TransformationExpandVectorReduction& message);
+ protobufs::TransformationExpandVectorReduction message);
TransformationExpandVectorReduction(const uint32_t instruction_result_id,
const std::vector<uint32_t>& fresh_ids);
diff --git a/source/fuzz/transformation_flatten_conditional_branch.cpp b/source/fuzz/transformation_flatten_conditional_branch.cpp
index fdee5130..b8c6de0c 100644
--- a/source/fuzz/transformation_flatten_conditional_branch.cpp
+++ b/source/fuzz/transformation_flatten_conditional_branch.cpp
@@ -21,8 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationFlattenConditionalBranch::TransformationFlattenConditionalBranch(
- const protobufs::TransformationFlattenConditionalBranch& message)
- : message_(message) {}
+ protobufs::TransformationFlattenConditionalBranch message)
+ : message_(std::move(message)) {}
TransformationFlattenConditionalBranch::TransformationFlattenConditionalBranch(
uint32_t header_block_id, bool true_branch_first,
@@ -844,7 +844,9 @@ bool TransformationFlattenConditionalBranch::OpSelectArgumentsAreRestricted(
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_UNIVERSAL_1_1:
case SPV_ENV_UNIVERSAL_1_2:
- case SPV_ENV_UNIVERSAL_1_3: {
+ case SPV_ENV_UNIVERSAL_1_3:
+ case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_VULKAN_1_1: {
return true;
}
default:
diff --git a/source/fuzz/transformation_flatten_conditional_branch.h b/source/fuzz/transformation_flatten_conditional_branch.h
index 9bdae937..4efff670 100644
--- a/source/fuzz/transformation_flatten_conditional_branch.h
+++ b/source/fuzz/transformation_flatten_conditional_branch.h
@@ -23,7 +23,7 @@ namespace fuzz {
class TransformationFlattenConditionalBranch : public Transformation {
public:
explicit TransformationFlattenConditionalBranch(
- const protobufs::TransformationFlattenConditionalBranch& message);
+ protobufs::TransformationFlattenConditionalBranch message);
TransformationFlattenConditionalBranch(
uint32_t header_block_id, bool true_branch_first,
diff --git a/source/fuzz/transformation_function_call.cpp b/source/fuzz/transformation_function_call.cpp
index ec95c320..0f88ce51 100644
--- a/source/fuzz/transformation_function_call.cpp
+++ b/source/fuzz/transformation_function_call.cpp
@@ -22,8 +22,8 @@ namespace spvtools {
namespace fuzz {
TransformationFunctionCall::TransformationFunctionCall(
- const spvtools::fuzz::protobufs::TransformationFunctionCall& message)
- : message_(message) {}
+ protobufs::TransformationFunctionCall message)
+ : message_(std::move(message)) {}
TransformationFunctionCall::TransformationFunctionCall(
uint32_t fresh_id, uint32_t callee_id,
diff --git a/source/fuzz/transformation_function_call.h b/source/fuzz/transformation_function_call.h
index e220d83d..a2aaf365 100644
--- a/source/fuzz/transformation_function_call.h
+++ b/source/fuzz/transformation_function_call.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationFunctionCall : public Transformation {
public:
explicit TransformationFunctionCall(
- const protobufs::TransformationFunctionCall& message);
+ protobufs::TransformationFunctionCall message);
TransformationFunctionCall(
uint32_t fresh_id, uint32_t callee_id,
diff --git a/source/fuzz/transformation_inline_function.cpp b/source/fuzz/transformation_inline_function.cpp
index f997491d..a48b8179 100644
--- a/source/fuzz/transformation_inline_function.cpp
+++ b/source/fuzz/transformation_inline_function.cpp
@@ -21,8 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationInlineFunction::TransformationInlineFunction(
- const spvtools::fuzz::protobufs::TransformationInlineFunction& message)
- : message_(message) {}
+ protobufs::TransformationInlineFunction message)
+ : message_(std::move(message)) {}
TransformationInlineFunction::TransformationInlineFunction(
uint32_t function_call_id,
diff --git a/source/fuzz/transformation_inline_function.h b/source/fuzz/transformation_inline_function.h
index 8105d92b..f4dc410a 100644
--- a/source/fuzz/transformation_inline_function.h
+++ b/source/fuzz/transformation_inline_function.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationInlineFunction : public Transformation {
public:
explicit TransformationInlineFunction(
- const protobufs::TransformationInlineFunction& message);
+ protobufs::TransformationInlineFunction message);
TransformationInlineFunction(
uint32_t function_call_id,
diff --git a/source/fuzz/transformation_load.cpp b/source/fuzz/transformation_load.cpp
index f8b35134..e22f8dd2 100644
--- a/source/fuzz/transformation_load.cpp
+++ b/source/fuzz/transformation_load.cpp
@@ -20,9 +20,8 @@
namespace spvtools {
namespace fuzz {
-TransformationLoad::TransformationLoad(
- const spvtools::fuzz::protobufs::TransformationLoad& message)
- : message_(message) {}
+TransformationLoad::TransformationLoad(protobufs::TransformationLoad message)
+ : message_(std::move(message)) {}
TransformationLoad::TransformationLoad(
uint32_t fresh_id, uint32_t pointer_id,
@@ -84,12 +83,19 @@ void TransformationLoad::Apply(opt::IRContext* ir_context,
uint32_t result_type = fuzzerutil::GetPointeeTypeIdFromPointerType(
ir_context, fuzzerutil::GetTypeId(ir_context, message_.pointer_id()));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- FindInstruction(message_.instruction_to_insert_before(), ir_context)
- ->InsertBefore(MakeUnique<opt::Instruction>(
- ir_context, SpvOpLoad, result_type, message_.fresh_id(),
- opt::Instruction::OperandList(
- {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}}})));
- ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+ auto insert_before =
+ FindInstruction(message_.instruction_to_insert_before(), ir_context);
+ auto new_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpLoad, result_type, message_.fresh_id(),
+ opt::Instruction::OperandList(
+ {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}}}));
+ auto new_instruction_ptr = new_instruction.get();
+ insert_before->InsertBefore(std::move(new_instruction));
+ // Inform the def-use manager about the new instruction and record its basic
+ // block.
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction_ptr);
+ ir_context->set_instr_block(new_instruction_ptr,
+ ir_context->get_instr_block(insert_before));
}
protobufs::Transformation TransformationLoad::ToMessage() const {
diff --git a/source/fuzz/transformation_load.h b/source/fuzz/transformation_load.h
index 683bba52..d10b0073 100644
--- a/source/fuzz/transformation_load.h
+++ b/source/fuzz/transformation_load.h
@@ -25,7 +25,7 @@ namespace fuzz {
class TransformationLoad : public Transformation {
public:
- explicit TransformationLoad(const protobufs::TransformationLoad& message);
+ explicit TransformationLoad(protobufs::TransformationLoad message);
TransformationLoad(
uint32_t fresh_id, uint32_t pointer_id,
diff --git a/source/fuzz/transformation_make_vector_operation_dynamic.cpp b/source/fuzz/transformation_make_vector_operation_dynamic.cpp
index d6d51404..bd0664c0 100644
--- a/source/fuzz/transformation_make_vector_operation_dynamic.cpp
+++ b/source/fuzz/transformation_make_vector_operation_dynamic.cpp
@@ -22,9 +22,8 @@ namespace fuzz {
TransformationMakeVectorOperationDynamic::
TransformationMakeVectorOperationDynamic(
- const spvtools::fuzz::protobufs::
- TransformationMakeVectorOperationDynamic& message)
- : message_(message) {}
+ protobufs::TransformationMakeVectorOperationDynamic message)
+ : message_(std::move(message)) {}
TransformationMakeVectorOperationDynamic::
TransformationMakeVectorOperationDynamic(uint32_t instruction_result_id,
diff --git a/source/fuzz/transformation_make_vector_operation_dynamic.h b/source/fuzz/transformation_make_vector_operation_dynamic.h
index d1765c52..e444f40c 100644
--- a/source/fuzz/transformation_make_vector_operation_dynamic.h
+++ b/source/fuzz/transformation_make_vector_operation_dynamic.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationMakeVectorOperationDynamic : public Transformation {
public:
explicit TransformationMakeVectorOperationDynamic(
- const protobufs::TransformationMakeVectorOperationDynamic& message);
+ protobufs::TransformationMakeVectorOperationDynamic message);
TransformationMakeVectorOperationDynamic(uint32_t instruction_result_id,
uint32_t constant_index_id);
diff --git a/source/fuzz/transformation_merge_blocks.cpp b/source/fuzz/transformation_merge_blocks.cpp
index 2a9e90cc..22236795 100644
--- a/source/fuzz/transformation_merge_blocks.cpp
+++ b/source/fuzz/transformation_merge_blocks.cpp
@@ -21,8 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationMergeBlocks::TransformationMergeBlocks(
- const spvtools::fuzz::protobufs::TransformationMergeBlocks& message)
- : message_(message) {}
+ protobufs::TransformationMergeBlocks message)
+ : message_(std::move(message)) {}
TransformationMergeBlocks::TransformationMergeBlocks(uint32_t block_id) {
message_.set_block_id(block_id);
diff --git a/source/fuzz/transformation_merge_blocks.h b/source/fuzz/transformation_merge_blocks.h
index d9a0ca05..f6306c5a 100644
--- a/source/fuzz/transformation_merge_blocks.h
+++ b/source/fuzz/transformation_merge_blocks.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationMergeBlocks : public Transformation {
public:
explicit TransformationMergeBlocks(
- const protobufs::TransformationMergeBlocks& message);
+ protobufs::TransformationMergeBlocks message);
TransformationMergeBlocks(uint32_t block_id);
diff --git a/source/fuzz/transformation_merge_function_returns.cpp b/source/fuzz/transformation_merge_function_returns.cpp
index c7cb5572..1aefedc0 100644
--- a/source/fuzz/transformation_merge_function_returns.cpp
+++ b/source/fuzz/transformation_merge_function_returns.cpp
@@ -21,8 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationMergeFunctionReturns::TransformationMergeFunctionReturns(
- const protobufs::TransformationMergeFunctionReturns& message)
- : message_(message) {}
+ protobufs::TransformationMergeFunctionReturns message)
+ : message_(std::move(message)) {}
TransformationMergeFunctionReturns::TransformationMergeFunctionReturns(
uint32_t function_id, uint32_t outer_header_id, uint32_t outer_return_id,
diff --git a/source/fuzz/transformation_merge_function_returns.h b/source/fuzz/transformation_merge_function_returns.h
index 4b299367..8f0937c2 100644
--- a/source/fuzz/transformation_merge_function_returns.h
+++ b/source/fuzz/transformation_merge_function_returns.h
@@ -22,7 +22,7 @@ namespace fuzz {
class TransformationMergeFunctionReturns : public Transformation {
public:
explicit TransformationMergeFunctionReturns(
- const protobufs::TransformationMergeFunctionReturns& message);
+ protobufs::TransformationMergeFunctionReturns message);
TransformationMergeFunctionReturns(
uint32_t function_id, uint32_t outer_header_id, uint32_t outer_return_id,
diff --git a/source/fuzz/transformation_move_block_down.cpp b/source/fuzz/transformation_move_block_down.cpp
index c5ed4333..dc1b2430 100644
--- a/source/fuzz/transformation_move_block_down.cpp
+++ b/source/fuzz/transformation_move_block_down.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationMoveBlockDown::TransformationMoveBlockDown(
- const spvtools::fuzz::protobufs::TransformationMoveBlockDown& message)
- : message_(message) {}
+ protobufs::TransformationMoveBlockDown message)
+ : message_(std::move(message)) {}
TransformationMoveBlockDown::TransformationMoveBlockDown(uint32_t id) {
message_.set_block_id(id);
diff --git a/source/fuzz/transformation_move_block_down.h b/source/fuzz/transformation_move_block_down.h
index 82f2599a..cbad9451 100644
--- a/source/fuzz/transformation_move_block_down.h
+++ b/source/fuzz/transformation_move_block_down.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationMoveBlockDown : public Transformation {
public:
explicit TransformationMoveBlockDown(
- const protobufs::TransformationMoveBlockDown& message);
+ protobufs::TransformationMoveBlockDown message);
explicit TransformationMoveBlockDown(uint32_t id);
diff --git a/source/fuzz/transformation_move_instruction_down.cpp b/source/fuzz/transformation_move_instruction_down.cpp
index dec05789..c8139e72 100644
--- a/source/fuzz/transformation_move_instruction_down.cpp
+++ b/source/fuzz/transformation_move_instruction_down.cpp
@@ -38,8 +38,8 @@ std::string GetExtensionSet(opt::IRContext* ir_context,
} // namespace
TransformationMoveInstructionDown::TransformationMoveInstructionDown(
- const protobufs::TransformationMoveInstructionDown& message)
- : message_(message) {}
+ protobufs::TransformationMoveInstructionDown message)
+ : message_(std::move(message)) {}
TransformationMoveInstructionDown::TransformationMoveInstructionDown(
const protobufs::InstructionDescriptor& instruction) {
diff --git a/source/fuzz/transformation_move_instruction_down.h b/source/fuzz/transformation_move_instruction_down.h
index 85852253..2a5a8f1f 100644
--- a/source/fuzz/transformation_move_instruction_down.h
+++ b/source/fuzz/transformation_move_instruction_down.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationMoveInstructionDown : public Transformation {
public:
explicit TransformationMoveInstructionDown(
- const protobufs::TransformationMoveInstructionDown& message);
+ protobufs::TransformationMoveInstructionDown message);
explicit TransformationMoveInstructionDown(
const protobufs::InstructionDescriptor& instruction);
diff --git a/source/fuzz/transformation_mutate_pointer.cpp b/source/fuzz/transformation_mutate_pointer.cpp
index fefedbd1..516a0d61 100644
--- a/source/fuzz/transformation_mutate_pointer.cpp
+++ b/source/fuzz/transformation_mutate_pointer.cpp
@@ -21,8 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationMutatePointer::TransformationMutatePointer(
- const protobufs::TransformationMutatePointer& message)
- : message_(message) {}
+ protobufs::TransformationMutatePointer message)
+ : message_(std::move(message)) {}
TransformationMutatePointer::TransformationMutatePointer(
uint32_t pointer_id, uint32_t fresh_id,
@@ -92,36 +92,47 @@ void TransformationMutatePointer::Apply(
auto* insert_before_inst =
FindInstruction(message_.insert_before(), ir_context);
assert(insert_before_inst && "|insert_before| descriptor is invalid");
+ opt::BasicBlock* enclosing_block =
+ ir_context->get_instr_block(insert_before_inst);
auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
ir_context, fuzzerutil::GetTypeId(ir_context, message_.pointer_id()));
// Back up the original value.
- insert_before_inst->InsertBefore(MakeUnique<opt::Instruction>(
+ auto backup_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpLoad, pointee_type_id, message_.fresh_id(),
opt::Instruction::OperandList{
- {SPV_OPERAND_TYPE_ID, {message_.pointer_id()}}}));
+ {SPV_OPERAND_TYPE_ID, {message_.pointer_id()}}});
+ auto backup_instruction_ptr = backup_instruction.get();
+ insert_before_inst->InsertBefore(std::move(backup_instruction));
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(backup_instruction_ptr);
+ ir_context->set_instr_block(backup_instruction_ptr, enclosing_block);
// Insert a new value.
- insert_before_inst->InsertBefore(MakeUnique<opt::Instruction>(
+ auto new_value_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpStore, 0, 0,
opt::Instruction::OperandList{
{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
{SPV_OPERAND_TYPE_ID,
{fuzzerutil::MaybeGetZeroConstant(
- ir_context, *transformation_context, pointee_type_id, true)}}}));
+ ir_context, *transformation_context, pointee_type_id, true)}}});
+ auto new_value_instruction_ptr = new_value_instruction.get();
+ insert_before_inst->InsertBefore(std::move(new_value_instruction));
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_value_instruction_ptr);
+ ir_context->set_instr_block(new_value_instruction_ptr, enclosing_block);
// Restore the original value.
- insert_before_inst->InsertBefore(MakeUnique<opt::Instruction>(
+ auto restore_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpStore, 0, 0,
opt::Instruction::OperandList{
{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
- {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}}));
+ {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}});
+ auto restore_instruction_ptr = restore_instruction.get();
+ insert_before_inst->InsertBefore(std::move(restore_instruction));
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(restore_instruction_ptr);
+ ir_context->set_instr_block(restore_instruction_ptr, enclosing_block);
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
-
- // Make sure analyses represent the correct state of the module.
- ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
}
protobufs::Transformation TransformationMutatePointer::ToMessage() const {
diff --git a/source/fuzz/transformation_mutate_pointer.h b/source/fuzz/transformation_mutate_pointer.h
index b9f09656..2c712909 100644
--- a/source/fuzz/transformation_mutate_pointer.h
+++ b/source/fuzz/transformation_mutate_pointer.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationMutatePointer : public Transformation {
public:
explicit TransformationMutatePointer(
- const protobufs::TransformationMutatePointer& message);
+ protobufs::TransformationMutatePointer message);
explicit TransformationMutatePointer(
uint32_t pointer_id, uint32_t fresh_id,
diff --git a/source/fuzz/transformation_outline_function.cpp b/source/fuzz/transformation_outline_function.cpp
index 643fd699..6ee91225 100644
--- a/source/fuzz/transformation_outline_function.cpp
+++ b/source/fuzz/transformation_outline_function.cpp
@@ -22,8 +22,8 @@ namespace spvtools {
namespace fuzz {
TransformationOutlineFunction::TransformationOutlineFunction(
- const spvtools::fuzz::protobufs::TransformationOutlineFunction& message)
- : message_(message) {}
+ protobufs::TransformationOutlineFunction message)
+ : message_(std::move(message)) {}
TransformationOutlineFunction::TransformationOutlineFunction(
uint32_t entry_block, uint32_t exit_block,
diff --git a/source/fuzz/transformation_outline_function.h b/source/fuzz/transformation_outline_function.h
index 36c0daf5..94ce556d 100644
--- a/source/fuzz/transformation_outline_function.h
+++ b/source/fuzz/transformation_outline_function.h
@@ -30,7 +30,7 @@ namespace fuzz {
class TransformationOutlineFunction : public Transformation {
public:
explicit TransformationOutlineFunction(
- const protobufs::TransformationOutlineFunction& message);
+ protobufs::TransformationOutlineFunction message);
TransformationOutlineFunction(
uint32_t entry_block, uint32_t exit_block,
diff --git a/source/fuzz/transformation_permute_function_parameters.cpp b/source/fuzz/transformation_permute_function_parameters.cpp
index a954cc18..5663d72f 100644
--- a/source/fuzz/transformation_permute_function_parameters.cpp
+++ b/source/fuzz/transformation_permute_function_parameters.cpp
@@ -23,9 +23,8 @@ namespace fuzz {
TransformationPermuteFunctionParameters::
TransformationPermuteFunctionParameters(
- const spvtools::fuzz::protobufs::
- TransformationPermuteFunctionParameters& message)
- : message_(message) {}
+ protobufs::TransformationPermuteFunctionParameters message)
+ : message_(std::move(message)) {}
TransformationPermuteFunctionParameters::
TransformationPermuteFunctionParameters(
diff --git a/source/fuzz/transformation_permute_function_parameters.h b/source/fuzz/transformation_permute_function_parameters.h
index 38de8b18..abb5675c 100644
--- a/source/fuzz/transformation_permute_function_parameters.h
+++ b/source/fuzz/transformation_permute_function_parameters.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationPermuteFunctionParameters : public Transformation {
public:
explicit TransformationPermuteFunctionParameters(
- const protobufs::TransformationPermuteFunctionParameters& message);
+ protobufs::TransformationPermuteFunctionParameters message);
TransformationPermuteFunctionParameters(
uint32_t function_id, uint32_t function_type_fresh_id,
diff --git a/source/fuzz/transformation_permute_phi_operands.cpp b/source/fuzz/transformation_permute_phi_operands.cpp
index ebd3c862..60563312 100644
--- a/source/fuzz/transformation_permute_phi_operands.cpp
+++ b/source/fuzz/transformation_permute_phi_operands.cpp
@@ -22,8 +22,8 @@ namespace spvtools {
namespace fuzz {
TransformationPermutePhiOperands::TransformationPermutePhiOperands(
- const spvtools::fuzz::protobufs::TransformationPermutePhiOperands& message)
- : message_(message) {}
+ protobufs::TransformationPermutePhiOperands message)
+ : message_(std::move(message)) {}
TransformationPermutePhiOperands::TransformationPermutePhiOperands(
uint32_t result_id, const std::vector<uint32_t>& permutation) {
@@ -80,9 +80,9 @@ void TransformationPermutePhiOperands::Apply(
inst->SetInOperands(std::move(permuted_operands));
- // Make sure our changes are analyzed
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ // Update the def-use manager.
+ ir_context->get_def_use_mgr()->ClearInst(inst);
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(inst);
}
protobufs::Transformation TransformationPermutePhiOperands::ToMessage() const {
diff --git a/source/fuzz/transformation_permute_phi_operands.h b/source/fuzz/transformation_permute_phi_operands.h
index 8198b706..16427113 100644
--- a/source/fuzz/transformation_permute_phi_operands.h
+++ b/source/fuzz/transformation_permute_phi_operands.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationPermutePhiOperands : public Transformation {
public:
explicit TransformationPermutePhiOperands(
- const protobufs::TransformationPermutePhiOperands& message);
+ protobufs::TransformationPermutePhiOperands message);
TransformationPermutePhiOperands(uint32_t result_id,
const std::vector<uint32_t>& permutation);
diff --git a/source/fuzz/transformation_propagate_instruction_down.cpp b/source/fuzz/transformation_propagate_instruction_down.cpp
index ba22e398..7713562e 100644
--- a/source/fuzz/transformation_propagate_instruction_down.cpp
+++ b/source/fuzz/transformation_propagate_instruction_down.cpp
@@ -21,8 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationPropagateInstructionDown::TransformationPropagateInstructionDown(
- const protobufs::TransformationPropagateInstructionDown& message)
- : message_(message) {}
+ protobufs::TransformationPropagateInstructionDown message)
+ : message_(std::move(message)) {}
TransformationPropagateInstructionDown::TransformationPropagateInstructionDown(
uint32_t block_id, uint32_t phi_fresh_id,
diff --git a/source/fuzz/transformation_propagate_instruction_down.h b/source/fuzz/transformation_propagate_instruction_down.h
index 7eca1ad1..560d7dc5 100644
--- a/source/fuzz/transformation_propagate_instruction_down.h
+++ b/source/fuzz/transformation_propagate_instruction_down.h
@@ -28,7 +28,7 @@ namespace fuzz {
class TransformationPropagateInstructionDown : public Transformation {
public:
explicit TransformationPropagateInstructionDown(
- const protobufs::TransformationPropagateInstructionDown& message);
+ protobufs::TransformationPropagateInstructionDown message);
TransformationPropagateInstructionDown(
uint32_t block_id, uint32_t phi_fresh_id,
diff --git a/source/fuzz/transformation_propagate_instruction_up.cpp b/source/fuzz/transformation_propagate_instruction_up.cpp
index a2cacf40..bf0e6630 100644
--- a/source/fuzz/transformation_propagate_instruction_up.cpp
+++ b/source/fuzz/transformation_propagate_instruction_up.cpp
@@ -79,8 +79,8 @@ bool HasValidDependencies(opt::IRContext* ir_context, opt::Instruction* inst) {
} // namespace
TransformationPropagateInstructionUp::TransformationPropagateInstructionUp(
- const protobufs::TransformationPropagateInstructionUp& message)
- : message_(message) {}
+ protobufs::TransformationPropagateInstructionUp message)
+ : message_(std::move(message)) {}
TransformationPropagateInstructionUp::TransformationPropagateInstructionUp(
uint32_t block_id,
diff --git a/source/fuzz/transformation_propagate_instruction_up.h b/source/fuzz/transformation_propagate_instruction_up.h
index 63540947..0ca051bf 100644
--- a/source/fuzz/transformation_propagate_instruction_up.h
+++ b/source/fuzz/transformation_propagate_instruction_up.h
@@ -28,7 +28,7 @@ namespace fuzz {
class TransformationPropagateInstructionUp : public Transformation {
public:
explicit TransformationPropagateInstructionUp(
- const protobufs::TransformationPropagateInstructionUp& message);
+ protobufs::TransformationPropagateInstructionUp message);
TransformationPropagateInstructionUp(
uint32_t block_id,
diff --git a/source/fuzz/transformation_push_id_through_variable.cpp b/source/fuzz/transformation_push_id_through_variable.cpp
index cdc40aab..0df1da6b 100644
--- a/source/fuzz/transformation_push_id_through_variable.cpp
+++ b/source/fuzz/transformation_push_id_through_variable.cpp
@@ -21,9 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationPushIdThroughVariable::TransformationPushIdThroughVariable(
- const spvtools::fuzz::protobufs::TransformationPushIdThroughVariable&
- message)
- : message_(message) {}
+ protobufs::TransformationPushIdThroughVariable message)
+ : message_(std::move(message)) {}
TransformationPushIdThroughVariable::TransformationPushIdThroughVariable(
uint32_t value_id, uint32_t value_synonym_id, uint32_t variable_id,
@@ -105,6 +104,10 @@ void TransformationPushIdThroughVariable::Apply(
auto value_instruction =
ir_context->get_def_use_mgr()->GetDef(message_.value_id());
+ opt::Instruction* insert_before =
+ FindInstruction(message_.instruction_descriptor(), ir_context);
+ opt::BasicBlock* enclosing_block = ir_context->get_instr_block(insert_before);
+
// A pointer type instruction pointing to the value type must be defined.
auto pointer_type_id = fuzzerutil::MaybeGetPointerType(
ir_context, value_instruction->type_id(),
@@ -113,36 +116,42 @@ void TransformationPushIdThroughVariable::Apply(
// Adds whether a global or local variable.
if (message_.variable_storage_class() == SpvStorageClassPrivate) {
- fuzzerutil::AddGlobalVariable(ir_context, message_.variable_id(),
- pointer_type_id, SpvStorageClassPrivate,
- message_.initializer_id());
+ opt::Instruction* global_variable = fuzzerutil::AddGlobalVariable(
+ ir_context, message_.variable_id(), pointer_type_id,
+ SpvStorageClassPrivate, message_.initializer_id());
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(global_variable);
} else {
- auto function_id = ir_context
- ->get_instr_block(FindInstruction(
- message_.instruction_descriptor(), ir_context))
- ->GetParent()
- ->result_id();
- fuzzerutil::AddLocalVariable(ir_context, message_.variable_id(),
- pointer_type_id, function_id,
- message_.initializer_id());
+ opt::Function* function =
+ ir_context
+ ->get_instr_block(
+ FindInstruction(message_.instruction_descriptor(), ir_context))
+ ->GetParent();
+ opt::Instruction* local_variable = fuzzerutil::AddLocalVariable(
+ ir_context, message_.variable_id(), pointer_type_id,
+ function->result_id(), message_.initializer_id());
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(local_variable);
+ ir_context->set_instr_block(local_variable, &*function->entry());
}
// First, insert the OpLoad instruction before |instruction_descriptor| and
// then insert the OpStore instruction before the OpLoad instruction.
fuzzerutil::UpdateModuleIdBound(ir_context, message_.value_synonym_id());
- FindInstruction(message_.instruction_descriptor(), ir_context)
- ->InsertBefore(MakeUnique<opt::Instruction>(
+ opt::Instruction* load_instruction =
+ insert_before->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpLoad, value_instruction->type_id(),
message_.value_synonym_id(),
opt::Instruction::OperandList(
- {{SPV_OPERAND_TYPE_ID, {message_.variable_id()}}})))
- ->InsertBefore(MakeUnique<opt::Instruction>(
+ {{SPV_OPERAND_TYPE_ID, {message_.variable_id()}}})));
+ opt::Instruction* store_instruction =
+ load_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpStore, 0, 0,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {message_.variable_id()}},
{SPV_OPERAND_TYPE_ID, {message_.value_id()}}})));
-
- ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(store_instruction);
+ ir_context->set_instr_block(store_instruction, enclosing_block);
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(load_instruction);
+ ir_context->set_instr_block(load_instruction, enclosing_block);
// We should be able to create a synonym of |value_id| if it's not irrelevant.
if (fuzzerutil::CanMakeSynonymOf(ir_context, *transformation_context,
diff --git a/source/fuzz/transformation_push_id_through_variable.h b/source/fuzz/transformation_push_id_through_variable.h
index d0558259..ec6943ca 100644
--- a/source/fuzz/transformation_push_id_through_variable.h
+++ b/source/fuzz/transformation_push_id_through_variable.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationPushIdThroughVariable : public Transformation {
public:
explicit TransformationPushIdThroughVariable(
- const protobufs::TransformationPushIdThroughVariable& message);
+ protobufs::TransformationPushIdThroughVariable message);
TransformationPushIdThroughVariable(
uint32_t value_id, uint32_t value_synonym_fresh_id,
diff --git a/source/fuzz/transformation_record_synonymous_constants.cpp b/source/fuzz/transformation_record_synonymous_constants.cpp
index 30ea94bb..3278d7d8 100644
--- a/source/fuzz/transformation_record_synonymous_constants.cpp
+++ b/source/fuzz/transformation_record_synonymous_constants.cpp
@@ -22,8 +22,8 @@ namespace fuzz {
TransformationRecordSynonymousConstants::
TransformationRecordSynonymousConstants(
- const protobufs::TransformationRecordSynonymousConstants& message)
- : message_(message) {}
+ protobufs::TransformationRecordSynonymousConstants message)
+ : message_(std::move(message)) {}
TransformationRecordSynonymousConstants::
TransformationRecordSynonymousConstants(uint32_t constant1_id,
diff --git a/source/fuzz/transformation_record_synonymous_constants.h b/source/fuzz/transformation_record_synonymous_constants.h
index 4376c878..d99b0e2a 100644
--- a/source/fuzz/transformation_record_synonymous_constants.h
+++ b/source/fuzz/transformation_record_synonymous_constants.h
@@ -24,7 +24,7 @@ namespace fuzz {
class TransformationRecordSynonymousConstants : public Transformation {
public:
explicit TransformationRecordSynonymousConstants(
- const protobufs::TransformationRecordSynonymousConstants& message);
+ protobufs::TransformationRecordSynonymousConstants message);
TransformationRecordSynonymousConstants(uint32_t constant1_id,
uint32_t constant2_id);
diff --git a/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp b/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp
index a2575153..e1977a64 100644
--- a/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp
+++ b/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp
@@ -27,9 +27,8 @@ const uint32_t kArithmeticInstructionIndexRightInOperand = 1;
TransformationReplaceAddSubMulWithCarryingExtended::
TransformationReplaceAddSubMulWithCarryingExtended(
- const spvtools::fuzz::protobufs::
- TransformationReplaceAddSubMulWithCarryingExtended& message)
- : message_(message) {}
+ protobufs::TransformationReplaceAddSubMulWithCarryingExtended message)
+ : message_(std::move(message)) {}
TransformationReplaceAddSubMulWithCarryingExtended::
TransformationReplaceAddSubMulWithCarryingExtended(uint32_t struct_fresh_id,
diff --git a/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.h b/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.h
index 243542c2..9deb2803 100644
--- a/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.h
+++ b/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.h
@@ -27,8 +27,7 @@ class TransformationReplaceAddSubMulWithCarryingExtended
: public Transformation {
public:
explicit TransformationReplaceAddSubMulWithCarryingExtended(
- const protobufs::TransformationReplaceAddSubMulWithCarryingExtended&
- message);
+ protobufs::TransformationReplaceAddSubMulWithCarryingExtended message);
explicit TransformationReplaceAddSubMulWithCarryingExtended(
uint32_t struct_fresh_id, uint32_t result_id);
diff --git a/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp b/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp
index b458b569..24293516 100644
--- a/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp
+++ b/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp
@@ -111,9 +111,9 @@ bool unsigned_int_binop_evaluates_to(T lhs, T rhs, SpvOp binop,
TransformationReplaceBooleanConstantWithConstantBinary::
TransformationReplaceBooleanConstantWithConstantBinary(
- const spvtools::fuzz::protobufs::
- TransformationReplaceBooleanConstantWithConstantBinary& message)
- : message_(message) {}
+ protobufs::TransformationReplaceBooleanConstantWithConstantBinary
+ message)
+ : message_(std::move(message)) {}
TransformationReplaceBooleanConstantWithConstantBinary::
TransformationReplaceBooleanConstantWithConstantBinary(
diff --git a/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h b/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h
index a0ece7f3..97c66bf9 100644
--- a/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h
+++ b/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h
@@ -27,7 +27,7 @@ class TransformationReplaceBooleanConstantWithConstantBinary
: public Transformation {
public:
explicit TransformationReplaceBooleanConstantWithConstantBinary(
- const protobufs::TransformationReplaceBooleanConstantWithConstantBinary&
+ protobufs::TransformationReplaceBooleanConstantWithConstantBinary
message);
TransformationReplaceBooleanConstantWithConstantBinary(
diff --git a/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp b/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp
index e8090121..9ea7cb6a 100644
--- a/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp
+++ b/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp
@@ -21,9 +21,8 @@ namespace fuzz {
TransformationReplaceBranchFromDeadBlockWithExit::
TransformationReplaceBranchFromDeadBlockWithExit(
- const spvtools::fuzz::protobufs::
- TransformationReplaceBranchFromDeadBlockWithExit& message)
- : message_(message) {}
+ protobufs::TransformationReplaceBranchFromDeadBlockWithExit message)
+ : message_(std::move(message)) {}
TransformationReplaceBranchFromDeadBlockWithExit::
TransformationReplaceBranchFromDeadBlockWithExit(uint32_t block_id,
@@ -162,7 +161,10 @@ bool TransformationReplaceBranchFromDeadBlockWithExit::BlockIsSuitable(
if (ir_context->cfg()->preds(successor->id()).size() < 2) {
return false;
}
- return true;
+ // Make sure that domination rules are satisfied when we remove the branch
+ // from the |block| to its |successor|.
+ return fuzzerutil::NewTerminatorPreservesDominationRules(
+ ir_context, block.id(), {ir_context, SpvOpUnreachable});
}
} // namespace fuzz
diff --git a/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h b/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h
index e1418c9d..89667fcd 100644
--- a/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h
+++ b/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h
@@ -27,8 +27,7 @@ namespace fuzz {
class TransformationReplaceBranchFromDeadBlockWithExit : public Transformation {
public:
explicit TransformationReplaceBranchFromDeadBlockWithExit(
- const protobufs::TransformationReplaceBranchFromDeadBlockWithExit&
- message);
+ protobufs::TransformationReplaceBranchFromDeadBlockWithExit message);
TransformationReplaceBranchFromDeadBlockWithExit(uint32_t block_id,
SpvOp opcode,
@@ -41,13 +40,17 @@ class TransformationReplaceBranchFromDeadBlockWithExit : public Transformation {
// predecessor
// - |message_.opcode()| must be one of OpKill, OpReturn, OpReturnValue and
// OpUnreachable
- // - |message_.opcode()| can only be OpKill the module's entry points all
+ // - |message_.opcode()| can only be OpKill if the module's entry points all
// have Fragment execution mode
// - |message_.opcode()| can only be OpReturn if the return type of the
// function containing the block is void
// - If |message_.opcode()| is OpReturnValue then |message_.return_value_id|
// must be an id that is available at the block terminator and that matches
// the return type of the enclosing function
+ // - Domination rules should be preserved when we apply this transformation.
+ // In particular, if some block appears after the |block_id|'s successor in
+ // the CFG, then that block cannot dominate |block_id|'s successor when this
+ // transformation is applied.
bool IsApplicable(
opt::IRContext* ir_context,
const TransformationContext& transformation_context) const override;
diff --git a/source/fuzz/transformation_replace_constant_with_uniform.cpp b/source/fuzz/transformation_replace_constant_with_uniform.cpp
index 95932bf6..c6698c03 100644
--- a/source/fuzz/transformation_replace_constant_with_uniform.cpp
+++ b/source/fuzz/transformation_replace_constant_with_uniform.cpp
@@ -22,9 +22,8 @@ namespace fuzz {
TransformationReplaceConstantWithUniform::
TransformationReplaceConstantWithUniform(
- const spvtools::fuzz::protobufs::
- TransformationReplaceConstantWithUniform& message)
- : message_(message) {}
+ protobufs::TransformationReplaceConstantWithUniform message)
+ : message_(std::move(message)) {}
TransformationReplaceConstantWithUniform::
TransformationReplaceConstantWithUniform(
@@ -254,28 +253,39 @@ void TransformationReplaceConstantWithUniform::Apply(
auto* insert_before_inst = GetInsertBeforeInstruction(ir_context);
assert(insert_before_inst &&
"There must exist an insertion point for OpAccessChain and OpLoad");
+ opt::BasicBlock* enclosing_block =
+ ir_context->get_instr_block(insert_before_inst);
// Add an access chain instruction to target the uniform element.
- insert_before_inst->InsertBefore(
- MakeAccessChainInstruction(ir_context, constant_type_id));
+ auto access_chain_instruction =
+ MakeAccessChainInstruction(ir_context, constant_type_id);
+ auto access_chain_instruction_ptr = access_chain_instruction.get();
+ insert_before_inst->InsertBefore(std::move(access_chain_instruction));
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(
+ access_chain_instruction_ptr);
+ ir_context->set_instr_block(access_chain_instruction_ptr, enclosing_block);
// Add a load from this access chain.
- insert_before_inst->InsertBefore(
- MakeLoadInstruction(ir_context, constant_type_id));
+ auto load_instruction = MakeLoadInstruction(ir_context, constant_type_id);
+ auto load_instruction_ptr = load_instruction.get();
+ insert_before_inst->InsertBefore(std::move(load_instruction));
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(load_instruction_ptr);
+ ir_context->set_instr_block(load_instruction_ptr, enclosing_block);
// Adjust the instruction containing the usage of the constant so that this
// usage refers instead to the result of the load.
instruction_containing_constant_use->SetInOperand(
message_.id_use_descriptor().in_operand_index(),
{message_.fresh_id_for_load()});
+ ir_context->get_def_use_mgr()->EraseUseRecordsOfOperandIds(
+ instruction_containing_constant_use);
+ ir_context->get_def_use_mgr()->AnalyzeInstUse(
+ instruction_containing_constant_use);
// Update the module id bound to reflect the new instructions.
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id_for_load());
fuzzerutil::UpdateModuleIdBound(ir_context,
message_.fresh_id_for_access_chain());
-
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
}
protobufs::Transformation TransformationReplaceConstantWithUniform::ToMessage()
diff --git a/source/fuzz/transformation_replace_constant_with_uniform.h b/source/fuzz/transformation_replace_constant_with_uniform.h
index 9e097484..21210927 100644
--- a/source/fuzz/transformation_replace_constant_with_uniform.h
+++ b/source/fuzz/transformation_replace_constant_with_uniform.h
@@ -28,7 +28,7 @@ namespace fuzz {
class TransformationReplaceConstantWithUniform : public Transformation {
public:
explicit TransformationReplaceConstantWithUniform(
- const protobufs::TransformationReplaceConstantWithUniform& message);
+ protobufs::TransformationReplaceConstantWithUniform message);
TransformationReplaceConstantWithUniform(
protobufs::IdUseDescriptor id_use,
diff --git a/source/fuzz/transformation_replace_copy_memory_with_load_store.cpp b/source/fuzz/transformation_replace_copy_memory_with_load_store.cpp
index 936b0542..de9d1fd3 100644
--- a/source/fuzz/transformation_replace_copy_memory_with_load_store.cpp
+++ b/source/fuzz/transformation_replace_copy_memory_with_load_store.cpp
@@ -22,9 +22,8 @@ namespace fuzz {
TransformationReplaceCopyMemoryWithLoadStore::
TransformationReplaceCopyMemoryWithLoadStore(
- const spvtools::fuzz::protobufs::
- TransformationReplaceCopyMemoryWithLoadStore& message)
- : message_(message) {}
+ protobufs::TransformationReplaceCopyMemoryWithLoadStore message)
+ : message_(std::move(message)) {}
TransformationReplaceCopyMemoryWithLoadStore::
TransformationReplaceCopyMemoryWithLoadStore(
diff --git a/source/fuzz/transformation_replace_copy_memory_with_load_store.h b/source/fuzz/transformation_replace_copy_memory_with_load_store.h
index 67d349ff..55d1e064 100644
--- a/source/fuzz/transformation_replace_copy_memory_with_load_store.h
+++ b/source/fuzz/transformation_replace_copy_memory_with_load_store.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationReplaceCopyMemoryWithLoadStore : public Transformation {
public:
explicit TransformationReplaceCopyMemoryWithLoadStore(
- const protobufs::TransformationReplaceCopyMemoryWithLoadStore& message);
+ protobufs::TransformationReplaceCopyMemoryWithLoadStore message);
TransformationReplaceCopyMemoryWithLoadStore(
uint32_t fresh_id, const protobufs::InstructionDescriptor&
diff --git a/source/fuzz/transformation_replace_copy_object_with_store_load.cpp b/source/fuzz/transformation_replace_copy_object_with_store_load.cpp
index 54c99d51..e0643bf3 100644
--- a/source/fuzz/transformation_replace_copy_object_with_store_load.cpp
+++ b/source/fuzz/transformation_replace_copy_object_with_store_load.cpp
@@ -22,9 +22,8 @@ namespace fuzz {
TransformationReplaceCopyObjectWithStoreLoad::
TransformationReplaceCopyObjectWithStoreLoad(
- const spvtools::fuzz::protobufs::
- TransformationReplaceCopyObjectWithStoreLoad& message)
- : message_(message) {}
+ protobufs::TransformationReplaceCopyObjectWithStoreLoad message)
+ : message_(std::move(message)) {}
TransformationReplaceCopyObjectWithStoreLoad::
TransformationReplaceCopyObjectWithStoreLoad(
@@ -88,6 +87,10 @@ void TransformationReplaceCopyObjectWithStoreLoad::Apply(
assert(copy_object_instruction &&
copy_object_instruction->opcode() == SpvOpCopyObject &&
"The required OpCopyObject instruction must be defined.");
+
+ opt::BasicBlock* enclosing_block =
+ ir_context->get_instr_block(copy_object_instruction);
+
// Get id used as a source by the OpCopyObject instruction.
uint32_t src_operand = copy_object_instruction->GetSingleWordInOperand(0);
// A pointer type instruction pointing to the value type must be defined.
@@ -98,37 +101,46 @@ void TransformationReplaceCopyObjectWithStoreLoad::Apply(
// Adds a global or local variable (according to the storage class).
if (message_.variable_storage_class() == SpvStorageClassPrivate) {
- fuzzerutil::AddGlobalVariable(ir_context, message_.fresh_variable_id(),
- pointer_type_id, SpvStorageClassPrivate,
- message_.variable_initializer_id());
+ opt::Instruction* new_global = fuzzerutil::AddGlobalVariable(
+ ir_context, message_.fresh_variable_id(), pointer_type_id,
+ SpvStorageClassPrivate, message_.variable_initializer_id());
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_global);
} else {
- auto function_id = ir_context->get_instr_block(copy_object_instruction)
- ->GetParent()
- ->result_id();
- fuzzerutil::AddLocalVariable(ir_context, message_.fresh_variable_id(),
- pointer_type_id, function_id,
- message_.variable_initializer_id());
+ opt::Function* function =
+ ir_context->get_instr_block(copy_object_instruction)->GetParent();
+ opt::Instruction* new_local = fuzzerutil::AddLocalVariable(
+ ir_context, message_.fresh_variable_id(), pointer_type_id,
+ function->result_id(), message_.variable_initializer_id());
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_local);
+ ir_context->set_instr_block(new_local, &*function->begin());
}
// First, insert the OpLoad instruction before the OpCopyObject instruction
// and then insert the OpStore instruction before the OpLoad instruction.
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_variable_id());
- copy_object_instruction
- ->InsertBefore(MakeUnique<opt::Instruction>(
+ opt::Instruction* load_instruction =
+ copy_object_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpLoad, copy_object_instruction->type_id(),
message_.copy_object_result_id(),
opt::Instruction::OperandList(
- {{SPV_OPERAND_TYPE_ID, {message_.fresh_variable_id()}}})))
- ->InsertBefore(MakeUnique<opt::Instruction>(
+ {{SPV_OPERAND_TYPE_ID, {message_.fresh_variable_id()}}})));
+ opt::Instruction* store_instruction =
+ load_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpStore, 0, 0,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {message_.fresh_variable_id()}},
{SPV_OPERAND_TYPE_ID, {src_operand}}})));
+
+ // Register the new instructions with the def-use manager, and record their
+ // enclosing block.
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(store_instruction);
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(load_instruction);
+ ir_context->set_instr_block(store_instruction, enclosing_block);
+ ir_context->set_instr_block(load_instruction, enclosing_block);
+
// Remove the CopyObject instruction.
ir_context->KillInst(copy_object_instruction);
- ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
-
if (!transformation_context->GetFactManager()->IdIsIrrelevant(
message_.copy_object_result_id()) &&
!transformation_context->GetFactManager()->IdIsIrrelevant(src_operand)) {
diff --git a/source/fuzz/transformation_replace_copy_object_with_store_load.h b/source/fuzz/transformation_replace_copy_object_with_store_load.h
index a90905c5..8c5ce9e2 100644
--- a/source/fuzz/transformation_replace_copy_object_with_store_load.h
+++ b/source/fuzz/transformation_replace_copy_object_with_store_load.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationReplaceCopyObjectWithStoreLoad : public Transformation {
public:
explicit TransformationReplaceCopyObjectWithStoreLoad(
- const protobufs::TransformationReplaceCopyObjectWithStoreLoad& message);
+ protobufs::TransformationReplaceCopyObjectWithStoreLoad message);
TransformationReplaceCopyObjectWithStoreLoad(
uint32_t copy_object_result_id, uint32_t fresh_variable_id,
diff --git a/source/fuzz/transformation_replace_id_with_synonym.cpp b/source/fuzz/transformation_replace_id_with_synonym.cpp
index 24e079ff..92ce751d 100644
--- a/source/fuzz/transformation_replace_id_with_synonym.cpp
+++ b/source/fuzz/transformation_replace_id_with_synonym.cpp
@@ -26,9 +26,8 @@ namespace spvtools {
namespace fuzz {
TransformationReplaceIdWithSynonym::TransformationReplaceIdWithSynonym(
- const spvtools::fuzz::protobufs::TransformationReplaceIdWithSynonym&
- message)
- : message_(message) {}
+ protobufs::TransformationReplaceIdWithSynonym message)
+ : message_(std::move(message)) {}
TransformationReplaceIdWithSynonym::TransformationReplaceIdWithSynonym(
protobufs::IdUseDescriptor id_use_descriptor, uint32_t synonymous_id) {
@@ -95,8 +94,12 @@ void TransformationReplaceIdWithSynonym::Apply(
instruction_to_change->SetInOperand(
message_.id_use_descriptor().in_operand_index(),
{message_.synonymous_id()});
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ ir_context->get_def_use_mgr()->EraseUseRecordsOfOperandIds(
+ instruction_to_change);
+ ir_context->get_def_use_mgr()->AnalyzeInstUse(instruction_to_change);
+
+ // No analyses need to be invalidated, since the transformation is local to a
+ // block, and the def-use analysis has been updated.
}
protobufs::Transformation TransformationReplaceIdWithSynonym::ToMessage()
diff --git a/source/fuzz/transformation_replace_id_with_synonym.h b/source/fuzz/transformation_replace_id_with_synonym.h
index 3101710a..1ac636b4 100644
--- a/source/fuzz/transformation_replace_id_with_synonym.h
+++ b/source/fuzz/transformation_replace_id_with_synonym.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationReplaceIdWithSynonym : public Transformation {
public:
explicit TransformationReplaceIdWithSynonym(
- const protobufs::TransformationReplaceIdWithSynonym& message);
+ protobufs::TransformationReplaceIdWithSynonym message);
TransformationReplaceIdWithSynonym(
protobufs::IdUseDescriptor id_use_descriptor, uint32_t synonymous_id);
diff --git a/source/fuzz/transformation_replace_irrelevant_id.cpp b/source/fuzz/transformation_replace_irrelevant_id.cpp
index 27f56eba..a71f96a8 100644
--- a/source/fuzz/transformation_replace_irrelevant_id.cpp
+++ b/source/fuzz/transformation_replace_irrelevant_id.cpp
@@ -21,8 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationReplaceIrrelevantId::TransformationReplaceIrrelevantId(
- const protobufs::TransformationReplaceIrrelevantId& message)
- : message_(message) {}
+ protobufs::TransformationReplaceIrrelevantId message)
+ : message_(std::move(message)) {}
TransformationReplaceIrrelevantId::TransformationReplaceIrrelevantId(
const protobufs::IdUseDescriptor& id_use_descriptor,
@@ -107,9 +107,12 @@ void TransformationReplaceIrrelevantId::Apply(
message_.id_use_descriptor().in_operand_index(),
{message_.replacement_id()});
- // Invalidate the analyses, since the usage of ids has been changed.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ ir_context->get_def_use_mgr()->EraseUseRecordsOfOperandIds(
+ instruction_to_change);
+ ir_context->get_def_use_mgr()->AnalyzeInstUse(instruction_to_change);
+
+ // No analyses need to be invalidated, since the transformation is local to a
+ // block, and the def-use analysis has been updated.
}
protobufs::Transformation TransformationReplaceIrrelevantId::ToMessage() const {
diff --git a/source/fuzz/transformation_replace_irrelevant_id.h b/source/fuzz/transformation_replace_irrelevant_id.h
index 35b1987d..e6210b4d 100644
--- a/source/fuzz/transformation_replace_irrelevant_id.h
+++ b/source/fuzz/transformation_replace_irrelevant_id.h
@@ -23,7 +23,7 @@ namespace fuzz {
class TransformationReplaceIrrelevantId : public Transformation {
public:
explicit TransformationReplaceIrrelevantId(
- const protobufs::TransformationReplaceIrrelevantId& message);
+ protobufs::TransformationReplaceIrrelevantId message);
TransformationReplaceIrrelevantId(
const protobufs::IdUseDescriptor& id_use_descriptor,
diff --git a/source/fuzz/transformation_replace_linear_algebra_instruction.cpp b/source/fuzz/transformation_replace_linear_algebra_instruction.cpp
index fc73a262..2430ccab 100644
--- a/source/fuzz/transformation_replace_linear_algebra_instruction.cpp
+++ b/source/fuzz/transformation_replace_linear_algebra_instruction.cpp
@@ -22,9 +22,8 @@ namespace fuzz {
TransformationReplaceLinearAlgebraInstruction::
TransformationReplaceLinearAlgebraInstruction(
- const spvtools::fuzz::protobufs::
- TransformationReplaceLinearAlgebraInstruction& message)
- : message_(message) {}
+ protobufs::TransformationReplaceLinearAlgebraInstruction message)
+ : message_(std::move(message)) {}
TransformationReplaceLinearAlgebraInstruction::
TransformationReplaceLinearAlgebraInstruction(
diff --git a/source/fuzz/transformation_replace_linear_algebra_instruction.h b/source/fuzz/transformation_replace_linear_algebra_instruction.h
index 45f4aa64..0f0c18bf 100644
--- a/source/fuzz/transformation_replace_linear_algebra_instruction.h
+++ b/source/fuzz/transformation_replace_linear_algebra_instruction.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationReplaceLinearAlgebraInstruction : public Transformation {
public:
explicit TransformationReplaceLinearAlgebraInstruction(
- const protobufs::TransformationReplaceLinearAlgebraInstruction& message);
+ protobufs::TransformationReplaceLinearAlgebraInstruction message);
TransformationReplaceLinearAlgebraInstruction(
const std::vector<uint32_t>& fresh_ids,
diff --git a/source/fuzz/transformation_replace_load_store_with_copy_memory.cpp b/source/fuzz/transformation_replace_load_store_with_copy_memory.cpp
index 6067fca8..e75337f6 100644
--- a/source/fuzz/transformation_replace_load_store_with_copy_memory.cpp
+++ b/source/fuzz/transformation_replace_load_store_with_copy_memory.cpp
@@ -29,9 +29,8 @@ const uint32_t kOpLoadOperandIndexSourceVariable = 2;
TransformationReplaceLoadStoreWithCopyMemory::
TransformationReplaceLoadStoreWithCopyMemory(
- const spvtools::fuzz::protobufs::
- TransformationReplaceLoadStoreWithCopyMemory& message)
- : message_(message) {}
+ protobufs::TransformationReplaceLoadStoreWithCopyMemory message)
+ : message_(std::move(message)) {}
TransformationReplaceLoadStoreWithCopyMemory::
TransformationReplaceLoadStoreWithCopyMemory(
diff --git a/source/fuzz/transformation_replace_load_store_with_copy_memory.h b/source/fuzz/transformation_replace_load_store_with_copy_memory.h
index 4dd728e7..bb4d27ef 100644
--- a/source/fuzz/transformation_replace_load_store_with_copy_memory.h
+++ b/source/fuzz/transformation_replace_load_store_with_copy_memory.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationReplaceLoadStoreWithCopyMemory : public Transformation {
public:
explicit TransformationReplaceLoadStoreWithCopyMemory(
- const protobufs::TransformationReplaceLoadStoreWithCopyMemory& message);
+ protobufs::TransformationReplaceLoadStoreWithCopyMemory message);
TransformationReplaceLoadStoreWithCopyMemory(
const protobufs::InstructionDescriptor& load_instruction_descriptor,
diff --git a/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp b/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp
index f13af7e7..84ca1aba 100644
--- a/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp
+++ b/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp
@@ -21,9 +21,8 @@ namespace fuzz {
TransformationReplaceOpPhiIdFromDeadPredecessor::
TransformationReplaceOpPhiIdFromDeadPredecessor(
- const protobufs::TransformationReplaceOpPhiIdFromDeadPredecessor&
- message)
- : message_(message) {}
+ protobufs::TransformationReplaceOpPhiIdFromDeadPredecessor message)
+ : message_(std::move(message)) {}
TransformationReplaceOpPhiIdFromDeadPredecessor::
TransformationReplaceOpPhiIdFromDeadPredecessor(uint32_t opphi_id,
diff --git a/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.h b/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.h
index d26b6b0a..87ce8ad1 100644
--- a/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.h
+++ b/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.h
@@ -23,8 +23,7 @@ namespace fuzz {
class TransformationReplaceOpPhiIdFromDeadPredecessor : public Transformation {
public:
explicit TransformationReplaceOpPhiIdFromDeadPredecessor(
- const protobufs::TransformationReplaceOpPhiIdFromDeadPredecessor&
- message);
+ protobufs::TransformationReplaceOpPhiIdFromDeadPredecessor message);
TransformationReplaceOpPhiIdFromDeadPredecessor(uint32_t opphi_id,
uint32_t pred_label_id,
diff --git a/source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp b/source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp
index 7160d4d5..c0e6e449 100644
--- a/source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp
+++ b/source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp
@@ -20,9 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationReplaceOpSelectWithConditionalBranch::
TransformationReplaceOpSelectWithConditionalBranch(
- const spvtools::fuzz::protobufs::
- TransformationReplaceOpSelectWithConditionalBranch& message)
- : message_(message) {}
+ protobufs::TransformationReplaceOpSelectWithConditionalBranch message)
+ : message_(std::move(message)) {}
TransformationReplaceOpSelectWithConditionalBranch::
TransformationReplaceOpSelectWithConditionalBranch(
diff --git a/source/fuzz/transformation_replace_opselect_with_conditional_branch.h b/source/fuzz/transformation_replace_opselect_with_conditional_branch.h
index 8ee5c7f1..ec926c65 100644
--- a/source/fuzz/transformation_replace_opselect_with_conditional_branch.h
+++ b/source/fuzz/transformation_replace_opselect_with_conditional_branch.h
@@ -24,8 +24,7 @@ class TransformationReplaceOpSelectWithConditionalBranch
: public Transformation {
public:
explicit TransformationReplaceOpSelectWithConditionalBranch(
- const protobufs::TransformationReplaceOpSelectWithConditionalBranch&
- message);
+ protobufs::TransformationReplaceOpSelectWithConditionalBranch message);
TransformationReplaceOpSelectWithConditionalBranch(uint32_t select_id,
uint32_t true_block_id,
diff --git a/source/fuzz/transformation_replace_parameter_with_global.cpp b/source/fuzz/transformation_replace_parameter_with_global.cpp
index cdf7645f..caf67168 100644
--- a/source/fuzz/transformation_replace_parameter_with_global.cpp
+++ b/source/fuzz/transformation_replace_parameter_with_global.cpp
@@ -23,8 +23,8 @@ namespace fuzz {
TransformationReplaceParameterWithGlobal::
TransformationReplaceParameterWithGlobal(
- const protobufs::TransformationReplaceParameterWithGlobal& message)
- : message_(message) {}
+ protobufs::TransformationReplaceParameterWithGlobal message)
+ : message_(std::move(message)) {}
TransformationReplaceParameterWithGlobal::
TransformationReplaceParameterWithGlobal(
diff --git a/source/fuzz/transformation_replace_parameter_with_global.h b/source/fuzz/transformation_replace_parameter_with_global.h
index c2d5f8ff..38a9c17f 100644
--- a/source/fuzz/transformation_replace_parameter_with_global.h
+++ b/source/fuzz/transformation_replace_parameter_with_global.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationReplaceParameterWithGlobal : public Transformation {
public:
explicit TransformationReplaceParameterWithGlobal(
- const protobufs::TransformationReplaceParameterWithGlobal& message);
+ protobufs::TransformationReplaceParameterWithGlobal message);
TransformationReplaceParameterWithGlobal(uint32_t function_type_fresh_id,
uint32_t parameter_id,
diff --git a/source/fuzz/transformation_replace_params_with_struct.cpp b/source/fuzz/transformation_replace_params_with_struct.cpp
index 0a135e56..13eeccb4 100644
--- a/source/fuzz/transformation_replace_params_with_struct.cpp
+++ b/source/fuzz/transformation_replace_params_with_struct.cpp
@@ -22,8 +22,8 @@ namespace spvtools {
namespace fuzz {
TransformationReplaceParamsWithStruct::TransformationReplaceParamsWithStruct(
- const protobufs::TransformationReplaceParamsWithStruct& message)
- : message_(message) {}
+ protobufs::TransformationReplaceParamsWithStruct message)
+ : message_(std::move(message)) {}
TransformationReplaceParamsWithStruct::TransformationReplaceParamsWithStruct(
const std::vector<uint32_t>& parameter_id, uint32_t fresh_function_type_id,
diff --git a/source/fuzz/transformation_replace_params_with_struct.h b/source/fuzz/transformation_replace_params_with_struct.h
index afa6b14f..705f3405 100644
--- a/source/fuzz/transformation_replace_params_with_struct.h
+++ b/source/fuzz/transformation_replace_params_with_struct.h
@@ -28,7 +28,7 @@ namespace fuzz {
class TransformationReplaceParamsWithStruct : public Transformation {
public:
explicit TransformationReplaceParamsWithStruct(
- const protobufs::TransformationReplaceParamsWithStruct& message);
+ protobufs::TransformationReplaceParamsWithStruct message);
TransformationReplaceParamsWithStruct(
const std::vector<uint32_t>& parameter_id,
diff --git a/source/fuzz/transformation_set_function_control.cpp b/source/fuzz/transformation_set_function_control.cpp
index 8ab9b8cb..02a8c9fe 100644
--- a/source/fuzz/transformation_set_function_control.cpp
+++ b/source/fuzz/transformation_set_function_control.cpp
@@ -18,8 +18,8 @@ namespace spvtools {
namespace fuzz {
TransformationSetFunctionControl::TransformationSetFunctionControl(
- const spvtools::fuzz::protobufs::TransformationSetFunctionControl& message)
- : message_(message) {}
+ protobufs::TransformationSetFunctionControl message)
+ : message_(std::move(message)) {}
TransformationSetFunctionControl::TransformationSetFunctionControl(
uint32_t function_id, uint32_t function_control) {
diff --git a/source/fuzz/transformation_set_function_control.h b/source/fuzz/transformation_set_function_control.h
index 2952cc6d..2e16e1ca 100644
--- a/source/fuzz/transformation_set_function_control.h
+++ b/source/fuzz/transformation_set_function_control.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationSetFunctionControl : public Transformation {
public:
explicit TransformationSetFunctionControl(
- const protobufs::TransformationSetFunctionControl& message);
+ protobufs::TransformationSetFunctionControl message);
TransformationSetFunctionControl(uint32_t function_id,
uint32_t function_control);
diff --git a/source/fuzz/transformation_set_loop_control.cpp b/source/fuzz/transformation_set_loop_control.cpp
index b2180d8a..14499606 100644
--- a/source/fuzz/transformation_set_loop_control.cpp
+++ b/source/fuzz/transformation_set_loop_control.cpp
@@ -18,8 +18,8 @@ namespace spvtools {
namespace fuzz {
TransformationSetLoopControl::TransformationSetLoopControl(
- const spvtools::fuzz::protobufs::TransformationSetLoopControl& message)
- : message_(message) {}
+ protobufs::TransformationSetLoopControl message)
+ : message_(std::move(message)) {}
TransformationSetLoopControl::TransformationSetLoopControl(
uint32_t block_id, uint32_t loop_control, uint32_t peel_count,
@@ -77,12 +77,14 @@ bool TransformationSetLoopControl::IsApplicable(
}
}
- if ((message_.loop_control() &
- (SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask)) &&
- !(PeelCountIsSupported(ir_context) &&
- PartialCountIsSupported(ir_context))) {
- // At least one of PeelCount or PartialCount is used, but the SPIR-V version
- // in question does not support these loop controls.
+ // Check that PeelCount and PartialCount are supported if used.
+ if ((message_.loop_control() & SpvLoopControlPeelCountMask) &&
+ !PeelCountIsSupported(ir_context)) {
+ return false;
+ }
+
+ if ((message_.loop_control() & SpvLoopControlPartialCountMask) &&
+ !PartialCountIsSupported(ir_context)) {
return false;
}
@@ -183,14 +185,16 @@ bool TransformationSetLoopControl::LoopControlBitIsAddedByTransformation(
bool TransformationSetLoopControl::PartialCountIsSupported(
opt::IRContext* ir_context) {
- // TODO(afd): We capture the universal environments for which this loop
- // control is definitely not supported. The check should be refined on
- // demand for other target environments.
+ // TODO(afd): We capture the environments for which this loop control is
+ // definitely not supported. The check should be refined on demand for other
+ // target environments.
switch (ir_context->grammar().target_env()) {
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_UNIVERSAL_1_1:
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_UNIVERSAL_1_3:
+ case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_VULKAN_1_1:
return false;
default:
return true;
@@ -199,14 +203,16 @@ bool TransformationSetLoopControl::PartialCountIsSupported(
bool TransformationSetLoopControl::PeelCountIsSupported(
opt::IRContext* ir_context) {
- // TODO(afd): We capture the universal environments for which this loop
- // control is definitely not supported. The check should be refined on
- // demand for other target environments.
+ // TODO(afd): We capture the environments for which this loop control is
+ // definitely not supported. The check should be refined on demand for other
+ // target environments.
switch (ir_context->grammar().target_env()) {
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_UNIVERSAL_1_1:
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_UNIVERSAL_1_3:
+ case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_VULKAN_1_1:
return false;
default:
return true;
diff --git a/source/fuzz/transformation_set_loop_control.h b/source/fuzz/transformation_set_loop_control.h
index c3480b19..bc17c8a4 100644
--- a/source/fuzz/transformation_set_loop_control.h
+++ b/source/fuzz/transformation_set_loop_control.h
@@ -29,7 +29,7 @@ class TransformationSetLoopControl : public Transformation {
const static uint32_t kLoopControlFirstLiteralInOperandIndex = 3;
explicit TransformationSetLoopControl(
- const protobufs::TransformationSetLoopControl& message);
+ protobufs::TransformationSetLoopControl message);
TransformationSetLoopControl(uint32_t block_id, uint32_t loop_control,
uint32_t peel_count, uint32_t partial_count);
diff --git a/source/fuzz/transformation_set_memory_operands_mask.cpp b/source/fuzz/transformation_set_memory_operands_mask.cpp
index deb207ae..5a986ad2 100644
--- a/source/fuzz/transformation_set_memory_operands_mask.cpp
+++ b/source/fuzz/transformation_set_memory_operands_mask.cpp
@@ -29,9 +29,8 @@ const uint32_t kOpCopyMemorySizedFirstMemoryOperandsMaskIndex = 3;
} // namespace
TransformationSetMemoryOperandsMask::TransformationSetMemoryOperandsMask(
- const spvtools::fuzz::protobufs::TransformationSetMemoryOperandsMask&
- message)
- : message_(message) {}
+ protobufs::TransformationSetMemoryOperandsMask message)
+ : message_(std::move(message)) {}
TransformationSetMemoryOperandsMask::TransformationSetMemoryOperandsMask(
const protobufs::InstructionDescriptor& memory_access_instruction,
@@ -53,7 +52,9 @@ bool TransformationSetMemoryOperandsMask::IsApplicable(
SpvOpCopyMemory ||
message_.memory_access_instruction().target_instruction_opcode() ==
SpvOpCopyMemorySized);
- assert(MultipleMemoryOperandMasksAreSupported(ir_context));
+ assert(MultipleMemoryOperandMasksAreSupported(ir_context) &&
+ "Multiple memory operand masks are not supported for this SPIR-V "
+ "version.");
}
auto instruction =
@@ -205,14 +206,16 @@ uint32_t TransformationSetMemoryOperandsMask::GetInOperandIndexForMask(
bool TransformationSetMemoryOperandsMask::
MultipleMemoryOperandMasksAreSupported(opt::IRContext* ir_context) {
- // TODO(afd): We capture the universal environments for which this loop
- // control is definitely not supported. The check should be refined on
- // demand for other target environments.
+ // TODO(afd): We capture the environments for which this loop control is
+ // definitely not supported. The check should be refined on demand for other
+ // target environments.
switch (ir_context->grammar().target_env()) {
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_UNIVERSAL_1_1:
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_UNIVERSAL_1_3:
+ case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_VULKAN_1_1:
return false;
default:
return true;
diff --git a/source/fuzz/transformation_set_memory_operands_mask.h b/source/fuzz/transformation_set_memory_operands_mask.h
index 7357b1ad..c52fbdba 100644
--- a/source/fuzz/transformation_set_memory_operands_mask.h
+++ b/source/fuzz/transformation_set_memory_operands_mask.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationSetMemoryOperandsMask : public Transformation {
public:
explicit TransformationSetMemoryOperandsMask(
- const protobufs::TransformationSetMemoryOperandsMask& message);
+ protobufs::TransformationSetMemoryOperandsMask message);
TransformationSetMemoryOperandsMask(
const protobufs::InstructionDescriptor& memory_access_instruction,
diff --git a/source/fuzz/transformation_set_selection_control.cpp b/source/fuzz/transformation_set_selection_control.cpp
index 625187ea..6dddbdf8 100644
--- a/source/fuzz/transformation_set_selection_control.cpp
+++ b/source/fuzz/transformation_set_selection_control.cpp
@@ -18,8 +18,8 @@ namespace spvtools {
namespace fuzz {
TransformationSetSelectionControl::TransformationSetSelectionControl(
- const spvtools::fuzz::protobufs::TransformationSetSelectionControl& message)
- : message_(message) {}
+ protobufs::TransformationSetSelectionControl message)
+ : message_(std::move(message)) {}
TransformationSetSelectionControl::TransformationSetSelectionControl(
uint32_t block_id, uint32_t selection_control) {
diff --git a/source/fuzz/transformation_set_selection_control.h b/source/fuzz/transformation_set_selection_control.h
index 56b58852..93b19049 100644
--- a/source/fuzz/transformation_set_selection_control.h
+++ b/source/fuzz/transformation_set_selection_control.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationSetSelectionControl : public Transformation {
public:
explicit TransformationSetSelectionControl(
- const protobufs::TransformationSetSelectionControl& message);
+ protobufs::TransformationSetSelectionControl message);
TransformationSetSelectionControl(uint32_t block_id,
uint32_t selection_control);
diff --git a/source/fuzz/transformation_split_block.cpp b/source/fuzz/transformation_split_block.cpp
index b383c405..e15dffa3 100644
--- a/source/fuzz/transformation_split_block.cpp
+++ b/source/fuzz/transformation_split_block.cpp
@@ -24,8 +24,8 @@ namespace spvtools {
namespace fuzz {
TransformationSplitBlock::TransformationSplitBlock(
- const spvtools::fuzz::protobufs::TransformationSplitBlock& message)
- : message_(message) {}
+ protobufs::TransformationSplitBlock message)
+ : message_(std::move(message)) {}
TransformationSplitBlock::TransformationSplitBlock(
const protobufs::InstructionDescriptor& instruction_to_split_before,
@@ -109,24 +109,37 @@ void TransformationSplitBlock::Apply(
split_before);
// The split does not automatically add a branch between the two parts of
// the original block, so we add one.
- block_to_split->AddInstruction(MakeUnique<opt::Instruction>(
+ auto branch_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpBranch, 0, 0,
std::initializer_list<opt::Operand>{opt::Operand(
- spv_operand_type_t::SPV_OPERAND_TYPE_ID, {message_.fresh_id()})}));
+ spv_operand_type_t::SPV_OPERAND_TYPE_ID, {message_.fresh_id()})});
+ auto branch_instruction_ptr = branch_instruction.get();
+ block_to_split->AddInstruction(std::move(branch_instruction));
+
+ // Inform the def-use manager about the branch instruction, and record its
+ // block.
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(branch_instruction_ptr);
+ ir_context->set_instr_block(branch_instruction_ptr, block_to_split);
+
// If we split before OpPhi instructions, we need to update their
// predecessor operand so that the block they used to be inside is now the
// predecessor.
- new_bb->ForEachPhiInst([block_to_split](opt::Instruction* phi_inst) {
+ new_bb->ForEachPhiInst([block_to_split,
+ ir_context](opt::Instruction* phi_inst) {
assert(
phi_inst->NumInOperands() == 2 &&
"Precondition: a block can only be split before an OpPhi if the block"
"has exactly one predecessor.");
phi_inst->SetInOperand(1, {block_to_split->id()});
+ ir_context->UpdateDefUse(phi_inst);
});
- // Invalidate all analyses
+ // We have updated the def-use manager and the instruction to block mapping,
+ // but other analyses (especially control flow-related ones) need to be
+ // recomputed.
ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ opt::IRContext::Analysis::kAnalysisDefUse |
+ opt::IRContext::Analysis::kAnalysisInstrToBlockMapping);
// If the block being split was dead, the new block arising from the split is
// also dead.
diff --git a/source/fuzz/transformation_split_block.h b/source/fuzz/transformation_split_block.h
index 27bf6f8c..ace77b5b 100644
--- a/source/fuzz/transformation_split_block.h
+++ b/source/fuzz/transformation_split_block.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationSplitBlock : public Transformation {
public:
explicit TransformationSplitBlock(
- const protobufs::TransformationSplitBlock& message);
+ protobufs::TransformationSplitBlock message);
TransformationSplitBlock(
const protobufs::InstructionDescriptor& instruction_to_split_before,
diff --git a/source/fuzz/transformation_store.cpp b/source/fuzz/transformation_store.cpp
index 460ca016..f8c6d013 100644
--- a/source/fuzz/transformation_store.cpp
+++ b/source/fuzz/transformation_store.cpp
@@ -20,9 +20,8 @@
namespace spvtools {
namespace fuzz {
-TransformationStore::TransformationStore(
- const spvtools::fuzz::protobufs::TransformationStore& message)
- : message_(message) {}
+TransformationStore::TransformationStore(protobufs::TransformationStore message)
+ : message_(std::move(message)) {}
TransformationStore::TransformationStore(
uint32_t pointer_id, uint32_t value_id,
@@ -110,13 +109,20 @@ bool TransformationStore::IsApplicable(
void TransformationStore::Apply(opt::IRContext* ir_context,
TransformationContext* /*unused*/) const {
- FindInstruction(message_.instruction_to_insert_before(), ir_context)
- ->InsertBefore(MakeUnique<opt::Instruction>(
- ir_context, SpvOpStore, 0, 0,
- opt::Instruction::OperandList(
- {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
- {SPV_OPERAND_TYPE_ID, {message_.value_id()}}})));
- ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+ auto insert_before =
+ FindInstruction(message_.instruction_to_insert_before(), ir_context);
+ auto new_instruction = MakeUnique<opt::Instruction>(
+ ir_context, SpvOpStore, 0, 0,
+ opt::Instruction::OperandList(
+ {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
+ {SPV_OPERAND_TYPE_ID, {message_.value_id()}}}));
+ auto new_instruction_ptr = new_instruction.get();
+ insert_before->InsertBefore(std::move(new_instruction));
+ // Inform the def-use manager about the new instruction and record its basic
+ // block.
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction_ptr);
+ ir_context->set_instr_block(new_instruction_ptr,
+ ir_context->get_instr_block(insert_before));
}
protobufs::Transformation TransformationStore::ToMessage() const {
diff --git a/source/fuzz/transformation_store.h b/source/fuzz/transformation_store.h
index 70520489..18ba1d7d 100644
--- a/source/fuzz/transformation_store.h
+++ b/source/fuzz/transformation_store.h
@@ -25,7 +25,7 @@ namespace fuzz {
class TransformationStore : public Transformation {
public:
- explicit TransformationStore(const protobufs::TransformationStore& message);
+ explicit TransformationStore(protobufs::TransformationStore message);
TransformationStore(
uint32_t pointer_id, uint32_t value_id,
diff --git a/source/fuzz/transformation_swap_commutable_operands.cpp b/source/fuzz/transformation_swap_commutable_operands.cpp
index b8bdb790..a02e95a0 100644
--- a/source/fuzz/transformation_swap_commutable_operands.cpp
+++ b/source/fuzz/transformation_swap_commutable_operands.cpp
@@ -21,9 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationSwapCommutableOperands::TransformationSwapCommutableOperands(
- const spvtools::fuzz::protobufs::TransformationSwapCommutableOperands&
- message)
- : message_(message) {}
+ protobufs::TransformationSwapCommutableOperands message)
+ : message_(std::move(message)) {}
TransformationSwapCommutableOperands::TransformationSwapCommutableOperands(
const protobufs::InstructionDescriptor& instruction_descriptor) {
diff --git a/source/fuzz/transformation_swap_commutable_operands.h b/source/fuzz/transformation_swap_commutable_operands.h
index c291c3ea..5e211f19 100644
--- a/source/fuzz/transformation_swap_commutable_operands.h
+++ b/source/fuzz/transformation_swap_commutable_operands.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationSwapCommutableOperands : public Transformation {
public:
explicit TransformationSwapCommutableOperands(
- const protobufs::TransformationSwapCommutableOperands& message);
+ protobufs::TransformationSwapCommutableOperands message);
TransformationSwapCommutableOperands(
const protobufs::InstructionDescriptor& instruction_descriptor);
diff --git a/source/fuzz/transformation_swap_conditional_branch_operands.cpp b/source/fuzz/transformation_swap_conditional_branch_operands.cpp
index 866fee66..340836d1 100644
--- a/source/fuzz/transformation_swap_conditional_branch_operands.cpp
+++ b/source/fuzz/transformation_swap_conditional_branch_operands.cpp
@@ -22,9 +22,8 @@ namespace fuzz {
TransformationSwapConditionalBranchOperands::
TransformationSwapConditionalBranchOperands(
- const spvtools::fuzz::protobufs::
- TransformationSwapConditionalBranchOperands& message)
- : message_(message) {}
+ protobufs::TransformationSwapConditionalBranchOperands message)
+ : message_(std::move(message)) {}
TransformationSwapConditionalBranchOperands::
TransformationSwapConditionalBranchOperands(
@@ -70,11 +69,13 @@ void TransformationSwapConditionalBranchOperands::Apply(
// We are swapping the labels in OpBranchConditional. This means that we must
// invert the guard as well. We are using OpLogicalNot for that purpose here.
- iter.InsertBefore(MakeUnique<opt::Instruction>(
+ auto new_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpLogicalNot, condition_inst->type_id(),
message_.fresh_id(),
opt::Instruction::OperandList{
- {SPV_OPERAND_TYPE_ID, {condition_inst->result_id()}}}));
+ {SPV_OPERAND_TYPE_ID, {condition_inst->result_id()}}});
+ auto new_instruction_ptr = new_instruction.get();
+ iter.InsertBefore(std::move(new_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
@@ -89,9 +90,13 @@ void TransformationSwapConditionalBranchOperands::Apply(
std::swap(branch_inst->GetInOperand(3), branch_inst->GetInOperand(4));
}
- // Make sure the changes are analyzed.
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction_ptr);
+ ir_context->set_instr_block(new_instruction_ptr, block);
+ ir_context->get_def_use_mgr()->EraseUseRecordsOfOperandIds(branch_inst);
+ ir_context->get_def_use_mgr()->AnalyzeInstUse(branch_inst);
+
+ // No analyses need to be invalidated since the transformation is local to a
+ // block and the def-use and instruction-to-block mappings have been updated.
}
protobufs::Transformation
diff --git a/source/fuzz/transformation_swap_conditional_branch_operands.h b/source/fuzz/transformation_swap_conditional_branch_operands.h
index 022c54a7..165ab806 100644
--- a/source/fuzz/transformation_swap_conditional_branch_operands.h
+++ b/source/fuzz/transformation_swap_conditional_branch_operands.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationSwapConditionalBranchOperands : public Transformation {
public:
explicit TransformationSwapConditionalBranchOperands(
- const protobufs::TransformationSwapConditionalBranchOperands& message);
+ protobufs::TransformationSwapConditionalBranchOperands message);
TransformationSwapConditionalBranchOperands(
const protobufs::InstructionDescriptor& instruction_descriptor,
diff --git a/source/fuzz/transformation_toggle_access_chain_instruction.cpp b/source/fuzz/transformation_toggle_access_chain_instruction.cpp
index 1952a343..34523fe8 100644
--- a/source/fuzz/transformation_toggle_access_chain_instruction.cpp
+++ b/source/fuzz/transformation_toggle_access_chain_instruction.cpp
@@ -22,9 +22,8 @@ namespace fuzz {
TransformationToggleAccessChainInstruction::
TransformationToggleAccessChainInstruction(
- const spvtools::fuzz::protobufs::
- TransformationToggleAccessChainInstruction& message)
- : message_(message) {}
+ protobufs::TransformationToggleAccessChainInstruction message)
+ : message_(std::move(message)) {}
TransformationToggleAccessChainInstruction::
TransformationToggleAccessChainInstruction(
diff --git a/source/fuzz/transformation_toggle_access_chain_instruction.h b/source/fuzz/transformation_toggle_access_chain_instruction.h
index 977b0d7a..be2718b0 100644
--- a/source/fuzz/transformation_toggle_access_chain_instruction.h
+++ b/source/fuzz/transformation_toggle_access_chain_instruction.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationToggleAccessChainInstruction : public Transformation {
public:
explicit TransformationToggleAccessChainInstruction(
- const protobufs::TransformationToggleAccessChainInstruction& message);
+ protobufs::TransformationToggleAccessChainInstruction message);
TransformationToggleAccessChainInstruction(
const protobufs::InstructionDescriptor& instruction_descriptor);
diff --git a/source/fuzz/transformation_vector_shuffle.cpp b/source/fuzz/transformation_vector_shuffle.cpp
index 05af18e6..ac0e3ccb 100644
--- a/source/fuzz/transformation_vector_shuffle.cpp
+++ b/source/fuzz/transformation_vector_shuffle.cpp
@@ -21,8 +21,8 @@ namespace spvtools {
namespace fuzz {
TransformationVectorShuffle::TransformationVectorShuffle(
- const spvtools::fuzz::protobufs::TransformationVectorShuffle& message)
- : message_(message) {}
+ protobufs::TransformationVectorShuffle message)
+ : message_(std::move(message)) {}
TransformationVectorShuffle::TransformationVectorShuffle(
const protobufs::InstructionDescriptor& instruction_to_insert_before,
@@ -130,13 +130,18 @@ void TransformationVectorShuffle::Apply(
// Add a shuffle instruction right before the instruction identified by
// |message_.instruction_to_insert_before|.
- FindInstruction(message_.instruction_to_insert_before(), ir_context)
- ->InsertBefore(MakeUnique<opt::Instruction>(
+ auto insert_before =
+ FindInstruction(message_.instruction_to_insert_before(), ir_context);
+ opt::Instruction* new_instruction =
+ insert_before->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpVectorShuffle, result_type_id, message_.fresh_id(),
shuffle_operands));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
- ir_context->InvalidateAnalysesExceptFor(
- opt::IRContext::Analysis::kAnalysisNone);
+ // Inform the def-use manager about the new instruction and record its basic
+ // block.
+ ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction);
+ ir_context->set_instr_block(new_instruction,
+ ir_context->get_instr_block(insert_before));
AddDataSynonymFacts(ir_context, transformation_context);
}
diff --git a/source/fuzz/transformation_vector_shuffle.h b/source/fuzz/transformation_vector_shuffle.h
index cf08a62c..7360906f 100644
--- a/source/fuzz/transformation_vector_shuffle.h
+++ b/source/fuzz/transformation_vector_shuffle.h
@@ -27,7 +27,7 @@ namespace fuzz {
class TransformationVectorShuffle : public Transformation {
public:
explicit TransformationVectorShuffle(
- const protobufs::TransformationVectorShuffle& message);
+ protobufs::TransformationVectorShuffle message);
TransformationVectorShuffle(
const protobufs::InstructionDescriptor& instruction_to_insert_before,
diff --git a/source/fuzz/transformation_wrap_early_terminator_in_function.cpp b/source/fuzz/transformation_wrap_early_terminator_in_function.cpp
index 4c436f5e..468d809f 100644
--- a/source/fuzz/transformation_wrap_early_terminator_in_function.cpp
+++ b/source/fuzz/transformation_wrap_early_terminator_in_function.cpp
@@ -23,9 +23,8 @@ namespace fuzz {
TransformationWrapEarlyTerminatorInFunction::
TransformationWrapEarlyTerminatorInFunction(
- const spvtools::fuzz::protobufs::
- TransformationWrapEarlyTerminatorInFunction& message)
- : message_(message) {}
+ protobufs::TransformationWrapEarlyTerminatorInFunction message)
+ : message_(std::move(message)) {}
TransformationWrapEarlyTerminatorInFunction::
TransformationWrapEarlyTerminatorInFunction(
diff --git a/source/fuzz/transformation_wrap_early_terminator_in_function.h b/source/fuzz/transformation_wrap_early_terminator_in_function.h
index 00151d40..d6e55517 100644
--- a/source/fuzz/transformation_wrap_early_terminator_in_function.h
+++ b/source/fuzz/transformation_wrap_early_terminator_in_function.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationWrapEarlyTerminatorInFunction : public Transformation {
public:
explicit TransformationWrapEarlyTerminatorInFunction(
- const protobufs::TransformationWrapEarlyTerminatorInFunction& message);
+ protobufs::TransformationWrapEarlyTerminatorInFunction message);
TransformationWrapEarlyTerminatorInFunction(
uint32_t fresh_id,
diff --git a/source/fuzz/transformation_wrap_region_in_selection.cpp b/source/fuzz/transformation_wrap_region_in_selection.cpp
index 9924e368..01c98cca 100644
--- a/source/fuzz/transformation_wrap_region_in_selection.cpp
+++ b/source/fuzz/transformation_wrap_region_in_selection.cpp
@@ -20,8 +20,8 @@ namespace spvtools {
namespace fuzz {
TransformationWrapRegionInSelection::TransformationWrapRegionInSelection(
- const protobufs::TransformationWrapRegionInSelection& message)
- : message_(message) {}
+ protobufs::TransformationWrapRegionInSelection message)
+ : message_(std::move(message)) {}
TransformationWrapRegionInSelection::TransformationWrapRegionInSelection(
uint32_t region_entry_block_id, uint32_t region_exit_block_id,
diff --git a/source/fuzz/transformation_wrap_region_in_selection.h b/source/fuzz/transformation_wrap_region_in_selection.h
index 57f4f64f..66d16dad 100644
--- a/source/fuzz/transformation_wrap_region_in_selection.h
+++ b/source/fuzz/transformation_wrap_region_in_selection.h
@@ -26,7 +26,7 @@ namespace fuzz {
class TransformationWrapRegionInSelection : public Transformation {
public:
explicit TransformationWrapRegionInSelection(
- const protobufs::TransformationWrapRegionInSelection& message);
+ protobufs::TransformationWrapRegionInSelection message);
TransformationWrapRegionInSelection(uint32_t region_entry_block_id,
uint32_t region_exit_block_id,
diff --git a/source/opcode.cpp b/source/opcode.cpp
index d87e8287..c96cde8d 100644
--- a/source/opcode.cpp
+++ b/source/opcode.cpp
@@ -417,8 +417,10 @@ bool spvOpcodeIsAtomicWithLoad(const SpvOp opcode) {
case SpvOpAtomicISub:
case SpvOpAtomicSMin:
case SpvOpAtomicUMin:
+ case SpvOpAtomicFMinEXT:
case SpvOpAtomicSMax:
case SpvOpAtomicUMax:
+ case SpvOpAtomicFMaxEXT:
case SpvOpAtomicAnd:
case SpvOpAtomicOr:
case SpvOpAtomicXor:
diff --git a/source/opt/CMakeLists.txt b/source/opt/CMakeLists.txt
index 14a6bee7..88d56589 100644
--- a/source/opt/CMakeLists.txt
+++ b/source/opt/CMakeLists.txt
@@ -62,6 +62,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
instruction.h
instruction_list.h
instrument_pass.h
+ interp_fixup_pass.h
ir_builder.h
ir_context.h
ir_loader.h
@@ -165,6 +166,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
instruction.cpp
instruction_list.cpp
instrument_pass.cpp
+ interp_fixup_pass.cpp
ir_context.cpp
ir_loader.cpp
licm_pass.cpp
diff --git a/source/opt/code_sink.cpp b/source/opt/code_sink.cpp
index e49029fe..cd777974 100644
--- a/source/opt/code_sink.cpp
+++ b/source/opt/code_sink.cpp
@@ -218,8 +218,10 @@ bool CodeSinkingPass::HasUniformMemorySync() {
case SpvOpAtomicISub:
case SpvOpAtomicSMin:
case SpvOpAtomicUMin:
+ case SpvOpAtomicFMinEXT:
case SpvOpAtomicSMax:
case SpvOpAtomicUMax:
+ case SpvOpAtomicFMaxEXT:
case SpvOpAtomicAnd:
case SpvOpAtomicOr:
case SpvOpAtomicXor:
diff --git a/source/opt/constants.h b/source/opt/constants.h
index e17ae6b6..5bd0ae32 100644
--- a/source/opt/constants.h
+++ b/source/opt/constants.h
@@ -58,7 +58,7 @@ class ConstantManager;
class Constant {
public:
Constant() = delete;
- virtual ~Constant() {}
+ virtual ~Constant() = default;
// Make a deep copy of this constant.
virtual std::unique_ptr<Constant> Copy() const = 0;
diff --git a/source/opt/folding_rules.cpp b/source/opt/folding_rules.cpp
index 010eec9c..1e7c424b 100644
--- a/source/opt/folding_rules.cpp
+++ b/source/opt/folding_rules.cpp
@@ -470,7 +470,7 @@ uint32_t PerformFloatingPointOperation(analysis::ConstantManager* const_mgr,
float fval = val.getAsFloat(); \
if (!IsValidResult(fval)) return 0; \
words = val.GetWords(); \
- }
+ } static_assert(true, "require extra semicolon")
switch (opcode) {
case SpvOpFMul:
FOLD_OP(*);
@@ -522,7 +522,7 @@ uint32_t PerformIntegerOperation(analysis::ConstantManager* const_mgr,
uint32_t val = input1->GetU32() op input2->GetU32(); \
words.push_back(val); \
} \
- }
+ } static_assert(true, "require extra semicalon")
switch (opcode) {
case SpvOpIMul:
FOLD_OP(*);
diff --git a/source/opt/inline_pass.h b/source/opt/inline_pass.h
index abe773af..9a5429ba 100644
--- a/source/opt/inline_pass.h
+++ b/source/opt/inline_pass.h
@@ -37,7 +37,7 @@ class InlinePass : public Pass {
using cbb_ptr = const BasicBlock*;
public:
- virtual ~InlinePass() = default;
+ virtual ~InlinePass() override = default;
protected:
InlinePass();
diff --git a/source/opt/interp_fixup_pass.cpp b/source/opt/interp_fixup_pass.cpp
new file mode 100644
index 00000000..ad29e6a7
--- /dev/null
+++ b/source/opt/interp_fixup_pass.cpp
@@ -0,0 +1,131 @@
+// Copyright (c) 2021 The Khronos Group Inc.
+// Copyright (c) 2021 Valve Corporation
+// Copyright (c) 2021 LunarG Inc.
+//
+// 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/opt/interp_fixup_pass.h"
+
+#include <set>
+#include <string>
+
+#include "ir_builder.h"
+#include "source/opt/ir_context.h"
+#include "type_manager.h"
+
+namespace spvtools {
+namespace opt {
+
+namespace {
+
+// Input Operand Indices
+static const int kSpvVariableStorageClassInIdx = 0;
+
+// Avoid unused variable warning/error on Linux
+#ifndef NDEBUG
+#define USE_ASSERT(x) assert(x)
+#else
+#define USE_ASSERT(x) ((void)(x))
+#endif
+
+// Folding rule function which attempts to replace |op(OpLoad(a),...)|
+// by |op(a,...)|, where |op| is one of the GLSLstd450 InterpolateAt*
+// instructions. Returns true if replaced, false otherwise.
+bool ReplaceInternalInterpolate(IRContext* ctx, Instruction* inst,
+ const std::vector<const analysis::Constant*>&) {
+ uint32_t glsl450_ext_inst_id =
+ ctx->get_feature_mgr()->GetExtInstImportId_GLSLstd450();
+ assert(glsl450_ext_inst_id != 0);
+
+ uint32_t ext_opcode = inst->GetSingleWordInOperand(1);
+
+ uint32_t op1_id = inst->GetSingleWordInOperand(2);
+
+ Instruction* load_inst = ctx->get_def_use_mgr()->GetDef(op1_id);
+ if (load_inst->opcode() != SpvOpLoad) return false;
+
+ Instruction* base_inst = load_inst->GetBaseAddress();
+ USE_ASSERT(base_inst->opcode() == SpvOpVariable &&
+ base_inst->GetSingleWordInOperand(kSpvVariableStorageClassInIdx) ==
+ SpvStorageClassInput &&
+ "unexpected interpolant in InterpolateAt*");
+
+ uint32_t ptr_id = load_inst->GetSingleWordInOperand(0);
+ uint32_t op2_id = (ext_opcode != GLSLstd450InterpolateAtCentroid)
+ ? inst->GetSingleWordInOperand(3)
+ : 0;
+
+ Instruction::OperandList new_operands;
+ new_operands.push_back({SPV_OPERAND_TYPE_ID, {glsl450_ext_inst_id}});
+ new_operands.push_back(
+ {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, {ext_opcode}});
+ new_operands.push_back({SPV_OPERAND_TYPE_ID, {ptr_id}});
+ if (op2_id != 0) new_operands.push_back({SPV_OPERAND_TYPE_ID, {op2_id}});
+
+ inst->SetInOperands(std::move(new_operands));
+ ctx->UpdateDefUse(inst);
+ return true;
+}
+
+class InterpFoldingRules : public FoldingRules {
+ public:
+ explicit InterpFoldingRules(IRContext* ctx) : FoldingRules(ctx) {}
+
+ protected:
+ virtual void AddFoldingRules() override {
+ uint32_t extension_id =
+ context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450();
+
+ if (extension_id != 0) {
+ ext_rules_[{extension_id, GLSLstd450InterpolateAtCentroid}].push_back(
+ ReplaceInternalInterpolate);
+ ext_rules_[{extension_id, GLSLstd450InterpolateAtSample}].push_back(
+ ReplaceInternalInterpolate);
+ ext_rules_[{extension_id, GLSLstd450InterpolateAtOffset}].push_back(
+ ReplaceInternalInterpolate);
+ }
+ }
+};
+
+class InterpConstFoldingRules : public ConstantFoldingRules {
+ public:
+ InterpConstFoldingRules(IRContext* ctx) : ConstantFoldingRules(ctx) {}
+
+ protected:
+ virtual void AddFoldingRules() override {}
+};
+
+} // namespace
+
+Pass::Status InterpFixupPass::Process() {
+ bool changed = false;
+
+ // Traverse the body of the functions to replace instructions that require
+ // the extensions.
+ InstructionFolder folder(
+ context(),
+ std::unique_ptr<InterpFoldingRules>(new InterpFoldingRules(context())),
+ MakeUnique<InterpConstFoldingRules>(context()));
+ for (Function& func : *get_module()) {
+ func.ForEachInst([&changed, &folder](Instruction* inst) {
+ if (folder.FoldInstruction(inst)) {
+ changed = true;
+ }
+ });
+ }
+
+ return changed ? Status::SuccessWithChange : Status::SuccessWithoutChange;
+}
+
+} // namespace opt
+} // namespace spvtools
diff --git a/source/opt/interp_fixup_pass.h b/source/opt/interp_fixup_pass.h
new file mode 100644
index 00000000..e112b651
--- /dev/null
+++ b/source/opt/interp_fixup_pass.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2021 The Khronos Group Inc.
+// Copyright (c) 2021 Valve Corporation
+// Copyright (c) 2021 LunarG Inc.
+//
+// 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_OPT_INTERP_FIXUP_H
+#define SOURCE_OPT_INTERP_FIXUP_H
+
+#include "source/opt/ir_context.h"
+#include "source/opt/module.h"
+#include "source/opt/pass.h"
+
+namespace spvtools {
+namespace opt {
+
+// Replaces overloaded internal form for GLSLstd450Interpolate* instructions
+// with external form. Specifically, removes OpLoad from the first argument
+// and replaces it with the pointer for the OpLoad. glslang generates the
+// internal form. This pass is called as part of glslang HLSL legalization.
+class InterpFixupPass : public Pass {
+ public:
+ const char* name() const override { return "interp-fixup"; }
+ Status Process() override;
+
+ IRContext::Analysis GetPreservedAnalyses() override {
+ return IRContext::kAnalysisInstrToBlockMapping |
+ IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
+ IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis |
+ IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
+ IRContext::kAnalysisScalarEvolution |
+ IRContext::kAnalysisRegisterPressure |
+ IRContext::kAnalysisValueNumberTable |
+ IRContext::kAnalysisStructuredCFG |
+ IRContext::kAnalysisBuiltinVarId |
+ IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes |
+ IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants;
+ }
+};
+
+} // namespace opt
+} // namespace spvtools
+
+#endif // SOURCE_OPT_INTERP_FIXUP_H
diff --git a/source/opt/iterator.h b/source/opt/iterator.h
index 444d457c..2280582d 100644
--- a/source/opt/iterator.h
+++ b/source/opt/iterator.h
@@ -30,18 +30,14 @@ namespace opt {
// std::unique_ptr managed elements in the vector, behaving like we are using
// std::vector<|ValueType|>.
template <typename ValueType, bool IsConst = false>
-class UptrVectorIterator
- : public std::iterator<std::random_access_iterator_tag,
- typename std::conditional<IsConst, const ValueType,
- ValueType>::type> {
+class UptrVectorIterator {
public:
- using super = std::iterator<
- std::random_access_iterator_tag,
- typename std::conditional<IsConst, const ValueType, ValueType>::type>;
+ using iterator_category = std::random_access_iterator_tag;
+ using value_type = ValueType;
- using pointer = typename super::pointer;
- using reference = typename super::reference;
- using difference_type = typename super::difference_type;
+ using pointer = value_type*;
+ using reference = value_type&;
+ using difference_type = std::ptrdiff_t;
// Type aliases. We need to apply constness properly if |IsConst| is true.
using Uptr = std::unique_ptr<ValueType>;
@@ -174,11 +170,7 @@ inline IteratorRange<IteratorType> make_const_range(
//
// Currently this iterator is always an input iterator.
template <typename SubIterator, typename Predicate>
-class FilterIterator
- : public std::iterator<
- std::input_iterator_tag, typename SubIterator::value_type,
- typename SubIterator::difference_type, typename SubIterator::pointer,
- typename SubIterator::reference> {
+class FilterIterator {
public:
// Iterator interface.
using iterator_category = typename SubIterator::iterator_category;
diff --git a/source/opt/mem_pass.h b/source/opt/mem_pass.h
index dcc16b65..5a77670d 100644
--- a/source/opt/mem_pass.h
+++ b/source/opt/mem_pass.h
@@ -38,7 +38,7 @@ namespace opt {
// utility functions and supporting state.
class MemPass : public Pass {
public:
- virtual ~MemPass() = default;
+ virtual ~MemPass() override = default;
// Returns an undef value for the given |var_id|'s type.
uint32_t GetUndefVal(uint32_t var_id) {
diff --git a/source/opt/optimizer.cpp b/source/opt/optimizer.cpp
index 909442cc..a5d10c3d 100644
--- a/source/opt/optimizer.cpp
+++ b/source/opt/optimizer.cpp
@@ -155,7 +155,8 @@ Optimizer& Optimizer::RegisterLegalizationPasses() {
.RegisterPass(CreateVectorDCEPass())
.RegisterPass(CreateDeadInsertElimPass())
.RegisterPass(CreateReduceLoadSizePass())
- .RegisterPass(CreateAggressiveDCEPass());
+ .RegisterPass(CreateAggressiveDCEPass())
+ .RegisterPass(CreateInterpolateFixupPass());
}
Optimizer& Optimizer::RegisterPerformancePasses() {
@@ -494,6 +495,8 @@ bool Optimizer::RegisterPassFromFlag(const std::string& flag) {
RegisterPass(CreateWrapOpKillPass());
} else if (pass_name == "amd-ext-to-khr") {
RegisterPass(CreateAmdExtToKhrPass());
+ } else if (pass_name == "interpolate-fixup") {
+ RegisterPass(CreateInterpolateFixupPass());
} else {
Errorf(consumer(), nullptr, {},
"Unknown flag '--%s'. Use --help for a list of valid flags",
@@ -925,4 +928,9 @@ Optimizer::PassToken CreateAmdExtToKhrPass() {
MakeUnique<opt::AmdExtensionToKhrPass>());
}
+Optimizer::PassToken CreateInterpolateFixupPass() {
+ return MakeUnique<Optimizer::PassToken::Impl>(
+ MakeUnique<opt::InterpFixupPass>());
+}
+
} // namespace spvtools
diff --git a/source/opt/passes.h b/source/opt/passes.h
index 1bc94c7e..bfb34af7 100644
--- a/source/opt/passes.h
+++ b/source/opt/passes.h
@@ -46,6 +46,7 @@
#include "source/opt/inst_bindless_check_pass.h"
#include "source/opt/inst_buff_addr_check_pass.h"
#include "source/opt/inst_debug_printf_pass.h"
+#include "source/opt/interp_fixup_pass.h"
#include "source/opt/licm_pass.h"
#include "source/opt/local_access_chain_convert_pass.h"
#include "source/opt/local_redundancy_elimination.h"
diff --git a/source/opt/scalar_replacement_pass.cpp b/source/opt/scalar_replacement_pass.cpp
index ba2d0675..4d47bdd8 100644
--- a/source/opt/scalar_replacement_pass.cpp
+++ b/source/opt/scalar_replacement_pass.cpp
@@ -861,6 +861,9 @@ bool ScalarReplacementPass::CheckUsesRelaxed(const Instruction* inst) const {
case SpvOpStore:
if (!CheckStore(user, index)) ok = false;
break;
+ case SpvOpImageTexelPointer:
+ if (!CheckImageTexelPointer(index)) ok = false;
+ break;
default:
ok = false;
break;
@@ -870,6 +873,10 @@ bool ScalarReplacementPass::CheckUsesRelaxed(const Instruction* inst) const {
return ok;
}
+bool ScalarReplacementPass::CheckImageTexelPointer(uint32_t index) const {
+ return index == 2u;
+}
+
bool ScalarReplacementPass::CheckLoad(const Instruction* inst,
uint32_t index) const {
if (index != 2u) return false;
diff --git a/source/opt/scalar_replacement_pass.h b/source/opt/scalar_replacement_pass.h
index 1f6c9281..9e9f0739 100644
--- a/source/opt/scalar_replacement_pass.h
+++ b/source/opt/scalar_replacement_pass.h
@@ -142,6 +142,10 @@ class ScalarReplacementPass : public Pass {
// of |inst| and the store is not to volatile memory.
bool CheckStore(const Instruction* inst, uint32_t index) const;
+ // Returns true if |index| is the pointer operand of an OpImageTexelPointer
+ // instruction.
+ bool CheckImageTexelPointer(uint32_t index) const;
+
// Creates a variable of type |typeId| from the |index|'th element of
// |varInst|. The new variable is added to |replacements|. If the variable
// could not be created, then |nullptr| is appended to |replacements|.
diff --git a/source/opt/type_manager.cpp b/source/opt/type_manager.cpp
index ce9c2c14..7935ad33 100644
--- a/source/opt/type_manager.cpp
+++ b/source/opt/type_manager.cpp
@@ -223,7 +223,7 @@ uint32_t TypeManager::GetTypeInstruction(const Type* type) {
case Type::k##kind: \
typeInst = MakeUnique<Instruction>(context(), SpvOpType##kind, 0, id, \
std::initializer_list<Operand>{}); \
- break;
+ break
DefineParameterlessCase(Void);
DefineParameterlessCase(Bool);
DefineParameterlessCase(Sampler);
@@ -513,7 +513,7 @@ Type* TypeManager::RebuildType(const Type& type) {
#define DefineNoSubtypeCase(kind) \
case Type::k##kind: \
rebuilt_ty.reset(type.Clone().release()); \
- return type_pool_.insert(std::move(rebuilt_ty)).first->get();
+ return type_pool_.insert(std::move(rebuilt_ty)).first->get()
DefineNoSubtypeCase(Void);
DefineNoSubtypeCase(Bool);
diff --git a/source/opt/types.h b/source/opt/types.h
index d5be9be4..9ecd41a6 100644
--- a/source/opt/types.h
+++ b/source/opt/types.h
@@ -101,7 +101,7 @@ class Type {
Type(Kind k) : kind_(k) {}
- virtual ~Type() {}
+ virtual ~Type() = default;
// Attaches a decoration directly on this type.
void AddDecoration(std::vector<uint32_t>&& d) {
diff --git a/source/reduce/reducer.cpp b/source/reduce/reducer.cpp
index 18eeaeb6..16bb94fe 100644
--- a/source/reduce/reducer.cpp
+++ b/source/reduce/reducer.cpp
@@ -54,10 +54,10 @@ void Reducer::SetInterestingnessFunction(
}
Reducer::ReductionResultStatus Reducer::Run(
- std::vector<uint32_t>&& binary_in, std::vector<uint32_t>* binary_out,
+ const std::vector<uint32_t>& binary_in, std::vector<uint32_t>* binary_out,
spv_const_reducer_options options,
spv_validator_options validator_options) {
- std::vector<uint32_t> current_binary(std::move(binary_in));
+ std::vector<uint32_t> current_binary(binary_in);
spvtools::SpirvTools tools(target_env_);
assert(tools.IsValid() && "Failed to create SPIRV-Tools interface");
@@ -138,13 +138,13 @@ void Reducer::AddDefaultReductionPasses() {
}
void Reducer::AddReductionPass(
- std::unique_ptr<ReductionOpportunityFinder>&& finder) {
+ std::unique_ptr<ReductionOpportunityFinder> finder) {
passes_.push_back(
spvtools::MakeUnique<ReductionPass>(target_env_, std::move(finder)));
-}
+}
void Reducer::AddCleanupReductionPass(
- std::unique_ptr<ReductionOpportunityFinder>&& finder) {
+ std::unique_ptr<ReductionOpportunityFinder> finder) {
cleanup_passes_.push_back(
spvtools::MakeUnique<ReductionPass>(target_env_, std::move(finder)));
}
diff --git a/source/reduce/reducer.h b/source/reduce/reducer.h
index 864ce757..f3ba1806 100644
--- a/source/reduce/reducer.h
+++ b/source/reduce/reducer.h
@@ -84,17 +84,17 @@ class Reducer {
// Adds a reduction pass based on the given finder to the sequence of passes
// that will be iterated over.
- void AddReductionPass(std::unique_ptr<ReductionOpportunityFinder>&& finder);
+ void AddReductionPass(std::unique_ptr<ReductionOpportunityFinder> finder);
// Adds a cleanup reduction pass based on the given finder to the sequence of
// passes that will run after other passes.
void AddCleanupReductionPass(
- std::unique_ptr<ReductionOpportunityFinder>&& finder);
+ std::unique_ptr<ReductionOpportunityFinder> finder);
// Reduces the given SPIR-V module |binary_out|.
// The reduced binary ends up in |binary_out|.
// A status is returned.
- ReductionResultStatus Run(std::vector<uint32_t>&& binary_in,
+ ReductionResultStatus Run(const std::vector<uint32_t>& binary_in,
std::vector<uint32_t>* binary_out,
spv_const_reducer_options options,
spv_validator_options validator_options);
diff --git a/source/val/basic_block.h b/source/val/basic_block.h
index 5eea4f92..5af4b9e4 100644
--- a/source/val/basic_block.h
+++ b/source/val/basic_block.h
@@ -139,9 +139,14 @@ class BasicBlock {
/// @brief A BasicBlock dominator iterator class
///
/// This iterator will iterate over the (post)dominators of the block
- class DominatorIterator
- : public std::iterator<std::forward_iterator_tag, BasicBlock*> {
+ class DominatorIterator {
public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = BasicBlock*;
+ using pointer = value_type*;
+ using reference = value_type&;
+ using difference_type = std::ptrdiff_t;
+
/// @brief Constructs the end of dominator iterator
///
/// This will create an iterator which will represent the element
diff --git a/source/val/validate.cpp b/source/val/validate.cpp
index a2e116b1..45b6a463 100644
--- a/source/val/validate.cpp
+++ b/source/val/validate.cpp
@@ -143,6 +143,7 @@ spv_result_t ValidateEntryPoints(ValidationState_t& _) {
if (_.recursive_entry_points().find(entry_point) !=
_.recursive_entry_points().end()) {
return _.diag(SPV_ERROR_INVALID_BINARY, _.FindDef(entry_point))
+ << _.VkErrorID(4634)
<< "Entry points may not have a call graph with cycles.";
}
}
diff --git a/source/val/validate_atomics.cpp b/source/val/validate_atomics.cpp
index dd263a79..fa53ca1f 100644
--- a/source/val/validate_atomics.cpp
+++ b/source/val/validate_atomics.cpp
@@ -47,6 +47,72 @@ bool IsStorageClassAllowedByUniversalRules(uint32_t storage_class) {
}
}
+bool HasReturnType(uint32_t opcode) {
+ switch (opcode) {
+ case SpvOpAtomicStore:
+ case SpvOpAtomicFlagClear:
+ return false;
+ break;
+ default:
+ return true;
+ }
+}
+
+bool HasOnlyFloatReturnType(uint32_t opcode) {
+ switch (opcode) {
+ case SpvOpAtomicFAddEXT:
+ case SpvOpAtomicFMinEXT:
+ case SpvOpAtomicFMaxEXT:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+bool HasOnlyIntReturnType(uint32_t opcode) {
+ switch (opcode) {
+ 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:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+bool HasIntOrFloatReturnType(uint32_t opcode) {
+ switch (opcode) {
+ case SpvOpAtomicLoad:
+ case SpvOpAtomicExchange:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+bool HasOnlyBoolReturnType(uint32_t opcode) {
+ switch (opcode) {
+ case SpvOpAtomicFlagTestAndSet:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
} // namespace
namespace spvtools {
@@ -55,12 +121,6 @@ namespace val {
// Validates correctness of atomic instructions.
spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
const SpvOp opcode = inst->opcode();
- const uint32_t result_type = inst->type_id();
- bool is_atomic_float_opcode = false;
- if (opcode == SpvOpAtomicLoad || opcode == SpvOpAtomicStore ||
- opcode == SpvOpAtomicFAddEXT || opcode == SpvOpAtomicExchange) {
- is_atomic_float_opcode = true;
- }
switch (opcode) {
case SpvOpAtomicLoad:
case SpvOpAtomicStore:
@@ -74,128 +134,47 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
case SpvOpAtomicISub:
case SpvOpAtomicSMin:
case SpvOpAtomicUMin:
+ case SpvOpAtomicFMinEXT:
case SpvOpAtomicSMax:
case SpvOpAtomicUMax:
+ case SpvOpAtomicFMaxEXT:
case SpvOpAtomicAnd:
case SpvOpAtomicOr:
case SpvOpAtomicXor:
case SpvOpAtomicFlagTestAndSet:
case SpvOpAtomicFlagClear: {
- if (_.HasCapability(SpvCapabilityKernel) &&
- (opcode == SpvOpAtomicLoad || opcode == SpvOpAtomicExchange ||
- opcode == SpvOpAtomicCompareExchange)) {
- if (!_.IsFloatScalarType(result_type) &&
- !_.IsIntScalarType(result_type)) {
+ const uint32_t result_type = inst->type_id();
+
+ // All current atomics only are scalar result
+ // Validate return type first so can just check if pointer type is same
+ // (if applicable)
+ if (HasReturnType(opcode)) {
+ if (HasOnlyFloatReturnType(opcode) &&
+ !_.IsFloatScalarType(result_type)) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< spvOpcodeString(opcode)
- << ": expected Result Type to be int or float scalar type";
- }
- } else if (opcode == SpvOpAtomicFlagTestAndSet) {
- if (!_.IsBoolScalarType(result_type)) {
+ << ": expected Result Type to be float scalar type";
+ } else if (HasOnlyIntReturnType(opcode) &&
+ !_.IsIntScalarType(result_type)) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< spvOpcodeString(opcode)
- << ": expected Result Type to be bool scalar type";
- }
- } else if (opcode == SpvOpAtomicFlagClear || opcode == SpvOpAtomicStore) {
- assert(result_type == 0);
- } else {
- if (_.IsFloatScalarType(result_type)) {
- if (is_atomic_float_opcode) {
- if (opcode == SpvOpAtomicFAddEXT) {
- if ((_.GetBitWidth(result_type) == 32) &&
- (!_.HasCapability(SpvCapabilityAtomicFloat32AddEXT))) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << spvOpcodeString(opcode)
- << ": float add atomics require the AtomicFloat32AddEXT "
- "capability";
- }
- if ((_.GetBitWidth(result_type) == 64) &&
- (!_.HasCapability(SpvCapabilityAtomicFloat64AddEXT))) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << spvOpcodeString(opcode)
- << ": float add atomics require the AtomicFloat64AddEXT "
- "capability";
- }
- }
- } else {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << spvOpcodeString(opcode)
- << ": expected Result Type to be int scalar type";
- }
- } else if (_.IsIntScalarType(result_type) &&
- opcode == SpvOpAtomicFAddEXT) {
+ << ": expected Result Type to be integer scalar type";
+ } else if (HasIntOrFloatReturnType(opcode) &&
+ !_.IsFloatScalarType(result_type) &&
+ !_.IsIntScalarType(result_type)) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< spvOpcodeString(opcode)
- << ": expected Result Type to be float scalar type";
- } else if (!_.IsFloatScalarType(result_type) &&
- !_.IsIntScalarType(result_type)) {
- switch (opcode) {
- case SpvOpAtomicFAddEXT:
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << spvOpcodeString(opcode)
- << ": expected Result Type to be float scalar type";
- case SpvOpAtomicIIncrement:
- case SpvOpAtomicIDecrement:
- case SpvOpAtomicIAdd:
- case SpvOpAtomicISub:
- case SpvOpAtomicSMin:
- case SpvOpAtomicSMax:
- case SpvOpAtomicUMin:
- case SpvOpAtomicUMax:
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << spvOpcodeString(opcode)
- << ": expected Result Type to be integer scalar type";
- default:
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << spvOpcodeString(opcode)
- << ": expected Result Type to be int or float scalar type";
- }
- }
-
- if (spvIsVulkanEnv(_.context()->target_env) &&
- (_.GetBitWidth(result_type) != 32 &&
- (_.GetBitWidth(result_type) != 64 ||
- !_.HasCapability(SpvCapabilityInt64ImageEXT)))) {
- switch (opcode) {
- case SpvOpAtomicSMin:
- case SpvOpAtomicUMin:
- case SpvOpAtomicSMax:
- case SpvOpAtomicUMax:
- case SpvOpAtomicAnd:
- case SpvOpAtomicOr:
- case SpvOpAtomicXor:
- case SpvOpAtomicIAdd:
- case SpvOpAtomicISub:
- case SpvOpAtomicFAddEXT:
- case SpvOpAtomicLoad:
- case SpvOpAtomicStore:
- case SpvOpAtomicExchange:
- case SpvOpAtomicIIncrement:
- case SpvOpAtomicIDecrement:
- case SpvOpAtomicCompareExchangeWeak:
- case SpvOpAtomicCompareExchange: {
- if (_.GetBitWidth(result_type) == 64 &&
- _.IsIntScalarType(result_type) &&
- !_.HasCapability(SpvCapabilityInt64Atomics))
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << spvOpcodeString(opcode)
- << ": 64-bit atomics require the Int64Atomics "
- "capability";
- } break;
- default:
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << spvOpcodeString(opcode)
- << ": according to the Vulkan spec atomic Result Type "
- "needs "
- "to be a 32-bit int scalar type";
- }
+ << ": expected Result Type to be integer or float scalar type";
+ } else if (HasOnlyBoolReturnType(opcode) &&
+ !_.IsBoolScalarType(result_type)) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << spvOpcodeString(opcode)
+ << ": expected Result Type to be bool scalar type";
}
}
- uint32_t operand_index =
- opcode == SpvOpAtomicFlagClear || opcode == SpvOpAtomicStore ? 0 : 2;
+ uint32_t operand_index = HasReturnType(opcode) ? 2 : 0;
const uint32_t pointer_type = _.GetOperandTypeId(inst, operand_index++);
-
uint32_t data_type = 0;
uint32_t storage_class = 0;
if (!_.GetPointerTypeInfo(pointer_type, &data_type, &storage_class)) {
@@ -204,6 +183,14 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
<< ": expected Pointer to be of type OpTypePointer";
}
+ // Can't use result_type because OpAtomicStore doesn't have a result
+ if (_.GetBitWidth(data_type) == 64 && _.IsIntScalarType(data_type) &&
+ !_.HasCapability(SpvCapabilityInt64Atomics)) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << spvOpcodeString(opcode)
+ << ": 64-bit atomics require the Int64Atomics capability";
+ }
+
// Validate storage class against universal rules
if (!IsStorageClassAllowedByUniversalRules(storage_class)) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -213,6 +200,7 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
// Then Shader rules
if (_.HasCapability(SpvCapabilityShader)) {
+ // Vulkan environment rule
if (spvIsVulkanEnv(_.context()->target_env)) {
if ((storage_class != SpvStorageClassUniform) &&
(storage_class != SpvStorageClassStorageBuffer) &&
@@ -231,6 +219,47 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
<< ": Function storage class forbidden when the Shader "
"capability is declared.";
}
+
+ if (opcode == SpvOpAtomicFAddEXT) {
+ // result type being float checked already
+ if ((_.GetBitWidth(result_type) == 32) &&
+ (!_.HasCapability(SpvCapabilityAtomicFloat32AddEXT))) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << spvOpcodeString(opcode)
+ << ": float add atomics require the AtomicFloat32AddEXT "
+ "capability";
+ }
+ if ((_.GetBitWidth(result_type) == 64) &&
+ (!_.HasCapability(SpvCapabilityAtomicFloat64AddEXT))) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << spvOpcodeString(opcode)
+ << ": float add atomics require the AtomicFloat64AddEXT "
+ "capability";
+ }
+ } else if (opcode == SpvOpAtomicFMinEXT ||
+ opcode == SpvOpAtomicFMaxEXT) {
+ if ((_.GetBitWidth(result_type) == 16) &&
+ (!_.HasCapability(SpvCapabilityAtomicFloat16MinMaxEXT))) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << spvOpcodeString(opcode)
+ << ": float min/max atomics require the "
+ "AtomicFloat16MinMaxEXT capability";
+ }
+ if ((_.GetBitWidth(result_type) == 32) &&
+ (!_.HasCapability(SpvCapabilityAtomicFloat32MinMaxEXT))) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << spvOpcodeString(opcode)
+ << ": float min/max atomics require the "
+ "AtomicFloat32MinMaxEXT capability";
+ }
+ if ((_.GetBitWidth(result_type) == 64) &&
+ (!_.HasCapability(SpvCapabilityAtomicFloat64MinMaxEXT))) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << spvOpcodeString(opcode)
+ << ": float min/max atomics require the "
+ "AtomicFloat64MinMaxEXT capability";
+ }
+ }
}
// And finally OpenCL environment rules
@@ -254,27 +283,27 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
}
}
+ // If result and pointer type are different, need to do special check here
if (opcode == SpvOpAtomicFlagTestAndSet ||
opcode == SpvOpAtomicFlagClear) {
if (!_.IsIntScalarType(data_type) || _.GetBitWidth(data_type) != 32) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< spvOpcodeString(opcode)
- << ": expected Pointer to point to a value of 32-bit int type";
+ << ": expected Pointer to point to a value of 32-bit integer "
+ "type";
}
} else if (opcode == SpvOpAtomicStore) {
if (!_.IsFloatScalarType(data_type) && !_.IsIntScalarType(data_type)) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< spvOpcodeString(opcode)
- << ": expected Pointer to be a pointer to int or float "
+ << ": expected Pointer to be a pointer to integer or float "
<< "scalar type";
}
- } else {
- if (data_type != result_type) {
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << spvOpcodeString(opcode)
- << ": expected Pointer to point to a value of type Result "
- "Type";
- }
+ } else if (data_type != result_type) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << spvOpcodeString(opcode)
+ << ": expected Pointer to point to a value of type Result "
+ "Type";
}
auto memory_scope = inst->GetOperandAs<const uint32_t>(operand_index++);
@@ -283,14 +312,15 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
}
const auto equal_semantics_index = operand_index++;
- if (auto error = ValidateMemorySemantics(_, inst, equal_semantics_index))
+ if (auto error = ValidateMemorySemantics(_, inst, equal_semantics_index,
+ memory_scope))
return error;
if (opcode == SpvOpAtomicCompareExchange ||
opcode == SpvOpAtomicCompareExchangeWeak) {
const auto unequal_semantics_index = operand_index++;
- if (auto error =
- ValidateMemorySemantics(_, inst, unequal_semantics_index))
+ if (auto error = ValidateMemorySemantics(
+ _, inst, unequal_semantics_index, memory_scope))
return error;
// Volatile bits must match for equal and unequal semantics. Previous
diff --git a/source/val/validate_barriers.cpp b/source/val/validate_barriers.cpp
index b499c8c0..3a9e3e7c 100644
--- a/source/val/validate_barriers.cpp
+++ b/source/val/validate_barriers.cpp
@@ -69,7 +69,7 @@ spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst) {
return error;
}
- if (auto error = ValidateMemorySemantics(_, inst, 2)) {
+ if (auto error = ValidateMemorySemantics(_, inst, 2, memory_scope)) {
return error;
}
break;
@@ -82,7 +82,7 @@ spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst) {
return error;
}
- if (auto error = ValidateMemorySemantics(_, inst, 1)) {
+ if (auto error = ValidateMemorySemantics(_, inst, 1, memory_scope)) {
return error;
}
break;
@@ -119,7 +119,7 @@ spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst) {
return error;
}
- if (auto error = ValidateMemorySemantics(_, inst, 2)) {
+ if (auto error = ValidateMemorySemantics(_, inst, 2, memory_scope)) {
return error;
}
break;
diff --git a/source/val/validate_cfg.cpp b/source/val/validate_cfg.cpp
index a5f6e6a1..36f632a8 100644
--- a/source/val/validate_cfg.cpp
+++ b/source/val/validate_cfg.cpp
@@ -654,18 +654,15 @@ spv_result_t ValidateStructuredSelections(
<< "Selection must be structured";
}
} else if (terminator->opcode() == SpvOpSwitch) {
- uint32_t count = 0;
- // Mark the targets as seen now, but only error out if this block was
- // missing a merge instruction and there were multiple unseen labels.
+ if (!merge) {
+ return _.diag(SPV_ERROR_INVALID_CFG, terminator)
+ << "OpSwitch must be preceeded by an OpSelectionMerge "
+ "instruction";
+ }
+ // Mark the targets as seen.
for (uint32_t i = 1; i < terminator->operands().size(); i += 2) {
const auto target = terminator->GetOperandAs<uint32_t>(i);
- if (seen.insert(target).second) {
- count++;
- }
- }
- if (!merge && count > 1) {
- return _.diag(SPV_ERROR_INVALID_CFG, terminator)
- << "Selection must be structured";
+ seen.insert(target);
}
}
}
diff --git a/source/val/validate_decorations.cpp b/source/val/validate_decorations.cpp
index ed336b47..f076b04c 100644
--- a/source/val/validate_decorations.cpp
+++ b/source/val/validate_decorations.cpp
@@ -1619,7 +1619,7 @@ spv_result_t CheckLocationDecoration(ValidationState_t& vstate,
{ \
spv_result_t e##LINE = (X); \
if (e##LINE != SPV_SUCCESS) return e##LINE; \
- }
+ } static_assert(true, "require extra semicolon")
#define PASS_OR_BAIL(X) PASS_OR_BAIL_AT_LINE(X, __LINE__)
// Check rules for decorations where we start from the decoration rather
diff --git a/source/val/validate_extensions.cpp b/source/val/validate_extensions.cpp
index dc8c0243..a7167fc1 100644
--- a/source/val/validate_extensions.cpp
+++ b/source/val/validate_extensions.cpp
@@ -692,8 +692,8 @@ spv_result_t ValidateExtension(ValidationState_t& _, const Instruction* inst) {
if (extension ==
ExtensionToString(kSPV_KHR_workgroup_memory_explicit_layout)) {
return _.diag(SPV_ERROR_WRONG_VERSION, inst)
- << "SPV_KHR_workgroup_memory_explicit_layout extension "
- "requires SPIR-V version 1.4 or later.";
+ << "SPV_KHR_workgroup_memory_explicit_layout extension "
+ "requires SPIR-V version 1.4 or later.";
}
}
@@ -1372,7 +1372,16 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
<< "or vector type";
}
- const uint32_t interpolant_type = _.GetOperandTypeId(inst, 4);
+ // If HLSL legalization and first operand is an OpLoad, use load
+ // pointer as the interpolant lvalue. Else use interpolate first
+ // operand.
+ uint32_t interp_id = inst->GetOperandAs<uint32_t>(4);
+ auto* interp_inst = _.FindDef(interp_id);
+ uint32_t interpolant_type = (_.options()->before_hlsl_legalization &&
+ interp_inst->opcode() == SpvOpLoad)
+ ? _.GetOperandTypeId(interp_inst, 2)
+ : _.GetOperandTypeId(inst, 4);
+
uint32_t interpolant_storage_class = 0;
uint32_t interpolant_data_type = 0;
if (!_.GetPointerTypeInfo(interpolant_type, &interpolant_data_type,
diff --git a/source/val/validate_logicals.cpp b/source/val/validate_logicals.cpp
index 5886dbf5..bb35f558 100644
--- a/source/val/validate_logicals.cpp
+++ b/source/val/validate_logicals.cpp
@@ -188,7 +188,7 @@ spv_result_t LogicalsPass(ValidationState_t& _, const Instruction* inst) {
case SpvOpTypeStruct: {
if (!composites) return fail();
break;
- };
+ }
default:
return fail();
diff --git a/source/val/validate_memory.cpp b/source/val/validate_memory.cpp
index 4dd6d941..a4bc0fab 100644
--- a/source/val/validate_memory.cpp
+++ b/source/val/validate_memory.cpp
@@ -466,6 +466,7 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
if (!_.IsValidStorageClass(storage_class)) {
return _.diag(SPV_ERROR_INVALID_BINARY, inst)
+ << _.VkErrorID(4643)
<< "Invalid storage class for target environment";
}
diff --git a/source/val/validate_memory_semantics.cpp b/source/val/validate_memory_semantics.cpp
index 6c3e1d44..d9189313 100644
--- a/source/val/validate_memory_semantics.cpp
+++ b/source/val/validate_memory_semantics.cpp
@@ -25,7 +25,8 @@ namespace val {
spv_result_t ValidateMemorySemantics(ValidationState_t& _,
const Instruction* inst,
- uint32_t operand_index) {
+ uint32_t operand_index,
+ uint32_t memory_scope) {
const SpvOp opcode = inst->opcode();
const auto id = inst->GetOperandAs<const uint32_t>(operand_index);
bool is_int32 = false, is_const_int32 = false;
@@ -178,6 +179,18 @@ spv_result_t ValidateMemorySemantics(ValidationState_t& _,
"of the following bits set: Acquire, Release, "
"AcquireRelease "
"or SequentiallyConsistent";
+ } else if (opcode != SpvOpMemoryBarrier && num_memory_order_set_bits) {
+ // should leave only atomics and control barriers for Vulkan env
+ bool memory_is_int32 = false, memory_is_const_int32 = false;
+ uint32_t memory_value = 0;
+ std::tie(memory_is_int32, memory_is_const_int32, memory_value) =
+ _.EvalInt32IfConst(memory_scope);
+ if (memory_is_int32 && memory_value == SpvScopeInvocation) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << _.VkErrorID(4641) << spvOpcodeString(opcode)
+ << ": Vulkan specification requires Memory Semantics to be None "
+ "if used with Invocation Memory Scope";
+ }
}
if (opcode == SpvOpMemoryBarrier && !includes_storage_class) {
diff --git a/source/val/validate_memory_semantics.h b/source/val/validate_memory_semantics.h
index 72a3e100..9e6f93a3 100644
--- a/source/val/validate_memory_semantics.h
+++ b/source/val/validate_memory_semantics.h
@@ -22,7 +22,8 @@ namespace val {
spv_result_t ValidateMemorySemantics(ValidationState_t& _,
const Instruction* inst,
- uint32_t operand_index);
+ uint32_t operand_index,
+ uint32_t memory_scope);
} // namespace val
} // namespace spvtools
diff --git a/source/val/validate_misc.cpp b/source/val/validate_misc.cpp
index 0c30f3ca..3bc15ca0 100644
--- a/source/val/validate_misc.cpp
+++ b/source/val/validate_misc.cpp
@@ -72,6 +72,37 @@ spv_result_t ValidateShaderClock(ValidationState_t& _,
return SPV_SUCCESS;
}
+spv_result_t ValidateAssumeTrue(ValidationState_t& _, const Instruction* inst) {
+ const auto operand_type_id = _.GetOperandTypeId(inst, 0);
+ if (!operand_type_id || !_.IsBoolScalarType(operand_type_id)) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "Value operand of OpAssumeTrueKHR must be a boolean scalar";
+ }
+ return SPV_SUCCESS;
+}
+
+spv_result_t ValidateExpect(ValidationState_t& _, const Instruction* inst) {
+ const auto result_type = inst->type_id();
+ if (!_.IsBoolScalarOrVectorType(result_type) &&
+ !_.IsIntScalarOrVectorType(result_type)) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "Result of OpExpectKHR must be a scalar or vector of integer "
+ "type or boolean type";
+ }
+
+ if (_.GetOperandTypeId(inst, 2) != result_type) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "Type of Value operand of OpExpectKHR does not match the result "
+ "type ";
+ }
+ if (_.GetOperandTypeId(inst, 3) != result_type) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "Type of ExpectedValue operand of OpExpectKHR does not match the "
+ "result type ";
+ }
+ return SPV_SUCCESS;
+}
+
} // namespace
spv_result_t MiscPass(ValidationState_t& _, const Instruction* inst) {
@@ -152,6 +183,16 @@ spv_result_t MiscPass(ValidationState_t& _, const Instruction* inst) {
return error;
}
break;
+ case SpvOpAssumeTrueKHR:
+ if (auto error = ValidateAssumeTrue(_, inst)) {
+ return error;
+ }
+ break;
+ case SpvOpExpectKHR:
+ if (auto error = ValidateExpect(_, inst)) {
+ return error;
+ }
+ break;
default:
break;
}
diff --git a/source/val/validate_scopes.cpp b/source/val/validate_scopes.cpp
index a92f7fd3..29ba5831 100644
--- a/source/val/validate_scopes.cpp
+++ b/source/val/validate_scopes.cpp
@@ -105,21 +105,30 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _,
}
}
- // If OpControlBarrier is used in fragment, vertex, tessellation evaluation,
- // or geometry stages, the execution Scope must be Subgroup.
+ // OpControlBarrier must only use Subgroup execution scope for a subset of
+ // execution models.
if (opcode == SpvOpControlBarrier && value != SpvScopeSubgroup) {
+ std::string errorVUID = _.VkErrorID(4682);
_.function(inst->function()->id())
- ->RegisterExecutionModelLimitation([](SpvExecutionModel model,
- std::string* message) {
+ ->RegisterExecutionModelLimitation([errorVUID](
+ SpvExecutionModel model,
+ std::string* message) {
if (model == SpvExecutionModelFragment ||
model == SpvExecutionModelVertex ||
model == SpvExecutionModelGeometry ||
- model == SpvExecutionModelTessellationEvaluation) {
+ model == SpvExecutionModelTessellationEvaluation ||
+ model == SpvExecutionModelRayGenerationKHR ||
+ model == SpvExecutionModelIntersectionKHR ||
+ model == SpvExecutionModelAnyHitKHR ||
+ model == SpvExecutionModelClosestHitKHR ||
+ model == SpvExecutionModelMissKHR) {
if (message) {
*message =
- "in Vulkan evironment, OpControlBarrier execution scope "
- "must be Subgroup for Fragment, Vertex, Geometry and "
- "TessellationEvaluation execution models";
+ errorVUID +
+ "in Vulkan environment, OpControlBarrier execution scope "
+ "must be Subgroup for Fragment, Vertex, Geometry, "
+ "TessellationEvaluation, RayGeneration, Intersection, "
+ "AnyHit, ClosestHit, and Miss execution models";
}
return false;
}
@@ -127,11 +136,34 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _,
});
}
+ // Only subset of execution models support Workgroup.
+ if (value == SpvScopeWorkgroup) {
+ std::string errorVUID = _.VkErrorID(4637);
+ _.function(inst->function()->id())
+ ->RegisterExecutionModelLimitation(
+ [errorVUID](SpvExecutionModel model, std::string* message) {
+ if (model != SpvExecutionModelTaskNV &&
+ model != SpvExecutionModelMeshNV &&
+ model != SpvExecutionModelTessellationControl &&
+ model != SpvExecutionModelGLCompute) {
+ if (message) {
+ *message =
+ errorVUID +
+ "in Vulkan environment, Workgroup execution scope is "
+ "only for TaskNV, MeshNV, TessellationControl, and "
+ "GLCompute execution models";
+ }
+ return false;
+ }
+ return true;
+ });
+ }
+
// Vulkan generic rules
// Scope for execution must be limited to Workgroup or Subgroup
if (value != SpvScopeWorkgroup && value != SpvScopeSubgroup) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
- << spvOpcodeString(opcode)
+ << _.VkErrorID(4636) << spvOpcodeString(opcode)
<< ": in Vulkan environment Execution Scope is limited to "
<< "Workgroup and Subgroup";
}
diff --git a/source/val/validate_type.cpp b/source/val/validate_type.cpp
index 6a5ea3c1..612fc5c2 100644
--- a/source/val/validate_type.cpp
+++ b/source/val/validate_type.cpp
@@ -427,7 +427,8 @@ spv_result_t ValidateTypeStruct(ValidationState_t& _, const Instruction* inst) {
if (spvIsVulkanEnv(_.context()->target_env) &&
!_.options()->before_hlsl_legalization && ContainsOpaqueType(_, inst)) {
return _.diag(SPV_ERROR_INVALID_ID, inst)
- << "In " << spvLogStringForEnv(_.context()->target_env)
+ << _.VkErrorID(4667) << "In "
+ << spvLogStringForEnv(_.context()->target_env)
<< ", OpTypeStruct must not contain an opaque type.";
}
@@ -462,6 +463,7 @@ spv_result_t ValidateTypePointer(ValidationState_t& _,
if (!_.IsValidStorageClass(storage_class)) {
return _.diag(SPV_ERROR_INVALID_BINARY, inst)
+ << _.VkErrorID(4643)
<< "Invalid storage class for target environment";
}
diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp
index 6dfc7bf6..db86fd25 100644
--- a/source/val/validation_state.cpp
+++ b/source/val/validation_state.cpp
@@ -1255,12 +1255,12 @@ bool ValidationState_t::IsValidStorageClass(
case SpvStorageClassFunction:
case SpvStorageClassPushConstant:
case SpvStorageClassPhysicalStorageBuffer:
- case SpvStorageClassRayPayloadNV:
- case SpvStorageClassIncomingRayPayloadNV:
- case SpvStorageClassHitAttributeNV:
- case SpvStorageClassCallableDataNV:
- case SpvStorageClassIncomingCallableDataNV:
- case SpvStorageClassShaderRecordBufferNV:
+ case SpvStorageClassRayPayloadKHR:
+ case SpvStorageClassIncomingRayPayloadKHR:
+ case SpvStorageClassHitAttributeKHR:
+ case SpvStorageClassCallableDataKHR:
+ case SpvStorageClassIncomingCallableDataKHR:
+ case SpvStorageClassShaderRecordBufferKHR:
return true;
default:
return false;
@@ -1676,16 +1676,26 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04492);
case 4633:
return VUID_WRAP(VUID-StandaloneSpirv-None-04633);
+ case 4634:
+ return VUID_WRAP(VUID-StandaloneSpirv-None-04634);
case 4635:
return VUID_WRAP(VUID-StandaloneSpirv-None-04635);
+ case 4636:
+ return VUID_WRAP(VUID-StandaloneSpirv-None-04636);
+ case 4637:
+ return VUID_WRAP(VUID-StandaloneSpirv-None-04637);
case 4638:
return VUID_WRAP(VUID-StandaloneSpirv-None-04638);
case 4639:
return VUID_WRAP(VUID-StandaloneSpirv-None-04639);
case 4640:
return VUID_WRAP(VUID-StandaloneSpirv-None-04640);
+ case 4641:
+ return VUID_WRAP(VUID-StandaloneSpirv-None-04641);
case 4642:
return VUID_WRAP(VUID-StandaloneSpirv-None-04642);
+ case 4643:
+ return VUID_WRAP(VUID-StandaloneSpirv-None-04643);
case 4651:
return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-04651);
case 4652:
@@ -1710,12 +1720,16 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
return VUID_WRAP(VUID-StandaloneSpirv-Offset-04663);
case 4664:
return VUID_WRAP(VUID-StandaloneSpirv-OpImageGather-04664);
+ case 4667:
+ return VUID_WRAP(VUID-StandaloneSpirv-None-04667);
case 4669:
return VUID_WRAP(VUID-StandaloneSpirv-GLSLShared-04669);
case 4675:
return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
case 4677:
return VUID_WRAP(VUID-StandaloneSpirv-Invariant-04677);
+ case 4682:
+ return VUID_WRAP(VUID-StandaloneSpirv-OpControlBarrier-04682);
case 4683:
return VUID_WRAP(VUID-StandaloneSpirv-LocalSize-04683);
case 4685:
@@ -1736,7 +1750,7 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04733);
default:
return ""; // unknown id
- };
+ }
// clang-format on
}
diff --git a/test/binary_parse_test.cpp b/test/binary_parse_test.cpp
index 93e87bdd..9a13f22c 100644
--- a/test/binary_parse_test.cpp
+++ b/test/binary_parse_test.cpp
@@ -198,7 +198,7 @@ ParsedInstruction MakeParsedInt32TypeInstruction(uint32_t result_id) {
class BinaryParseTest : public spvtest::TextToBinaryTestBase<::testing::Test> {
protected:
- ~BinaryParseTest() { spvDiagnosticDestroy(diagnostic_); }
+ ~BinaryParseTest() override { spvDiagnosticDestroy(diagnostic_); }
void Parse(const SpirvVector& words, spv_result_t expected_result,
bool flip_words = false) {
diff --git a/test/binary_to_text_test.cpp b/test/binary_to_text_test.cpp
index e8a02fd5..9cad9661 100644
--- a/test/binary_to_text_test.cpp
+++ b/test/binary_to_text_test.cpp
@@ -36,12 +36,12 @@ class BinaryToText : public ::testing::Test {
public:
BinaryToText()
: context(spvContextCreate(SPV_ENV_UNIVERSAL_1_0)), binary(nullptr) {}
- ~BinaryToText() {
+ ~BinaryToText() override {
spvBinaryDestroy(binary);
spvContextDestroy(context);
}
- virtual void SetUp() {
+ void SetUp() override {
const char* textStr = R"(
OpSource OpenCL_C 12
OpMemoryModel Physical64 OpenCL
@@ -72,7 +72,7 @@ class BinaryToText : public ::testing::Test {
ASSERT_EQ(SPV_SUCCESS, error);
}
- virtual void TearDown() {
+ void TearDown() override {
spvBinaryDestroy(binary);
binary = nullptr;
}
diff --git a/test/enum_string_mapping_test.cpp b/test/enum_string_mapping_test.cpp
index 9bbd8ca8..52aa653e 100644
--- a/test/enum_string_mapping_test.cpp
+++ b/test/enum_string_mapping_test.cpp
@@ -181,6 +181,8 @@ INSTANTIATE_TEST_SUITE_P(
{SpvCapabilityDeviceGroup, "DeviceGroup"},
{SpvCapabilityAtomicFloat32AddEXT, "AtomicFloat32AddEXT"},
{SpvCapabilityAtomicFloat64AddEXT, "AtomicFloat64AddEXT"},
+ {SpvCapabilityAtomicFloat32MinMaxEXT, "AtomicFloat32MinMaxEXT"},
+ {SpvCapabilityAtomicFloat64MinMaxEXT, "AtomicFloat64MinMaxEXT"},
{SpvCapabilityMultiView, "MultiView"},
{SpvCapabilityInt64ImageEXT, "Int64ImageEXT"},
{SpvCapabilitySampleMaskOverrideCoverageNV,
diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt
index 2e93293c..56fbed81 100644
--- a/test/fuzz/CMakeLists.txt
+++ b/test/fuzz/CMakeLists.txt
@@ -17,6 +17,7 @@ if (${SPIRV_BUILD_FUZZER})
set(SOURCES
fuzz_test_util.h
+ available_instructions_test.cpp
call_graph_test.cpp
comparator_deep_blocks_first_test.cpp
data_synonym_transformation_test.cpp
diff --git a/test/fuzz/available_instructions_test.cpp b/test/fuzz/available_instructions_test.cpp
new file mode 100644
index 00000000..dc8a3b5a
--- /dev/null
+++ b/test/fuzz/available_instructions_test.cpp
@@ -0,0 +1,328 @@
+// Copyright (c) 2021 Alastair F. Donaldson
+//
+// 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/available_instructions.h"
+
+#include "gtest/gtest.h"
+#include "source/fuzz/fuzzer_util.h"
+#include "test/fuzz/fuzz_test_util.h"
+
+namespace spvtools {
+namespace fuzz {
+namespace {
+
+TEST(AvailableInstructionsTest, BasicTest) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %7 = OpTypePointer Function %6
+ %8 = OpTypeFloat 32
+ %9 = OpTypePointer Function %8
+ %10 = OpTypeFunction %6 %7 %9
+ %15 = OpTypeVector %8 2
+ %16 = OpTypePointer Private %15
+ %17 = OpVariable %16 Private
+ %18 = OpConstant %8 1
+ %19 = OpConstant %8 2
+ %20 = OpConstantComposite %15 %18 %19
+ %21 = OpTypeVector %8 4
+ %22 = OpTypePointer Private %21
+ %23 = OpVariable %22 Private
+ %24 = OpConstant %8 10
+ %25 = OpConstant %8 20
+ %26 = OpConstant %8 30
+ %27 = OpConstant %8 40
+ %28 = OpConstantComposite %21 %24 %25 %26 %27
+ %31 = OpTypeInt 32 0
+ %32 = OpConstant %31 0
+ %33 = OpTypePointer Private %8
+ %41 = OpTypeBool
+ %46 = OpConstant %6 1
+ %54 = OpConstant %6 10
+ %57 = OpConstant %31 3
+ %61 = OpConstant %6 0
+ %66 = OpConstant %6 3
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %55 = OpVariable %7 Function
+ %56 = OpVariable %9 Function
+ %65 = OpVariable %7 Function
+ %68 = OpVariable %7 Function
+ OpStore %17 %20
+ OpStore %23 %28
+ OpStore %55 %54
+ %58 = OpAccessChain %33 %23 %57
+ %59 = OpLoad %8 %58
+ OpStore %56 %59
+ %60 = OpFunctionCall %6 %13 %55 %56
+ %100 = OpCopyObject %21 %28
+ %62 = OpSGreaterThan %41 %60 %61
+ OpSelectionMerge %64 None
+ OpBranchConditional %62 %63 %67
+ %63 = OpLabel
+ OpStore %65 %66
+ %101 = OpCopyObject %21 %28
+ OpBranch %64
+ %67 = OpLabel
+ OpStore %68 %61
+ OpBranch %69
+ %69 = OpLabel
+ OpLoopMerge %71 %72 None
+ OpBranch %73
+ %73 = OpLabel
+ %74 = OpLoad %6 %68
+ %75 = OpSLessThan %41 %74 %54
+ OpBranchConditional %75 %70 %71
+ %70 = OpLabel
+ %76 = OpLoad %6 %65
+ %77 = OpIAdd %6 %76 %46
+ OpStore %65 %77
+ OpBranch %72
+ %72 = OpLabel
+ %78 = OpLoad %6 %68
+ %79 = OpIAdd %6 %78 %46
+ OpStore %68 %79
+ OpBranch %69
+ %71 = OpLabel
+ %102 = OpCopyObject %21 %28
+ OpBranch %64
+ %64 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ %13 = OpFunction %6 None %10
+ %11 = OpFunctionParameter %7
+ %12 = OpFunctionParameter %9
+ %14 = OpLabel
+ %29 = OpVariable %7 Function
+ %30 = OpLoad %6 %11
+ %34 = OpAccessChain %33 %17 %32
+ %35 = OpLoad %8 %34
+ %36 = OpConvertFToS %6 %35
+ %37 = OpIAdd %6 %30 %36
+ OpStore %29 %37
+ %38 = OpLoad %6 %11
+ %39 = OpLoad %8 %12
+ %40 = OpConvertFToS %6 %39
+ %42 = OpSLessThan %41 %38 %40
+ %103 = OpCopyObject %21 %28
+ OpSelectionMerge %44 None
+ OpBranchConditional %42 %43 %48
+ %43 = OpLabel
+ %45 = OpLoad %6 %29
+ %47 = OpIAdd %6 %45 %46
+ OpStore %29 %47
+ OpBranch %44
+ %48 = OpLabel
+ %49 = OpLoad %6 %29
+ %50 = OpISub %6 %49 %46
+ OpStore %29 %50
+ OpBranch %44
+ %44 = OpLabel
+ %51 = OpLoad %6 %29
+ OpReturnValue %51
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+
+ opt::Instruction* i1 = context->get_def_use_mgr()->GetDef(55);
+ opt::Instruction* i2 = context->get_def_use_mgr()->GetDef(101);
+ opt::Instruction* i3 = &*context->cfg()->block(67)->begin();
+ opt::Instruction* i4 = context->get_def_use_mgr()->GetDef(74);
+ opt::Instruction* i5 = context->get_def_use_mgr()->GetDef(102);
+ opt::Instruction* i6 = context->get_def_use_mgr()->GetDef(30);
+ opt::Instruction* i7 = context->get_def_use_mgr()->GetDef(47);
+ opt::Instruction* i8 = context->get_def_use_mgr()->GetDef(50);
+ opt::Instruction* i9 = context->get_def_use_mgr()->GetDef(51);
+
+ {
+ AvailableInstructions no_instructions(
+ context.get(),
+ [](opt::IRContext*, opt::Instruction*) -> bool { return false; });
+ for (auto i : {i1, i2, i3, i4, i5, i6, i7, i8, i9}) {
+ auto available = no_instructions.GetAvailableBeforeInstruction(i);
+ ASSERT_EQ(0, available.size());
+ ASSERT_TRUE(available.empty());
+ }
+ }
+ {
+ AvailableInstructions all_instructions(
+ context.get(),
+ [](opt::IRContext*, opt::Instruction*) -> bool { return true; });
+ {
+ auto available = all_instructions.GetAvailableBeforeInstruction(i1);
+ ASSERT_FALSE(available.empty());
+ ASSERT_EQ(30, available.size());
+ ASSERT_EQ(SpvOpTypeVoid, available[0]->opcode());
+ ASSERT_EQ(SpvOpVariable, available[15]->opcode());
+ }
+ {
+ auto available = all_instructions.GetAvailableBeforeInstruction(i2);
+ ASSERT_FALSE(available.empty());
+ ASSERT_EQ(46, available.size());
+ ASSERT_EQ(SpvOpTypeVoid, available[0]->opcode());
+ ASSERT_EQ(SpvOpTypePointer, available[3]->opcode());
+ ASSERT_EQ(SpvOpVariable, available[15]->opcode());
+ ASSERT_EQ(SpvOpFunctionCall, available[40]->opcode());
+ ASSERT_EQ(SpvOpStore, available[45]->opcode());
+ }
+ {
+ auto available = all_instructions.GetAvailableBeforeInstruction(i3);
+ ASSERT_FALSE(available.empty());
+ ASSERT_EQ(45, available.size());
+ ASSERT_EQ(SpvOpTypeVoid, available[0]->opcode());
+ ASSERT_EQ(SpvOpTypePointer, available[3]->opcode());
+ ASSERT_EQ(SpvOpVariable, available[15]->opcode());
+ ASSERT_EQ(SpvOpFunctionCall, available[40]->opcode());
+ ASSERT_EQ(SpvOpBranchConditional, available[44]->opcode());
+ }
+ {
+ auto available = all_instructions.GetAvailableBeforeInstruction(i6);
+ ASSERT_FALSE(available.empty());
+ ASSERT_EQ(33, available.size());
+ ASSERT_EQ(SpvOpTypeVoid, available[0]->opcode());
+ ASSERT_EQ(SpvOpTypeFloat, available[4]->opcode());
+ ASSERT_EQ(SpvOpTypePointer, available[8]->opcode());
+ ASSERT_EQ(SpvOpConstantComposite, available[12]->opcode());
+ ASSERT_EQ(SpvOpConstant, available[16]->opcode());
+ ASSERT_EQ(SpvOpFunctionParameter, available[30]->opcode());
+ ASSERT_EQ(SpvOpFunctionParameter, available[31]->opcode());
+ ASSERT_EQ(SpvOpVariable, available[32]->opcode());
+ }
+ }
+ {
+ AvailableInstructions vector_instructions(
+ context.get(),
+ [](opt::IRContext* ir_context, opt::Instruction* inst) -> bool {
+ return inst->type_id() != 0 && ir_context->get_type_mgr()
+ ->GetType(inst->type_id())
+ ->AsVector() != nullptr;
+ });
+ {
+ auto available = vector_instructions.GetAvailableBeforeInstruction(i4);
+ ASSERT_FALSE(available.empty());
+ ASSERT_EQ(3, available.size());
+ ASSERT_EQ(SpvOpConstantComposite, available[0]->opcode());
+ ASSERT_EQ(SpvOpConstantComposite, available[1]->opcode());
+ ASSERT_EQ(SpvOpCopyObject, available[2]->opcode());
+ }
+ {
+ auto available = vector_instructions.GetAvailableBeforeInstruction(i5);
+ ASSERT_FALSE(available.empty());
+ ASSERT_EQ(3, available.size());
+ ASSERT_EQ(SpvOpConstantComposite, available[0]->opcode());
+ ASSERT_EQ(SpvOpConstantComposite, available[1]->opcode());
+ ASSERT_EQ(SpvOpCopyObject, available[2]->opcode());
+ }
+ {
+ auto available = vector_instructions.GetAvailableBeforeInstruction(i6);
+ ASSERT_FALSE(available.empty());
+ ASSERT_EQ(2, available.size());
+ ASSERT_EQ(SpvOpConstantComposite, available[0]->opcode());
+ ASSERT_EQ(SpvOpConstantComposite, available[1]->opcode());
+ }
+ }
+ {
+ AvailableInstructions integer_add_instructions(
+ context.get(), [](opt::IRContext*, opt::Instruction* inst) -> bool {
+ return inst->opcode() == SpvOpIAdd;
+ });
+ {
+ auto available =
+ integer_add_instructions.GetAvailableBeforeInstruction(i7);
+ ASSERT_FALSE(available.empty());
+ ASSERT_EQ(1, available.size());
+ ASSERT_EQ(SpvOpIAdd, available[0]->opcode());
+ }
+ {
+ auto available =
+ integer_add_instructions.GetAvailableBeforeInstruction(i8);
+ ASSERT_FALSE(available.empty());
+ ASSERT_EQ(1, available.size());
+ ASSERT_EQ(SpvOpIAdd, available[0]->opcode());
+ }
+ {
+ auto available =
+ integer_add_instructions.GetAvailableBeforeInstruction(i9);
+ ASSERT_FALSE(available.empty());
+ ASSERT_EQ(1, available.size());
+ ASSERT_EQ(SpvOpIAdd, available[0]->opcode());
+ }
+ }
+}
+
+TEST(AvailableInstructionsTest, UnreachableBlock) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ OpName %4 "main"
+ OpName %8 "x"
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %7 = OpTypePointer Function %6
+ %9 = OpConstant %6 2
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %8 = OpVariable %7 Function
+ OpStore %8 %9
+ %12 = OpLoad %6 %8
+ OpReturn
+ %10 = OpLabel
+ %11 = OpLoad %6 %8
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_3;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+
+ AvailableInstructions all_instructions(
+ context.get(),
+ [](opt::IRContext*, opt::Instruction*) -> bool { return true; });
+ ASSERT_EQ(7, all_instructions
+ .GetAvailableBeforeInstruction(
+ context->get_def_use_mgr()->GetDef(12))
+ .size());
+
+#ifndef NDEBUG
+ ASSERT_DEATH(all_instructions.GetAvailableBeforeInstruction(
+ context->get_def_use_mgr()->GetDef(11)),
+ "Availability can only be queried for reachable instructions.");
+#endif
+}
+
+} // namespace
+} // namespace fuzz
+} // namespace spvtools
diff --git a/test/fuzz/fuzzer_pass_add_opphi_synonyms_test.cpp b/test/fuzz/fuzzer_pass_add_opphi_synonyms_test.cpp
index f7a09964..734f47af 100644
--- a/test/fuzz/fuzzer_pass_add_opphi_synonyms_test.cpp
+++ b/test/fuzz/fuzzer_pass_add_opphi_synonyms_test.cpp
@@ -128,8 +128,8 @@ TEST(FuzzerPassAddOpPhiSynonymsTest, HelperFunctions) {
kConsoleMessageConsumer));
TransformationContext transformation_context(
MakeUnique<FactManager>(context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassAddOpPhiSynonyms fuzzer_pass(context.get(), &transformation_context,
diff --git a/test/fuzz/fuzzer_pass_construct_composites_test.cpp b/test/fuzz/fuzzer_pass_construct_composites_test.cpp
index d49d1d68..a02176b2 100644
--- a/test/fuzz/fuzzer_pass_construct_composites_test.cpp
+++ b/test/fuzz/fuzzer_pass_construct_composites_test.cpp
@@ -77,7 +77,8 @@ TEST(FuzzerPassConstructCompositesTest, IsomorphicStructs) {
const auto env = SPV_ENV_UNIVERSAL_1_3;
const auto consumer = nullptr;
- auto prng = MakeUnique<PseudoRandomGenerator>(0);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
for (uint32_t i = 0; i < 10; i++) {
const auto context =
@@ -87,7 +88,6 @@ TEST(FuzzerPassConstructCompositesTest, IsomorphicStructs) {
context.get(), validator_options, kConsoleMessageConsumer));
TransformationContext transformation_context(
MakeUnique<FactManager>(context.get()), validator_options);
- FuzzerContext fuzzer_context(prng.get(), 100);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassConstructComposites fuzzer_pass(
@@ -158,7 +158,8 @@ TEST(FuzzerPassConstructCompositesTest, IsomorphicArrays) {
const auto env = SPV_ENV_UNIVERSAL_1_3;
const auto consumer = nullptr;
- auto prng = MakeUnique<PseudoRandomGenerator>(0);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
for (uint32_t i = 0; i < 10; i++) {
const auto context =
@@ -168,7 +169,6 @@ TEST(FuzzerPassConstructCompositesTest, IsomorphicArrays) {
context.get(), validator_options, kConsoleMessageConsumer));
TransformationContext transformation_context(
MakeUnique<FactManager>(context.get()), validator_options);
- FuzzerContext fuzzer_context(prng.get(), 100);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassConstructComposites fuzzer_pass(
diff --git a/test/fuzz/fuzzer_pass_donate_modules_test.cpp b/test/fuzz/fuzzer_pass_donate_modules_test.cpp
index 1a7cd4ab..f11885d4 100644
--- a/test/fuzz/fuzzer_pass_donate_modules_test.cpp
+++ b/test/fuzz/fuzzer_pass_donate_modules_test.cpp
@@ -204,8 +204,8 @@ TEST(FuzzerPassDonateModulesTest, BasicDonation) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -285,8 +285,8 @@ TEST(FuzzerPassDonateModulesTest, DonationWithUniforms) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -416,8 +416,8 @@ TEST(FuzzerPassDonateModulesTest, DonationWithInputAndOutputVariables) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -511,8 +511,8 @@ TEST(FuzzerPassDonateModulesTest, DonateFunctionTypeWithDifferentPointers) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -581,8 +581,8 @@ TEST(FuzzerPassDonateModulesTest, DonateOpConstantNull) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -709,8 +709,8 @@ TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImages) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -805,8 +805,8 @@ TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesSampler) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -937,8 +937,8 @@ TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImageStructField) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -1073,8 +1073,8 @@ TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImageFunctionParameter) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -1155,8 +1155,8 @@ TEST(FuzzerPassDonateModulesTest, DonateShaderWithImageStorageClass) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -1242,8 +1242,8 @@ TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithRuntimeArray) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -1346,8 +1346,8 @@ TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithRuntimeArrayLivesafe) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -1418,8 +1418,8 @@ TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithWorkgroupVariables) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -1528,8 +1528,8 @@ TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithAtomics) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -1712,8 +1712,8 @@ TEST(FuzzerPassDonateModulesTest, Miscellaneous1) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator rng(0);
- FuzzerContext fuzzer_context(&rng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -1784,8 +1784,8 @@ TEST(FuzzerPassDonateModulesTest, OpSpecConstantInstructions) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -1941,8 +1941,8 @@ TEST(FuzzerPassDonateModulesTest, DonationSupportsOpTypeRuntimeArray) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator rng(0);
- FuzzerContext fuzzer_context(&rng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -2014,8 +2014,8 @@ TEST(FuzzerPassDonateModulesTest, HandlesCapabilities) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator rng(0);
- FuzzerContext fuzzer_context(&rng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
@@ -2247,8 +2247,8 @@ TEST(FuzzerPassDonateModulesTest, HandlesOpPhisInMergeBlock) {
TransformationContext transformation_context(
MakeUnique<FactManager>(recipient_context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
diff --git a/test/fuzz/fuzzer_pass_outline_functions_test.cpp b/test/fuzz/fuzzer_pass_outline_functions_test.cpp
index 576962c3..0d2c5bf7 100644
--- a/test/fuzz/fuzzer_pass_outline_functions_test.cpp
+++ b/test/fuzz/fuzzer_pass_outline_functions_test.cpp
@@ -124,8 +124,8 @@ TEST(FuzzerPassOutlineFunctionsTest, EntryIsAlreadySuitable) {
kConsoleMessageConsumer));
TransformationContext transformation_context(
MakeUnique<FactManager>(context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassOutlineFunctions fuzzer_pass(context.get(), &transformation_context,
@@ -167,8 +167,8 @@ TEST(FuzzerPassOutlineFunctionsTest, EntryHasOpVariable) {
kConsoleMessageConsumer));
TransformationContext transformation_context(
MakeUnique<FactManager>(context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassOutlineFunctions fuzzer_pass(context.get(), &transformation_context,
@@ -291,8 +291,8 @@ TEST(FuzzerPassOutlineFunctionsTest, EntryBlockIsHeader) {
kConsoleMessageConsumer));
TransformationContext transformation_context(
MakeUnique<FactManager>(context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassOutlineFunctions fuzzer_pass(context.get(), &transformation_context,
@@ -458,8 +458,8 @@ TEST(FuzzerPassOutlineFunctionsTest, ExitBlock) {
kConsoleMessageConsumer));
TransformationContext transformation_context(
MakeUnique<FactManager>(context.get()), validator_options);
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformation_sequence;
FuzzerPassOutlineFunctions fuzzer_pass(context.get(), &transformation_context,
diff --git a/test/fuzz/fuzzer_pass_test.cpp b/test/fuzz/fuzzer_pass_test.cpp
index 283aa114..b035de74 100644
--- a/test/fuzz/fuzzer_pass_test.cpp
+++ b/test/fuzz/fuzzer_pass_test.cpp
@@ -87,8 +87,8 @@ TEST(FuzzerPassTest, ForEachInstructionWithInstructionDescriptor) {
ASSERT_TRUE(dominator_analysis->IsReachable(5));
ASSERT_FALSE(dominator_analysis->IsReachable(8));
- PseudoRandomGenerator prng(0);
- FuzzerContext fuzzer_context(&prng, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
protobufs::TransformationSequence transformations;
FuzzerPassMock fuzzer_pass_mock(context.get(), &transformation_context,
&fuzzer_context, &transformations);
diff --git a/test/fuzz/fuzzer_replayer_test.cpp b/test/fuzz/fuzzer_replayer_test.cpp
index dc905741..6dc7ffb1 100644
--- a/test/fuzz/fuzzer_replayer_test.cpp
+++ b/test/fuzz/fuzzer_replayer_test.cpp
@@ -12,12 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "source/fuzz/fuzzer.h"
-#include "source/fuzz/replayer.h"
-
#include "gtest/gtest.h"
+#include "source/fuzz/fuzzer.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/pseudo_random_generator.h"
+#include "source/fuzz/replayer.h"
#include "source/fuzz/uniform_buffer_element_descriptor.h"
#include "test/fuzz/fuzz_test_util.h"
@@ -1642,37 +1641,53 @@ void RunFuzzerAndReplayer(const std::string& shader,
});
}
- std::vector<Fuzzer::RepeatedPassStrategy> strategies{
- Fuzzer::RepeatedPassStrategy::kSimple,
- Fuzzer::RepeatedPassStrategy::kLoopedWithRecommendations,
- Fuzzer::RepeatedPassStrategy::kRandomWithRecommendations};
+ std::vector<RepeatedPassStrategy> strategies{
+ RepeatedPassStrategy::kSimple,
+ RepeatedPassStrategy::kLoopedWithRecommendations,
+ RepeatedPassStrategy::kRandomWithRecommendations};
uint32_t strategy_index = 0;
for (uint32_t seed = initial_seed; seed < initial_seed + num_runs; seed++) {
spvtools::ValidatorOptions validator_options;
+
+ std::unique_ptr<opt::IRContext> ir_context;
+ ASSERT_TRUE(fuzzerutil::BuildIRContext(env, kConsoleMessageConsumer,
+ binary_in, validator_options,
+ &ir_context));
+
+ auto fuzzer_context = MakeUnique<FuzzerContext>(
+ MakeUnique<PseudoRandomGenerator>(seed),
+ FuzzerContext::GetMinFreshId(ir_context.get()), false);
+
+ auto transformation_context = MakeUnique<TransformationContext>(
+ MakeUnique<FactManager>(ir_context.get()), validator_options);
+ transformation_context->GetFactManager()->AddInitialFacts(
+ kConsoleMessageConsumer, initial_facts);
+
// Every 4th time we run the fuzzer, enable all fuzzer passes.
bool enable_all_passes = (seed % 4) == 0;
- auto fuzzer_result =
- Fuzzer(env, kConsoleMessageConsumer, binary_in, initial_facts,
- donor_suppliers, MakeUnique<PseudoRandomGenerator>(seed),
- enable_all_passes, strategies[strategy_index], true,
- validator_options)
- .Run();
+ Fuzzer fuzzer(std::move(ir_context), std::move(transformation_context),
+ std::move(fuzzer_context), kConsoleMessageConsumer,
+ donor_suppliers, enable_all_passes,
+ strategies[strategy_index], true, validator_options);
+ auto fuzzer_result = fuzzer.Run(0);
// Cycle the repeated pass strategy so that we try a different one next time
// we run the fuzzer.
strategy_index =
(strategy_index + 1) % static_cast<uint32_t>(strategies.size());
- ASSERT_EQ(Fuzzer::FuzzerResultStatus::kComplete, fuzzer_result.status);
- ASSERT_TRUE(t.Validate(fuzzer_result.transformed_binary));
+ ASSERT_NE(Fuzzer::Status::kFuzzerPassLedToInvalidModule,
+ fuzzer_result.status);
+ std::vector<uint32_t> transformed_binary;
+ fuzzer.GetIRContext()->module()->ToBinary(&transformed_binary, true);
+ ASSERT_TRUE(t.Validate(transformed_binary));
auto replayer_result =
- Replayer(
- env, kConsoleMessageConsumer, binary_in, initial_facts,
- fuzzer_result.applied_transformations,
- static_cast<uint32_t>(
- fuzzer_result.applied_transformations.transformation_size()),
- false, validator_options)
+ Replayer(env, kConsoleMessageConsumer, binary_in, initial_facts,
+ fuzzer.GetTransformationSequence(),
+ static_cast<uint32_t>(
+ fuzzer.GetTransformationSequence().transformation_size()),
+ false, validator_options)
.Run();
ASSERT_EQ(Replayer::ReplayerResultStatus::kComplete,
replayer_result.status);
@@ -1682,12 +1697,12 @@ void RunFuzzerAndReplayer(const std::string& shader,
// replay should be identical to that which resulted from fuzzing.
std::string fuzzer_transformations_string;
std::string replayer_transformations_string;
- fuzzer_result.applied_transformations.SerializeToString(
+ fuzzer.GetTransformationSequence().SerializeToString(
&fuzzer_transformations_string);
replayer_result.applied_transformations.SerializeToString(
&replayer_transformations_string);
ASSERT_EQ(fuzzer_transformations_string, replayer_transformations_string);
- ASSERT_TRUE(IsEqual(env, fuzzer_result.transformed_binary,
+ ASSERT_TRUE(IsEqual(env, transformed_binary,
replayer_result.transformed_module.get()));
}
}
diff --git a/test/fuzz/fuzzer_shrinker_test.cpp b/test/fuzz/fuzzer_shrinker_test.cpp
index 6d9dad35..e7921169 100644
--- a/test/fuzz/fuzzer_shrinker_test.cpp
+++ b/test/fuzz/fuzzer_shrinker_test.cpp
@@ -12,15 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "source/fuzz/fuzzer.h"
-#include "source/fuzz/shrinker.h"
-
#include <functional>
#include <vector>
#include "gtest/gtest.h"
+#include "source/fuzz/fuzzer.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/pseudo_random_generator.h"
+#include "source/fuzz/shrinker.h"
#include "source/fuzz/uniform_buffer_element_descriptor.h"
#include "test/fuzz/fuzz_test_util.h"
@@ -1044,24 +1043,38 @@ void RunFuzzerAndShrinker(const std::string& shader,
// Depending on the seed, decide whether to enable all passes and which
// repeated pass manager to use.
bool enable_all_passes = (seed % 4) == 0;
- Fuzzer::RepeatedPassStrategy repeated_pass_strategy;
+ RepeatedPassStrategy repeated_pass_strategy;
if ((seed % 3) == 0) {
- repeated_pass_strategy = Fuzzer::RepeatedPassStrategy::kSimple;
+ repeated_pass_strategy = RepeatedPassStrategy::kSimple;
} else if ((seed % 3) == 1) {
- repeated_pass_strategy =
- Fuzzer::RepeatedPassStrategy::kLoopedWithRecommendations;
+ repeated_pass_strategy = RepeatedPassStrategy::kLoopedWithRecommendations;
} else {
- repeated_pass_strategy =
- Fuzzer::RepeatedPassStrategy::kRandomWithRecommendations;
+ repeated_pass_strategy = RepeatedPassStrategy::kRandomWithRecommendations;
}
- auto fuzzer_result =
- Fuzzer(env, kConsoleMessageConsumer, binary_in, initial_facts,
- donor_suppliers, MakeUnique<PseudoRandomGenerator>(seed),
- enable_all_passes, repeated_pass_strategy, true, validator_options)
- .Run();
- ASSERT_EQ(Fuzzer::FuzzerResultStatus::kComplete, fuzzer_result.status);
- ASSERT_TRUE(t.Validate(fuzzer_result.transformed_binary));
+ std::unique_ptr<opt::IRContext> ir_context;
+ ASSERT_TRUE(fuzzerutil::BuildIRContext(
+ env, kConsoleMessageConsumer, binary_in, validator_options, &ir_context));
+
+ auto fuzzer_context = MakeUnique<FuzzerContext>(
+ MakeUnique<PseudoRandomGenerator>(seed),
+ FuzzerContext::GetMinFreshId(ir_context.get()), false);
+
+ auto transformation_context = MakeUnique<TransformationContext>(
+ MakeUnique<FactManager>(ir_context.get()), validator_options);
+ transformation_context->GetFactManager()->AddInitialFacts(
+ kConsoleMessageConsumer, initial_facts);
+
+ Fuzzer fuzzer(std::move(ir_context), std::move(transformation_context),
+ std::move(fuzzer_context), kConsoleMessageConsumer,
+ donor_suppliers, enable_all_passes, repeated_pass_strategy,
+ true, validator_options);
+ auto fuzzer_result = fuzzer.Run(0);
+ ASSERT_NE(Fuzzer::Status::kFuzzerPassLedToInvalidModule,
+ fuzzer_result.status);
+ std::vector<uint32_t> transformed_binary;
+ fuzzer.GetIRContext()->module()->ToBinary(&transformed_binary, true);
+ ASSERT_TRUE(t.Validate(transformed_binary));
const uint32_t kReasonableStepLimit = 50;
const uint32_t kSmallStepLimit = 20;
@@ -1069,30 +1082,30 @@ void RunFuzzerAndShrinker(const std::string& shader,
// With the AlwaysInteresting test, we should quickly shrink to the original
// binary with no transformations remaining.
RunAndCheckShrinker(env, binary_in, initial_facts,
- fuzzer_result.applied_transformations,
+ fuzzer.GetTransformationSequence(),
AlwaysInteresting().AsFunction(), binary_in, 0,
kReasonableStepLimit, validator_options);
// With the OnlyInterestingFirstTime test, no shrinking should be achieved.
RunAndCheckShrinker(
- env, binary_in, initial_facts, fuzzer_result.applied_transformations,
- OnlyInterestingFirstTime().AsFunction(), fuzzer_result.transformed_binary,
+ env, binary_in, initial_facts, fuzzer.GetTransformationSequence(),
+ OnlyInterestingFirstTime().AsFunction(), transformed_binary,
static_cast<uint32_t>(
- fuzzer_result.applied_transformations.transformation_size()),
+ fuzzer.GetTransformationSequence().transformation_size()),
kReasonableStepLimit, validator_options);
// The PingPong test is unpredictable; passing an empty expected binary
// means that we don't check anything beyond that shrinking completes
// successfully.
RunAndCheckShrinker(
- env, binary_in, initial_facts, fuzzer_result.applied_transformations,
+ env, binary_in, initial_facts, fuzzer.GetTransformationSequence(),
PingPong().AsFunction(), {}, 0, kSmallStepLimit, validator_options);
// The InterestingThenRandom test is unpredictable; passing an empty
// expected binary means that we do not check anything about shrinking
// results.
RunAndCheckShrinker(
- env, binary_in, initial_facts, fuzzer_result.applied_transformations,
+ env, binary_in, initial_facts, fuzzer.GetTransformationSequence(),
InterestingThenRandom(PseudoRandomGenerator(seed)).AsFunction(), {}, 0,
kSmallStepLimit, validator_options);
}
diff --git a/test/fuzz/shrinker_test.cpp b/test/fuzz/shrinker_test.cpp
index 42cd182c..447ebecd 100644
--- a/test/fuzz/shrinker_test.cpp
+++ b/test/fuzz/shrinker_test.cpp
@@ -163,8 +163,8 @@ TEST(ShrinkerTest, ReduceAddedFunctions) {
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
donor_ir_context.get(), validator_options, kConsoleMessageConsumer));
- PseudoRandomGenerator random_generator(0);
- FuzzerContext fuzzer_context(&random_generator, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
TransformationContext transformation_context(
MakeUnique<FactManager>(variant_ir_context.get()), validator_options);
@@ -341,8 +341,8 @@ TEST(ShrinkerTest, HitStepLimitWhenReducingAddedFunctions) {
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
donor_ir_context.get(), validator_options, kConsoleMessageConsumer));
- PseudoRandomGenerator random_generator(0);
- FuzzerContext fuzzer_context(&random_generator, 100);
+ FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
+ false);
TransformationContext transformation_context(
MakeUnique<FactManager>(variant_ir_context.get()), validator_options);
@@ -365,7 +365,6 @@ TEST(ShrinkerTest, HitStepLimitWhenReducingAddedFunctions) {
if (inst->opcode() == SpvOpCopyObject) {
copy_object_count++;
}
-
});
return copy_object_count >= 8;
};
diff --git a/test/fuzz/transformation_add_bit_instruction_synonym_test.cpp b/test/fuzz/transformation_add_bit_instruction_synonym_test.cpp
index fa8f7bf3..ccfbcf53 100644
--- a/test/fuzz/transformation_add_bit_instruction_synonym_test.cpp
+++ b/test/fuzz/transformation_add_bit_instruction_synonym_test.cpp
@@ -937,6 +937,88 @@ TEST(TransformationAddBitInstructionSynonymTest, NoSynonymWhenBlockIsDead) {
MakeDataDescriptor(166, {}), MakeDataDescriptor(39, {})));
}
+TEST(TransformationAddBitInstructionSynonymTest, DISABLED_DifferentSingedness) {
+ // This test will fail due to a bug in the transformation. The reason is that
+ // OpNot supports its operand and result type having different signedness.
+ // OpBitFieldUExtract and OpBitFieldInsert, however, don't support this
+ // (these instructions are added by the transformation).
+ std::string reference_shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %37 "main"
+
+; Types
+ %2 = OpTypeInt 32 0
+ %200 = OpTypeInt 32 1
+ %3 = OpTypeVoid
+ %4 = OpTypeFunction %3
+
+; Constants
+ %5 = OpConstant %2 0
+ %6 = OpConstant %2 1
+ %7 = OpConstant %2 2
+ %8 = OpConstant %2 3
+ %9 = OpConstant %2 4
+ %10 = OpConstant %2 5
+ %11 = OpConstant %2 6
+ %12 = OpConstant %2 7
+ %13 = OpConstant %2 8
+ %14 = OpConstant %2 9
+ %15 = OpConstant %2 10
+ %16 = OpConstant %2 11
+ %17 = OpConstant %2 12
+ %18 = OpConstant %2 13
+ %19 = OpConstant %2 14
+ %20 = OpConstant %2 15
+ %21 = OpConstant %2 16
+ %22 = OpConstant %2 17
+ %23 = OpConstant %2 18
+ %24 = OpConstant %2 19
+ %25 = OpConstant %2 20
+ %26 = OpConstant %2 21
+ %27 = OpConstant %2 22
+ %28 = OpConstant %2 23
+ %29 = OpConstant %2 24
+ %30 = OpConstant %2 25
+ %31 = OpConstant %2 26
+ %32 = OpConstant %2 27
+ %33 = OpConstant %2 28
+ %34 = OpConstant %2 29
+ %35 = OpConstant %2 30
+ %36 = OpConstant %2 31
+
+; main function
+ %37 = OpFunction %3 None %4
+ %38 = OpLabel
+ %39 = OpNot %200 %5 ; bit instruction
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_5;
+ const auto consumer = nullptr;
+ const auto context =
+ BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+
+ // Adds OpNot synonym.
+ auto transformation = TransformationAddBitInstructionSynonym(
+ 39, {40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134});
+ ASSERT_FALSE(
+ transformation.IsApplicable(context.get(), transformation_context));
+}
+
} // namespace
} // namespace fuzz
} // namespace spvtools
diff --git a/test/fuzz/transformation_add_constant_boolean_test.cpp b/test/fuzz/transformation_add_constant_boolean_test.cpp
index 3506db6b..bd8d91c9 100644
--- a/test/fuzz/transformation_add_constant_boolean_test.cpp
+++ b/test/fuzz/transformation_add_constant_boolean_test.cpp
@@ -46,6 +46,7 @@ TEST(TransformationAddConstantBooleanTest, NeitherPresentInitiallyAddBoth) {
spvtools::ValidatorOptions validator_options;
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));
+
TransformationContext transformation_context(
MakeUnique<FactManager>(context.get()), validator_options);
// True and false can both be added as neither is present.
@@ -68,7 +69,14 @@ TEST(TransformationAddConstantBooleanTest, NeitherPresentInitiallyAddBoth) {
auto add_false = TransformationAddConstantBoolean(8, false, false);
ASSERT_TRUE(add_true.IsApplicable(context.get(), transformation_context));
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(7));
+ ASSERT_EQ(nullptr, context->get_constant_mgr()->FindDeclaredConstant(7));
ApplyAndCheckFreshIds(add_true, context.get(), &transformation_context);
+ ASSERT_EQ(SpvOpConstantTrue, context->get_def_use_mgr()->GetDef(7)->opcode());
+ ASSERT_TRUE(context->get_constant_mgr()
+ ->FindDeclaredConstant(7)
+ ->AsBoolConstant()
+ ->value());
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));
diff --git a/test/fuzz/transformation_add_constant_composite_test.cpp b/test/fuzz/transformation_add_constant_composite_test.cpp
index 2c296fbc..e5cbeec2 100644
--- a/test/fuzz/transformation_add_constant_composite_test.cpp
+++ b/test/fuzz/transformation_add_constant_composite_test.cpp
@@ -82,10 +82,30 @@ TEST(TransformationAddConstantCompositeTest, BasicTest) {
ASSERT_FALSE(TransformationAddConstantComposite(100, 39, {11, 12}, false)
.IsApplicable(context.get(), transformation_context));
- TransformationAddConstantComposite transformations[] = {
- // %100 = OpConstantComposite %7 %11 %12
- TransformationAddConstantComposite(100, 7, {11, 12}, false),
+ {
+ // %100 = OpConstantComposite %7 %11 %12
+ TransformationAddConstantComposite transformation(100, 7, {11, 12}, false);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+ ASSERT_EQ(nullptr, context->get_constant_mgr()->FindDeclaredConstant(100));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ ASSERT_EQ(SpvOpConstantComposite,
+ context->get_def_use_mgr()->GetDef(100)->opcode());
+ ASSERT_EQ(0.0F, context->get_constant_mgr()
+ ->FindDeclaredConstant(100)
+ ->AsVectorConstant()
+ ->GetComponents()[0]
+ ->GetFloat());
+ ASSERT_EQ(1.0F, context->get_constant_mgr()
+ ->FindDeclaredConstant(100)
+ ->AsVectorConstant()
+ ->GetComponents()[1]
+ ->GetFloat());
+ }
+ TransformationAddConstantComposite transformations[] = {
// %101 = OpConstantComposite %7 %14 %15
TransformationAddConstantComposite(101, 7, {14, 15}, false),
diff --git a/test/fuzz/transformation_add_constant_null_test.cpp b/test/fuzz/transformation_add_constant_null_test.cpp
index ce20a677..1553e9f9 100644
--- a/test/fuzz/transformation_add_constant_null_test.cpp
+++ b/test/fuzz/transformation_add_constant_null_test.cpp
@@ -78,9 +78,23 @@ TEST(TransformationAddConstantNullTest, BasicTest) {
ASSERT_FALSE(TransformationAddConstantNull(100, 22).IsApplicable(
context.get(), transformation_context));
+ {
+ // %100 = OpConstantNull %6
+ TransformationAddConstantNull transformation(100, 6);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+ ASSERT_EQ(nullptr, context->get_constant_mgr()->FindDeclaredConstant(100));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ ASSERT_EQ(SpvOpConstantNull,
+ context->get_def_use_mgr()->GetDef(100)->opcode());
+ ASSERT_EQ(
+ 0.0F,
+ context->get_constant_mgr()->FindDeclaredConstant(100)->GetFloat());
+ }
+
TransformationAddConstantNull transformations[] = {
- // %100 = OpConstantNull %6
- TransformationAddConstantNull(100, 6),
// %101 = OpConstantNull %7
TransformationAddConstantNull(101, 7),
diff --git a/test/fuzz/transformation_add_constant_scalar_test.cpp b/test/fuzz/transformation_add_constant_scalar_test.cpp
index a153fb1c..91339dbb 100644
--- a/test/fuzz/transformation_add_constant_scalar_test.cpp
+++ b/test/fuzz/transformation_add_constant_scalar_test.cpp
@@ -171,7 +171,11 @@ TEST(TransformationAddConstantScalarTest, Apply) {
MakeUnique<FactManager>(context.get()), validator_options);
// Adds 32-bit unsigned integer (1 logical operand with 1 word).
auto transformation = TransformationAddConstantScalar(19, 2, {4}, false);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(19));
+ ASSERT_EQ(nullptr, context->get_constant_mgr()->FindDeclaredConstant(19));
ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+ ASSERT_EQ(SpvOpConstant, context->get_def_use_mgr()->GetDef(19)->opcode());
+ ASSERT_EQ(4, context->get_constant_mgr()->FindDeclaredConstant(19)->GetU32());
auto* constant_instruction = context->get_def_use_mgr()->GetDef(19);
EXPECT_EQ(constant_instruction->NumInOperands(), 1);
EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
diff --git a/test/fuzz/transformation_add_global_undef_test.cpp b/test/fuzz/transformation_add_global_undef_test.cpp
index c3a49e47..03b91570 100644
--- a/test/fuzz/transformation_add_global_undef_test.cpp
+++ b/test/fuzz/transformation_add_global_undef_test.cpp
@@ -63,9 +63,18 @@ TEST(TransformationAddGlobalUndefTest, BasicTest) {
ASSERT_FALSE(TransformationAddGlobalUndef(100, 3).IsApplicable(
context.get(), transformation_context));
+ {
+ // %100 = OpUndef %6
+ TransformationAddGlobalUndef transformation(100, 6);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ ASSERT_EQ(SpvOpUndef, context->get_def_use_mgr()->GetDef(100)->opcode());
+ }
+
TransformationAddGlobalUndef transformations[] = {
- // %100 = OpUndef %6
- TransformationAddGlobalUndef(100, 6),
// %101 = OpUndef %7
TransformationAddGlobalUndef(101, 7),
diff --git a/test/fuzz/transformation_add_global_variable_test.cpp b/test/fuzz/transformation_add_global_variable_test.cpp
index eb958a77..9531ade7 100644
--- a/test/fuzz/transformation_add_global_variable_test.cpp
+++ b/test/fuzz/transformation_add_global_variable_test.cpp
@@ -118,11 +118,24 @@ TEST(TransformationAddGlobalVariableTest, BasicTest) {
14, false)
.IsApplicable(context.get(), transformation_context));
- TransformationAddGlobalVariable transformations[] = {
- // %100 = OpVariable %12 Private
- TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
- true),
+ {
+ // %100 = OpVariable %12 Private
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+ TransformationAddGlobalVariable transformation(
+ 100, 12, SpvStorageClassPrivate, 16, true);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ ASSERT_EQ(SpvOpVariable, context->get_def_use_mgr()->GetDef(100)->opcode());
+ ASSERT_EQ(
+ SpvStorageClassPrivate,
+ static_cast<SpvStorageClass>(
+ context->get_def_use_mgr()->GetDef(100)->GetSingleWordInOperand(
+ 0)));
+ }
+ TransformationAddGlobalVariable transformations[] = {
// %101 = OpVariable %10 Private
TransformationAddGlobalVariable(101, 10, SpvStorageClassPrivate, 40,
false),
@@ -225,12 +238,10 @@ TEST(TransformationAddGlobalVariableTest, TestEntryPointInterfaceEnlargement) {
%8 = OpTypeVector %6 2
%9 = OpTypePointer Function %6
%10 = OpTypePointer Private %6
- %20 = OpTypePointer Uniform %6
%11 = OpTypePointer Function %7
%12 = OpTypePointer Private %7
%13 = OpTypePointer Private %8
%14 = OpVariable %10 Private
- %15 = OpVariable %20 Uniform
%16 = OpConstant %7 1
%17 = OpTypePointer Private %10
%18 = OpTypeBool
@@ -246,48 +257,96 @@ TEST(TransformationAddGlobalVariableTest, TestEntryPointInterfaceEnlargement) {
OpFunctionEnd
)";
- const auto env = SPV_ENV_UNIVERSAL_1_4;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- spvtools::ValidatorOptions validator_options;
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
- TransformationAddGlobalVariable transformations[] = {
- // %100 = OpVariable %12 Private
- TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
- true),
-
- // %101 = OpVariable %12 Private %16
- TransformationAddGlobalVariable(101, 12, SpvStorageClassPrivate, 16,
- false),
-
- // %102 = OpVariable %19 Private %21
- TransformationAddGlobalVariable(102, 19, SpvStorageClassPrivate, 21,
- true)};
+ for (auto env : {SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5,
+ SPV_ENV_VULKAN_1_1_SPIRV_1_4, SPV_ENV_VULKAN_1_2}) {
+ const auto consumer = nullptr;
+ const auto context =
+ BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+ TransformationAddGlobalVariable transformations[] = {
+ // %100 = OpVariable %12 Private
+ TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
+ true),
+
+ // %101 = OpVariable %12 Private %16
+ TransformationAddGlobalVariable(101, 12, SpvStorageClassPrivate, 16,
+ false),
+
+ // %102 = OpVariable %19 Private %21
+ TransformationAddGlobalVariable(102, 19, SpvStorageClassPrivate, 21,
+ true)};
+
+ for (auto& transformation : transformations) {
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
+ ASSERT_TRUE(
+ transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
+ ASSERT_TRUE(
+ transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
+ ASSERT_FALSE(
+ transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+
+ std::string after_transformation_enlarged_interface = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "m1" %100 %101 %102
+ OpEntryPoint Vertex %5 "m2" %100 %101 %102
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeInt 32 1
+ %8 = OpTypeVector %6 2
+ %9 = OpTypePointer Function %6
+ %10 = OpTypePointer Private %6
+ %11 = OpTypePointer Function %7
+ %12 = OpTypePointer Private %7
+ %13 = OpTypePointer Private %8
+ %14 = OpVariable %10 Private
+ %16 = OpConstant %7 1
+ %17 = OpTypePointer Private %10
+ %18 = OpTypeBool
+ %19 = OpTypePointer Private %18
+ %21 = OpConstantTrue %18
+ %100 = OpVariable %12 Private %16
+ %101 = OpVariable %12 Private %16
+ %102 = OpVariable %19 Private %21
+ %4 = OpFunction %2 None %3
+ %30 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ %5 = OpFunction %2 None %3
+ %31 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
- for (auto& transformation : transformations) {
ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
+ IsEqual(env, after_transformation_enlarged_interface, context.get()));
}
- ASSERT_TRUE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
- ASSERT_TRUE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
- ASSERT_FALSE(
- transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
+}
- std::string after_transformation = R"(
+TEST(TransformationAddGlobalVariableTest,
+ TestEntryPointInterfaceNoEnlargement) {
+ // This checks that when global variables are added to a SPIR-V 1.3- module,
+ // they are not added to entry points of that module.
+ std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "m1" %100 %101 %102
- OpEntryPoint Vertex %5 "m2" %100 %101 %102
+ OpEntryPoint Fragment %4 "m1"
+ OpEntryPoint Vertex %5 "m2"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
@@ -297,20 +356,15 @@ TEST(TransformationAddGlobalVariableTest, TestEntryPointInterfaceEnlargement) {
%8 = OpTypeVector %6 2
%9 = OpTypePointer Function %6
%10 = OpTypePointer Private %6
- %20 = OpTypePointer Uniform %6
%11 = OpTypePointer Function %7
%12 = OpTypePointer Private %7
%13 = OpTypePointer Private %8
%14 = OpVariable %10 Private
- %15 = OpVariable %20 Uniform
%16 = OpConstant %7 1
%17 = OpTypePointer Private %10
%18 = OpTypeBool
%19 = OpTypePointer Private %18
%21 = OpConstantTrue %18
- %100 = OpVariable %12 Private %16
- %101 = OpVariable %12 Private %16
- %102 = OpVariable %19 Private %21
%4 = OpFunction %2 None %3
%30 = OpLabel
OpReturn
@@ -320,7 +374,86 @@ TEST(TransformationAddGlobalVariableTest, TestEntryPointInterfaceEnlargement) {
OpReturn
OpFunctionEnd
)";
- ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+
+ for (auto env :
+ {SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2,
+ SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1}) {
+ const auto consumer = nullptr;
+ const auto context =
+ BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+ TransformationAddGlobalVariable transformations[] = {
+ // %100 = OpVariable %12 Private
+ TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
+ true),
+
+ // %101 = OpVariable %12 Private %16
+ TransformationAddGlobalVariable(101, 12, SpvStorageClassPrivate, 16,
+ false),
+
+ // %102 = OpVariable %19 Private %21
+ TransformationAddGlobalVariable(102, 19, SpvStorageClassPrivate, 21,
+ true)};
+
+ for (auto& transformation : transformations) {
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
+ ASSERT_TRUE(
+ transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
+ ASSERT_TRUE(
+ transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
+ ASSERT_FALSE(
+ transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+
+ std::string after_transformation_fixed_interface = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "m1"
+ OpEntryPoint Vertex %5 "m2"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeInt 32 1
+ %8 = OpTypeVector %6 2
+ %9 = OpTypePointer Function %6
+ %10 = OpTypePointer Private %6
+ %11 = OpTypePointer Function %7
+ %12 = OpTypePointer Private %7
+ %13 = OpTypePointer Private %8
+ %14 = OpVariable %10 Private
+ %16 = OpConstant %7 1
+ %17 = OpTypePointer Private %10
+ %18 = OpTypeBool
+ %19 = OpTypePointer Private %18
+ %21 = OpConstantTrue %18
+ %100 = OpVariable %12 Private %16
+ %101 = OpVariable %12 Private %16
+ %102 = OpVariable %19 Private %21
+ %4 = OpFunction %2 None %3
+ %30 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ %5 = OpFunction %2 None %3
+ %31 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ ASSERT_TRUE(
+ IsEqual(env, after_transformation_fixed_interface, context.get()));
+ }
}
TEST(TransformationAddGlobalVariableTest, TestAddingWorkgroupGlobals) {
diff --git a/test/fuzz/transformation_add_local_variable_test.cpp b/test/fuzz/transformation_add_local_variable_test.cpp
index ed57a28b..de88573a 100644
--- a/test/fuzz/transformation_add_local_variable_test.cpp
+++ b/test/fuzz/transformation_add_local_variable_test.cpp
@@ -98,10 +98,14 @@ TEST(TransformationAddLocalVariableTest, BasicTest) {
// %105 = OpVariable %50 Function %51
{
TransformationAddLocalVariable transformation(105, 50, 4, 51, true);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(105));
+ ASSERT_EQ(nullptr, context->get_instr_block(105));
ASSERT_TRUE(
transformation.IsApplicable(context.get(), transformation_context));
ApplyAndCheckFreshIds(transformation, context.get(),
&transformation_context);
+ ASSERT_EQ(SpvOpVariable, context->get_def_use_mgr()->GetDef(105)->opcode());
+ ASSERT_EQ(5, context->get_instr_block(105)->id());
}
// %104 = OpVariable %41 Function %46
diff --git a/test/fuzz/transformation_add_type_array_test.cpp b/test/fuzz/transformation_add_type_array_test.cpp
index ab4ed9a1..2ef8200e 100644
--- a/test/fuzz/transformation_add_type_array_test.cpp
+++ b/test/fuzz/transformation_add_type_array_test.cpp
@@ -90,19 +90,34 @@ TEST(TransformationAddTypeArrayTest, BasicTest) {
ASSERT_FALSE(TransformationAddTypeArray(100, 11, 17)
.IsApplicable(context.get(), transformation_context));
- TransformationAddTypeArray transformations[] = {
- // %100 = OpTypeArray %10 %16
- TransformationAddTypeArray(100, 10, 16),
-
- // %101 = OpTypeArray %7 %12
- TransformationAddTypeArray(101, 7, 12)};
+ {
+ // %100 = OpTypeArray %10 %16
+ TransformationAddTypeArray transformation(100, 10, 16);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+ ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(100));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ ASSERT_EQ(SpvOpTypeArray,
+ context->get_def_use_mgr()->GetDef(100)->opcode());
+ ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsArray());
+ }
- for (auto& transformation : transformations) {
+ {
+ // %101 = OpTypeArray %7 %12
+ TransformationAddTypeArray transformation(101, 7, 12);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(101));
+ ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(101));
ASSERT_TRUE(
transformation.IsApplicable(context.get(), transformation_context));
ApplyAndCheckFreshIds(transformation, context.get(),
&transformation_context);
+ ASSERT_EQ(SpvOpTypeArray,
+ context->get_def_use_mgr()->GetDef(100)->opcode());
+ ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsArray());
}
+
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));
diff --git a/test/fuzz/transformation_add_type_boolean_test.cpp b/test/fuzz/transformation_add_type_boolean_test.cpp
index 88d9f5b9..a8e657ba 100644
--- a/test/fuzz/transformation_add_type_boolean_test.cpp
+++ b/test/fuzz/transformation_add_type_boolean_test.cpp
@@ -52,9 +52,13 @@ TEST(TransformationAddTypeBooleanTest, BasicTest) {
context.get(), transformation_context));
auto add_type_bool = TransformationAddTypeBoolean(100);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+ ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(100));
ASSERT_TRUE(
add_type_bool.IsApplicable(context.get(), transformation_context));
ApplyAndCheckFreshIds(add_type_bool, context.get(), &transformation_context);
+ ASSERT_EQ(SpvOpTypeBool, context->get_def_use_mgr()->GetDef(100)->opcode());
+ ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsBool());
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));
diff --git a/test/fuzz/transformation_add_type_float_test.cpp b/test/fuzz/transformation_add_type_float_test.cpp
index 235d61b6..dc57ccda 100644
--- a/test/fuzz/transformation_add_type_float_test.cpp
+++ b/test/fuzz/transformation_add_type_float_test.cpp
@@ -103,15 +103,27 @@ TEST(TransformationAddTypeFloatTest, Apply) {
MakeUnique<FactManager>(context.get()), validator_options);
// Adds 16-bit float type.
auto transformation = TransformationAddTypeFloat(6, 16);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(6));
+ ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(6));
ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+ ASSERT_EQ(SpvOpTypeFloat, context->get_def_use_mgr()->GetDef(6)->opcode());
+ ASSERT_NE(nullptr, context->get_type_mgr()->GetType(6)->AsFloat());
// Adds 32-bit float type.
transformation = TransformationAddTypeFloat(7, 32);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(7));
+ ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(7));
ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+ ASSERT_EQ(SpvOpTypeFloat, context->get_def_use_mgr()->GetDef(7)->opcode());
+ ASSERT_NE(nullptr, context->get_type_mgr()->GetType(7)->AsFloat());
// Adds 64-bit float type.
transformation = TransformationAddTypeFloat(8, 64);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(8));
+ ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(8));
ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+ ASSERT_EQ(SpvOpTypeFloat, context->get_def_use_mgr()->GetDef(8)->opcode());
+ ASSERT_NE(nullptr, context->get_type_mgr()->GetType(8)->AsFloat());
std::string variant_shader = R"(
OpCapability Shader
diff --git a/test/fuzz/transformation_add_type_int_test.cpp b/test/fuzz/transformation_add_type_int_test.cpp
index ee4e7996..273420c5 100644
--- a/test/fuzz/transformation_add_type_int_test.cpp
+++ b/test/fuzz/transformation_add_type_int_test.cpp
@@ -118,8 +118,14 @@ TEST(TransformationAddTypeIntTest, Apply) {
TransformationContext transformation_context(
MakeUnique<FactManager>(context.get()), validator_options);
// Adds signed 8-bit integer type.
+ // For this transformation we also check that the def-use manager and type
+ // manager are updated appropriately.
auto transformation = TransformationAddTypeInt(6, 8, true);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(6));
+ ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(6));
ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+ ASSERT_EQ(SpvOpTypeInt, context->get_def_use_mgr()->GetDef(6)->opcode());
+ ASSERT_NE(nullptr, context->get_type_mgr()->GetType(6)->AsInteger());
// Adds signed 16-bit integer type.
transformation = TransformationAddTypeInt(7, 16, true);
diff --git a/test/fuzz/transformation_add_type_matrix_test.cpp b/test/fuzz/transformation_add_type_matrix_test.cpp
index 926e983e..df0111e2 100644
--- a/test/fuzz/transformation_add_type_matrix_test.cpp
+++ b/test/fuzz/transformation_add_type_matrix_test.cpp
@@ -63,10 +63,21 @@ TEST(TransformationAddTypeMatrixTest, BasicTest) {
ASSERT_FALSE(TransformationAddTypeMatrix(100, 11, 2)
.IsApplicable(context.get(), transformation_context));
- TransformationAddTypeMatrix transformations[] = {
- // %100 = OpTypeMatrix %8 2
- TransformationAddTypeMatrix(100, 8, 2),
+ {
+ // %100 = OpTypeMatrix %8 2
+ TransformationAddTypeMatrix transformation(100, 8, 2);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+ ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(100));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ ASSERT_EQ(SpvOpTypeMatrix,
+ context->get_def_use_mgr()->GetDef(100)->opcode());
+ ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsMatrix());
+ }
+ TransformationAddTypeMatrix transformations[] = {
// %101 = OpTypeMatrix %8 3
TransformationAddTypeMatrix(101, 8, 3),
diff --git a/test/fuzz/transformation_add_type_pointer_test.cpp b/test/fuzz/transformation_add_type_pointer_test.cpp
index 985e9044..b9072e3c 100644
--- a/test/fuzz/transformation_add_type_pointer_test.cpp
+++ b/test/fuzz/transformation_add_type_pointer_test.cpp
@@ -133,10 +133,24 @@ TEST(TransformationAddTypePointerTest, BasicTest) {
ASSERT_FALSE(bad_result_id_is_not_fresh.IsApplicable(context.get(),
transformation_context));
+ {
+ auto& transformation = good_new_private_pointer_to_t;
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(101));
+ ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(101));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+ ASSERT_EQ(SpvOpTypePointer,
+ context->get_def_use_mgr()->GetDef(101)->opcode());
+ ASSERT_NE(nullptr, context->get_type_mgr()->GetType(101)->AsPointer());
+ }
+
for (auto& transformation :
- {good_new_private_pointer_to_t, good_new_uniform_pointer_to_t,
- good_another_function_pointer_to_s, good_new_uniform_pointer_to_s,
- good_another_private_pointer_to_float,
+ {good_new_uniform_pointer_to_t, good_another_function_pointer_to_s,
+ good_new_uniform_pointer_to_s, good_another_private_pointer_to_float,
good_new_private_pointer_to_private_pointer_to_float,
good_new_uniform_pointer_to_vec2,
good_new_private_pointer_to_uniform_pointer_to_vec2}) {
diff --git a/test/fuzz/transformation_add_type_struct_test.cpp b/test/fuzz/transformation_add_type_struct_test.cpp
index b57bab25..7fb91ab4 100644
--- a/test/fuzz/transformation_add_type_struct_test.cpp
+++ b/test/fuzz/transformation_add_type_struct_test.cpp
@@ -63,10 +63,21 @@ TEST(TransformationAddTypeStructTest, BasicTest) {
ASSERT_FALSE(TransformationAddTypeStruct(100, {3}).IsApplicable(
context.get(), transformation_context));
- TransformationAddTypeStruct transformations[] = {
- // %100 = OpTypeStruct %6 %7 %8 %9 %10 %11
- TransformationAddTypeStruct(100, {6, 7, 8, 9, 10, 11}),
+ {
+ // %100 = OpTypeStruct %6 %7 %8 %9 %10 %11
+ TransformationAddTypeStruct transformation(100, {6, 7, 8, 9, 10, 11});
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+ ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(100));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ ASSERT_EQ(SpvOpTypeStruct,
+ context->get_def_use_mgr()->GetDef(100)->opcode());
+ ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsStruct());
+ }
+ TransformationAddTypeStruct transformations[] = {
// %101 = OpTypeStruct
TransformationAddTypeStruct(101, {}),
diff --git a/test/fuzz/transformation_add_type_vector_test.cpp b/test/fuzz/transformation_add_type_vector_test.cpp
index a49ba6e6..755bc4a8 100644
--- a/test/fuzz/transformation_add_type_vector_test.cpp
+++ b/test/fuzz/transformation_add_type_vector_test.cpp
@@ -57,10 +57,21 @@ TEST(TransformationAddTypeVectorTest, BasicTest) {
ASSERT_FALSE(TransformationAddTypeVector(100, 1, 2).IsApplicable(
context.get(), transformation_context));
- TransformationAddTypeVector transformations[] = {
- // %100 = OpTypeVector %6 2
- TransformationAddTypeVector(100, 6, 2),
+ {
+ // %100 = OpTypeVector %6 2
+ TransformationAddTypeVector transformation(100, 6, 2);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+ ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(100));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ ASSERT_EQ(SpvOpTypeVector,
+ context->get_def_use_mgr()->GetDef(100)->opcode());
+ ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsVector());
+ }
+ TransformationAddTypeVector transformations[] = {
// %101 = OpTypeVector %7 3
TransformationAddTypeVector(101, 7, 3),
diff --git a/test/fuzz/transformation_composite_construct_test.cpp b/test/fuzz/transformation_composite_construct_test.cpp
index edbfe3b6..9b68721d 100644
--- a/test/fuzz/transformation_composite_construct_test.cpp
+++ b/test/fuzz/transformation_composite_construct_test.cpp
@@ -146,8 +146,19 @@ TEST(TransformationCompositeConstructTest, ConstructArrays) {
transformation_context));
ASSERT_FALSE(make_vec2_array_length_3_bad.IsApplicable(
context.get(), transformation_context));
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(200));
+ ASSERT_EQ(nullptr, context->get_instr_block(200));
+ uint32_t num_uses_of_41_before = context->get_def_use_mgr()->NumUses(41);
+ uint32_t num_uses_of_45_before = context->get_def_use_mgr()->NumUses(45);
+ uint32_t num_uses_of_27_before = context->get_def_use_mgr()->NumUses(27);
ApplyAndCheckFreshIds(make_vec2_array_length_3, context.get(),
&transformation_context);
+ ASSERT_EQ(SpvOpCompositeConstruct,
+ context->get_def_use_mgr()->GetDef(200)->opcode());
+ ASSERT_EQ(34, context->get_instr_block(200)->id());
+ ASSERT_EQ(num_uses_of_41_before + 1, context->get_def_use_mgr()->NumUses(41));
+ ASSERT_EQ(num_uses_of_45_before + 1, context->get_def_use_mgr()->NumUses(45));
+ ASSERT_EQ(num_uses_of_27_before + 1, context->get_def_use_mgr()->NumUses(27));
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
diff --git a/test/fuzz/transformation_composite_extract_test.cpp b/test/fuzz/transformation_composite_extract_test.cpp
index 383a4db1..1df55918 100644
--- a/test/fuzz/transformation_composite_extract_test.cpp
+++ b/test/fuzz/transformation_composite_extract_test.cpp
@@ -143,10 +143,18 @@ TEST(TransformationCompositeExtractTest, BasicTest) {
TransformationCompositeExtract transformation_1(
MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(201));
+ ASSERT_EQ(nullptr, context->get_instr_block(201));
+ uint32_t num_uses_of_100_before = context->get_def_use_mgr()->NumUses(100);
ASSERT_TRUE(
transformation_1.IsApplicable(context.get(), transformation_context));
ApplyAndCheckFreshIds(transformation_1, context.get(),
&transformation_context);
+ ASSERT_EQ(SpvOpCompositeExtract,
+ context->get_def_use_mgr()->GetDef(201)->opcode());
+ ASSERT_EQ(15, context->get_instr_block(201)->id());
+ ASSERT_EQ(num_uses_of_100_before + 1,
+ context->get_def_use_mgr()->NumUses(100));
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));
diff --git a/test/fuzz/transformation_equation_instruction_test.cpp b/test/fuzz/transformation_equation_instruction_test.cpp
index 654fffcb..5b5033d2 100644
--- a/test/fuzz/transformation_equation_instruction_test.cpp
+++ b/test/fuzz/transformation_equation_instruction_test.cpp
@@ -102,8 +102,12 @@ TEST(TransformationEquationInstructionTest, SignedNegate) {
14, SpvOpSNegate, {7}, return_instruction);
ASSERT_TRUE(
transformation1.IsApplicable(context.get(), transformation_context));
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(14));
+ ASSERT_EQ(nullptr, context->get_instr_block(14));
ApplyAndCheckFreshIds(transformation1, context.get(),
&transformation_context);
+ ASSERT_EQ(SpvOpSNegate, context->get_def_use_mgr()->GetDef(14)->opcode());
+ ASSERT_EQ(13, context->get_instr_block(14)->id());
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));
diff --git a/test/fuzz/transformation_flatten_conditional_branch_test.cpp b/test/fuzz/transformation_flatten_conditional_branch_test.cpp
index 1a0ff6aa..800af0ea 100644
--- a/test/fuzz/transformation_flatten_conditional_branch_test.cpp
+++ b/test/fuzz/transformation_flatten_conditional_branch_test.cpp
@@ -1334,20 +1334,24 @@ TEST(TransformationFlattenConditionalBranchTest,
OpFunctionEnd
)";
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- spvtools::ValidatorOptions validator_options;
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
-
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
-
- auto transformation =
- TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {});
- ASSERT_FALSE(
- transformation.IsApplicable(context.get(), transformation_context));
+ for (auto env :
+ {SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2,
+ SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1}) {
+ const auto consumer = nullptr;
+ const auto context =
+ BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+
+ auto transformation =
+ TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {});
+ ASSERT_FALSE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ }
}
TEST(TransformationFlattenConditionalBranchTest,
diff --git a/test/fuzz/transformation_permute_phi_operands_test.cpp b/test/fuzz/transformation_permute_phi_operands_test.cpp
index 2843cfc5..3df399a5 100644
--- a/test/fuzz/transformation_permute_phi_operands_test.cpp
+++ b/test/fuzz/transformation_permute_phi_operands_test.cpp
@@ -105,6 +105,23 @@ TEST(TransformationPermutePhiOperandsTest, BasicTest) {
transformation.IsApplicable(context.get(), transformation_context));
ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+ // Check that the def-use manager knows that the phi instruction's ids have
+ // been permuted.
+ std::vector<std::pair<uint32_t, uint32_t>> phi_operand_to_new_operand_index =
+ {{20, 4}, {16, 5}, {24, 2}, {21, 3}};
+ for (std::pair<uint32_t, uint32_t>& entry :
+ phi_operand_to_new_operand_index) {
+ context->get_def_use_mgr()->WhileEachUse(
+ entry.first,
+ [&entry](opt::Instruction* inst, uint32_t operand_index) -> bool {
+ if (inst->result_id() == 25) {
+ EXPECT_EQ(entry.second, operand_index);
+ return false;
+ }
+ return true;
+ });
+ }
+
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
diff --git a/test/fuzz/transformation_push_id_through_variable_test.cpp b/test/fuzz/transformation_push_id_through_variable_test.cpp
index cd45c4ce..7487cab9 100644
--- a/test/fuzz/transformation_push_id_through_variable_test.cpp
+++ b/test/fuzz/transformation_push_id_through_variable_test.cpp
@@ -341,7 +341,26 @@ TEST(TransformationPushIdThroughVariableTest, Apply) {
auto transformation = TransformationPushIdThroughVariable(
value_id, value_synonym_id, variable_id, variable_storage_class,
initializer_id, instruction_descriptor);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(value_synonym_id));
+ ASSERT_EQ(nullptr, context->get_instr_block(value_synonym_id));
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(variable_id));
+ ASSERT_EQ(nullptr, context->get_instr_block(variable_id));
ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+ ASSERT_EQ(SpvOpLoad,
+ context->get_def_use_mgr()->GetDef(value_synonym_id)->opcode());
+ ASSERT_EQ(36, context->get_instr_block(value_synonym_id)->id());
+ ASSERT_EQ(SpvOpVariable,
+ context->get_def_use_mgr()->GetDef(variable_id)->opcode());
+ ASSERT_EQ(5, context->get_instr_block(variable_id)->id());
+ uint32_t variable_use_count = 0;
+ context->get_def_use_mgr()->ForEachUse(
+ variable_id,
+ [&variable_use_count](opt::Instruction* inst, uint32_t /*unused*/) {
+ ASSERT_TRUE(inst->opcode() == SpvOpLoad ||
+ inst->opcode() == SpvOpStore);
+ variable_use_count++;
+ });
+ ASSERT_EQ(2, variable_use_count);
value_id = 21;
value_synonym_id = 102;
diff --git a/test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp b/test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp
index 45325038..6bba14f6 100644
--- a/test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp
+++ b/test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp
@@ -566,6 +566,302 @@ TEST(TransformationReplaceBranchFromDeadBlockWithExitTest, OpPhi) {
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
+TEST(TransformationReplaceBranchFromDeadBlockWithExitTest,
+ DominatorAfterDeadBlockSuccessor) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeBool
+ %7 = OpConstantFalse %6
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpSelectionMerge %8 None
+ OpBranchConditional %7 %9 %10
+ %9 = OpLabel
+ OpBranch %11
+ %11 = OpLabel
+ %12 = OpCopyObject %6 %7
+ OpBranch %8
+ %10 = OpLabel
+ OpBranch %13
+ %8 = OpLabel
+ OpReturn
+ %13 = OpLabel
+ OpBranch %8
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_4;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+
+ transformation_context.GetFactManager()->AddFactBlockIsDead(9);
+ transformation_context.GetFactManager()->AddFactBlockIsDead(11);
+
+ ASSERT_FALSE(
+ TransformationReplaceBranchFromDeadBlockWithExit(11, SpvOpUnreachable, 0)
+ .IsApplicable(context.get(), transformation_context));
+}
+
+TEST(TransformationReplaceBranchFromDeadBlockWithExitTest,
+ UnreachableSuccessor) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeBool
+ %7 = OpConstantFalse %6
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpSelectionMerge %8 None
+ OpBranchConditional %7 %9 %10
+ %9 = OpLabel
+ OpBranch %11
+ %11 = OpLabel
+ %12 = OpCopyObject %6 %7
+ OpBranch %8
+ %10 = OpLabel
+ OpReturn
+ %8 = OpLabel
+ OpReturn
+ %13 = OpLabel
+ OpBranch %8
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_4;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+
+ transformation_context.GetFactManager()->AddFactBlockIsDead(9);
+ transformation_context.GetFactManager()->AddFactBlockIsDead(11);
+
+ TransformationReplaceBranchFromDeadBlockWithExit transformation(
+ 11, SpvOpUnreachable, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ transformation.Apply(context.get(), &transformation_context);
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+
+ std::string after_transformation = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeBool
+ %7 = OpConstantFalse %6
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpSelectionMerge %8 None
+ OpBranchConditional %7 %9 %10
+ %9 = OpLabel
+ OpBranch %11
+ %11 = OpLabel
+ %12 = OpCopyObject %6 %7
+ OpUnreachable
+ %10 = OpLabel
+ OpReturn
+ %8 = OpLabel
+ OpReturn
+ %13 = OpLabel
+ OpBranch %8
+ OpFunctionEnd
+ )";
+
+ ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+}
+
+TEST(TransformationReplaceBranchFromDeadBlockWithExitTest,
+ DeadBlockAfterItsSuccessor) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeBool
+ %7 = OpConstantTrue %6
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpSelectionMerge %8 None
+ OpBranchConditional %7 %9 %10
+ %9 = OpLabel
+ OpBranch %11
+ %11 = OpLabel
+ %12 = OpCopyObject %6 %7
+ OpBranch %8
+ %10 = OpLabel
+ OpBranch %13
+ %8 = OpLabel
+ OpReturn
+ %13 = OpLabel
+ OpBranch %8
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_4;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+
+ transformation_context.GetFactManager()->AddFactBlockIsDead(10);
+ transformation_context.GetFactManager()->AddFactBlockIsDead(13);
+
+ TransformationReplaceBranchFromDeadBlockWithExit transformation(
+ 13, SpvOpUnreachable, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ transformation.Apply(context.get(), &transformation_context);
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+
+ std::string after_transformation = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeBool
+ %7 = OpConstantTrue %6
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpSelectionMerge %8 None
+ OpBranchConditional %7 %9 %10
+ %9 = OpLabel
+ OpBranch %11
+ %11 = OpLabel
+ %12 = OpCopyObject %6 %7
+ OpBranch %8
+ %10 = OpLabel
+ OpBranch %13
+ %8 = OpLabel
+ OpReturn
+ %13 = OpLabel
+ OpUnreachable
+ OpFunctionEnd
+ )";
+
+ ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+}
+
+TEST(TransformationReplaceBranchFromDeadBlockWithExitTest,
+ BranchToOuterMergeBlock) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeBool
+ %7 = OpConstantTrue %6
+ %15 = OpTypeInt 32 0
+ %14 = OpUndef %15
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpSelectionMerge %8 None
+ OpSwitch %14 %9 1 %8
+ %9 = OpLabel
+ OpSelectionMerge %10 None
+ OpBranchConditional %7 %11 %10
+ %8 = OpLabel
+ OpReturn
+ %11 = OpLabel
+ OpBranch %8
+ %10 = OpLabel
+ OpBranch %8
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_4;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+
+ transformation_context.GetFactManager()->AddFactBlockIsDead(10);
+
+ TransformationReplaceBranchFromDeadBlockWithExit transformation(
+ 10, SpvOpUnreachable, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ transformation.Apply(context.get(), &transformation_context);
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+
+ std::string after_transformation = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeBool
+ %7 = OpConstantTrue %6
+ %15 = OpTypeInt 32 0
+ %14 = OpUndef %15
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ OpSelectionMerge %8 None
+ OpSwitch %14 %9 1 %8
+ %9 = OpLabel
+ OpSelectionMerge %10 None
+ OpBranchConditional %7 %11 %10
+ %8 = OpLabel
+ OpReturn
+ %11 = OpLabel
+ OpBranch %8
+ %10 = OpLabel
+ OpUnreachable
+ OpFunctionEnd
+ )";
+
+ ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+}
+
} // namespace
} // namespace fuzz
} // namespace spvtools
diff --git a/test/fuzz/transformation_replace_id_with_synonym_test.cpp b/test/fuzz/transformation_replace_id_with_synonym_test.cpp
index 5c10fc59..629a00ee 100644
--- a/test/fuzz/transformation_replace_id_with_synonym_test.cpp
+++ b/test/fuzz/transformation_replace_id_with_synonym_test.cpp
@@ -303,10 +303,18 @@ TEST(TransformationReplaceIdWithSynonymTest, LegalTransformations) {
auto global_constant_synonym = TransformationReplaceIdWithSynonym(
MakeIdUseDescriptor(19, MakeInstructionDescriptor(47, SpvOpStore, 0), 1),
210);
+ uint32_t num_uses_of_original_id_before_replacement =
+ context->get_def_use_mgr()->NumUses(19);
+ uint32_t num_uses_of_synonym_before_replacement =
+ context->get_def_use_mgr()->NumUses(210);
ASSERT_TRUE(global_constant_synonym.IsApplicable(context.get(),
transformation_context));
ApplyAndCheckFreshIds(global_constant_synonym, context.get(),
&transformation_context);
+ ASSERT_EQ(num_uses_of_original_id_before_replacement - 1,
+ context->get_def_use_mgr()->NumUses(19));
+ ASSERT_EQ(num_uses_of_synonym_before_replacement + 1,
+ context->get_def_use_mgr()->NumUses(210));
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
kConsoleMessageConsumer));
diff --git a/test/fuzz/transformation_set_loop_control_test.cpp b/test/fuzz/transformation_set_loop_control_test.cpp
index 3312a679..88b4aab5 100644
--- a/test/fuzz/transformation_set_loop_control_test.cpp
+++ b/test/fuzz/transformation_set_loop_control_test.cpp
@@ -947,7 +947,9 @@ TEST(TransformationSetLoopControlTest, CheckSPIRVVersionsRespected) {
for (auto env :
{SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2,
- SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5}) {
+ SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5,
+ SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_1_SPIRV_1_4,
+ SPV_ENV_VULKAN_1_2}) {
const auto consumer = nullptr;
const auto context =
BuildModule(env, consumer, shader, kFuzzAssembleOption);
@@ -956,23 +958,33 @@ TEST(TransformationSetLoopControlTest, CheckSPIRVVersionsRespected) {
context.get(), validator_options, kConsoleMessageConsumer));
TransformationContext transformation_context(
MakeUnique<FactManager>(context.get()), validator_options);
- TransformationSetLoopControl transformation(
- 10, SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, 4, 4);
+ TransformationSetLoopControl peel_count(10, SpvLoopControlPeelCountMask, 4,
+ 0);
+ TransformationSetLoopControl partial_count(
+ 10, SpvLoopControlPartialCountMask, 0, 4);
switch (env) {
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_UNIVERSAL_1_1:
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_UNIVERSAL_1_3:
+ case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_VULKAN_1_1:
// PeelCount and PartialCount were introduced in SPIRV 1.4, so are not
// valid in the context of older versions.
ASSERT_FALSE(
- transformation.IsApplicable(context.get(), transformation_context));
+ peel_count.IsApplicable(context.get(), transformation_context));
+ ASSERT_FALSE(
+ partial_count.IsApplicable(context.get(), transformation_context));
break;
case SPV_ENV_UNIVERSAL_1_4:
case SPV_ENV_UNIVERSAL_1_5:
+ case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
+ case SPV_ENV_VULKAN_1_2:
+ ASSERT_TRUE(
+ peel_count.IsApplicable(context.get(), transformation_context));
ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
+ partial_count.IsApplicable(context.get(), transformation_context));
break;
default:
assert(false && "Unhandled environment");
diff --git a/test/fuzz/transformation_set_memory_operands_mask_test.cpp b/test/fuzz/transformation_set_memory_operands_mask_test.cpp
index 4763d7ad..29e57f42 100644
--- a/test/fuzz/transformation_set_memory_operands_mask_test.cpp
+++ b/test/fuzz/transformation_set_memory_operands_mask_test.cpp
@@ -90,187 +90,205 @@ TEST(TransformationSetMemoryOperandsMaskTest, PreSpirv14) {
OpFunctionEnd
)";
- const auto env = SPV_ENV_UNIVERSAL_1_3;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- spvtools::ValidatorOptions validator_options;
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
- // Not OK: the instruction is not a memory access.
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpAccessChain, 0),
- SpvMemoryAccessMaskNone, 0)
- .IsApplicable(context.get(), transformation_context));
+ for (auto env :
+ {SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2,
+ SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1}) {
+ const auto consumer = nullptr;
+ const auto context =
+ BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
- // Not OK to remove Aligned
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(147, SpvOpLoad, 0),
- SpvMemoryAccessVolatileMask | SpvMemoryAccessNontemporalMask,
- 0)
- .IsApplicable(context.get(), transformation_context));
+#ifndef NDEBUG
+ {
+ // Not OK: multiple operands are not supported pre SPIR-V 1.4.
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 3),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
+ ASSERT_DEATH(
+ transformation.IsApplicable(context.get(), transformation_context),
+ "Multiple memory operand masks are not supported");
+ }
+#endif
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(147, SpvOpLoad, 0),
- SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ // Not OK: the instruction is not a memory access.
+ ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpAccessChain, 0),
+ SpvMemoryAccessMaskNone, 0)
+ .IsApplicable(context.get(), transformation_context));
- // Not OK to remove Aligned
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
- SpvMemoryAccessMaskNone, 0)
- .IsApplicable(context.get(), transformation_context));
+ // Not OK to remove Aligned
+ ASSERT_FALSE(
+ TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(147, SpvOpLoad, 0),
+ SpvMemoryAccessVolatileMask | SpvMemoryAccessNontemporalMask, 0)
+ .IsApplicable(context.get(), transformation_context));
- // OK: leaves the mask as is
- ASSERT_TRUE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
- SpvMemoryAccessAlignedMask, 0)
- .IsApplicable(context.get(), transformation_context));
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(147, SpvOpLoad, 0),
+ SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- // OK: adds Nontemporal and Volatile
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
- SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask |
- SpvMemoryAccessVolatileMask,
- 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ // Not OK to remove Aligned
+ ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
+ SpvMemoryAccessMaskNone, 0)
+ .IsApplicable(context.get(), transformation_context));
- // Not OK to remove Volatile
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
- SpvMemoryAccessNontemporalMask, 0)
- .IsApplicable(context.get(), transformation_context));
+ // OK: leaves the mask as is
+ ASSERT_TRUE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
+ SpvMemoryAccessAlignedMask, 0)
+ .IsApplicable(context.get(), transformation_context));
- // Not OK to add Aligned
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
- SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 0)
- .IsApplicable(context.get(), transformation_context));
+ {
+ // OK: adds Nontemporal and Volatile
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
+ SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask |
+ SpvMemoryAccessVolatileMask,
+ 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- // OK: adds Nontemporal
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
- SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ // Not OK to remove Volatile
+ ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
+ SpvMemoryAccessNontemporalMask, 0)
+ .IsApplicable(context.get(), transformation_context));
- {
- // OK: adds Nontemporal (creates new operand)
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 2),
- SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ // Not OK to add Aligned
+ ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
+ SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask,
+ 0)
+ .IsApplicable(context.get(), transformation_context));
- {
- // OK: adds Nontemporal and Volatile
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
- SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ // OK: adds Nontemporal
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- // OK: removes Nontemporal, adds Volatile
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(148, SpvOpStore, 0),
- SpvMemoryAccessVolatileMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ // OK: adds Nontemporal (creates new operand)
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 2),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- std::string after_transformation = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main"
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- OpName %4 "main"
- OpName %7 "Point3D"
- OpMemberName %7 0 "x"
- OpMemberName %7 1 "y"
- OpMemberName %7 2 "z"
- OpName %12 "global_points"
- OpName %15 "block"
- OpMemberName %15 0 "in_points"
- OpMemberName %15 1 "in_point"
- OpName %17 ""
- OpName %133 "local_points"
- OpMemberDecorate %7 0 Offset 0
- OpMemberDecorate %7 1 Offset 4
- OpMemberDecorate %7 2 Offset 8
- OpDecorate %10 ArrayStride 16
- OpMemberDecorate %15 0 Offset 0
- OpMemberDecorate %15 1 Offset 192
- OpDecorate %15 Block
- OpDecorate %17 DescriptorSet 0
- OpDecorate %17 Binding 0
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %7 = OpTypeStruct %6 %6 %6
- %8 = OpTypeInt 32 0
- %9 = OpConstant %8 12
- %10 = OpTypeArray %7 %9
- %11 = OpTypePointer Private %10
- %12 = OpVariable %11 Private
- %15 = OpTypeStruct %10 %7
- %16 = OpTypePointer Uniform %15
- %17 = OpVariable %16 Uniform
- %18 = OpTypeInt 32 1
- %19 = OpConstant %18 0
- %20 = OpTypePointer Uniform %10
- %24 = OpTypePointer Private %7
- %27 = OpTypePointer Private %6
- %30 = OpConstant %18 1
- %132 = OpTypePointer Function %10
- %135 = OpTypePointer Uniform %7
- %145 = OpTypePointer Function %7
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- %133 = OpVariable %132 Function
- %21 = OpAccessChain %20 %17 %19
- OpCopyMemory %12 %21 Aligned|Nontemporal|Volatile 16
- OpCopyMemory %133 %12 Nontemporal|Volatile
- OpCopyMemory %133 %12 Nontemporal|Volatile
- %136 = OpAccessChain %135 %17 %30
- %138 = OpAccessChain %24 %12 %19
- OpCopyMemory %138 %136 Nontemporal|Volatile
- %146 = OpAccessChain %145 %133 %30
- %147 = OpLoad %7 %146 Aligned|Volatile 16
- %148 = OpAccessChain %24 %12 %19
- OpStore %148 %147 Volatile
- OpReturn
- OpFunctionEnd
- )";
- ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+ {
+ // OK: adds Nontemporal and Volatile
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
+
+ {
+ // OK: removes Nontemporal, adds Volatile
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(148, SpvOpStore, 0),
+ SpvMemoryAccessVolatileMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
+
+ std::string after_transformation = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ OpName %4 "main"
+ OpName %7 "Point3D"
+ OpMemberName %7 0 "x"
+ OpMemberName %7 1 "y"
+ OpMemberName %7 2 "z"
+ OpName %12 "global_points"
+ OpName %15 "block"
+ OpMemberName %15 0 "in_points"
+ OpMemberName %15 1 "in_point"
+ OpName %17 ""
+ OpName %133 "local_points"
+ OpMemberDecorate %7 0 Offset 0
+ OpMemberDecorate %7 1 Offset 4
+ OpMemberDecorate %7 2 Offset 8
+ OpDecorate %10 ArrayStride 16
+ OpMemberDecorate %15 0 Offset 0
+ OpMemberDecorate %15 1 Offset 192
+ OpDecorate %15 Block
+ OpDecorate %17 DescriptorSet 0
+ OpDecorate %17 Binding 0
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeStruct %6 %6 %6
+ %8 = OpTypeInt 32 0
+ %9 = OpConstant %8 12
+ %10 = OpTypeArray %7 %9
+ %11 = OpTypePointer Private %10
+ %12 = OpVariable %11 Private
+ %15 = OpTypeStruct %10 %7
+ %16 = OpTypePointer Uniform %15
+ %17 = OpVariable %16 Uniform
+ %18 = OpTypeInt 32 1
+ %19 = OpConstant %18 0
+ %20 = OpTypePointer Uniform %10
+ %24 = OpTypePointer Private %7
+ %27 = OpTypePointer Private %6
+ %30 = OpConstant %18 1
+ %132 = OpTypePointer Function %10
+ %135 = OpTypePointer Uniform %7
+ %145 = OpTypePointer Function %7
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %133 = OpVariable %132 Function
+ %21 = OpAccessChain %20 %17 %19
+ OpCopyMemory %12 %21 Aligned|Nontemporal|Volatile 16
+ OpCopyMemory %133 %12 Nontemporal|Volatile
+ OpCopyMemory %133 %12 Nontemporal|Volatile
+ %136 = OpAccessChain %135 %17 %30
+ %138 = OpAccessChain %24 %12 %19
+ OpCopyMemory %138 %136 Nontemporal|Volatile
+ %146 = OpAccessChain %145 %133 %30
+ %147 = OpLoad %7 %146 Aligned|Volatile 16
+ %148 = OpAccessChain %24 %12 %19
+ OpStore %148 %147 Volatile
+ OpReturn
+ OpFunctionEnd
+ )";
+ ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+ }
}
-TEST(TransformationSetMemoryOperandsMaskTest, Spirv14) {
+TEST(TransformationSetMemoryOperandsMaskTest, Spirv14OrHigher) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
@@ -339,180 +357,183 @@ TEST(TransformationSetMemoryOperandsMaskTest, Spirv14) {
OpFunctionEnd
)";
- const auto env = SPV_ENV_UNIVERSAL_1_4;
- const auto consumer = nullptr;
- const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
- spvtools::ValidatorOptions validator_options;
- ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
- kConsoleMessageConsumer));
- TransformationContext transformation_context(
- MakeUnique<FactManager>(context.get()), validator_options);
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
- SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 1);
- // Bad: cannot remove aligned
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
- SpvMemoryAccessVolatileMask, 1)
- .IsApplicable(context.get(), transformation_context));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ for (auto env : {SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5,
+ SPV_ENV_VULKAN_1_1_SPIRV_1_4, SPV_ENV_VULKAN_1_2}) {
+ const auto consumer = nullptr;
+ const auto context =
+ BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+ context.get(), validator_options, kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
+ SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 1);
+ // Bad: cannot remove aligned
+ ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
+ SpvMemoryAccessVolatileMask, 1)
+ .IsApplicable(context.get(), transformation_context));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
- SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
- // Bad: cannot remove volatile
- ASSERT_FALSE(TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
- SpvMemoryAccessNontemporalMask, 0)
- .IsApplicable(context.get(), transformation_context));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
+ // Bad: cannot remove volatile
+ ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
+ SpvMemoryAccessNontemporalMask, 0)
+ .IsApplicable(context.get(), transformation_context));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- // Creates the first operand.
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 2),
- SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ // Creates the first operand.
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 2),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- // Creates both operands.
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(21, SpvOpCopyMemory, 3),
- SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ // Creates both operands.
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(21, SpvOpCopyMemory, 3),
+ SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
- SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 1);
- // Bad: the first mask is None, so Aligned cannot be added to it.
- ASSERT_FALSE(
- TransformationSetMemoryOperandsMask(
- MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
- SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 0)
- .IsApplicable(context.get(), transformation_context));
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
+ SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 1);
+ // Bad: the first mask is None, so Aligned cannot be added to it.
+ ASSERT_FALSE(
+ TransformationSetMemoryOperandsMask(
+ MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
+ SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 0)
+ .IsApplicable(context.get(), transformation_context));
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(138, SpvOpCopyMemory, 1),
- SpvMemoryAccessVolatileMask, 1);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(138, SpvOpCopyMemory, 1),
+ SpvMemoryAccessVolatileMask, 1);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(147, SpvOpLoad, 0),
- SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask, 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(147, SpvOpLoad, 0),
+ SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- {
- TransformationSetMemoryOperandsMask transformation(
- MakeInstructionDescriptor(148, SpvOpStore, 0), SpvMemoryAccessMaskNone,
- 0);
- ASSERT_TRUE(
- transformation.IsApplicable(context.get(), transformation_context));
- ApplyAndCheckFreshIds(transformation, context.get(),
- &transformation_context);
- }
+ {
+ TransformationSetMemoryOperandsMask transformation(
+ MakeInstructionDescriptor(148, SpvOpStore, 0),
+ SpvMemoryAccessMaskNone, 0);
+ ASSERT_TRUE(
+ transformation.IsApplicable(context.get(), transformation_context));
+ ApplyAndCheckFreshIds(transformation, context.get(),
+ &transformation_context);
+ }
- std::string after_transformation = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main" %12 %17
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- OpName %4 "main"
- OpName %7 "Point3D"
- OpMemberName %7 0 "x"
- OpMemberName %7 1 "y"
- OpMemberName %7 2 "z"
- OpName %12 "global_points"
- OpName %15 "block"
- OpMemberName %15 0 "in_points"
- OpMemberName %15 1 "in_point"
- OpName %17 ""
- OpName %133 "local_points"
- OpMemberDecorate %7 0 Offset 0
- OpMemberDecorate %7 1 Offset 4
- OpMemberDecorate %7 2 Offset 8
- OpDecorate %10 ArrayStride 16
- OpMemberDecorate %15 0 Offset 0
- OpMemberDecorate %15 1 Offset 192
- OpDecorate %15 Block
- OpDecorate %17 DescriptorSet 0
- OpDecorate %17 Binding 0
- %2 = OpTypeVoid
- %3 = OpTypeFunction %2
- %6 = OpTypeFloat 32
- %7 = OpTypeStruct %6 %6 %6
- %8 = OpTypeInt 32 0
- %9 = OpConstant %8 12
- %10 = OpTypeArray %7 %9
- %11 = OpTypePointer Private %10
- %12 = OpVariable %11 Private
- %15 = OpTypeStruct %10 %7
- %16 = OpTypePointer Uniform %15
- %17 = OpVariable %16 Uniform
- %18 = OpTypeInt 32 1
- %19 = OpConstant %18 0
- %20 = OpTypePointer Uniform %10
- %24 = OpTypePointer Private %7
- %27 = OpTypePointer Private %6
- %30 = OpConstant %18 1
- %132 = OpTypePointer Function %10
- %135 = OpTypePointer Uniform %7
- %145 = OpTypePointer Function %7
- %4 = OpFunction %2 None %3
- %5 = OpLabel
- %133 = OpVariable %132 Function
- %21 = OpAccessChain %20 %17 %19
- OpCopyMemory %12 %21 Aligned 16 Aligned|Volatile 16
- OpCopyMemory %133 %12 Volatile Nontemporal|Volatile
- OpCopyMemory %133 %12 Nontemporal|Volatile
- OpCopyMemory %133 %12 None Nontemporal|Volatile
- %136 = OpAccessChain %135 %17 %30
- %138 = OpAccessChain %24 %12 %19
- OpCopyMemory %138 %136 None Aligned|Nontemporal 16
- OpCopyMemory %138 %136 Aligned 16 Volatile
- %146 = OpAccessChain %145 %133 %30
- %147 = OpLoad %7 %146 Volatile|Aligned 16
- %148 = OpAccessChain %24 %12 %19
- OpStore %148 %147 None
- OpReturn
- OpFunctionEnd
- )";
- ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+ std::string after_transformation = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main" %12 %17
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 310
+ OpName %4 "main"
+ OpName %7 "Point3D"
+ OpMemberName %7 0 "x"
+ OpMemberName %7 1 "y"
+ OpMemberName %7 2 "z"
+ OpName %12 "global_points"
+ OpName %15 "block"
+ OpMemberName %15 0 "in_points"
+ OpMemberName %15 1 "in_point"
+ OpName %17 ""
+ OpName %133 "local_points"
+ OpMemberDecorate %7 0 Offset 0
+ OpMemberDecorate %7 1 Offset 4
+ OpMemberDecorate %7 2 Offset 8
+ OpDecorate %10 ArrayStride 16
+ OpMemberDecorate %15 0 Offset 0
+ OpMemberDecorate %15 1 Offset 192
+ OpDecorate %15 Block
+ OpDecorate %17 DescriptorSet 0
+ OpDecorate %17 Binding 0
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeStruct %6 %6 %6
+ %8 = OpTypeInt 32 0
+ %9 = OpConstant %8 12
+ %10 = OpTypeArray %7 %9
+ %11 = OpTypePointer Private %10
+ %12 = OpVariable %11 Private
+ %15 = OpTypeStruct %10 %7
+ %16 = OpTypePointer Uniform %15
+ %17 = OpVariable %16 Uniform
+ %18 = OpTypeInt 32 1
+ %19 = OpConstant %18 0
+ %20 = OpTypePointer Uniform %10
+ %24 = OpTypePointer Private %7
+ %27 = OpTypePointer Private %6
+ %30 = OpConstant %18 1
+ %132 = OpTypePointer Function %10
+ %135 = OpTypePointer Uniform %7
+ %145 = OpTypePointer Function %7
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %133 = OpVariable %132 Function
+ %21 = OpAccessChain %20 %17 %19
+ OpCopyMemory %12 %21 Aligned 16 Aligned|Volatile 16
+ OpCopyMemory %133 %12 Volatile Nontemporal|Volatile
+ OpCopyMemory %133 %12 Nontemporal|Volatile
+ OpCopyMemory %133 %12 None Nontemporal|Volatile
+ %136 = OpAccessChain %135 %17 %30
+ %138 = OpAccessChain %24 %12 %19
+ OpCopyMemory %138 %136 None Aligned|Nontemporal 16
+ OpCopyMemory %138 %136 Aligned 16 Volatile
+ %146 = OpAccessChain %145 %133 %30
+ %147 = OpLoad %7 %146 Volatile|Aligned 16
+ %148 = OpAccessChain %24 %12 %19
+ OpStore %148 %147 None
+ OpReturn
+ OpFunctionEnd
+ )";
+ ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+ }
}
} // namespace
diff --git a/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp b/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp
index e7a8732e..6133a7a8 100644
--- a/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp
+++ b/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp
@@ -91,9 +91,31 @@ TEST(TransformationSwapConditionalBranchOperandsTest, BasicTest) {
TransformationSwapConditionalBranchOperands transformation(
MakeInstructionDescriptor(15, SpvOpBranchConditional, 0), 26);
+ ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(26));
+ ASSERT_EQ(nullptr, context->get_instr_block(26));
ASSERT_TRUE(
transformation.IsApplicable(context.get(), transformation_context));
ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+ ASSERT_EQ(SpvOpLogicalNot, context->get_def_use_mgr()->GetDef(26)->opcode());
+ ASSERT_EQ(5, context->get_instr_block(26)->id());
+ ASSERT_EQ(1, context->get_def_use_mgr()->NumUses(26));
+
+ // Check that the def-use manager knows that the conditional branch operands
+ // have been swapped.
+ std::vector<std::pair<uint32_t, uint32_t>> phi_operand_to_new_operand_index =
+ {{16, 2}, {21, 1}};
+ for (std::pair<uint32_t, uint32_t>& entry :
+ phi_operand_to_new_operand_index) {
+ context->get_def_use_mgr()->WhileEachUse(
+ entry.first,
+ [&entry](opt::Instruction* inst, uint32_t operand_index) -> bool {
+ if (inst->opcode() == SpvOpBranchConditional) {
+ EXPECT_EQ(entry.second, operand_index);
+ return false;
+ }
+ return true;
+ });
+ }
std::string after_transformation = R"(
OpCapability Shader
diff --git a/test/opt/CMakeLists.txt b/test/opt/CMakeLists.txt
index 79cb3fc4..f65d2ff3 100644
--- a/test/opt/CMakeLists.txt
+++ b/test/opt/CMakeLists.txt
@@ -57,6 +57,7 @@ add_spvtools_unittest(TARGET opt
inst_debug_printf_test.cpp
instruction_list_test.cpp
instruction_test.cpp
+ interp_fixup_test.cpp
ir_builder.cpp
ir_context_test.cpp
ir_loader_test.cpp
diff --git a/test/opt/aggressive_dead_code_elim_test.cpp b/test/opt/aggressive_dead_code_elim_test.cpp
index 972e6e57..5b4291da 100644
--- a/test/opt/aggressive_dead_code_elim_test.cpp
+++ b/test/opt/aggressive_dead_code_elim_test.cpp
@@ -3948,12 +3948,15 @@ OpBranch %12
OpLoopMerge %14 %15 None
OpBranch %16
%16 = OpLabel
-OpSwitch %13 %14 0 %17 1 %15
+OpSelectionMerge %18 None
+OpSwitch %13 %18 0 %17 1 %15
%17 = OpLabel
OpStore %3 %uint_1
OpBranch %15
%15 = OpLabel
OpBranch %12
+%18 = OpLabel
+OpBranch %14
%14 = OpLabel
OpStore %3 %uint_0
OpReturn
diff --git a/test/opt/block_merge_test.cpp b/test/opt/block_merge_test.cpp
index 7381908e..140a5c09 100644
--- a/test/opt/block_merge_test.cpp
+++ b/test/opt/block_merge_test.cpp
@@ -744,6 +744,7 @@ TEST_F(BlockMergeTest, DontMergeSwitch) {
; CHECK: OpLoopMerge [[merge:%\w+]] [[cont:%\w+]] None
; CHECK-NEXT: OpBranch [[ret:%\w+]]
; CHECK: [[ret:%\w+]] = OpLabel
+; CHECK-NEXT: OpSelectionMerge
; CHECK-NEXT: OpSwitch
; CHECK-DAG: [[cont]] = OpLabel
; CHECK-DAG: [[merge]] = OpLabel
@@ -763,6 +764,7 @@ OpBranch %2
OpLoopMerge %3 %4 None
OpBranch %5
%5 = OpLabel
+OpSelectionMerge %6 None
OpSwitch %int_0 %6
%6 = OpLabel
OpReturn
diff --git a/test/opt/dead_branch_elim_test.cpp b/test/opt/dead_branch_elim_test.cpp
index 41ce31da..f89befb4 100644
--- a/test/opt/dead_branch_elim_test.cpp
+++ b/test/opt/dead_branch_elim_test.cpp
@@ -2722,6 +2722,7 @@ OpSource GLSL 140
; CHECK: [[bb1]] = OpLabel
; CHECK-NEXT: OpBranch [[bb2:%\w+]]
; CHECK: [[bb2]] = OpLabel
+; CHECK-NEXT: OpSelectionMerge
; CHECK-NEXT: OpSwitch {{%\w+}} [[bb3:%\w+]] 0 [[loop_merge]] 1 [[bb3:%\w+]]
; CHECK: [[bb3]] = OpLabel
; CHECK-NEXT: OpBranch [[sel_merge:%\w+]]
@@ -2739,6 +2740,7 @@ OpBranch %bb1
OpSelectionMerge %sel_merge None
OpBranchConditional %true %bb2 %bb4
%bb2 = OpLabel
+OpSelectionMerge %bb3 None
OpSwitch %undef_int %bb3 0 %loop_merge 1 %bb3
%bb3 = OpLabel
OpBranch %sel_merge
@@ -2782,6 +2784,7 @@ OpSource GLSL 140
; CHECK: [[bb1]] = OpLabel
; CHECK-NEXT: OpBranch [[bb2:%\w+]]
; CHECK: [[bb2]] = OpLabel
+; CHECK-NEXT: OpSelectionMerge
; CHECK-NEXT: OpSwitch {{%\w+}} [[bb3:%\w+]] 0 [[loop_cont]] 1 [[bb3:%\w+]]
; CHECK: [[bb3]] = OpLabel
; CHECK-NEXT: OpBranch [[sel_merge:%\w+]]
@@ -2799,6 +2802,7 @@ OpBranch %bb1
OpSelectionMerge %sel_merge None
OpBranchConditional %true %bb2 %bb4
%bb2 = OpLabel
+OpSelectionMerge %bb3 None
OpSwitch %undef_int %bb3 0 %cont 1 %bb3
%bb3 = OpLabel
OpBranch %sel_merge
diff --git a/test/opt/instruction_list_test.cpp b/test/opt/instruction_list_test.cpp
index e745790a..2c3c2429 100644
--- a/test/opt/instruction_list_test.cpp
+++ b/test/opt/instruction_list_test.cpp
@@ -35,7 +35,7 @@ class TestInstruction : public Instruction {
public:
TestInstruction() : Instruction() { created_instructions_.push_back(this); }
- ~TestInstruction() { deleted_instructions_.push_back(this); }
+ ~TestInstruction() override{ deleted_instructions_.push_back(this); }
static std::vector<TestInstruction*> created_instructions_;
static std::vector<TestInstruction*> deleted_instructions_;
diff --git a/test/opt/interp_fixup_test.cpp b/test/opt/interp_fixup_test.cpp
new file mode 100644
index 00000000..a43a29c0
--- /dev/null
+++ b/test/opt/interp_fixup_test.cpp
@@ -0,0 +1,172 @@
+// Copyright (c) 2021 The Khronos Group Inc.
+// Copyright (c) 2021 Valve Corporation
+// Copyright (c) 2021 LunarG Inc.
+//
+// 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 <vector>
+
+#include "gmock/gmock.h"
+#include "test/opt/pass_fixture.h"
+#include "test/opt/pass_utils.h"
+
+namespace spvtools {
+namespace opt {
+namespace {
+
+using InterpFixupTest = PassTest<::testing::Test>;
+
+using ::testing::HasSubstr;
+
+TEST_F(InterpFixupTest, FixInterpAtSample) {
+ const std::string text = R"(
+ OpCapability Shader
+ OpCapability InterpolationFunction
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %MainPs "MainPs" %i_vPositionOs %_entryPointOutput
+ OpExecutionMode %MainPs OriginUpperLeft
+ OpSource HLSL 500
+ OpName %MainPs "MainPs"
+ OpName %i_vPositionOs "i.vPositionOs"
+ OpName %_entryPointOutput "@entryPointOutput"
+ OpDecorate %i_vPositionOs Location 0
+ OpDecorate %_entryPointOutput Location 0
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %float_0 = OpConstant %float 0
+ %10 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+ %uint_4 = OpConstant %uint 4
+ %bool = OpTypeBool
+ %int = OpTypeInt 32 1
+ %int_1 = OpConstant %int 1
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%i_vPositionOs = OpVariable %_ptr_Input_v4float Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
+ %MainPs = OpFunction %void None %6
+ %19 = OpLabel
+ %20 = OpLoad %v4float %i_vPositionOs
+ OpBranch %21
+ %21 = OpLabel
+ %22 = OpPhi %v4float %10 %19 %23 %24
+ %25 = OpPhi %uint %uint_0 %19 %26 %24
+ %27 = OpULessThan %bool %25 %uint_4
+ OpLoopMerge %28 %24 None
+ OpBranchConditional %27 %24 %28
+ %24 = OpLabel
+ %29 = OpExtInst %v4float %1 InterpolateAtSample %20 %25
+;CHECK: %29 = OpExtInst %v4float %1 InterpolateAtSample %i_vPositionOs %25
+ %30 = OpCompositeExtract %float %29 0
+ %31 = OpCompositeExtract %float %22 0
+ %32 = OpFAdd %float %31 %30
+ %23 = OpCompositeInsert %v4float %32 %22 0
+ %26 = OpIAdd %uint %25 %int_1
+ OpBranch %21
+ %28 = OpLabel
+ OpStore %_entryPointOutput %22
+ OpReturn
+ OpFunctionEnd
+)";
+
+ SinglePassRunAndMatch<InterpFixupPass>(text, false);
+}
+
+TEST_F(InterpFixupTest, FixInterpAtCentroid) {
+ const std::string text = R"(
+ OpCapability Shader
+ OpCapability InterpolationFunction
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %MainPs "MainPs" %i_vPositionOs %_entryPointOutput
+ OpExecutionMode %MainPs OriginUpperLeft
+ OpSource HLSL 500
+ OpName %MainPs "MainPs"
+ OpName %i_vPositionOs "i.vPositionOs"
+ OpName %_entryPointOutput "@entryPointOutput"
+ OpDecorate %i_vPositionOs Location 0
+ OpDecorate %_entryPointOutput Location 0
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %float_0 = OpConstant %float 0
+ %10 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%i_vPositionOs = OpVariable %_ptr_Input_v4float Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
+ %MainPs = OpFunction %void None %6
+ %13 = OpLabel
+ %14 = OpLoad %v4float %i_vPositionOs
+ %15 = OpExtInst %v4float %1 InterpolateAtCentroid %14
+;CHECK: %15 = OpExtInst %v4float %1 InterpolateAtCentroid %i_vPositionOs
+ %16 = OpCompositeExtract %float %15 0
+ %17 = OpCompositeInsert %v4float %16 %10 0
+ OpStore %_entryPointOutput %17
+ OpReturn
+ OpFunctionEnd
+)";
+
+ SinglePassRunAndMatch<InterpFixupPass>(text, false);
+}
+
+TEST_F(InterpFixupTest, FixInterpAtOffset) {
+ const std::string text = R"(
+ OpCapability Shader
+ OpCapability InterpolationFunction
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %MainPs "MainPs" %i_vPositionOs %_entryPointOutput
+ OpExecutionMode %MainPs OriginUpperLeft
+ OpSource HLSL 500
+ OpName %MainPs "MainPs"
+ OpName %i_vPositionOs "i.vPositionOs"
+ OpName %_entryPointOutput "@entryPointOutput"
+ OpDecorate %i_vPositionOs Location 0
+ OpDecorate %_entryPointOutput Location 0
+ %void = OpTypeVoid
+ %6 = OpTypeFunction %void
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+ %float_0 = OpConstant %float 0
+ %10 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+ %v2float = OpTypeVector %float 2
+%float_0_0625 = OpConstant %float 0.0625
+ %13 = OpConstantComposite %v2float %float_0_0625 %float_0_0625
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%i_vPositionOs = OpVariable %_ptr_Input_v4float Input
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_entryPointOutput = OpVariable %_ptr_Output_v4float Output
+ %MainPs = OpFunction %void None %6
+ %16 = OpLabel
+ %17 = OpLoad %v4float %i_vPositionOs
+ %18 = OpExtInst %v4float %1 InterpolateAtOffset %17 %13
+;CHECK: %18 = OpExtInst %v4float %1 InterpolateAtOffset %i_vPositionOs %13
+ %19 = OpCompositeExtract %float %18 0
+ %20 = OpCompositeInsert %v4float %19 %10 0
+ OpStore %_entryPointOutput %20
+ OpReturn
+ OpFunctionEnd
+)";
+
+ SinglePassRunAndMatch<InterpFixupPass>(text, false);
+}
+
+} // namespace
+} // namespace opt
+} // namespace spvtools
diff --git a/test/opt/scalar_replacement_test.cpp b/test/opt/scalar_replacement_test.cpp
index 10738558..8115f5fb 100644
--- a/test/opt/scalar_replacement_test.cpp
+++ b/test/opt/scalar_replacement_test.cpp
@@ -2197,6 +2197,46 @@ OpFunctionEnd
SinglePassRunAndMatch<ScalarReplacementPass>(text, true);
}
+TEST_F(ScalarReplacementTest, ImageTexelPointer) {
+ // Test whether the scalar replacement correctly checks the
+ // OpImageTexelPointer user of an aggregate with an image type.
+ const std::string text = R"(
+;
+; CHECK: [[imgTy:%\w+]] = OpTypeImage %uint Buffer 2 0 0 2 R32ui
+; CHECK: [[ptrImgTy:%\w+]] = OpTypePointer Function [[imgTy]]
+; CHECK: [[img:%\w+]] = OpVariable [[ptrImgTy]] Function
+; CHECK: [[imgTexelPtr:%\w+]] = OpImageTexelPointer {{%\w+}} [[img]] %uint_0 %uint_0
+; CHECK: OpAtomicIAdd %uint [[imgTexelPtr]] %uint_1 %uint_0 %uint_1
+;
+OpCapability Shader
+OpCapability SampledBuffer
+OpCapability ImageBuffer
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %1 "main"
+OpExecutionMode %1 LocalSize 64 1 1
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%uint_0 = OpConstant %uint 0
+%uint_1 = OpConstant %uint 1
+%_ptr_Image_uint = OpTypePointer Image %uint
+%type_buffer_image = OpTypeImage %uint Buffer 2 0 0 2 R32ui
+%_ptr_Function_type_buffer_image = OpTypePointer Function %type_buffer_image
+%image_struct = OpTypeStruct %type_buffer_image %type_buffer_image
+%_ptr_Function_image_struct = OpTypePointer Function %image_struct
+%func = OpTypeFunction %void
+%1 = OpFunction %void None %func
+%2 = OpLabel
+%3 = OpVariable %_ptr_Function_image_struct Function
+%4 = OpAccessChain %_ptr_Function_type_buffer_image %3 %uint_1
+%5 = OpImageTexelPointer %_ptr_Image_uint %4 %uint_0 %uint_0
+%6 = OpAtomicIAdd %uint %5 %uint_1 %uint_0 %uint_1
+OpReturn
+OpFunctionEnd
+ )";
+
+ SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
+}
+
} // namespace
} // namespace opt
} // namespace spvtools
diff --git a/test/test_fixture.h b/test/test_fixture.h
index 436993e2..0c5bfc9c 100644
--- a/test/test_fixture.h
+++ b/test/test_fixture.h
@@ -46,7 +46,7 @@ class TextToBinaryTestBase : public T {
text = {textStr, strlen(textStr)};
}
- virtual ~TextToBinaryTestBase() {
+ ~TextToBinaryTestBase() override {
DestroyBinary();
if (diagnostic) spvDiagnosticDestroy(diagnostic);
}
diff --git a/test/text_to_binary.extension_test.cpp b/test/text_to_binary.extension_test.cpp
index 023763b7..8c42f72c 100644
--- a/test/text_to_binary.extension_test.cpp
+++ b/test/text_to_binary.extension_test.cpp
@@ -905,5 +905,36 @@ INSTANTIATE_TEST_SUITE_P(
MakeInstruction(SpvOpDecorate, {1, 5300})},
})));
+// SPV_KHR_linkonce_odr
+
+INSTANTIATE_TEST_SUITE_P(
+ SPV_KHR_linkonce_odr, ExtensionRoundTripTest,
+ Combine(
+ Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0,
+ SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2),
+ ValuesIn(std::vector<AssemblyCase>{
+ {"OpExtension \"SPV_KHR_linkonce_odr\"\n",
+ MakeInstruction(SpvOpExtension,
+ MakeVector("SPV_KHR_linkonce_odr"))},
+ {"OpDecorate %1 LinkageAttributes \"foobar\" LinkOnceODR\n",
+ MakeInstruction(SpvOpDecorate,
+ Concatenate({{1, SpvDecorationLinkageAttributes},
+ MakeVector("foobar"),
+ {SpvLinkageTypeLinkOnceODR}}))},
+ })));
+
+// SPV_KHR_expect_assume
+
+INSTANTIATE_TEST_SUITE_P(
+ SPV_KHR_expect_assume, ExtensionRoundTripTest,
+ Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_3,
+ SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2),
+ ValuesIn(std::vector<AssemblyCase>{
+ {"OpExtension \"SPV_KHR_expect_assume\"\n",
+ MakeInstruction(SpvOpExtension,
+ MakeVector("SPV_KHR_expect_assume"))},
+ {"OpAssumeTrueKHR %1\n",
+ MakeInstruction(SpvOpAssumeTrueKHR, {1})}})));
+
} // namespace
} // namespace spvtools
diff --git a/test/val/CMakeLists.txt b/test/val/CMakeLists.txt
index b17d1cb1..4aec2497 100644
--- a/test/val/CMakeLists.txt
+++ b/test/val/CMakeLists.txt
@@ -38,6 +38,8 @@ add_spvtools_unittest(TARGET val_abcde
val_entry_point.cpp
val_explicit_reserved_test.cpp
val_extensions_test.cpp
+ val_extension_spv_khr_expect_assume.cpp
+ val_extension_spv_khr_linkonce_odr.cpp
val_extension_spv_khr_terminate_invocation.cpp
val_ext_inst_test.cpp
${VAL_TEST_COMMON_SRCS}
diff --git a/test/val/val_atomics_test.cpp b/test/val/val_atomics_test.cpp
index fccfabc3..e2ca71fe 100644
--- a/test/val/val_atomics_test.cpp
+++ b/test/val/val_atomics_test.cpp
@@ -95,6 +95,7 @@ OpFunctionEnd)";
std::string GenerateShaderCode(
const std::string& body,
const std::string& capabilities_and_extensions = "",
+ const std::string& extra_defs = "",
const std::string& memory_model = "GLSL450") {
const std::string execution = R"(
OpEntryPoint Fragment %main "main"
@@ -113,7 +114,8 @@ OpExecutionMode %main OriginUpperLeft
%s64_var = OpVariable %s64_ptr Workgroup
)";
return GenerateShaderCodeImpl(
- body, "OpCapability Int64\n" + capabilities_and_extensions, defintions,
+ body, "OpCapability Int64\n" + capabilities_and_extensions,
+ defintions + extra_defs,
memory_model, execution);
}
@@ -222,7 +224,6 @@ TEST_F(ValidateAtomics, AtomicLoadShaderSuccess) {
const std::string body = R"(
%val1 = OpAtomicLoad %u32 %u32_var %device %relaxed
%val2 = OpAtomicLoad %u32 %u32_var %workgroup %acquire
-%val3 = OpAtomicLoad %u64 %u64_var %subgroup %sequentially_consistent
)";
CompileSuccessfully(GenerateShaderCode(body));
@@ -233,17 +234,35 @@ TEST_F(ValidateAtomics, AtomicLoadKernelSuccess) {
const std::string body = R"(
%val1 = OpAtomicLoad %f32 %f32_var %device %relaxed
%val2 = OpAtomicLoad %u32 %u32_var %workgroup %sequentially_consistent
-%val3 = OpAtomicLoad %u64 %u64_var %subgroup %acquire
)";
CompileSuccessfully(GenerateKernelCode(body));
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
}
+TEST_F(ValidateAtomics, AtomicLoadInt64ShaderSuccess) {
+ const std::string body = R"(
+%val1 = OpAtomicLoad %u64 %u64_var %subgroup %sequentially_consistent
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, "OpCapability Int64Atomics\n"));
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateAtomics, AtomicLoadInt64KernelSuccess) {
+ const std::string body = R"(
+%val1 = OpAtomicLoad %u64 %u64_var %subgroup %acquire
+)";
+
+ CompileSuccessfully(GenerateKernelCode(body, "OpCapability Int64Atomics\n"));
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
TEST_F(ValidateAtomics, AtomicLoadInt32VulkanSuccess) {
const std::string body = R"(
%val1 = OpAtomicLoad %u32 %u32_var %device %relaxed
%val2 = OpAtomicLoad %u32 %u32_var %workgroup %acquire
+%val3 = OpAtomicLoad %u32 %u32_var %invocation %relaxed
)";
CompileSuccessfully(GenerateShaderComputeCode(body), SPV_ENV_VULKAN_1_0);
@@ -259,7 +278,7 @@ TEST_F(ValidateAtomics, AtomicAddIntVulkanWrongType1) {
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("AtomicIAdd: "
- "expected Result Type to be int scalar type"));
+ "expected Result Type to be integer scalar type"));
}
TEST_F(ValidateAtomics, AtomicAddIntVulkanWrongType2) {
@@ -287,6 +306,32 @@ TEST_F(ValidateAtomics, AtomicAddFloatVulkan) {
"AtomicFloat32AddEXT AtomicFloat64AddEXT"));
}
+TEST_F(ValidateAtomics, AtomicMinFloatVulkan) {
+ const std::string body = R"(
+%val1 = OpAtomicFMinEXT %f32 %f32_var %device %relaxed %f32_1
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body));
+ ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Opcode AtomicFMinEXT requires one of these capabilities: "
+ "AtomicFloat32MinMaxEXT AtomicFloat64MinMaxEXT AtomicFloat16MinMaxEXT"));
+}
+
+TEST_F(ValidateAtomics, AtomicMaxFloatVulkan) {
+ const std::string body = R"(
+%val1 = OpAtomicFMaxEXT %f32 %f32_var %device %relaxed %f32_1
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body));
+ ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Opcode AtomicFMaxEXT requires one of these capabilities: "
+ "AtomicFloat32MinMaxEXT AtomicFloat64MinMaxEXT AtomicFloat16MinMaxEXT"));
+}
+
TEST_F(ValidateAtomics, AtomicAddFloatVulkanWrongType1) {
const std::string body = R"(
%val1 = OpAtomicFAddEXT %f32vec4 %f32vec4_var %device %relaxed %f32_1
@@ -303,6 +348,38 @@ OpExtension "SPV_EXT_shader_atomic_float_add"
"expected Result Type to be float scalar type"));
}
+TEST_F(ValidateAtomics, AtomicMinFloatVulkanWrongType1) {
+ const std::string body = R"(
+%val1 = OpAtomicFMinEXT %f32vec4 %f32vec4_var %device %relaxed %f32_1
+)";
+ const std::string extra = R"(
+OpCapability AtomicFloat32MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("AtomicFMinEXT: "
+ "expected Result Type to be float scalar type"));
+}
+
+TEST_F(ValidateAtomics, AtomicMaxFloatVulkanWrongType1) {
+ const std::string body = R"(
+%val1 = OpAtomicFMaxEXT %f32vec4 %f32vec4_var %device %relaxed %f32_1
+)";
+ const std::string extra = R"(
+OpCapability AtomicFloat32MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("AtomicFMaxEXT: "
+ "expected Result Type to be float scalar type"));
+}
+
TEST_F(ValidateAtomics, AtomicAddFloatVulkanWrongType2) {
const std::string body = R"(
%val1 = OpAtomicFAddEXT %u32 %u32_var %device %relaxed %u32_1
@@ -319,6 +396,38 @@ OpExtension "SPV_EXT_shader_atomic_float_add"
"expected Result Type to be float scalar type"));
}
+TEST_F(ValidateAtomics, AtomicMinFloatVulkanWrongType2) {
+ const std::string body = R"(
+%val1 = OpAtomicFMinEXT %u32 %u32_var %device %relaxed %u32_1
+)";
+ const std::string extra = R"(
+OpCapability AtomicFloat32MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("AtomicFMinEXT: "
+ "expected Result Type to be float scalar type"));
+}
+
+TEST_F(ValidateAtomics, AtomicMaxFloatVulkanWrongType2) {
+ const std::string body = R"(
+%val1 = OpAtomicFMaxEXT %u32 %u32_var %device %relaxed %u32_1
+)";
+ const std::string extra = R"(
+OpCapability AtomicFloat32MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("AtomicFMaxEXT: "
+ "expected Result Type to be float scalar type"));
+}
+
TEST_F(ValidateAtomics, AtomicAddFloatVulkanWrongType3) {
const std::string body = R"(
%val1 = OpAtomicFAddEXT %u64 %u64_var %device %relaxed %u64_1
@@ -335,6 +444,38 @@ OpExtension "SPV_EXT_shader_atomic_float_add"
"expected Result Type to be float scalar type"));
}
+TEST_F(ValidateAtomics, AtomicMinFloatVulkanWrongType3) {
+ const std::string body = R"(
+%val1 = OpAtomicFMinEXT %u64 %u64_var %device %relaxed %u64_1
+)";
+ const std::string extra = R"(
+OpCapability AtomicFloat32MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("AtomicFMinEXT: "
+ "expected Result Type to be float scalar type"));
+}
+
+TEST_F(ValidateAtomics, AtomicMaxFloatVulkanWrongType3) {
+ const std::string body = R"(
+%val1 = OpAtomicFMaxEXT %u64 %u64_var %device %relaxed %u64_1
+)";
+ const std::string extra = R"(
+OpCapability AtomicFloat32MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("AtomicFMaxEXT: "
+ "expected Result Type to be float scalar type"));
+}
+
TEST_F(ValidateAtomics, AtomicAddFloatVulkanWrongCapability) {
const std::string body = R"(
%val1 = OpAtomicFAddEXT %f32 %f32_var %device %relaxed %f32_1
@@ -351,9 +492,42 @@ OpExtension "SPV_EXT_shader_atomic_float_add"
"require the AtomicFloat32AddEXT capability"));
}
+TEST_F(ValidateAtomics, AtomicMinFloatVulkanWrongCapability) {
+ const std::string body = R"(
+%val1 = OpAtomicFMinEXT %f32 %f32_var %device %relaxed %f32_1
+)";
+ const std::string extra = R"(
+OpCapability AtomicFloat64MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("AtomicFMinEXT: float min/max atomics "
+ "require the AtomicFloat32MinMaxEXT capability"));
+}
+
+TEST_F(ValidateAtomics, AtomicMaxFloatVulkanWrongCapability) {
+ const std::string body = R"(
+%val1 = OpAtomicFMaxEXT %f32 %f32_var %device %relaxed %f32_1
+)";
+ const std::string extra = R"(
+OpCapability AtomicFloat64MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("AtomicFMaxEXT: float min/max atomics "
+ "require the AtomicFloat32MinMaxEXT capability"));
+}
+
TEST_F(ValidateAtomics, AtomicAddFloatVulkanSuccess) {
const std::string body = R"(
%val1 = OpAtomicFAddEXT %f32 %f32_var %device %relaxed %f32_1
+%val2 = OpAtomicFAddEXT %f32 %f32_var %invocation %relaxed %f32_1
)";
const std::string extra = R"(
OpCapability AtomicFloat32AddEXT
@@ -364,6 +538,112 @@ OpExtension "SPV_EXT_shader_atomic_float_add"
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
}
+TEST_F(ValidateAtomics, AtomicMinFloat16VulkanSuccess) {
+ const std::string defs = R"(
+%f16 = OpTypeFloat 16
+%f16_1 = OpConstant %f16 1
+%f16_ptr = OpTypePointer Workgroup %f16
+%f16_var = OpVariable %f16_ptr Workgroup
+)";
+ const std::string body = R"(
+%val1 = OpAtomicFMinEXT %f16 %f16_var %device %relaxed %f16_1
+)";
+ const std::string extra = R"(
+OpCapability Float16
+OpCapability AtomicFloat16MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra, defs), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+}
+
+TEST_F(ValidateAtomics, AtomicMaxFloat16VulkanSuccess) {
+ const std::string defs = R"(
+%f16 = OpTypeFloat 16
+%f16_1 = OpConstant %f16 1
+%f16_ptr = OpTypePointer Workgroup %f16
+%f16_var = OpVariable %f16_ptr Workgroup
+)";
+ const std::string body = R"(
+%val1 = OpAtomicFMaxEXT %f16 %f16_var %device %relaxed %f16_1
+)";
+ const std::string extra = R"(
+OpCapability Float16
+OpCapability AtomicFloat16MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra, defs), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+}
+
+TEST_F(ValidateAtomics, AtomicMinFloat32VulkanSuccess) {
+ const std::string body = R"(
+%val1 = OpAtomicFMinEXT %f32 %f32_var %device %relaxed %f32_1
+)";
+ const std::string extra = R"(
+OpCapability AtomicFloat32MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+}
+
+TEST_F(ValidateAtomics, AtomicMaxFloat32VulkanSuccess) {
+ const std::string body = R"(
+%val1 = OpAtomicFMaxEXT %f32 %f32_var %device %relaxed %f32_1
+)";
+ const std::string extra = R"(
+OpCapability AtomicFloat32MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+}
+
+TEST_F(ValidateAtomics, AtomicMinFloat64VulkanSuccess) {
+ const std::string defs = R"(
+%f64 = OpTypeFloat 64
+%f64_1 = OpConstant %f64 1
+%f64_ptr = OpTypePointer Workgroup %f64
+%f64_var = OpVariable %f64_ptr Workgroup
+)";
+ const std::string body = R"(
+%val1 = OpAtomicFMinEXT %f64 %f64_var %device %relaxed %f64_1
+)";
+ const std::string extra = R"(
+OpCapability Float64
+OpCapability AtomicFloat64MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra, defs), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+}
+
+TEST_F(ValidateAtomics, AtomicMaxFloat64VulkanSuccess) {
+ const std::string defs = R"(
+%f64 = OpTypeFloat 64
+%f64_1 = OpConstant %f64 1
+%f64_ptr = OpTypePointer Workgroup %f64
+%f64_var = OpVariable %f64_ptr Workgroup
+)";
+ const std::string body = R"(
+%val1 = OpAtomicFMaxEXT %f64 %f64_var %device %relaxed %f64_1
+)";
+ const std::string extra = R"(
+OpCapability Float64
+OpCapability AtomicFloat64MinMaxEXT
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra, defs), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+}
+
TEST_F(ValidateAtomics, AtomicLoadFloatVulkan) {
const std::string body = R"(
%val1 = OpAtomicLoad %f32 %f32_var %device %relaxed
@@ -396,6 +676,7 @@ TEST_F(ValidateAtomics, AtomicLoadInt64WithCapabilityVulkanSuccess) {
const std::string body = R"(
%val1 = OpAtomicLoad %u64 %u64_var %device %relaxed
%val2 = OpAtomicLoad %u64 %u64_var %workgroup %acquire
+ %val3 = OpAtomicLoad %u64 %u64_var %invocation %relaxed
)";
CompileSuccessfully(
@@ -515,6 +796,21 @@ TEST_F(ValidateAtomics, AtomicLoadVulkanSequentiallyConsistent) {
"Release, AcquireRelease and SequentiallyConsistent"));
}
+TEST_F(ValidateAtomics, AtomicLoadVulkanInvocationSemantics) {
+ const std::string body = R"(
+%val1 = OpAtomicLoad %u32 %u32_var %invocation %acquire
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04641"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("AtomicLoad: Vulkan specification requires Memory Semantics to "
+ "be None if used with Invocation Memory Scope"));
+}
+
TEST_F(ValidateAtomics, AtomicLoadShaderFloat) {
const std::string body = R"(
%val1 = OpAtomicLoad %f32 %f32_var %device %relaxed
@@ -537,6 +833,45 @@ TEST_F(ValidateAtomics, AtomicLoadVulkanInt64) {
"AtomicLoad: 64-bit atomics require the Int64Atomics capability"));
}
+TEST_F(ValidateAtomics, AtomicLoadKernelInt64) {
+ const std::string body = R"(
+%val1 = OpAtomicLoad %u64 %u64_var %device %relaxed
+)";
+
+ CompileSuccessfully(GenerateKernelCode(body));
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "AtomicLoad: 64-bit atomics require the Int64Atomics capability"));
+}
+
+TEST_F(ValidateAtomics, AtomicStoreVulkanInt64) {
+ const std::string body = R"(
+OpAtomicStore %u64_var %device %relaxed %u64_1
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "AtomicStore: 64-bit atomics require the Int64Atomics capability"));
+}
+
+TEST_F(ValidateAtomics, AtomicStoreKernelInt64) {
+ const std::string body = R"(
+OpAtomicStore %u64_var %device %relaxed %u64_1
+)";
+
+ CompileSuccessfully(GenerateKernelCode(body));
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "AtomicStore: 64-bit atomics require the Int64Atomics capability"));
+}
+
TEST_F(ValidateAtomics, VK_KHR_shader_atomic_int64Success) {
const std::string body = R"(
%val1 = OpAtomicUMin %u64 %u64_var %device %relaxed %u64_1
@@ -593,9 +928,10 @@ TEST_F(ValidateAtomics, AtomicLoadWrongResultType) {
CompileSuccessfully(GenerateKernelCode(body));
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("AtomicLoad: "
- "expected Result Type to be int or float scalar type"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("AtomicLoad: "
+ "expected Result Type to be integer or float scalar type"));
}
TEST_F(ValidateAtomics, AtomicLoadWrongPointerType) {
@@ -668,6 +1004,7 @@ OpAtomicStore %u32_var %subgroup %sequentially_consistent %u32_1
TEST_F(ValidateAtomics, AtomicStoreVulkanSuccess) {
const std::string body = R"(
OpAtomicStore %u32_var %device %release %u32_1
+OpAtomicStore %u32_var %invocation %relaxed %u32_1
)";
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
@@ -719,6 +1056,21 @@ OpAtomicStore %u32_var %device %sequentially_consistent %u32_1
"Acquire, AcquireRelease and SequentiallyConsistent"));
}
+TEST_F(ValidateAtomics, AtomicStoreVulkanInvocationSemantics) {
+ const std::string body = R"(
+OpAtomicStore %u32_var %invocation %acquire %u32_1
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04641"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("AtomicStore: Vulkan specification requires Memory Semantics "
+ "to be None if used with Invocation Memory Scope"));
+}
+
TEST_F(ValidateAtomics, AtomicStoreWrongPointerType) {
const std::string body = R"(
OpAtomicStore %f32_1 %device %relaxed %f32_1
@@ -740,9 +1092,9 @@ OpAtomicStore %f32vec4_var %device %relaxed %f32_1
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(
getDiagnosticString(),
- HasSubstr("AtomicStore: "
- "expected Pointer to be a pointer to int or float scalar "
- "type"));
+ HasSubstr(
+ "AtomicStore: "
+ "expected Pointer to be a pointer to integer or float scalar type"));
}
TEST_F(ValidateAtomics, AtomicStoreWrongPointerStorageTypeForOpenCL) {
@@ -848,9 +1200,10 @@ OpStore %f32vec4_var %f32vec4_0000
CompileSuccessfully(GenerateKernelCode(body));
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("AtomicExchange: "
- "expected Result Type to be int or float scalar type"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("AtomicExchange: "
+ "expected Result Type to be integer or float scalar type"));
}
TEST_F(ValidateAtomics, AtomicExchangeWrongPointerType) {
@@ -918,6 +1271,22 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
"expected Value to be of type Result Type"));
}
+TEST_F(ValidateAtomics, AtomicExchangeVulkanInvocationSemantics) {
+ const std::string body = R"(
+OpAtomicStore %u32_var %invocation %relaxed %u32_1
+%val2 = OpAtomicExchange %u32 %u32_var %invocation %acquire %u32_0
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04641"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("AtomicExchange: Vulkan specification requires Memory "
+ "Semantics to be None if used with Invocation Memory Scope"));
+}
+
TEST_F(ValidateAtomics, AtomicCompareExchangeShaderSuccess) {
const std::string body = R"(
OpAtomicStore %u32_var %device %relaxed %u32_1
@@ -930,10 +1299,8 @@ OpAtomicStore %u32_var %device %relaxed %u32_1
TEST_F(ValidateAtomics, AtomicCompareExchangeKernelSuccess) {
const std::string body = R"(
-OpAtomicStore %f32_var %device %relaxed %f32_1
-%val2 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %relaxed %f32_0 %f32_1
OpAtomicStore %u32_var %device %relaxed %u32_1
-%val4 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
+%val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %u32_0 %u32_0
)";
CompileSuccessfully(GenerateKernelCode(body));
@@ -950,7 +1317,7 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("AtomicCompareExchange: "
- "expected Result Type to be int scalar type"));
+ "expected Result Type to be integer scalar type"));
}
TEST_F(ValidateAtomics, AtomicCompareExchangeWrongResultType) {
@@ -963,7 +1330,7 @@ OpStore %f32vec4_var %f32vec4_0000
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("AtomicCompareExchange: "
- "expected Result Type to be int or float scalar type"));
+ "expected Result Type to be integer scalar type"));
}
TEST_F(ValidateAtomics, AtomicCompareExchangeWrongPointerType) {
@@ -981,7 +1348,7 @@ TEST_F(ValidateAtomics, AtomicCompareExchangeWrongPointerType) {
TEST_F(ValidateAtomics, AtomicCompareExchangeWrongPointerDataType) {
const std::string body = R"(
OpStore %f32vec4_var %f32vec4_0000
-%val2 = OpAtomicCompareExchange %f32 %f32vec4_var %device %relaxed %relaxed %f32_0 %f32_1
+%val2 = OpAtomicCompareExchange %u32 %f32vec4_var %device %relaxed %relaxed %u32_0 %u32_0
)";
CompileSuccessfully(GenerateKernelCode(body));
@@ -994,11 +1361,11 @@ OpStore %f32vec4_var %f32vec4_0000
TEST_F(ValidateAtomics, AtomicCompareExchangeWrongScopeType) {
const std::string body = R"(
-OpAtomicStore %f32_var %device %relaxed %f32_1
-%val2 = OpAtomicCompareExchange %f32 %f32_var %f32_1 %relaxed %relaxed %f32_0 %f32_0
+OpAtomicStore %u64_var %device %relaxed %u64_1
+%val2 = OpAtomicCompareExchange %u64 %u64_var %u64_1 %relaxed %relaxed %u32_0 %u32_0
)";
- CompileSuccessfully(GenerateKernelCode(body));
+ CompileSuccessfully(GenerateKernelCode(body, "OpCapability Int64Atomics\n"));
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("AtomicCompareExchange: expected scope to be a 32-bit "
@@ -1007,8 +1374,8 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
TEST_F(ValidateAtomics, AtomicCompareExchangeWrongMemorySemanticsType1) {
const std::string body = R"(
-OpAtomicStore %f32_var %device %relaxed %f32_1
-%val2 = OpAtomicCompareExchange %f32 %f32_var %device %f32_1 %relaxed %f32_0 %f32_0
+OpAtomicStore %u32_var %device %relaxed %u32_1
+%val2 = OpAtomicCompareExchange %u32 %u32_var %device %f32_1 %relaxed %u32_0 %u32_0
)";
CompileSuccessfully(GenerateKernelCode(body));
@@ -1020,8 +1387,8 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
TEST_F(ValidateAtomics, AtomicCompareExchangeWrongMemorySemanticsType2) {
const std::string body = R"(
-OpAtomicStore %f32_var %device %relaxed %f32_1
-%val2 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %f32_1 %f32_0 %f32_0
+OpAtomicStore %u32_var %device %relaxed %u32_1
+%val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %f32_1 %u32_0 %u32_0
)";
CompileSuccessfully(GenerateKernelCode(body));
@@ -1033,8 +1400,8 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
TEST_F(ValidateAtomics, AtomicCompareExchangeUnequalRelease) {
const std::string body = R"(
-OpAtomicStore %f32_var %device %relaxed %f32_1
-%val2 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %release %f32_0 %f32_0
+OpAtomicStore %u32_var %device %relaxed %u32_1
+%val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %release %u32_0 %u32_0
)";
CompileSuccessfully(GenerateKernelCode(body));
@@ -1046,8 +1413,8 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
TEST_F(ValidateAtomics, AtomicCompareExchangeWrongValueType) {
const std::string body = R"(
-OpAtomicStore %f32_var %device %relaxed %f32_1
-%val2 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %relaxed %u32_0 %f32_1
+OpAtomicStore %u32_var %device %relaxed %u32_1
+%val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %f32_1 %u32_0
)";
CompileSuccessfully(GenerateKernelCode(body));
@@ -1059,8 +1426,8 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
TEST_F(ValidateAtomics, AtomicCompareExchangeWrongComparatorType) {
const std::string body = R"(
-OpAtomicStore %f32_var %device %relaxed %f32_1
-%val2 = OpAtomicCompareExchange %f32 %f32_var %device %relaxed %relaxed %f32_0 %u32_1
+OpAtomicStore %u32_var %device %relaxed %u32_1
+%val2 = OpAtomicCompareExchange %u32 %u32_var %device %relaxed %relaxed %u32_0 %f32_0
)";
CompileSuccessfully(GenerateKernelCode(body));
@@ -1090,7 +1457,39 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("AtomicCompareExchangeWeak: "
- "expected Result Type to be int scalar type"));
+ "expected Result Type to be integer scalar type"));
+}
+
+TEST_F(ValidateAtomics, AtomicCompareExchangeVulkanInvocationSemanticsEqual) {
+ const std::string body = R"(
+OpAtomicStore %u32_var %device %relaxed %u32_1
+%val2 = OpAtomicCompareExchange %u32 %u32_var %invocation %release %relaxed %u32_0 %u32_0
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04641"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("AtomicCompareExchange: Vulkan specification requires Memory "
+ "Semantics to be None if used with Invocation Memory Scope"));
+}
+
+TEST_F(ValidateAtomics, AtomicCompareExchangeVulkanInvocationSemanticsUnequal) {
+ const std::string body = R"(
+OpAtomicStore %u32_var %device %relaxed %u32_1
+%val2 = OpAtomicCompareExchange %u32 %u32_var %invocation %relaxed %acquire %u32_0 %u32_0
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04641"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("AtomicCompareExchange: Vulkan specification requires Memory "
+ "Semantics to be None if used with Invocation Memory Scope"));
}
TEST_F(ValidateAtomics, AtomicArithmeticsSuccess) {
@@ -1157,7 +1556,7 @@ TEST_F(ValidateAtomics, AtomicFlagTestAndSetNotIntPointer) {
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("AtomicFlagTestAndSet: "
- "expected Pointer to point to a value of 32-bit int type"));
+ "expected Pointer to point to a value of 32-bit integer type"));
}
TEST_F(ValidateAtomics, AtomicFlagTestAndSetNotInt32Pointer) {
@@ -1165,12 +1564,12 @@ TEST_F(ValidateAtomics, AtomicFlagTestAndSetNotInt32Pointer) {
%val1 = OpAtomicFlagTestAndSet %bool %u64_var %device %relaxed
)";
- CompileSuccessfully(GenerateKernelCode(body));
+ CompileSuccessfully(GenerateKernelCode(body, "OpCapability Int64Atomics\n"));
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("AtomicFlagTestAndSet: "
- "expected Pointer to point to a value of 32-bit int type"));
+ "expected Pointer to point to a value of 32-bit integer type"));
}
TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongScopeType) {
@@ -1231,7 +1630,7 @@ OpAtomicFlagClear %f32_var %device %relaxed
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("AtomicFlagClear: "
- "expected Pointer to point to a value of 32-bit int type"));
+ "expected Pointer to point to a value of 32-bit integer type"));
}
TEST_F(ValidateAtomics, AtomicFlagClearNotInt32Pointer) {
@@ -1239,12 +1638,12 @@ TEST_F(ValidateAtomics, AtomicFlagClearNotInt32Pointer) {
OpAtomicFlagClear %u64_var %device %relaxed
)";
- CompileSuccessfully(GenerateKernelCode(body));
+ CompileSuccessfully(GenerateKernelCode(body, "OpCapability Int64Atomics\n"));
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("AtomicFlagClear: "
- "expected Pointer to point to a value of 32-bit int type"));
+ "expected Pointer to point to a value of 32-bit integer type"));
}
TEST_F(ValidateAtomics, AtomicFlagClearWrongScopeType) {
@@ -1342,7 +1741,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1361,7 +1760,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1381,7 +1780,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1401,7 +1800,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1421,7 +1820,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1441,7 +1840,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1461,7 +1860,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1480,7 +1879,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1499,7 +1898,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1518,7 +1917,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1537,7 +1936,28 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
+ SPV_ENV_UNIVERSAL_1_3);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("SequentiallyConsistent memory semantics cannot be "
+ "used with the VulkanKHR memory model."));
+}
+
+TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicFMinEXT) {
+ const std::string body = R"(
+%max = OpAtomicFMinEXT %f32 %f32_var %workgroup %sequentially_consistent %f32_0
+)";
+
+ const std::string extra = R"(
+OpCapability VulkanMemoryModelKHR
+OpCapability AtomicFloat32MinMaxEXT
+OpExtension "SPV_KHR_vulkan_memory_model"
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1556,7 +1976,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1575,7 +1995,28 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
+ SPV_ENV_UNIVERSAL_1_3);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA,
+ ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("SequentiallyConsistent memory semantics cannot be "
+ "used with the VulkanKHR memory model."));
+}
+
+TEST_F(ValidateAtomics, VulkanMemoryModelBanSequentiallyConsistentAtomicFMaxEXT) {
+ const std::string body = R"(
+%max = OpAtomicFMaxEXT %f32 %f32_var %workgroup %sequentially_consistent %f32_0
+)";
+
+ const std::string extra = R"(
+OpCapability VulkanMemoryModelKHR
+OpCapability AtomicFloat32MinMaxEXT
+OpExtension "SPV_KHR_vulkan_memory_model"
+OpExtension "SPV_EXT_shader_atomic_float_min_max"
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1594,7 +2035,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1613,7 +2054,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1632,7 +2073,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1856,7 +2297,7 @@ OpCapability VulkanMemoryModelKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_VULKAN_1_1);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
}
@@ -1984,7 +2425,7 @@ TEST_F(ValidateAtomics, VulkanMemoryModelDeviceScopeBad) {
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -2004,7 +2445,7 @@ OpCapability VulkanMemoryModelDeviceScopeKHR
OpExtension "SPV_KHR_vulkan_memory_model"
)";
- CompileSuccessfully(GenerateShaderCode(body, extra, "VulkanKHR"),
+ CompileSuccessfully(GenerateShaderCode(body, extra, "", "VulkanKHR"),
SPV_ENV_UNIVERSAL_1_3);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
}
diff --git a/test/val/val_barriers_test.cpp b/test/val/val_barriers_test.cpp
index 46f5b5a1..1178ca02 100644
--- a/test/val/val_barriers_test.cpp
+++ b/test/val/val_barriers_test.cpp
@@ -346,6 +346,8 @@ OpControlBarrier %device %workgroup %none
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04636"));
+ EXPECT_THAT(getDiagnosticString(),
HasSubstr("ControlBarrier: in Vulkan environment Execution Scope "
"is limited to Workgroup and Subgroup"));
}
@@ -388,9 +390,10 @@ OpControlBarrier %subgroup %cross_device %none
"cannot be CrossDevice"));
}
-TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeFailure) {
+TEST_F(ValidateBarriers,
+ OpControlBarrierVulkan1p1WorkgroupNonComputeMemoryFailure) {
const std::string body = R"(
-OpControlBarrier %workgroup %workgroup %acquire
+OpControlBarrier %subgroup %workgroup %acquire
)";
CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
@@ -402,7 +405,23 @@ OpControlBarrier %workgroup %workgroup %acquire
"and GLCompute execution model"));
}
-TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeSuccess) {
+TEST_F(ValidateBarriers,
+ OpControlBarrierVulkan1p1WorkgroupNonComputeExecutionFailure) {
+ const std::string body = R"(
+OpControlBarrier %workgroup %subgroup %acquire
+)";
+
+ CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
+ EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
+ EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04637"));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("in Vulkan environment, Workgroup execution scope is "
+ "only for TaskNV, MeshNV, TessellationControl, and "
+ "GLCompute execution models"));
+}
+
+TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupComputeSuccess) {
const std::string body = R"(
OpControlBarrier %workgroup %workgroup %acquire
)";
@@ -411,6 +430,39 @@ OpControlBarrier %workgroup %workgroup %acquire
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
}
+TEST_F(ValidateBarriers, OpControlBarrierVulkan1p1WorkgroupNonComputeSuccess) {
+ const std::string body = R"(
+OpControlBarrier %subgroup %subgroup %acquire
+)";
+
+ CompileSuccessfully(GenerateVulkanVertexShaderCode(body), SPV_ENV_VULKAN_1_1);
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
+}
+
+TEST_F(ValidateBarriers, OpControlBarrierVulkanInvocationSuccess) {
+ const std::string body = R"(
+OpControlBarrier %workgroup %invocation %none
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+}
+
+TEST_F(ValidateBarriers, OpControlBarrierVulkanInvocationFailure) {
+ const std::string body = R"(
+OpControlBarrier %workgroup %invocation %acquire
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04641"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("ControlBarrier: Vulkan specification requires Memory "
+ "Semantics to be None if used with Invocation Memory Scope"));
+}
+
TEST_F(ValidateBarriers, OpControlBarrierAcquireAndRelease) {
const std::string body = R"(
OpControlBarrier %device %device %acquire_and_release_uniform
@@ -459,9 +511,13 @@ OpControlBarrier %workgroup %workgroup %acquire_release
SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
- HasSubstr("OpControlBarrier execution scope must be Subgroup for "
- "Fragment, Vertex, Geometry and TessellationEvaluation "
- "execution models"));
+ AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "OpControlBarrier execution scope must be Subgroup for Fragment, "
+ "Vertex, Geometry, TessellationEvaluation, RayGeneration, "
+ "Intersection, AnyHit, ClosestHit, and Miss execution models"));
}
TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionFragment1p0) {
@@ -497,9 +553,13 @@ OpControlBarrier %workgroup %workgroup %acquire_release
SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
- HasSubstr("OpControlBarrier execution scope must be Subgroup for "
- "Fragment, Vertex, Geometry and TessellationEvaluation "
- "execution models"));
+ AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "OpControlBarrier execution scope must be Subgroup for Fragment, "
+ "Vertex, Geometry, TessellationEvaluation, RayGeneration, "
+ "Intersection, AnyHit, ClosestHit, and Miss execution models"));
}
TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionVertex1p0) {
@@ -537,9 +597,13 @@ OpControlBarrier %workgroup %workgroup %acquire_release
SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
- HasSubstr("OpControlBarrier execution scope must be Subgroup for "
- "Fragment, Vertex, Geometry and TessellationEvaluation "
- "execution models"));
+ AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "OpControlBarrier execution scope must be Subgroup for Fragment, "
+ "Vertex, Geometry, TessellationEvaluation, RayGeneration, "
+ "Intersection, AnyHit, ClosestHit, and Miss execution models"));
}
TEST_F(ValidateBarriers, OpControlBarrierSubgroupExecutionGeometry1p0) {
@@ -580,9 +644,13 @@ OpControlBarrier %workgroup %workgroup %acquire_release
SPV_ENV_VULKAN_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
- HasSubstr("OpControlBarrier execution scope must be Subgroup for "
- "Fragment, Vertex, Geometry and TessellationEvaluation "
- "execution models"));
+ AnyVUID("VUID-StandaloneSpirv-OpControlBarrier-04682"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "OpControlBarrier execution scope must be Subgroup for Fragment, "
+ "Vertex, Geometry, TessellationEvaluation, RayGeneration, "
+ "Intersection, AnyHit, ClosestHit, and Miss execution models"));
}
TEST_F(ValidateBarriers,
@@ -1464,6 +1532,8 @@ TEST_F(ValidateBarriers, OpControlBarrierShaderCallRayGenFailure) {
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04636"));
+ EXPECT_THAT(getDiagnosticString(),
HasSubstr("in Vulkan environment Execution Scope is limited to "
"Workgroup and Subgroup"));
}
diff --git a/test/val/val_builtins_test.cpp b/test/val/val_builtins_test.cpp
index bbcdbb11..2116fff2 100644
--- a/test/val/val_builtins_test.cpp
+++ b/test/val/val_builtins_test.cpp
@@ -3658,23 +3658,25 @@ OpFunctionEnd
INSTANTIATE_TEST_SUITE_P(
SubgroupInvocationIdAndSizeNotU32, ValidateVulkanSubgroupBuiltIns,
- Combine(Values("SubgroupLocalInvocationId", "SubgroupSize"),
- Values("GLCompute"), Values("Input"), Values("%f32"),
- Values("VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-"
- "04381 VUID-SubgroupSize-SubgroupSize-04383"),
- Values(TestResult(SPV_ERROR_INVALID_DATA,
- "needs to be a 32-bit int"))));
+ Combine(
+ Values("SubgroupLocalInvocationId", "SubgroupSize"),
+ Values("GLCompute"), Values("Input"), Values("%f32"),
+ Values("VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04381 "
+ "VUID-SubgroupSize-SubgroupSize-04383"),
+ Values(TestResult(SPV_ERROR_INVALID_DATA,
+ "needs to be a 32-bit int"))));
INSTANTIATE_TEST_SUITE_P(
SubgroupInvocationIdAndSizeNotInput, ValidateVulkanSubgroupBuiltIns,
- Combine(Values("SubgroupLocalInvocationId", "SubgroupSize"),
- Values("GLCompute"), Values("Output", "Workgroup", "Private"),
- Values("%u32"),
- Values("VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-"
- "04380 VUID-SubgroupSize-SubgroupSize-04382"),
- Values(TestResult(
- SPV_ERROR_INVALID_DATA,
- "to be only used for variables with Input storage class"))));
+ Combine(
+ Values("SubgroupLocalInvocationId", "SubgroupSize"),
+ Values("GLCompute"), Values("Output", "Workgroup", "Private"),
+ Values("%u32"),
+ Values("VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04380 "
+ "VUID-SubgroupSize-SubgroupSize-04382"),
+ Values(TestResult(
+ SPV_ERROR_INVALID_DATA,
+ "to be only used for variables with Input storage class"))));
INSTANTIATE_TEST_SUITE_P(
SubgroupInvocationIdAndSizeOk, ValidateVulkanSubgroupBuiltIns,
diff --git a/test/val/val_cfg_test.cpp b/test/val/val_cfg_test.cpp
index 9698fb1c..9715a5a2 100644
--- a/test/val/val_cfg_test.cpp
+++ b/test/val/val_cfg_test.cpp
@@ -3520,7 +3520,10 @@ OpFunctionEnd
CompileSuccessfully(text);
EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(), HasSubstr("Selection must be structured"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "OpSwitch must be preceeded by an OpSelectionMerge instruction"));
}
TEST_F(ValidateCFG, MissingMergeSwitchBad2) {
@@ -3544,7 +3547,10 @@ OpFunctionEnd
CompileSuccessfully(text);
EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(), HasSubstr("Selection must be structured"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "OpSwitch must be preceeded by an OpSelectionMerge instruction"));
}
TEST_F(ValidateCFG, MissingMergeOneBranchToMergeGood) {
@@ -3594,7 +3600,7 @@ OpFunctionEnd
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
}
-TEST_F(ValidateCFG, MissingMergeOneTargetSwitchGood) {
+TEST_F(ValidateCFG, MissingMergeOneTargetSwitchBad) {
const std::string text = R"(
OpCapability Shader
OpCapability Linkage
@@ -3612,10 +3618,14 @@ OpFunctionEnd
)";
CompileSuccessfully(text);
- EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+ EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "OpSwitch must be preceeded by an OpSelectionMerge instruction"));
}
-TEST_F(ValidateCFG, MissingMergeOneUnseenTargetSwitchGood) {
+TEST_F(ValidateCFG, MissingMergeOneUnseenTargetSwitchBad) {
const std::string text = R"(
OpCapability Shader
OpCapability Linkage
@@ -3640,7 +3650,11 @@ OpFunctionEnd
)";
CompileSuccessfully(text);
- EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+ EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "OpSwitch must be preceeded by an OpSelectionMerge instruction"));
}
TEST_F(ValidateCFG, MissingMergeLoopBreakGood) {
diff --git a/test/val/val_decoration_test.cpp b/test/val/val_decoration_test.cpp
index cbf6d7c1..096fd172 100644
--- a/test/val/val_decoration_test.cpp
+++ b/test/val/val_decoration_test.cpp
@@ -4992,6 +4992,8 @@ TEST_F(ValidateDecorations, UniformDecorationWithScopeIdV14VulkanEnv) {
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04636"));
+ EXPECT_THAT(getDiagnosticString(),
HasSubstr(": in Vulkan environment Execution Scope is limited to "
"Workgroup and Subgroup"));
}
diff --git a/test/val/val_ext_inst_test.cpp b/test/val/val_ext_inst_test.cpp
index 683a76f5..b73ec341 100644
--- a/test/val/val_ext_inst_test.cpp
+++ b/test/val/val_ext_inst_test.cpp
@@ -5204,6 +5204,49 @@ TEST_F(ValidateExtInst, GlslStd450InterpolateAtCentroidSuccess) {
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
}
+TEST_F(ValidateExtInst, GlslStd450InterpolateAtCentroidInternalSuccess) {
+ const std::string body = R"(
+%ld1 = OpLoad %f32 %f32_input
+%val1 = OpExtInst %f32 %extinst InterpolateAtCentroid %ld1
+%ld2 = OpLoad %f32vec2 %f32vec2_input
+%val2 = OpExtInst %f32vec2 %extinst InterpolateAtCentroid %ld2
+)";
+
+ CompileSuccessfully(
+ GenerateShaderCode(body, "OpCapability InterpolationFunction\n"));
+ getValidatorOptions()->before_hlsl_legalization = true;
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateExtInst, GlslStd450InterpolateAtCentroidInternalInvalidDataF32) {
+ const std::string body = R"(
+%ld1 = OpLoad %f32 %f32_input
+%val1 = OpExtInst %f32 %extinst InterpolateAtCentroid %ld1
+)";
+
+ CompileSuccessfully(
+ GenerateShaderCode(body, "OpCapability InterpolationFunction\n"));
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("GLSL.std.450 InterpolateAtCentroid: "
+ "expected Interpolant to be a pointer"));
+}
+
+TEST_F(ValidateExtInst,
+ GlslStd450InterpolateAtCentroidInternalInvalidDataF32Vec2) {
+ const std::string body = R"(
+%ld2 = OpLoad %f32vec2 %f32vec2_input
+%val2 = OpExtInst %f32vec2 %extinst InterpolateAtCentroid %ld2
+)";
+
+ CompileSuccessfully(
+ GenerateShaderCode(body, "OpCapability InterpolationFunction\n"));
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("GLSL.std.450 InterpolateAtCentroid: "
+ "expected Interpolant to be a pointer"));
+}
+
TEST_F(ValidateExtInst, GlslStd450InterpolateAtCentroidNoCapability) {
const std::string body = R"(
%val1 = OpExtInst %f32 %extinst InterpolateAtCentroid %f32_input
@@ -5308,6 +5351,49 @@ TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleSuccess) {
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
}
+TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleInternalSuccess) {
+ const std::string body = R"(
+%ld1 = OpLoad %f32 %f32_input
+%val1 = OpExtInst %f32 %extinst InterpolateAtSample %ld1 %u32_1
+%ld2 = OpLoad %f32vec2 %f32vec2_input
+%val2 = OpExtInst %f32vec2 %extinst InterpolateAtSample %ld2 %u32_1
+)";
+
+ CompileSuccessfully(
+ GenerateShaderCode(body, "OpCapability InterpolationFunction\n"));
+ getValidatorOptions()->before_hlsl_legalization = true;
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleInternalInvalidDataF32) {
+ const std::string body = R"(
+%ld1 = OpLoad %f32 %f32_input
+%val1 = OpExtInst %f32 %extinst InterpolateAtSample %ld1 %u32_1
+)";
+
+ CompileSuccessfully(
+ GenerateShaderCode(body, "OpCapability InterpolationFunction\n"));
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("GLSL.std.450 InterpolateAtSample: "
+ "expected Interpolant to be a pointer"));
+}
+
+TEST_F(ValidateExtInst,
+ GlslStd450InterpolateAtSampleInternalInvalidDataF32Vec2) {
+ const std::string body = R"(
+%ld2 = OpLoad %f32vec2 %f32vec2_input
+%val2 = OpExtInst %f32vec2 %extinst InterpolateAtSample %ld2 %u32_1
+)";
+
+ CompileSuccessfully(
+ GenerateShaderCode(body, "OpCapability InterpolationFunction\n"));
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("GLSL.std.450 InterpolateAtSample: "
+ "expected Interpolant to be a pointer"));
+}
+
TEST_F(ValidateExtInst, GlslStd450InterpolateAtSampleNoCapability) {
const std::string body = R"(
%val1 = OpExtInst %f32 %extinst InterpolateAtSample %f32_input %u32_1
@@ -5438,6 +5524,48 @@ TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetSuccess) {
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
}
+TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetInternalSuccess) {
+ const std::string body = R"(
+%ld1 = OpLoad %f32 %f32_input
+%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %ld1 %f32vec2_01
+%ld2 = OpLoad %f32vec2 %f32vec2_input
+%val2 = OpExtInst %f32vec2 %extinst InterpolateAtOffset %ld2 %f32vec2_01
+)";
+
+ CompileSuccessfully(
+ GenerateShaderCode(body, "OpCapability InterpolationFunction\n"));
+ getValidatorOptions()->before_hlsl_legalization = true;
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetInternalInvalidDataF32) {
+ const std::string body = R"(
+%ld1 = OpLoad %f32 %f32_input
+%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %ld1 %f32vec2_01
+)";
+
+ CompileSuccessfully(
+ GenerateShaderCode(body, "OpCapability InterpolationFunction\n"));
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("GLSL.std.450 InterpolateAtOffset: "
+ "expected Interpolant to be a pointer"));
+}
+
+TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetInternalInvalidDataF32Vec2) {
+ const std::string body = R"(
+%ld2 = OpLoad %f32vec2 %f32vec2_input
+%val2 = OpExtInst %f32vec2 %extinst InterpolateAtOffset %ld2 %f32vec2_01
+)";
+
+ CompileSuccessfully(
+ GenerateShaderCode(body, "OpCapability InterpolationFunction\n"));
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("GLSL.std.450 InterpolateAtOffset: "
+ "expected Interpolant to be a pointer"));
+}
+
TEST_F(ValidateExtInst, GlslStd450InterpolateAtOffsetNoCapability) {
const std::string body = R"(
%val1 = OpExtInst %f32 %extinst InterpolateAtOffset %f32_input %f32vec2_01
diff --git a/test/val/val_extension_spv_khr_expect_assume.cpp b/test/val/val_extension_spv_khr_expect_assume.cpp
new file mode 100644
index 00000000..6ece15d1
--- /dev/null
+++ b/test/val/val_extension_spv_khr_expect_assume.cpp
@@ -0,0 +1,310 @@
+// Copyright (c) 2020 Google Inc.
+//
+// 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.
+
+// Tests for OpExtension validator rules.
+
+#include <string>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "source/enum_string_mapping.h"
+#include "source/extensions.h"
+#include "source/spirv_target_env.h"
+#include "test/test_fixture.h"
+#include "test/unit_spirv.h"
+#include "test/val/val_fixtures.h"
+
+namespace spvtools {
+namespace val {
+namespace {
+
+using ::testing::HasSubstr;
+using ::testing::Values;
+using ::testing::ValuesIn;
+
+using ValidateSpvExpectAssumeKHR = spvtest::ValidateBase<bool>;
+
+TEST_F(ValidateSpvExpectAssumeKHR, Valid) {
+ const std::string str = R"(
+ OpCapability Kernel
+ OpCapability Addresses
+ OpCapability Linkage
+ OpCapability ExpectAssumeKHR
+ OpExtension "SPV_KHR_expect_assume"
+ OpMemoryModel Physical32 OpenCL
+
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+
+ %bool = OpTypeBool
+ %true = OpConstantTrue %bool
+ %undef = OpUndef %bool
+
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+
+ %v2bool = OpTypeVector %bool 2
+ %v2uint = OpTypeVector %uint 2
+
+ %null_v2bool = OpConstantNull %v2bool
+ %null_v2uint = OpConstantNull %v2uint
+
+ %main = OpFunction %void None %voidfn
+ %entry = OpLabel
+ OpAssumeTrueKHR %true
+ OpAssumeTrueKHR %undef ; probably undefined behaviour
+ %bool_val = OpExpectKHR %bool %true %true
+ %uint_val = OpExpectKHR %uint %uint_1 %uint_2 ; a bad expectation
+ %v2bool_val = OpExpectKHR %v2bool %null_v2bool %null_v2bool
+ %v2uint_val = OpExpectKHR %v2uint %null_v2uint %null_v2uint
+ OpReturn
+ OpFunctionEnd
+
+)";
+ CompileSuccessfully(str.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateSpvExpectAssumeKHR, RequiresExtension) {
+ const std::string str = R"(
+ OpCapability Kernel
+ OpCapability Addresses
+ OpCapability Linkage
+ OpCapability ExpectAssumeKHR
+ OpMemoryModel Physical32 OpenCL
+
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+
+ %bool = OpTypeBool
+ %true = OpConstantTrue %bool
+ %undef = OpUndef %bool
+
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+
+ %main = OpFunction %void None %voidfn
+ %entry = OpLabel
+ OpAssumeTrueKHR %true
+ OpAssumeTrueKHR %undef ; probably undefined behaviour
+ %val = OpExpectKHR %uint %uint_1 %uint_2 ; a bad expectation
+ OpReturn
+ OpFunctionEnd
+
+)";
+ CompileSuccessfully(str.c_str());
+ EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Capability: operand ExpectAssumeKHR(5629) requires "
+ "one of these extensions: SPV_KHR_expect_assume"));
+}
+
+TEST_F(ValidateSpvExpectAssumeKHR,
+ AssumeTrueKHR_RequiresExpectAssumeCapability) {
+ const std::string str = R"(
+ OpCapability Kernel
+ OpCapability Addresses
+ OpCapability Linkage
+ OpExtension "SPV_KHR_expect_assume"
+ OpMemoryModel Physical32 OpenCL
+
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+
+ %bool = OpTypeBool
+ %true = OpConstantTrue %bool
+ %undef = OpUndef %bool
+
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+
+ %main = OpFunction %void None %voidfn
+ %entry = OpLabel
+ OpAssumeTrueKHR %true
+ OpAssumeTrueKHR %undef ; probably undefined behaviour
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(str.c_str());
+ EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Opcode AssumeTrueKHR requires one of these "
+ "capabilities: ExpectAssumeKHR \n"
+ " OpAssumeTrueKHR %true\n"));
+}
+
+TEST_F(ValidateSpvExpectAssumeKHR, AssumeTrueKHR_OperandMustBeBool) {
+ const std::string str = R"(
+ OpCapability Kernel
+ OpCapability Addresses
+ OpCapability Linkage
+ OpCapability ExpectAssumeKHR
+ OpExtension "SPV_KHR_expect_assume"
+ OpMemoryModel Physical32 OpenCL
+
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+
+ %bool = OpTypeBool
+ %true = OpConstantTrue %bool
+ %undef = OpUndef %bool
+
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+
+ %main = OpFunction %void None %voidfn
+ %entry = OpLabel
+ OpAssumeTrueKHR %uint_1 ; bad type
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(str.c_str());
+ EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Value operand of OpAssumeTrueKHR must be a boolean scalar\n"
+ " OpAssumeTrueKHR %uint_1\n"));
+}
+
+TEST_F(ValidateSpvExpectAssumeKHR, ExpectKHR_RequiresExpectAssumeCapability) {
+ const std::string str = R"(
+ OpCapability Kernel
+ OpCapability Addresses
+ OpCapability Linkage
+ OpExtension "SPV_KHR_expect_assume"
+ OpMemoryModel Physical32 OpenCL
+
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+
+ %bool = OpTypeBool
+ %true = OpConstantTrue %bool
+ %undef = OpUndef %bool
+
+ %uint = OpTypeInt 32 0
+ %uint_1 = OpConstant %uint 1
+ %uint_2 = OpConstant %uint 2
+
+ %main = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %val = OpExpectKHR %uint %uint_1 %uint_2 ; a bad expectation
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(str.c_str());
+ EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Opcode ExpectKHR requires one of these capabilities: "
+ "ExpectAssumeKHR \n"
+ " %11 = OpExpectKHR %uint %uint_1 %uint_2\n"));
+}
+
+TEST_F(ValidateSpvExpectAssumeKHR, ExpectKHR_ResultMustBeBoolOrIntScalar) {
+ const std::string str = R"(
+ OpCapability Kernel
+ OpCapability Addresses
+ OpCapability Linkage
+ OpCapability ExpectAssumeKHR
+ OpExtension "SPV_KHR_expect_assume"
+ OpMemoryModel Physical32 OpenCL
+
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+
+ %float = OpTypeFloat 32
+
+ %float_0 = OpConstant %float 0
+
+ %main = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %val = OpExpectKHR %float %float_0 %float_0
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(str.c_str());
+ EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Result of OpExpectKHR must be a scalar or vector of "
+ "integer type or boolean type\n"
+ " %7 = OpExpectKHR %float %float_0 %float_0\n"));
+}
+
+TEST_F(ValidateSpvExpectAssumeKHR, ExpectKHR_Value0MustMatchResultType) {
+ const std::string str = R"(
+ OpCapability Kernel
+ OpCapability Addresses
+ OpCapability Linkage
+ OpCapability ExpectAssumeKHR
+ OpExtension "SPV_KHR_expect_assume"
+ OpMemoryModel Physical32 OpenCL
+
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+
+ %uint = OpTypeInt 32 0
+ %float = OpTypeFloat 32
+ %float_0 = OpConstant %float 0
+
+ %main = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %val = OpExpectKHR %uint %float_0 %float_0
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(str.c_str());
+ EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Type of Value operand of OpExpectKHR does not match "
+ "the result type \n"
+ " %8 = OpExpectKHR %uint %float_0 %float_0\n"));
+}
+
+TEST_F(ValidateSpvExpectAssumeKHR, ExpectKHR_Value1MustMatchResultType) {
+ const std::string str = R"(
+ OpCapability Kernel
+ OpCapability Addresses
+ OpCapability Linkage
+ OpCapability ExpectAssumeKHR
+ OpExtension "SPV_KHR_expect_assume"
+ OpMemoryModel Physical32 OpenCL
+
+ %void = OpTypeVoid
+ %voidfn = OpTypeFunction %void
+
+ %uint = OpTypeInt 32 0
+ %uint_0 = OpConstant %uint 0
+ %float = OpTypeFloat 32
+ %float_0 = OpConstant %float 0
+
+ %main = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %val = OpExpectKHR %uint %uint_0 %float_0
+ OpReturn
+ OpFunctionEnd
+)";
+ CompileSuccessfully(str.c_str());
+ EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Type of ExpectedValue operand of OpExpectKHR does not "
+ "match the result type \n"
+ " %9 = OpExpectKHR %uint %uint_0 %float_0\n"));
+}
+
+} // namespace
+} // namespace val
+} // namespace spvtools
diff --git a/test/val/val_extension_spv_khr_linkonce_odr.cpp b/test/val/val_extension_spv_khr_linkonce_odr.cpp
new file mode 100644
index 00000000..ac15558b
--- /dev/null
+++ b/test/val/val_extension_spv_khr_linkonce_odr.cpp
@@ -0,0 +1,100 @@
+// Copyright (c) 2020 Google Inc.
+//
+// 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.
+
+// Tests for OpExtension validator rules.
+
+#include <string>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "source/enum_string_mapping.h"
+#include "source/extensions.h"
+#include "source/spirv_target_env.h"
+#include "test/test_fixture.h"
+#include "test/unit_spirv.h"
+#include "test/val/val_fixtures.h"
+
+namespace spvtools {
+namespace val {
+namespace {
+
+using ::testing::HasSubstr;
+using ::testing::Values;
+using ::testing::ValuesIn;
+
+using ValidateSpvKHRLinkOnceODR = spvtest::ValidateBase<bool>;
+
+TEST_F(ValidateSpvKHRLinkOnceODR, Valid) {
+ const std::string str = R"(
+ OpCapability Kernel
+ OpCapability Addresses
+ OpCapability Linkage
+ OpExtension "SPV_KHR_linkonce_odr"
+ OpMemoryModel Physical32 OpenCL
+ OpDecorate %var LinkageAttributes "foobar" LinkOnceODR
+
+ %uint = OpTypeInt 32 0
+ %ptr = OpTypePointer CrossWorkgroup %uint
+ %var = OpVariable %ptr CrossWorkgroup
+
+)";
+ CompileSuccessfully(str.c_str());
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateSpvKHRLinkOnceODR, RequiresExtension) {
+ const std::string str = R"(
+ OpCapability Kernel
+ OpCapability Addresses
+ OpCapability Linkage
+ OpMemoryModel Physical32 OpenCL
+ OpDecorate %var LinkageAttributes "foobar" LinkOnceODR
+
+ %uint = OpTypeInt 32 0
+ %ptr = OpTypePointer CrossWorkgroup %uint
+ %var = OpVariable %ptr CrossWorkgroup
+)";
+ CompileSuccessfully(str.c_str());
+ EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("4th operand of Decorate: operand LinkOnceODR(2) requires one "
+ "of these extensions: SPV_KHR_linkonce_odr \n"
+ " OpDecorate %1 LinkageAttributes \"foobar\" LinkOnceODR\n"));
+}
+
+TEST_F(ValidateSpvKHRLinkOnceODR, RequiresLinkageCapability) {
+ const std::string str = R"(
+ OpCapability Kernel
+ OpCapability Addresses
+ OpExtension "SPV_KHR_linkonce_odr"
+ OpMemoryModel Physical32 OpenCL
+ OpDecorate %var LinkageAttributes "foobar" LinkOnceODR
+
+ %uint = OpTypeInt 32 0
+ %ptr = OpTypePointer CrossWorkgroup %uint
+ %var = OpVariable %ptr CrossWorkgroup
+)";
+ CompileSuccessfully(str.c_str());
+ EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "Operand 2 of Decorate requires one of these capabilities: Linkage \n"
+ " OpDecorate %1 LinkageAttributes \"foobar\" LinkOnceODR"));
+}
+
+} // namespace
+} // namespace val
+} // namespace spvtools
diff --git a/test/val/val_id_test.cpp b/test/val/val_id_test.cpp
index c65d1715..dd4c952c 100644
--- a/test/val/val_id_test.cpp
+++ b/test/val/val_id_test.cpp
@@ -835,7 +835,7 @@ class OpTypeArrayLengthTest
position_(spv_position_t{0, 0, 0}),
diagnostic_(spvDiagnosticCreate(&position_, "")) {}
- ~OpTypeArrayLengthTest() { spvDiagnosticDestroy(diagnostic_); }
+ ~OpTypeArrayLengthTest() override { spvDiagnosticDestroy(diagnostic_); }
// Runs spvValidate() on v, printing any errors via spvDiagnosticPrint().
spv_result_t Val(const SpirvVector& v, const std::string& expected_err = "") {
@@ -1056,6 +1056,8 @@ TEST_F(ValidateIdWithMessage, OpTypeStructOpaqueTypeBad) {
CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04667"));
+ EXPECT_THAT(getDiagnosticString(),
HasSubstr("OpTypeStruct must not contain an opaque type"));
}
diff --git a/test/val/val_image_test.cpp b/test/val/val_image_test.cpp
index 6a0333cd..1d3b1a7d 100644
--- a/test/val/val_image_test.cpp
+++ b/test/val/val_image_test.cpp
@@ -5815,6 +5815,11 @@ static const std::string capabilities_and_extensions_image64 = R"(
OpCapability Int64ImageEXT
OpExtension "SPV_EXT_shader_image_int64"
)";
+static const std::string capabilities_and_extensions_image64_atomic = R"(
+OpCapability Int64Atomics
+OpCapability Int64ImageEXT
+OpExtension "SPV_EXT_shader_image_int64"
+)";
static const std::string declarations_image64 = R"(
%type_image_u64_buffer_0002_r64ui = OpTypeImage %u64 Buffer 0 0 0 2 R64ui
%ptr_Image_u64 = OpTypePointer Image %u64
@@ -5854,11 +5859,11 @@ TEST_F(ValidateImage, ImageTexelPointer64Success) {
%sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
)";
- CompileSuccessfully(GenerateShaderCode(body,
- capabilities_and_extensions_image64,
- "Fragment", "", SPV_ENV_UNIVERSAL_1_3,
- "GLSL450", declarations_image64)
- .c_str());
+ CompileSuccessfully(
+ GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
+ "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
+ declarations_image64)
+ .c_str());
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
}
@@ -5868,11 +5873,11 @@ TEST_F(ValidateImage, ImageTexelPointer64ResultTypeNotPointer) {
%sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
)";
- CompileSuccessfully(GenerateShaderCode(body,
- capabilities_and_extensions_image64,
- "Fragment", "", SPV_ENV_UNIVERSAL_1_3,
- "GLSL450", declarations_image64)
- .c_str());
+ CompileSuccessfully(
+ GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
+ "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
+ declarations_image64)
+ .c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Expected Result Type to be OpTypePointer"));
@@ -5884,11 +5889,11 @@ TEST_F(ValidateImage, ImageTexelPointer64ResultTypeNotImageClass) {
%sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
)";
- CompileSuccessfully(GenerateShaderCode(body,
- capabilities_and_extensions_image64,
- "Fragment", "", SPV_ENV_UNIVERSAL_1_3,
- "GLSL450", declarations_image64)
- .c_str());
+ CompileSuccessfully(
+ GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
+ "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
+ declarations_image64)
+ .c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Expected Result Type to be OpTypePointer whose "
@@ -5901,11 +5906,11 @@ TEST_F(ValidateImage, ImageTexelPointer64SampleNotZeroForImageWithMSZero) {
%sum = OpAtomicIAdd %u64 %texel_ptr %u32_1 %u32_0 %u64_1
)";
- CompileSuccessfully(GenerateShaderCode(body,
- capabilities_and_extensions_image64,
- "Fragment", "", SPV_ENV_UNIVERSAL_1_3,
- "GLSL450", declarations_image64)
- .c_str());
+ CompileSuccessfully(
+ GenerateShaderCode(body, capabilities_and_extensions_image64_atomic,
+ "Fragment", "", SPV_ENV_UNIVERSAL_1_3, "GLSL450",
+ declarations_image64)
+ .c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Expected Sample for Image with MS 0 to be a valid "
diff --git a/test/val/val_limits_test.cpp b/test/val/val_limits_test.cpp
index 0ef61e21..8fb80a46 100644
--- a/test/val/val_limits_test.cpp
+++ b/test/val/val_limits_test.cpp
@@ -212,6 +212,7 @@ TEST_F(ValidateLimits, SwitchNumBranchesGood) {
%5 = OpFunction %1 None %2
%7 = OpLabel
%8 = OpIAdd %3 %4 %4
+ OpSelectionMerge %10 None
OpSwitch %4 %10)";
// Now add the (literal, label) pairs
@@ -240,6 +241,7 @@ TEST_F(ValidateLimits, SwitchNumBranchesBad) {
%5 = OpFunction %1 None %2
%7 = OpLabel
%8 = OpIAdd %3 %4 %4
+ OpSelectionMerge %10 None
OpSwitch %4 %10)";
// Now add the (literal, label) pairs
@@ -271,6 +273,7 @@ TEST_F(ValidateLimits, CustomizedSwitchNumBranchesGood) {
%5 = OpFunction %1 None %2
%7 = OpLabel
%8 = OpIAdd %3 %4 %4
+ OpSelectionMerge %10 None
OpSwitch %4 %10)";
// Now add the (literal, label) pairs
@@ -301,6 +304,7 @@ TEST_F(ValidateLimits, CustomizedSwitchNumBranchesBad) {
%5 = OpFunction %1 None %2
%7 = OpLabel
%8 = OpIAdd %3 %4 %4
+ OpSelectionMerge %10 None
OpSwitch %4 %10)";
// Now add the (literal, label) pairs
diff --git a/test/val/val_misc_test.cpp b/test/val/val_misc_test.cpp
index 499b5b28..b0e46bf9 100644
--- a/test/val/val_misc_test.cpp
+++ b/test/val/val_misc_test.cpp
@@ -273,6 +273,30 @@ TEST_F(ValidateMisc, UndefVoid) {
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Cannot create undefined values with void type"));
}
+
+TEST_F(ValidateMisc, VulkanInvalidStorageClass) {
+ const std::string spirv = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Vertex %func "shader"
+%int = OpTypeInt 32 0
+%ptr = OpTypePointer CrossWorkgroup %int
+%var = OpVariable %ptr CrossWorkgroup
+%void = OpTypeVoid
+%void_f = OpTypeFunction %void
+%func = OpFunction %void None %void_f
+%label = OpLabel
+ OpReturn
+ OpFunctionEnd
+)";
+
+ CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
+ ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_VULKAN_1_0));
+ EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04643"));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Invalid storage class for target environment"));
+}
} // namespace
} // namespace val
} // namespace spvtools
diff --git a/test/val/val_state_test.cpp b/test/val/val_state_test.cpp
index b2d26045..65cb1c3a 100644
--- a/test/val/val_state_test.cpp
+++ b/test/val/val_state_test.cpp
@@ -43,7 +43,7 @@ class ValidationStateTest : public testing::Test {
options_(spvValidatorOptionsCreate()),
state_(context_, options_, kFakeBinary, 0, 1) {}
- ~ValidationStateTest() {
+ ~ValidationStateTest() override {
spvContextDestroy(context_);
spvValidatorOptionsDestroy(options_);
}
diff --git a/test/val/val_validation_state_test.cpp b/test/val/val_validation_state_test.cpp
index 7a38d3a1..3dd9e64a 100644
--- a/test/val/val_validation_state_test.cpp
+++ b/test/val/val_validation_state_test.cpp
@@ -257,6 +257,8 @@ TEST_F(ValidationStateTest, CheckVulkanDirectlyRecursiveBodyBad) {
EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04634"));
+ EXPECT_THAT(getDiagnosticString(),
HasSubstr("Entry points may not have a call graph with cycles.\n "
" %1 = OpFunction %void Pure|Const %3\n"));
}
@@ -274,6 +276,8 @@ TEST_F(ValidationStateTest, CheckVulkanIndirectlyRecursiveBodyBad) {
EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
EXPECT_THAT(getDiagnosticString(),
+ AnyVUID("VUID-StandaloneSpirv-None-04634"));
+ EXPECT_THAT(getDiagnosticString(),
HasSubstr("Entry points may not have a call graph with cycles.\n "
" %1 = OpFunction %void Pure|Const %3\n"));
}
diff --git a/tools/as/as.cpp b/tools/as/as.cpp
index f6e96294..c8a44456 100644
--- a/tools/as/as.cpp
+++ b/tools/as/as.cpp
@@ -129,7 +129,7 @@ int main(int argc, char** argv) {
}
std::vector<char> contents;
- if (!ReadFile<char>(inFile, "r", &contents)) return 1;
+ if (!ReadTextFile<char>(inFile, &contents)) return 1;
spv_binary binary;
spv_diagnostic diagnostic = nullptr;
diff --git a/tools/cfg/cfg.cpp b/tools/cfg/cfg.cpp
index ce7f1c22..a93488d5 100644
--- a/tools/cfg/cfg.cpp
+++ b/tools/cfg/cfg.cpp
@@ -104,7 +104,7 @@ int main(int argc, char** argv) {
// Read the input binary.
std::vector<uint32_t> contents;
- if (!ReadFile<uint32_t>(inFile, "rb", &contents)) return 1;
+ if (!ReadBinaryFile<uint32_t>(inFile, &contents)) return 1;
spv_context context = spvContextCreate(kDefaultEnvironment);
spv_diagnostic diagnostic = nullptr;
diff --git a/tools/dis/dis.cpp b/tools/dis/dis.cpp
index bdeeef11..64380db0 100644
--- a/tools/dis/dis.cpp
+++ b/tools/dis/dis.cpp
@@ -180,7 +180,7 @@ int main(int argc, char** argv) {
// Read the input binary.
std::vector<uint32_t> contents;
- if (!ReadFile<uint32_t>(inFile, "rb", &contents)) return 1;
+ if (!ReadBinaryFile<uint32_t>(inFile, &contents)) return 1;
// If printing to standard output, then spvBinaryToText should
// do the printing. In particular, colour printing on Windows is
diff --git a/tools/fuzz/fuzz.cpp b/tools/fuzz/fuzz.cpp
index 5ee0fb18..422bea53 100644
--- a/tools/fuzz/fuzz.cpp
+++ b/tools/fuzz/fuzz.cpp
@@ -39,6 +39,8 @@
namespace {
+enum class FuzzingTarget { kSpirv, kWgsl };
+
// Check that the std::system function can actually be used.
bool CheckExecuteCommand() {
int res = std::system(nullptr);
@@ -141,6 +143,12 @@ Options (in lexicographical order):
that was used previously.
- simple: each time a fuzzer pass is requested, one is provided
at random from the set of enabled passes.
+ --fuzzing-target=
+ This option will adjust probabilities of applying certain
+ transformations s.t. the module always remains valid according
+ to the semantics of some fuzzing target. Available targets:
+ - spir-v - module is valid according to the SPIR-V spec.
+ - wgsl - module is valid according to the WGSL spec.
--replay
File from which to read a sequence of transformations to replay
(instead of fuzzing)
@@ -204,15 +212,15 @@ FuzzStatus ParseFlags(
std::vector<std::string>* interestingness_test,
std::string* shrink_transformations_file,
std::string* shrink_temp_file_prefix,
- spvtools::fuzz::Fuzzer::RepeatedPassStrategy* repeated_pass_strategy,
- spvtools::FuzzerOptions* fuzzer_options,
+ spvtools::fuzz::RepeatedPassStrategy* repeated_pass_strategy,
+ FuzzingTarget* fuzzing_target, spvtools::FuzzerOptions* fuzzer_options,
spvtools::ValidatorOptions* validator_options) {
uint32_t positional_arg_index = 0;
bool only_positional_arguments_remain = false;
bool force_render_red = false;
*repeated_pass_strategy =
- spvtools::fuzz::Fuzzer::RepeatedPassStrategy::kLoopedWithRecommendations;
+ spvtools::fuzz::RepeatedPassStrategy::kLoopedWithRecommendations;
for (int argi = 1; argi < argc; ++argi) {
const char* cur_arg = argv[argi];
@@ -250,14 +258,14 @@ FuzzStatus ParseFlags(
sizeof("--repeated-pass-strategy=") - 1)) {
std::string strategy = spvtools::utils::SplitFlagArgs(cur_arg).second;
if (strategy == "looped") {
- *repeated_pass_strategy = spvtools::fuzz::Fuzzer::
- RepeatedPassStrategy::kLoopedWithRecommendations;
+ *repeated_pass_strategy =
+ spvtools::fuzz::RepeatedPassStrategy::kLoopedWithRecommendations;
} else if (strategy == "random") {
- *repeated_pass_strategy = spvtools::fuzz::Fuzzer::
- RepeatedPassStrategy::kRandomWithRecommendations;
+ *repeated_pass_strategy =
+ spvtools::fuzz::RepeatedPassStrategy::kRandomWithRecommendations;
} else if (strategy == "simple") {
*repeated_pass_strategy =
- spvtools::fuzz::Fuzzer::RepeatedPassStrategy::kSimple;
+ spvtools::fuzz::RepeatedPassStrategy::kSimple;
} else {
std::stringstream ss;
ss << "Unknown repeated pass strategy '" << strategy << "'"
@@ -266,6 +274,20 @@ FuzzStatus ParseFlags(
spvtools::Error(FuzzDiagnostic, nullptr, {}, ss.str().c_str());
return {FuzzActions::STOP, 1};
}
+ } else if (0 == strncmp(cur_arg, "--fuzzing-target=",
+ sizeof("--fuzzing-target=") - 1)) {
+ std::string target = spvtools::utils::SplitFlagArgs(cur_arg).second;
+ if (target == "spir-v") {
+ *fuzzing_target = FuzzingTarget::kSpirv;
+ } else if (target == "wgsl") {
+ *fuzzing_target = FuzzingTarget::kWgsl;
+ } else {
+ std::stringstream ss;
+ ss << "Unknown fuzzing target '" << target << "'" << std::endl;
+ ss << "Valid options are 'spir-v' and 'wgsl'.";
+ spvtools::Error(FuzzDiagnostic, nullptr, {}, ss.str().c_str());
+ return {FuzzActions::STOP, 1};
+ }
} else if (0 == strncmp(cur_arg, "--replay-range=",
sizeof("--replay-range=") - 1)) {
const auto split_flag = spvtools::utils::SplitFlagArgs(cur_arg);
@@ -549,8 +571,8 @@ bool Fuzz(const spv_target_env& target_env,
const std::vector<uint32_t>& binary_in,
const spvtools::fuzz::protobufs::FactSequence& initial_facts,
const std::string& donors,
- spvtools::fuzz::Fuzzer::RepeatedPassStrategy repeated_pass_strategy,
- std::vector<uint32_t>* binary_out,
+ spvtools::fuzz::RepeatedPassStrategy repeated_pass_strategy,
+ FuzzingTarget fuzzing_target, std::vector<uint32_t>* binary_out,
spvtools::fuzz::protobufs::TransformationSequence*
transformations_applied) {
auto message_consumer = spvtools::utils::CLIMessageConsumer;
@@ -568,8 +590,8 @@ bool Fuzz(const spv_target_env& target_env,
[donor_filename, message_consumer,
target_env]() -> std::unique_ptr<spvtools::opt::IRContext> {
std::vector<uint32_t> donor_binary;
- if (!ReadFile<uint32_t>(donor_filename.c_str(), "rb",
- &donor_binary)) {
+ if (!ReadBinaryFile<uint32_t>(donor_filename.c_str(),
+ &donor_binary)) {
return nullptr;
}
return spvtools::BuildModule(target_env, message_consumer,
@@ -578,24 +600,46 @@ bool Fuzz(const spv_target_env& target_env,
});
}
- auto fuzz_result =
- spvtools::fuzz::Fuzzer(
- target_env, message_consumer, binary_in, initial_facts,
- donor_suppliers,
- spvtools::MakeUnique<spvtools::fuzz::PseudoRandomGenerator>(
- fuzzer_options->has_random_seed
- ? fuzzer_options->random_seed
- : static_cast<uint32_t>(std::random_device()())),
- fuzzer_options->all_passes_enabled, repeated_pass_strategy,
- fuzzer_options->fuzzer_pass_validation_enabled, validator_options)
- .Run();
- *binary_out = std::move(fuzz_result.transformed_binary);
- *transformations_applied = std::move(fuzz_result.applied_transformations);
- if (fuzz_result.status !=
- spvtools::fuzz::Fuzzer::FuzzerResultStatus::kComplete) {
+ std::unique_ptr<spvtools::opt::IRContext> ir_context;
+ if (!spvtools::fuzz::fuzzerutil::BuildIRContext(target_env, message_consumer,
+ binary_in, validator_options,
+ &ir_context)) {
+ spvtools::Error(FuzzDiagnostic, nullptr, {}, "Initial binary is invalid");
+ return false;
+ }
+
+ assert((fuzzing_target == FuzzingTarget::kWgsl ||
+ fuzzing_target == FuzzingTarget::kSpirv) &&
+ "Not all fuzzing targets are handled");
+ auto fuzzer_context = spvtools::MakeUnique<spvtools::fuzz::FuzzerContext>(
+ spvtools::MakeUnique<spvtools::fuzz::PseudoRandomGenerator>(
+ fuzzer_options->has_random_seed
+ ? fuzzer_options->random_seed
+ : static_cast<uint32_t>(std::random_device()())),
+ spvtools::fuzz::FuzzerContext::GetMinFreshId(ir_context.get()),
+ fuzzing_target == FuzzingTarget::kWgsl);
+
+ auto transformation_context =
+ spvtools::MakeUnique<spvtools::fuzz::TransformationContext>(
+ spvtools::MakeUnique<spvtools::fuzz::FactManager>(ir_context.get()),
+ validator_options);
+ transformation_context->GetFactManager()->AddInitialFacts(message_consumer,
+ initial_facts);
+
+ spvtools::fuzz::Fuzzer fuzzer(
+ std::move(ir_context), std::move(transformation_context),
+ std::move(fuzzer_context), message_consumer, donor_suppliers,
+ fuzzer_options->all_passes_enabled, repeated_pass_strategy,
+ fuzzer_options->fuzzer_pass_validation_enabled, validator_options);
+ auto fuzz_result = fuzzer.Run(0);
+ if (fuzz_result.status ==
+ spvtools::fuzz::Fuzzer::Status::kFuzzerPassLedToInvalidModule) {
spvtools::Error(FuzzDiagnostic, nullptr, {}, "Error running fuzzer");
return false;
}
+
+ fuzzer.GetIRContext()->module()->ToBinary(binary_out, true);
+ *transformations_applied = fuzzer.GetTransformationSequence();
return true;
}
@@ -656,7 +700,8 @@ int main(int argc, const char** argv) {
std::vector<std::string> interestingness_test;
std::string shrink_transformations_file;
std::string shrink_temp_file_prefix = "temp_";
- spvtools::fuzz::Fuzzer::RepeatedPassStrategy repeated_pass_strategy;
+ spvtools::fuzz::RepeatedPassStrategy repeated_pass_strategy;
+ auto fuzzing_target = FuzzingTarget::kSpirv;
spvtools::FuzzerOptions fuzzer_options;
spvtools::ValidatorOptions validator_options;
@@ -665,14 +710,15 @@ int main(int argc, const char** argv) {
ParseFlags(argc, argv, &in_binary_file, &out_binary_file, &donors_file,
&replay_transformations_file, &interestingness_test,
&shrink_transformations_file, &shrink_temp_file_prefix,
- &repeated_pass_strategy, &fuzzer_options, &validator_options);
+ &repeated_pass_strategy, &fuzzing_target, &fuzzer_options,
+ &validator_options);
if (status.action == FuzzActions::STOP) {
return status.code;
}
std::vector<uint32_t> binary_in;
- if (!ReadFile<uint32_t>(in_binary_file.c_str(), "rb", &binary_in)) {
+ if (!ReadBinaryFile<uint32_t>(in_binary_file.c_str(), &binary_in)) {
return 1;
}
@@ -703,16 +749,16 @@ int main(int argc, const char** argv) {
switch (status.action) {
case FuzzActions::FORCE_RENDER_RED:
- if (!spvtools::fuzz::ForceRenderRed(target_env, validator_options,
- binary_in, initial_facts,
- &binary_out)) {
+ if (!spvtools::fuzz::ForceRenderRed(
+ target_env, validator_options, binary_in, initial_facts,
+ spvtools::utils::CLIMessageConsumer, &binary_out)) {
return 1;
}
break;
case FuzzActions::FUZZ:
if (!Fuzz(target_env, fuzzer_options, validator_options, binary_in,
- initial_facts, donors_file, repeated_pass_strategy, &binary_out,
- &transformations_applied)) {
+ initial_facts, donors_file, repeated_pass_strategy,
+ fuzzing_target, &binary_out, &transformations_applied)) {
return 1;
}
break;
diff --git a/tools/io.h b/tools/io.h
index f9cfd9d1..aff9eabd 100644
--- a/tools/io.h
+++ b/tools/io.h
@@ -20,45 +20,101 @@
#include <cstring>
#include <vector>
-// Appends the content from the file named as |filename| to |data|, assuming
-// each element in the file is of type |T|. The file is opened with the given
-// |mode|. If |filename| is nullptr or "-", reads from the standard input, but
-// reopened with the given mode. If any error occurs, writes error messages to
-// standard error and returns false.
+#if defined(SPIRV_WINDOWS)
+#include <fcntl.h>
+#include <io.h>
+
+#define SET_STDIN_TO_BINARY_MODE() _setmode(_fileno(stdin), O_BINARY);
+#define SET_STDIN_TO_TEXT_MODE() _setmode(_fileno(stdin), O_TEXT);
+#else
+#define SET_STDIN_TO_BINARY_MODE()
+#define SET_STDIN_TO_TEXT_MODE()
+#endif
+
+// Appends the contents of the |file| to |data|, assuming each element in the
+// file is of type |T|.
template <typename T>
-bool ReadFile(const char* filename, const char* mode, std::vector<T>* data) {
+void ReadFile(FILE* file, std::vector<T>* data) {
+ if (file == nullptr) return;
+
const int buf_size = 1024;
- const bool use_file = filename && strcmp("-", filename);
- if (FILE* fp =
- (use_file ? fopen(filename, mode) : freopen(nullptr, mode, stdin))) {
- T buf[buf_size];
- while (size_t len = fread(buf, sizeof(T), buf_size, fp)) {
- data->insert(data->end(), buf, buf + len);
- }
- if (ftell(fp) == -1L) {
- if (ferror(fp)) {
- fprintf(stderr, "error: error reading file '%s'\n", filename);
- if (use_file) fclose(fp);
- return false;
- }
- } else {
- if (sizeof(T) != 1 && (ftell(fp) % sizeof(T))) {
- fprintf(
- stderr,
- "error: file size should be a multiple of %zd; file '%s' corrupt\n",
- sizeof(T), filename);
- if (use_file) fclose(fp);
- return false;
- }
- }
- if (use_file) fclose(fp);
- } else {
+ T buf[buf_size];
+ while (size_t len = fread(buf, sizeof(T), buf_size, file)) {
+ data->insert(data->end(), buf, buf + len);
+ }
+}
+
+// Returns true if |file| has encountered an error opening the file or reading
+// the file as a series of element of type |T|. If there was an error, writes an
+// error message to standard error.
+template <class T>
+bool WasFileCorrectlyRead(FILE* file, const char* filename) {
+ if (file == nullptr) {
fprintf(stderr, "error: file does not exist '%s'\n", filename);
return false;
}
+
+ if (ftell(file) == -1L) {
+ if (ferror(file)) {
+ fprintf(stderr, "error: error reading file '%s'\n", filename);
+ return false;
+ }
+ } else {
+ if (sizeof(T) != 1 && (ftell(file) % sizeof(T))) {
+ fprintf(
+ stderr,
+ "error: file size should be a multiple of %zd; file '%s' corrupt\n",
+ sizeof(T), filename);
+ return false;
+ }
+ }
return true;
}
+// Appends the contents of the file named |filename| to |data|, assuming
+// each element in the file is of type |T|. The file is opened as a binary file
+// If |filename| is nullptr or "-", reads from the standard input, but
+// reopened as a binary file. If any error occurs, writes error messages to
+// standard error and returns false.
+template <typename T>
+bool ReadBinaryFile(const char* filename, std::vector<T>* data) {
+ const bool use_file = filename && strcmp("-", filename);
+ FILE* fp = nullptr;
+ if (use_file) {
+ fp = fopen(filename, "rb");
+ } else {
+ SET_STDIN_TO_BINARY_MODE();
+ fp = stdin;
+ }
+
+ ReadFile(fp, data);
+ bool succeeded = WasFileCorrectlyRead<T>(fp, filename);
+ if (use_file) fclose(fp);
+ return succeeded;
+}
+
+// Appends the contents of the file named |filename| to |data|, assuming
+// each element in the file is of type |T|. The file is opened as a text file
+// If |filename| is nullptr or "-", reads from the standard input, but
+// reopened as a text file. If any error occurs, writes error messages to
+// standard error and returns false.
+template <typename T>
+bool ReadTextFile(const char* filename, std::vector<T>* data) {
+ const bool use_file = filename && strcmp("-", filename);
+ FILE* fp = nullptr;
+ if (use_file) {
+ fp = fopen(filename, "r");
+ } else {
+ SET_STDIN_TO_TEXT_MODE();
+ fp = stdin;
+ }
+
+ ReadFile(fp, data);
+ bool succeeded = WasFileCorrectlyRead<T>(fp, filename);
+ if (use_file) fclose(fp);
+ return succeeded;
+}
+
// Writes the given |data| into the file named as |filename| using the given
// |mode|, assuming |data| is an array of |count| elements of type |T|. If
// |filename| is nullptr or "-", writes to standard output. If any error occurs,
diff --git a/tools/link/linker.cpp b/tools/link/linker.cpp
index 1956f595..359e8030 100644
--- a/tools/link/linker.cpp
+++ b/tools/link/linker.cpp
@@ -130,7 +130,7 @@ int main(int argc, char** argv) {
std::vector<std::vector<uint32_t>> contents(inFiles.size());
for (size_t i = 0u; i < inFiles.size(); ++i) {
- if (!ReadFile<uint32_t>(inFiles[i], "rb", &contents[i])) return 1;
+ if (!ReadBinaryFile<uint32_t>(inFiles[i], &contents[i])) return 1;
}
const spvtools::MessageConsumer consumer = [](spv_message_level_t level,
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index 6999b39a..b9339abe 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -807,7 +807,7 @@ int main(int argc, const char** argv) {
}
std::vector<uint32_t> binary;
- if (!ReadFile<uint32_t>(in_file, "rb", &binary)) {
+ if (!ReadBinaryFile<uint32_t>(in_file, &binary)) {
return 1;
}
diff --git a/tools/reduce/reduce.cpp b/tools/reduce/reduce.cpp
index 49a5efef..4447b356 100644
--- a/tools/reduce/reduce.cpp
+++ b/tools/reduce/reduce.cpp
@@ -318,7 +318,7 @@ int main(int argc, const char** argv) {
reducer.SetMessageConsumer(spvtools::utils::CLIMessageConsumer);
std::vector<uint32_t> binary_in;
- if (!ReadFile<uint32_t>(in_binary_file.c_str(), "rb", &binary_in)) {
+ if (!ReadBinaryFile<uint32_t>(in_binary_file.c_str(), &binary_in)) {
return 1;
}
diff --git a/tools/val/val.cpp b/tools/val/val.cpp
index 5450023a..21a7d8f4 100644
--- a/tools/val/val.cpp
+++ b/tools/val/val.cpp
@@ -186,7 +186,7 @@ int main(int argc, char** argv) {
}
std::vector<uint32_t> contents;
- if (!ReadFile<uint32_t>(inFile, "rb", &contents)) return 1;
+ if (!ReadBinaryFile<uint32_t>(inFile, &contents)) return 1;
spvtools::SpirvTools tools(target_env);
tools.SetMessageConsumer(spvtools::utils::CLIMessageConsumer);
diff --git a/utils/check_copyright.py b/utils/check_copyright.py
index b15bc206..1bc39f67 100755
--- a/utils/check_copyright.py
+++ b/utils/check_copyright.py
@@ -36,7 +36,8 @@ AUTHORS = ['The Khronos Group Inc.',
'André Perez Maselco',
'Vasyl Teliman',
'Advanced Micro Devices, Inc.',
- 'Stefano Milizia']
+ 'Stefano Milizia',
+ 'Alastair F. Donaldson']
CURRENT_YEAR='2020'
YEARS = '(2014-2016|2015-2016|2015-2020|2016|2016-2017|2017|2017-2019|2018|2019|2020|2021)'
diff --git a/utils/generate_grammar_tables.py b/utils/generate_grammar_tables.py
index 2a677336..c4ed180a 100755
--- a/utils/generate_grammar_tables.py
+++ b/utils/generate_grammar_tables.py
@@ -601,7 +601,7 @@ def generate_extension_to_string_mapping(extensions):
' return "{extension}";\n'
function += ''.join([template.format(extension=extension)
for extension in extensions])
- function += ' };\n\n return "";\n}'
+ function += ' }\n\n return "";\n}'
return function
@@ -647,7 +647,7 @@ def generate_capability_to_string_mapping(operand_kinds):
function += ' case SpvCapabilityMax:\n' \
' assert(0 && "Attempting to convert SpvCapabilityMax to string");\n' \
' return "";\n'
- function += ' };\n\n return "";\n}'
+ function += ' }\n\n return "";\n}'
return function
diff --git a/utils/vscode/README.md b/utils/vscode/README.md
index bc022112..d7aa2b41 100644
--- a/utils/vscode/README.md
+++ b/utils/vscode/README.md
@@ -1,12 +1,20 @@
# Visual Studio Code extension for SPIR-V disassembly files
-This directory holds a Visual Studio Code extension adding syntax highlighting for SPIR-V assembly files (`.spvasm`)
+This directory holds a Visual Studio Code language server extension for SPIR-V assembly files (`.spvasm`)
+
+The extension supports:
+* Syntax highlighting
+* Jump to definition
+* Find all references
+* Symbol renaming
+* Operand hover information
+* Formatting
## Dependencies
In order to build and install the Visual Studio Code language server extension, you will need to install and have on your `PATH` the following dependencies:
* [`npm`](https://www.npmjs.com/)
-* [`golang`](https://golang.org/)
+* [`golang 1.16+`](https://golang.org/)
## Installing (macOS / Linux)
diff --git a/utils/vscode/go.mod b/utils/vscode/go.mod
new file mode 100644
index 00000000..ea4901a4
--- /dev/null
+++ b/utils/vscode/go.mod
@@ -0,0 +1,8 @@
+module github.com/KhronosGroup/SPIRV-Tools/utils/vscode
+
+go 1.16
+
+require (
+ github.com/pkg/errors v0.9.1
+ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
+)
diff --git a/utils/vscode/go.sum b/utils/vscode/go.sum
new file mode 100644
index 00000000..328c8578
--- /dev/null
+++ b/utils/vscode/go.sum
@@ -0,0 +1,4 @@
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/utils/vscode/install.bat b/utils/vscode/install.bat
index 21a52ecd..aa06fa91 100644
--- a/utils/vscode/install.bat
+++ b/utils/vscode/install.bat
@@ -23,7 +23,7 @@ copy %ROOT_PATH%\extension.js %EXT_PATH%
copy %ROOT_PATH%\package.json %EXT_PATH%
copy %ROOT_PATH%\spirv.json %EXT_PATH%
-go build -o %EXT_PATH%\langsvr %ROOT_PATH%\src\langsvr.go
+go build -o %EXT_PATH%\langsvr.exe %ROOT_PATH%\src\langsvr.go
@pushd %EXT_PATH%
call npm install
diff --git a/utils/vscode/spirv.json b/utils/vscode/spirv.json
index 7999b523..29b679c3 100644
--- a/utils/vscode/spirv.json
+++ b/utils/vscode/spirv.json
@@ -11,6 +11,8 @@
{ "include": "#BitEnum_MemorySemantics" },
{ "include": "#BitEnum_MemoryAccess" },
{ "include": "#BitEnum_KernelProfilingInfo" },
+ { "include": "#BitEnum_RayFlags" },
+ { "include": "#BitEnum_FragmentShadingRate" },
{ "include": "#ValueEnum_SourceLanguage" },
{ "include": "#ValueEnum_ExecutionModel" },
{ "include": "#ValueEnum_AddressingModel" },
@@ -24,6 +26,8 @@
{ "include": "#ValueEnum_ImageChannelOrder" },
{ "include": "#ValueEnum_ImageChannelDataType" },
{ "include": "#ValueEnum_FPRoundingMode" },
+ { "include": "#ValueEnum_FPDenormMode" },
+ { "include": "#ValueEnum_FPOperationMode" },
{ "include": "#ValueEnum_LinkageType" },
{ "include": "#ValueEnum_AccessQualifier" },
{ "include": "#ValueEnum_FunctionParameterAttribute" },
@@ -33,6 +37,9 @@
{ "include": "#ValueEnum_GroupOperation" },
{ "include": "#ValueEnum_KernelEnqueueFlags" },
{ "include": "#ValueEnum_Capability" },
+ { "include": "#ValueEnum_RayQueryIntersection" },
+ { "include": "#ValueEnum_RayQueryCommittedIntersectionType" },
+ { "include": "#ValueEnum_RayQueryCandidateIntersectionType" },
{ "include": "#BitEnum_DebugInfoFlags" },
{ "include": "#ValueEnum_DebugBaseTypeAttributeEncoding" },
{ "include": "#ValueEnum_DebugCompositeType" },
@@ -53,7 +60,7 @@
"name": "keyword.spirv"
},
"BitEnum_FPFastMathMode": {
- "match": "\\b(None|NotNaN|NotInf|NSZ|AllowRecip|Fast)\\b",
+ "match": "\\b(None|NotNaN|NotInf|NSZ|AllowRecip|Fast|AllowContractFastINTEL|AllowReassocINTEL)\\b",
"name": "keyword.spirv"
},
"BitEnum_SelectionControl": {
@@ -61,7 +68,7 @@
"name": "keyword.spirv"
},
"BitEnum_LoopControl": {
- "match": "\\b(None|Unroll|DontUnroll|DependencyInfinite|DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount)\\b",
+ "match": "\\b(None|Unroll|DontUnroll|DependencyInfinite|DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount|InitiationIntervalINTEL|MaxConcurrencyINTEL|DependencyArrayINTEL|PipelineEnableINTEL|LoopCoalesceINTEL|MaxInterleavingINTEL|SpeculatedIterationsINTEL|NoFusionINTEL)\\b",
"name": "keyword.spirv"
},
"BitEnum_FunctionControl": {
@@ -80,12 +87,20 @@
"match": "\\b(None|CmdExecTime)\\b",
"name": "keyword.spirv"
},
+ "BitEnum_RayFlags": {
+ "match": "\\b(NoneKHR|OpaqueKHR|NoOpaqueKHR|TerminateOnFirstHitKHR|SkipClosestHitShaderKHR|CullBackFacingTrianglesKHR|CullFrontFacingTrianglesKHR|CullOpaqueKHR|CullNoOpaqueKHR|SkipTrianglesKHR|SkipAABBsKHR)\\b",
+ "name": "keyword.spirv"
+ },
+ "BitEnum_FragmentShadingRate": {
+ "match": "\\b(Vertical2Pixels|Vertical4Pixels|Horizontal2Pixels|Horizontal4Pixels)\\b",
+ "name": "keyword.spirv"
+ },
"ValueEnum_SourceLanguage": {
"match": "\\b(Unknown|ESSL|GLSL|OpenCL_C|OpenCL_CPP|HLSL)\\b",
"name": "keyword.spirv"
},
"ValueEnum_ExecutionModel": {
- "match": "\\b(Vertex|TessellationControl|TessellationEvaluation|Geometry|Fragment|GLCompute|Kernel|TaskNV|MeshNV|RayGenerationNV|IntersectionNV|AnyHitNV|ClosestHitNV|MissNV|CallableNV)\\b",
+ "match": "\\b(Vertex|TessellationControl|TessellationEvaluation|Geometry|Fragment|GLCompute|Kernel|TaskNV|MeshNV|RayGenerationNV|RayGenerationKHR|IntersectionNV|IntersectionKHR|AnyHitNV|AnyHitKHR|ClosestHitNV|ClosestHitKHR|MissNV|MissKHR|CallableNV|CallableKHR)\\b",
"name": "keyword.spirv"
},
"ValueEnum_AddressingModel": {
@@ -97,11 +112,11 @@
"name": "keyword.spirv"
},
"ValueEnum_ExecutionMode": {
- "match": "\\b(Invocations|SpacingEqual|SpacingFractionalEven|SpacingFractionalOdd|VertexOrderCw|VertexOrderCcw|PixelCenterInteger|OriginUpperLeft|OriginLowerLeft|EarlyFragmentTests|PointMode|Xfb|DepthReplacing|DepthGreater|DepthLess|DepthUnchanged|LocalSize|LocalSizeHint|InputPoints|InputLines|InputLinesAdjacency|Triangles|InputTrianglesAdjacency|Quads|Isolines|OutputVertices|OutputPoints|OutputLineStrip|OutputTriangleStrip|VecTypeHint|ContractionOff|Initializer|Finalizer|SubgroupSize|SubgroupsPerWorkgroup|SubgroupsPerWorkgroupId|LocalSizeId|LocalSizeHintId|PostDepthCoverage|DenormPreserve|DenormFlushToZero|SignedZeroInfNanPreserve|RoundingModeRTE|RoundingModeRTZ|StencilRefReplacingEXT|OutputLinesNV|OutputPrimitivesNV|DerivativeGroupQuadsNV|DerivativeGroupLinearNV|OutputTrianglesNV|PixelInterlockOrderedEXT|PixelInterlockUnorderedEXT|SampleInterlockOrderedEXT|SampleInterlockUnorderedEXT|ShadingRateInterlockOrderedEXT|ShadingRateInterlockUnorderedEXT)\\b",
+ "match": "\\b(Invocations|SpacingEqual|SpacingFractionalEven|SpacingFractionalOdd|VertexOrderCw|VertexOrderCcw|PixelCenterInteger|OriginUpperLeft|OriginLowerLeft|EarlyFragmentTests|PointMode|Xfb|DepthReplacing|DepthGreater|DepthLess|DepthUnchanged|LocalSize|LocalSizeHint|InputPoints|InputLines|InputLinesAdjacency|Triangles|InputTrianglesAdjacency|Quads|Isolines|OutputVertices|OutputPoints|OutputLineStrip|OutputTriangleStrip|VecTypeHint|ContractionOff|Initializer|Finalizer|SubgroupSize|SubgroupsPerWorkgroup|SubgroupsPerWorkgroupId|LocalSizeId|LocalSizeHintId|PostDepthCoverage|DenormPreserve|DenormFlushToZero|SignedZeroInfNanPreserve|RoundingModeRTE|RoundingModeRTZ|StencilRefReplacingEXT|OutputLinesNV|OutputPrimitivesNV|DerivativeGroupQuadsNV|DerivativeGroupLinearNV|OutputTrianglesNV|PixelInterlockOrderedEXT|PixelInterlockUnorderedEXT|SampleInterlockOrderedEXT|SampleInterlockUnorderedEXT|ShadingRateInterlockOrderedEXT|ShadingRateInterlockUnorderedEXT|SharedLocalMemorySizeINTEL|RoundingModeRTPINTEL|RoundingModeRTNINTEL|FloatingPointModeALTINTEL|FloatingPointModeIEEEINTEL|MaxWorkgroupSizeINTEL|MaxWorkDimINTEL|NoGlobalOffsetINTEL|NumSIMDWorkitemsINTEL|SchedulerTargetFmaxMhzINTEL)\\b",
"name": "keyword.spirv"
},
"ValueEnum_StorageClass": {
- "match": "\\b(UniformConstant|Input|Uniform|Output|Workgroup|CrossWorkgroup|Private|Function|Generic|PushConstant|AtomicCounter|Image|StorageBuffer|CallableDataNV|IncomingCallableDataNV|RayPayloadNV|HitAttributeNV|IncomingRayPayloadNV|ShaderRecordBufferNV|PhysicalStorageBuffer|PhysicalStorageBufferEXT)\\b",
+ "match": "\\b(UniformConstant|Input|Uniform|Output|Workgroup|CrossWorkgroup|Private|Function|Generic|PushConstant|AtomicCounter|Image|StorageBuffer|CallableDataNV|CallableDataKHR|IncomingCallableDataNV|IncomingCallableDataKHR|RayPayloadNV|RayPayloadKHR|HitAttributeNV|HitAttributeKHR|IncomingRayPayloadNV|IncomingRayPayloadKHR|ShaderRecordBufferNV|ShaderRecordBufferKHR|PhysicalStorageBuffer|PhysicalStorageBufferEXT|CodeSectionINTEL|DeviceOnlyINTEL|HostOnlyINTEL)\\b",
"name": "keyword.spirv"
},
"ValueEnum_Dim": {
@@ -117,7 +132,7 @@
"name": "keyword.spirv"
},
"ValueEnum_ImageFormat": {
- "match": "\\b(Unknown|Rgba32f|Rgba16f|R32f|Rgba8|Rgba8Snorm|Rg32f|Rg16f|R11fG11fB10f|R16f|Rgba16|Rgb10A2|Rg16|Rg8|R16|R8|Rgba16Snorm|Rg16Snorm|Rg8Snorm|R16Snorm|R8Snorm|Rgba32i|Rgba16i|Rgba8i|R32i|Rg32i|Rg16i|Rg8i|R16i|R8i|Rgba32ui|Rgba16ui|Rgba8ui|R32ui|Rgb10a2ui|Rg32ui|Rg16ui|Rg8ui|R16ui|R8ui)\\b",
+ "match": "\\b(Unknown|Rgba32f|Rgba16f|R32f|Rgba8|Rgba8Snorm|Rg32f|Rg16f|R11fG11fB10f|R16f|Rgba16|Rgb10A2|Rg16|Rg8|R16|R8|Rgba16Snorm|Rg16Snorm|Rg8Snorm|R16Snorm|R8Snorm|Rgba32i|Rgba16i|Rgba8i|R32i|Rg32i|Rg16i|Rg8i|R16i|R8i|Rgba32ui|Rgba16ui|Rgba8ui|R32ui|Rgb10a2ui|Rg32ui|Rg16ui|Rg8ui|R16ui|R8ui|R64ui|R64i)\\b",
"name": "keyword.spirv"
},
"ValueEnum_ImageChannelOrder": {
@@ -132,6 +147,14 @@
"match": "\\b(RTE|RTZ|RTP|RTN)\\b",
"name": "keyword.spirv"
},
+ "ValueEnum_FPDenormMode": {
+ "match": "\\b(Preserve|FlushToZero)\\b",
+ "name": "keyword.spirv"
+ },
+ "ValueEnum_FPOperationMode": {
+ "match": "\\b(IEEE|ALT)\\b",
+ "name": "keyword.spirv"
+ },
"ValueEnum_LinkageType": {
"match": "\\b(Export|Import)\\b",
"name": "keyword.spirv"
@@ -145,15 +168,15 @@
"name": "keyword.spirv"
},
"ValueEnum_Decoration": {
- "match": "\\b(RelaxedPrecision|SpecId|Block|BufferBlock|RowMajor|ColMajor|ArrayStride|MatrixStride|GLSLShared|GLSLPacked|CPacked|BuiltIn|NoPerspective|Flat|Patch|Centroid|Sample|Invariant|Restrict|Aliased|Volatile|Constant|Coherent|NonWritable|NonReadable|Uniform|UniformId|SaturatedConversion|Stream|Location|Component|Index|Binding|DescriptorSet|Offset|XfbBuffer|XfbStride|FuncParamAttr|FPRoundingMode|FPFastMathMode|LinkageAttributes|NoContraction|InputAttachmentIndex|Alignment|MaxByteOffset|AlignmentId|MaxByteOffsetId|NoSignedWrap|NoUnsignedWrap|ExplicitInterpAMD|OverrideCoverageNV|PassthroughNV|ViewportRelativeNV|SecondaryViewportRelativeNV|PerPrimitiveNV|PerViewNV|PerTaskNV|PerVertexNV|NonUniform|NonUniformEXT|RestrictPointer|RestrictPointerEXT|AliasedPointer|AliasedPointerEXT|CounterBuffer|HlslCounterBufferGOOGLE|UserSemantic|HlslSemanticGOOGLE|UserTypeGOOGLE)\\b",
+ "match": "\\b(RelaxedPrecision|SpecId|Block|BufferBlock|RowMajor|ColMajor|ArrayStride|MatrixStride|GLSLShared|GLSLPacked|CPacked|BuiltIn|NoPerspective|Flat|Patch|Centroid|Sample|Invariant|Restrict|Aliased|Volatile|Constant|Coherent|NonWritable|NonReadable|Uniform|UniformId|SaturatedConversion|Stream|Location|Component|Index|Binding|DescriptorSet|Offset|XfbBuffer|XfbStride|FuncParamAttr|FPRoundingMode|FPFastMathMode|LinkageAttributes|NoContraction|InputAttachmentIndex|Alignment|MaxByteOffset|AlignmentId|MaxByteOffsetId|NoSignedWrap|NoUnsignedWrap|ExplicitInterpAMD|OverrideCoverageNV|PassthroughNV|ViewportRelativeNV|SecondaryViewportRelativeNV|PerPrimitiveNV|PerViewNV|PerTaskNV|PerVertexNV|NonUniform|NonUniformEXT|RestrictPointer|RestrictPointerEXT|AliasedPointer|AliasedPointerEXT|SIMTCallINTEL|ReferencedIndirectlyINTEL|ClobberINTEL|SideEffectsINTEL|VectorComputeVariableINTEL|FuncParamIOKindINTEL|VectorComputeFunctionINTEL|StackCallINTEL|GlobalVariableOffsetINTEL|CounterBuffer|HlslCounterBufferGOOGLE|UserSemantic|HlslSemanticGOOGLE|UserTypeGOOGLE|FunctionRoundingModeINTEL|FunctionDenormModeINTEL|RegisterINTEL|MemoryINTEL|NumbanksINTEL|BankwidthINTEL|MaxPrivateCopiesINTEL|SinglepumpINTEL|DoublepumpINTEL|MaxReplicatesINTEL|SimpleDualPortINTEL|MergeINTEL|BankBitsINTEL|ForcePow2DepthINTEL|BurstCoalesceINTEL|CacheSizeINTEL|DontStaticallyCoalesceINTEL|PrefetchINTEL|StallEnableINTEL|FuseLoopsInFunctionINTEL|BufferLocationINTEL|IOPipeStorageINTEL|FunctionFloatingPointModeINTEL|SingleElementVectorINTEL|VectorComputeCallableFunctionINTEL)\\b",
"name": "keyword.spirv"
},
"ValueEnum_BuiltIn": {
- "match": "\\b(Position|PointSize|ClipDistance|CullDistance|VertexId|InstanceId|PrimitiveId|InvocationId|Layer|ViewportIndex|TessLevelOuter|TessLevelInner|TessCoord|PatchVertices|FragCoord|PointCoord|FrontFacing|SampleId|SamplePosition|SampleMask|FragDepth|HelperInvocation|NumWorkgroups|WorkgroupSize|WorkgroupId|LocalInvocationId|GlobalInvocationId|LocalInvocationIndex|WorkDim|GlobalSize|EnqueuedWorkgroupSize|GlobalOffset|GlobalLinearId|SubgroupSize|SubgroupMaxSize|NumSubgroups|NumEnqueuedSubgroups|SubgroupId|SubgroupLocalInvocationId|VertexIndex|InstanceIndex|SubgroupEqMask|SubgroupGeMask|SubgroupGtMask|SubgroupLeMask|SubgroupLtMask|SubgroupEqMaskKHR|SubgroupGeMaskKHR|SubgroupGtMaskKHR|SubgroupLeMaskKHR|SubgroupLtMaskKHR|BaseVertex|BaseInstance|DrawIndex|DeviceIndex|ViewIndex|BaryCoordNoPerspAMD|BaryCoordNoPerspCentroidAMD|BaryCoordNoPerspSampleAMD|BaryCoordSmoothAMD|BaryCoordSmoothCentroidAMD|BaryCoordSmoothSampleAMD|BaryCoordPullModelAMD|FragStencilRefEXT|ViewportMaskNV|SecondaryPositionNV|SecondaryViewportMaskNV|PositionPerViewNV|ViewportMaskPerViewNV|FullyCoveredEXT|TaskCountNV|PrimitiveCountNV|PrimitiveIndicesNV|ClipDistancePerViewNV|CullDistancePerViewNV|LayerPerViewNV|MeshViewCountNV|MeshViewIndicesNV|BaryCoordNV|BaryCoordNoPerspNV|FragSizeEXT|FragmentSizeNV|FragInvocationCountEXT|InvocationsPerPixelNV|LaunchIdNV|LaunchSizeNV|WorldRayOriginNV|WorldRayDirectionNV|ObjectRayOriginNV|ObjectRayDirectionNV|RayTminNV|RayTmaxNV|InstanceCustomIndexNV|ObjectToWorldNV|WorldToObjectNV|HitTNV|HitKindNV|IncomingRayFlagsNV|WarpsPerSMNV|SMCountNV|WarpIDNV|SMIDNV)\\b",
+ "match": "\\b(Position|PointSize|ClipDistance|CullDistance|VertexId|InstanceId|PrimitiveId|InvocationId|Layer|ViewportIndex|TessLevelOuter|TessLevelInner|TessCoord|PatchVertices|FragCoord|PointCoord|FrontFacing|SampleId|SamplePosition|SampleMask|FragDepth|HelperInvocation|NumWorkgroups|WorkgroupSize|WorkgroupId|LocalInvocationId|GlobalInvocationId|LocalInvocationIndex|WorkDim|GlobalSize|EnqueuedWorkgroupSize|GlobalOffset|GlobalLinearId|SubgroupSize|SubgroupMaxSize|NumSubgroups|NumEnqueuedSubgroups|SubgroupId|SubgroupLocalInvocationId|VertexIndex|InstanceIndex|SubgroupEqMask|SubgroupEqMaskKHR|SubgroupGeMask|SubgroupGeMaskKHR|SubgroupGtMask|SubgroupGtMaskKHR|SubgroupLeMask|SubgroupLeMaskKHR|SubgroupLtMask|SubgroupLtMaskKHR|BaseVertex|BaseInstance|DrawIndex|PrimitiveShadingRateKHR|DeviceIndex|ViewIndex|ShadingRateKHR|BaryCoordNoPerspAMD|BaryCoordNoPerspCentroidAMD|BaryCoordNoPerspSampleAMD|BaryCoordSmoothAMD|BaryCoordSmoothCentroidAMD|BaryCoordSmoothSampleAMD|BaryCoordPullModelAMD|FragStencilRefEXT|ViewportMaskNV|SecondaryPositionNV|SecondaryViewportMaskNV|PositionPerViewNV|ViewportMaskPerViewNV|FullyCoveredEXT|TaskCountNV|PrimitiveCountNV|PrimitiveIndicesNV|ClipDistancePerViewNV|CullDistancePerViewNV|LayerPerViewNV|MeshViewCountNV|MeshViewIndicesNV|BaryCoordNV|BaryCoordNoPerspNV|FragSizeEXT|FragmentSizeNV|FragInvocationCountEXT|InvocationsPerPixelNV|LaunchIdNV|LaunchIdKHR|LaunchSizeNV|LaunchSizeKHR|WorldRayOriginNV|WorldRayOriginKHR|WorldRayDirectionNV|WorldRayDirectionKHR|ObjectRayOriginNV|ObjectRayOriginKHR|ObjectRayDirectionNV|ObjectRayDirectionKHR|RayTminNV|RayTminKHR|RayTmaxNV|RayTmaxKHR|InstanceCustomIndexNV|InstanceCustomIndexKHR|ObjectToWorldNV|ObjectToWorldKHR|WorldToObjectNV|WorldToObjectKHR|HitTNV|HitKindNV|HitKindKHR|IncomingRayFlagsNV|IncomingRayFlagsKHR|RayGeometryIndexKHR|WarpsPerSMNV|SMCountNV|WarpIDNV|SMIDNV)\\b",
"name": "keyword.spirv"
},
"ValueEnum_Scope": {
- "match": "\\b(CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|QueueFamilyKHR)\\b",
+ "match": "\\b(CrossDevice|Device|Workgroup|Subgroup|Invocation|QueueFamily|QueueFamilyKHR|ShaderCallKHR)\\b",
"name": "keyword.spirv"
},
"ValueEnum_GroupOperation": {
@@ -165,11 +188,23 @@
"name": "keyword.spirv"
},
"ValueEnum_Capability": {
- "match": "\\b(Matrix|Shader|Geometry|Tessellation|Addresses|Linkage|Kernel|Vector16|Float16Buffer|Float16|Float64|Int64|Int64Atomics|ImageBasic|ImageReadWrite|ImageMipmap|Pipes|Groups|DeviceEnqueue|LiteralSampler|AtomicStorage|Int16|TessellationPointSize|GeometryPointSize|ImageGatherExtended|StorageImageMultisample|UniformBufferArrayDynamicIndexing|SampledImageArrayDynamicIndexing|StorageBufferArrayDynamicIndexing|StorageImageArrayDynamicIndexing|ClipDistance|CullDistance|ImageCubeArray|SampleRateShading|ImageRect|SampledRect|GenericPointer|Int8|InputAttachment|SparseResidency|MinLod|Sampled1D|Image1D|SampledCubeArray|SampledBuffer|ImageBuffer|ImageMSArray|StorageImageExtendedFormats|ImageQuery|DerivativeControl|InterpolationFunction|TransformFeedback|GeometryStreams|StorageImageReadWithoutFormat|StorageImageWriteWithoutFormat|MultiViewport|SubgroupDispatch|NamedBarrier|PipeStorage|GroupNonUniform|GroupNonUniformVote|GroupNonUniformArithmetic|GroupNonUniformBallot|GroupNonUniformShuffle|GroupNonUniformShuffleRelative|GroupNonUniformClustered|GroupNonUniformQuad|ShaderLayer|ShaderViewportIndex|SubgroupBallotKHR|DrawParameters|SubgroupVoteKHR|StorageBuffer16BitAccess|StorageUniformBufferBlock16|UniformAndStorageBuffer16BitAccess|StorageUniform16|StoragePushConstant16|StorageInputOutput16|DeviceGroup|MultiView|VariablePointersStorageBuffer|VariablePointers|AtomicStorageOps|SampleMaskPostDepthCoverage|StorageBuffer8BitAccess|UniformAndStorageBuffer8BitAccess|StoragePushConstant8|DenormPreserve|DenormFlushToZero|SignedZeroInfNanPreserve|RoundingModeRTE|RoundingModeRTZ|Float16ImageAMD|ImageGatherBiasLodAMD|FragmentMaskAMD|StencilExportEXT|ImageReadWriteLodAMD|ShaderClockKHR|SampleMaskOverrideCoverageNV|GeometryShaderPassthroughNV|ShaderViewportIndexLayerEXT|ShaderViewportIndexLayerNV|ShaderViewportMaskNV|ShaderStereoViewNV|PerViewAttributesNV|FragmentFullyCoveredEXT|MeshShadingNV|ImageFootprintNV|FragmentBarycentricNV|ComputeDerivativeGroupQuadsNV|FragmentDensityEXT|ShadingRateNV|GroupNonUniformPartitionedNV|ShaderNonUniform|ShaderNonUniformEXT|RuntimeDescriptorArray|RuntimeDescriptorArrayEXT|InputAttachmentArrayDynamicIndexing|InputAttachmentArrayDynamicIndexingEXT|UniformTexelBufferArrayDynamicIndexing|UniformTexelBufferArrayDynamicIndexingEXT|StorageTexelBufferArrayDynamicIndexing|StorageTexelBufferArrayDynamicIndexingEXT|UniformBufferArrayNonUniformIndexing|UniformBufferArrayNonUniformIndexingEXT|SampledImageArrayNonUniformIndexing|SampledImageArrayNonUniformIndexingEXT|StorageBufferArrayNonUniformIndexing|StorageBufferArrayNonUniformIndexingEXT|StorageImageArrayNonUniformIndexing|StorageImageArrayNonUniformIndexingEXT|InputAttachmentArrayNonUniformIndexing|InputAttachmentArrayNonUniformIndexingEXT|UniformTexelBufferArrayNonUniformIndexing|UniformTexelBufferArrayNonUniformIndexingEXT|StorageTexelBufferArrayNonUniformIndexing|StorageTexelBufferArrayNonUniformIndexingEXT|RayTracingNV|VulkanMemoryModel|VulkanMemoryModelKHR|VulkanMemoryModelDeviceScope|VulkanMemoryModelDeviceScopeKHR|PhysicalStorageBufferAddresses|PhysicalStorageBufferAddressesEXT|ComputeDerivativeGroupLinearNV|CooperativeMatrixNV|FragmentShaderSampleInterlockEXT|FragmentShaderShadingRateInterlockEXT|ShaderSMBuiltinsNV|FragmentShaderPixelInterlockEXT|DemoteToHelperInvocationEXT|SubgroupShuffleINTEL|SubgroupBufferBlockIOINTEL|SubgroupImageBlockIOINTEL|SubgroupImageMediaBlockIOINTEL|IntegerFunctions2INTEL|SubgroupAvcMotionEstimationINTEL|SubgroupAvcMotionEstimationIntraINTEL|SubgroupAvcMotionEstimationChromaINTEL)\\b",
+ "match": "\\b(Matrix|Shader|Geometry|Tessellation|Addresses|Linkage|Kernel|Vector16|Float16Buffer|Float16|Float64|Int64|Int64Atomics|ImageBasic|ImageReadWrite|ImageMipmap|Pipes|Groups|DeviceEnqueue|LiteralSampler|AtomicStorage|Int16|TessellationPointSize|GeometryPointSize|ImageGatherExtended|StorageImageMultisample|UniformBufferArrayDynamicIndexing|SampledImageArrayDynamicIndexing|StorageBufferArrayDynamicIndexing|StorageImageArrayDynamicIndexing|ClipDistance|CullDistance|ImageCubeArray|SampleRateShading|ImageRect|SampledRect|GenericPointer|Int8|InputAttachment|SparseResidency|MinLod|Sampled1D|Image1D|SampledCubeArray|SampledBuffer|ImageBuffer|ImageMSArray|StorageImageExtendedFormats|ImageQuery|DerivativeControl|InterpolationFunction|TransformFeedback|GeometryStreams|StorageImageReadWithoutFormat|StorageImageWriteWithoutFormat|MultiViewport|SubgroupDispatch|NamedBarrier|PipeStorage|GroupNonUniform|GroupNonUniformVote|GroupNonUniformArithmetic|GroupNonUniformBallot|GroupNonUniformShuffle|GroupNonUniformShuffleRelative|GroupNonUniformClustered|GroupNonUniformQuad|ShaderLayer|ShaderViewportIndex|FragmentShadingRateKHR|SubgroupBallotKHR|DrawParameters|WorkgroupMemoryExplicitLayoutKHR|WorkgroupMemoryExplicitLayout8BitAccessKHR|WorkgroupMemoryExplicitLayout16BitAccessKHR|SubgroupVoteKHR|StorageBuffer16BitAccess|StorageUniformBufferBlock16|UniformAndStorageBuffer16BitAccess|StorageUniform16|StoragePushConstant16|StorageInputOutput16|DeviceGroup|MultiView|VariablePointersStorageBuffer|VariablePointers|AtomicStorageOps|SampleMaskPostDepthCoverage|StorageBuffer8BitAccess|UniformAndStorageBuffer8BitAccess|StoragePushConstant8|DenormPreserve|DenormFlushToZero|SignedZeroInfNanPreserve|RoundingModeRTE|RoundingModeRTZ|RayQueryProvisionalKHR|RayQueryKHR|RayTraversalPrimitiveCullingKHR|RayTracingKHR|Float16ImageAMD|ImageGatherBiasLodAMD|FragmentMaskAMD|StencilExportEXT|ImageReadWriteLodAMD|Int64ImageEXT|ShaderClockKHR|SampleMaskOverrideCoverageNV|GeometryShaderPassthroughNV|ShaderViewportIndexLayerEXT|ShaderViewportIndexLayerNV|ShaderViewportMaskNV|ShaderStereoViewNV|PerViewAttributesNV|FragmentFullyCoveredEXT|MeshShadingNV|ImageFootprintNV|FragmentBarycentricNV|ComputeDerivativeGroupQuadsNV|FragmentDensityEXT|ShadingRateNV|GroupNonUniformPartitionedNV|ShaderNonUniform|ShaderNonUniformEXT|RuntimeDescriptorArray|RuntimeDescriptorArrayEXT|InputAttachmentArrayDynamicIndexing|InputAttachmentArrayDynamicIndexingEXT|UniformTexelBufferArrayDynamicIndexing|UniformTexelBufferArrayDynamicIndexingEXT|StorageTexelBufferArrayDynamicIndexing|StorageTexelBufferArrayDynamicIndexingEXT|UniformBufferArrayNonUniformIndexing|UniformBufferArrayNonUniformIndexingEXT|SampledImageArrayNonUniformIndexing|SampledImageArrayNonUniformIndexingEXT|StorageBufferArrayNonUniformIndexing|StorageBufferArrayNonUniformIndexingEXT|StorageImageArrayNonUniformIndexing|StorageImageArrayNonUniformIndexingEXT|InputAttachmentArrayNonUniformIndexing|InputAttachmentArrayNonUniformIndexingEXT|UniformTexelBufferArrayNonUniformIndexing|UniformTexelBufferArrayNonUniformIndexingEXT|StorageTexelBufferArrayNonUniformIndexing|StorageTexelBufferArrayNonUniformIndexingEXT|RayTracingNV|VulkanMemoryModel|VulkanMemoryModelKHR|VulkanMemoryModelDeviceScope|VulkanMemoryModelDeviceScopeKHR|PhysicalStorageBufferAddresses|PhysicalStorageBufferAddressesEXT|ComputeDerivativeGroupLinearNV|RayTracingProvisionalKHR|CooperativeMatrixNV|FragmentShaderSampleInterlockEXT|FragmentShaderShadingRateInterlockEXT|ShaderSMBuiltinsNV|FragmentShaderPixelInterlockEXT|DemoteToHelperInvocationEXT|SubgroupShuffleINTEL|SubgroupBufferBlockIOINTEL|SubgroupImageBlockIOINTEL|SubgroupImageMediaBlockIOINTEL|RoundToInfinityINTEL|FloatingPointModeINTEL|IntegerFunctions2INTEL|FunctionPointersINTEL|IndirectReferencesINTEL|AsmINTEL|AtomicFloat32MinMaxEXT|AtomicFloat64MinMaxEXT|AtomicFloat16MinMaxEXT|VectorComputeINTEL|VectorAnyINTEL|SubgroupAvcMotionEstimationINTEL|SubgroupAvcMotionEstimationIntraINTEL|SubgroupAvcMotionEstimationChromaINTEL|VariableLengthArrayINTEL|FunctionFloatControlINTEL|FPGAMemoryAttributesINTEL|FPFastMathModeINTEL|ArbitraryPrecisionIntegersINTEL|UnstructuredLoopControlsINTEL|FPGALoopControlsINTEL|KernelAttributesINTEL|FPGAKernelAttributesINTEL|FPGAMemoryAccessesINTEL|FPGAClusterAttributesINTEL|LoopFuseINTEL|FPGABufferLocationINTEL|USMStorageClassesINTEL|IOPipesINTEL|BlockingPipesINTEL|FPGARegINTEL|AtomicFloat32AddEXT|AtomicFloat64AddEXT|LongConstantCompositeINTEL)\\b",
+ "name": "keyword.spirv"
+ },
+ "ValueEnum_RayQueryIntersection": {
+ "match": "\\b(RayQueryCandidateIntersectionKHR|RayQueryCommittedIntersectionKHR)\\b",
+ "name": "keyword.spirv"
+ },
+ "ValueEnum_RayQueryCommittedIntersectionType": {
+ "match": "\\b(RayQueryCommittedIntersectionNoneKHR|RayQueryCommittedIntersectionTriangleKHR|RayQueryCommittedIntersectionGeneratedKHR)\\b",
+ "name": "keyword.spirv"
+ },
+ "ValueEnum_RayQueryCandidateIntersectionType": {
+ "match": "\\b(RayQueryCandidateIntersectionTriangleKHR|RayQueryCandidateIntersectionAABBKHR)\\b",
"name": "keyword.spirv"
},
"BitEnum_DebugInfoFlags": {
- "match": "\\b(FlagIsProtected|FlagIsPrivate|FlagIsPublic|FlagIsLocal|FlagIsDefinition|FlagFwdDecl|FlagArtificial|FlagExplicit|FlagPrototyped|FlagObjectPointer|FlagStaticMember|FlagIndirectVariable|FlagLValueReference|FlagRValueReference|FlagIsOptimized|FlagIsEnumClass|FlagTypePassByValue|FlagTypePassByReference)\\b",
+ "match": "\\b(None|FlagIsProtected|FlagIsPrivate|FlagIsPublic|FlagIsLocal|FlagIsDefinition|FlagFwdDecl|FlagArtificial|FlagExplicit|FlagPrototyped|FlagObjectPointer|FlagStaticMember|FlagIndirectVariable|FlagLValueReference|FlagRValueReference|FlagIsOptimized|FlagIsEnumClass|FlagTypePassByValue|FlagTypePassByReference)\\b",
"name": "keyword.spirv"
},
"ValueEnum_DebugBaseTypeAttributeEncoding": {
diff --git a/utils/vscode/src/langsvr.go b/utils/vscode/src/langsvr.go
index d1b80dca..4ed441cb 100644
--- a/utils/vscode/src/langsvr.go
+++ b/utils/vscode/src/langsvr.go
@@ -28,11 +28,15 @@ import (
"sync"
"unicode/utf8"
- "./parser"
- "./schema"
+ "github.com/KhronosGroup/SPIRV-Tools/utils/vscode/src/parser"
+ "github.com/KhronosGroup/SPIRV-Tools/utils/vscode/src/schema"
- "./lsp/jsonrpc2"
- lsp "./lsp/protocol"
+ "github.com/KhronosGroup/SPIRV-Tools/utils/vscode/src/lsp/jsonrpc2"
+ lsp "github.com/KhronosGroup/SPIRV-Tools/utils/vscode/src/lsp/protocol"
+)
+
+const (
+ enableDebugLogging = false
)
// rSpy is a reader 'spy' that wraps an io.Reader, and logs all data that passes
@@ -63,12 +67,13 @@ func (s wSpy) Write(p []byte) (n int, err error) {
// main entry point.
func main() {
- // create a log file in the executable's directory.
- if logfile, err := os.Create(path.Join(path.Dir(os.Args[0]), "log.txt")); err == nil {
- defer logfile.Close()
- log.SetOutput(logfile)
- } else {
- log.SetOutput(ioutil.Discard)
+ log.SetOutput(ioutil.Discard)
+ if enableDebugLogging {
+ // create a log file in the executable's directory.
+ if logfile, err := os.Create(path.Join(path.Dir(os.Args[0]), "log.txt")); err == nil {
+ defer logfile.Close()
+ log.SetOutput(logfile)
+ }
}
log.Println("language server started")
diff --git a/utils/vscode/src/lsp/protocol/log.go b/utils/vscode/src/lsp/protocol/log.go
index f245881e..2fd7bbbd 100644
--- a/utils/vscode/src/lsp/protocol/log.go
+++ b/utils/vscode/src/lsp/protocol/log.go
@@ -23,7 +23,7 @@ import (
"sync"
"time"
- "../jsonrpc2"
+ "github.com/KhronosGroup/SPIRV-Tools/utils/vscode/src/lsp/jsonrpc2"
)
type loggingStream struct {
diff --git a/utils/vscode/src/lsp/protocol/protocol.go b/utils/vscode/src/lsp/protocol/protocol.go
index e396c832..886b0aaa 100644
--- a/utils/vscode/src/lsp/protocol/protocol.go
+++ b/utils/vscode/src/lsp/protocol/protocol.go
@@ -19,7 +19,7 @@ import (
"encoding/json"
"log"
- "../jsonrpc2"
+ "github.com/KhronosGroup/SPIRV-Tools/utils/vscode/src/lsp/jsonrpc2"
)
const (
diff --git a/utils/vscode/src/lsp/protocol/span.go b/utils/vscode/src/lsp/protocol/span.go
index 33cc2a65..799c2288 100644
--- a/utils/vscode/src/lsp/protocol/span.go
+++ b/utils/vscode/src/lsp/protocol/span.go
@@ -19,7 +19,8 @@ package protocol
import (
"fmt"
- "../span"
+ "github.com/KhronosGroup/SPIRV-Tools/utils/vscode/src/lsp/span"
+
errors "golang.org/x/xerrors"
)
diff --git a/utils/vscode/src/lsp/protocol/tsclient.go b/utils/vscode/src/lsp/protocol/tsclient.go
index 2f9beef4..f68d63d0 100644
--- a/utils/vscode/src/lsp/protocol/tsclient.go
+++ b/utils/vscode/src/lsp/protocol/tsclient.go
@@ -19,7 +19,7 @@ import (
"encoding/json"
"log"
- "../jsonrpc2"
+ "github.com/KhronosGroup/SPIRV-Tools/utils/vscode/src/lsp/jsonrpc2"
)
type Client interface {
diff --git a/utils/vscode/src/lsp/protocol/tsserver.go b/utils/vscode/src/lsp/protocol/tsserver.go
index d7605012..37e8c6a7 100644
--- a/utils/vscode/src/lsp/protocol/tsserver.go
+++ b/utils/vscode/src/lsp/protocol/tsserver.go
@@ -19,7 +19,7 @@ import (
"encoding/json"
"log"
- "../jsonrpc2"
+ "github.com/KhronosGroup/SPIRV-Tools/utils/vscode/src/lsp/jsonrpc2"
)
type Server interface {
diff --git a/utils/vscode/src/parser/parser.go b/utils/vscode/src/parser/parser.go
index 260a616c..cc6f3332 100644
--- a/utils/vscode/src/parser/parser.go
+++ b/utils/vscode/src/parser/parser.go
@@ -23,7 +23,7 @@ import (
"unicode"
"unicode/utf8"
- "../schema"
+ "github.com/KhronosGroup/SPIRV-Tools/utils/vscode/src/schema"
)
// Type is an enumerator of token types.
diff --git a/utils/vscode/src/schema/schema.go b/utils/vscode/src/schema/schema.go
index 0fde3fea..86d856fd 100755
--- a/utils/vscode/src/schema/schema.go
+++ b/utils/vscode/src/schema/schema.go
@@ -447,12 +447,25 @@ var (
"OpPtrEqual": OpPtrEqual,
"OpPtrNotEqual": OpPtrNotEqual,
"OpPtrDiff": OpPtrDiff,
+ "OpTerminateInvocation": OpTerminateInvocation,
"OpSubgroupBallotKHR": OpSubgroupBallotKHR,
"OpSubgroupFirstInvocationKHR": OpSubgroupFirstInvocationKHR,
"OpSubgroupAllKHR": OpSubgroupAllKHR,
"OpSubgroupAnyKHR": OpSubgroupAnyKHR,
"OpSubgroupAllEqualKHR": OpSubgroupAllEqualKHR,
"OpSubgroupReadInvocationKHR": OpSubgroupReadInvocationKHR,
+ "OpTraceRayKHR": OpTraceRayKHR,
+ "OpExecuteCallableKHR": OpExecuteCallableKHR,
+ "OpConvertUToAccelerationStructureKHR": OpConvertUToAccelerationStructureKHR,
+ "OpIgnoreIntersectionKHR": OpIgnoreIntersectionKHR,
+ "OpTerminateRayKHR": OpTerminateRayKHR,
+ "OpTypeRayQueryKHR": OpTypeRayQueryKHR,
+ "OpRayQueryInitializeKHR": OpRayQueryInitializeKHR,
+ "OpRayQueryTerminateKHR": OpRayQueryTerminateKHR,
+ "OpRayQueryGenerateIntersectionKHR": OpRayQueryGenerateIntersectionKHR,
+ "OpRayQueryConfirmIntersectionKHR": OpRayQueryConfirmIntersectionKHR,
+ "OpRayQueryProceedKHR": OpRayQueryProceedKHR,
+ "OpRayQueryGetIntersectionTypeKHR": OpRayQueryGetIntersectionTypeKHR,
"OpGroupIAddNonUniformAMD": OpGroupIAddNonUniformAMD,
"OpGroupFAddNonUniformAMD": OpGroupFAddNonUniformAMD,
"OpGroupFMinNonUniformAMD": OpGroupFMinNonUniformAMD,
@@ -470,39 +483,11 @@ var (
"OpReportIntersectionNV": OpReportIntersectionNV,
"OpReportIntersectionKHR": OpReportIntersectionKHR,
"OpIgnoreIntersectionNV": OpIgnoreIntersectionNV,
- "OpIgnoreIntersectionKHR": OpIgnoreIntersectionKHR,
"OpTerminateRayNV": OpTerminateRayNV,
- "OpTerminateRayKHR": OpTerminateRayKHR,
"OpTraceNV": OpTraceNV,
- "OpTraceRayKHR": OpTraceRayKHR,
"OpTypeAccelerationStructureNV": OpTypeAccelerationStructureNV,
"OpTypeAccelerationStructureKHR": OpTypeAccelerationStructureKHR,
- "OpTypeRayQueryKHR": OpTypeRayQueryKHR,
- "OpRayQueryInitializeKHR": OpRayQueryInitializeKHR,
- "OpRayQueryTerminateKHR": OpRayQueryTerminateKHR,
- "OpRayQueryGenerateIntersectionKHR": OpRayQueryGenerateIntersectionKHR,
- "OpRayQueryConfirmIntersectionKHR": OpRayQueryConfirmIntersectionKHR,
- "OpRayQueryProceedKHR": OpRayQueryProceedKHR,
- "OpRayQueryGetIntersectionTypeKHR": OpRayQueryGetIntersectionTypeKHR,
- "OpRayQueryGetRayTMinKHR": OpRayQueryGetRayTMinKHR,
- "OpRayQueryGetRayFlagsKHR": OpRayQueryGetRayFlagsKHR,
- "OpRayQueryGetIntersectionTKHR": OpRayQueryGetIntersectionTKHR,
- "OpRayQueryGetIntersectionInstanceCustomIndexKHR": OpRayQueryGetIntersectionInstanceCustomIndexKHR,
- "OpRayQueryGetIntersectionInstanceIdKHR": OpRayQueryGetIntersectionInstanceIdKHR,
- "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR": OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR,
- "OpRayQueryGetIntersectionGeometryIndexKHR": OpRayQueryGetIntersectionGeometryIndexKHR,
- "OpRayQueryGetIntersectionPrimitiveIndexKHR": OpRayQueryGetIntersectionPrimitiveIndexKHR,
- "OpRayQueryGetIntersectionBarycentricsKHR": OpRayQueryGetIntersectionBarycentricsKHR,
- "OpRayQueryGetIntersectionFrontFaceKHR": OpRayQueryGetIntersectionFrontFaceKHR,
- "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR": OpRayQueryGetIntersectionCandidateAABBOpaqueKHR,
- "OpRayQueryGetIntersectionObjectRayDirectionKHR": OpRayQueryGetIntersectionObjectRayDirectionKHR,
- "OpRayQueryGetIntersectionObjectRayOriginKHR": OpRayQueryGetIntersectionObjectRayOriginKHR,
- "OpRayQueryGetWorldRayDirectionKHR": OpRayQueryGetWorldRayDirectionKHR,
- "OpRayQueryGetWorldRayOriginKHR": OpRayQueryGetWorldRayOriginKHR,
- "OpRayQueryGetIntersectionObjectToWorldKHR": OpRayQueryGetIntersectionObjectToWorldKHR,
- "OpRayQueryGetIntersectionWorldToObjectKHR": OpRayQueryGetIntersectionWorldToObjectKHR,
"OpExecuteCallableNV": OpExecuteCallableNV,
- "OpExecuteCallableKHR": OpExecuteCallableKHR,
"OpTypeCooperativeMatrixNV": OpTypeCooperativeMatrixNV,
"OpCooperativeMatrixLoadNV": OpCooperativeMatrixLoadNV,
"OpCooperativeMatrixStoreNV": OpCooperativeMatrixStoreNV,
@@ -536,6 +521,13 @@ var (
"OpUSubSatINTEL": OpUSubSatINTEL,
"OpIMul32x16INTEL": OpIMul32x16INTEL,
"OpUMul32x16INTEL": OpUMul32x16INTEL,
+ "OpConstFunctionPointerINTEL": OpConstFunctionPointerINTEL,
+ "OpFunctionPointerCallINTEL": OpFunctionPointerCallINTEL,
+ "OpAsmTargetINTEL": OpAsmTargetINTEL,
+ "OpAsmINTEL": OpAsmINTEL,
+ "OpAsmCallINTEL": OpAsmCallINTEL,
+ "OpAtomicFMinEXT": OpAtomicFMinEXT,
+ "OpAtomicFMaxEXT": OpAtomicFMaxEXT,
"OpDecorateString": OpDecorateString,
"OpDecorateStringGOOGLE": OpDecorateStringGOOGLE,
"OpMemberDecorateString": OpMemberDecorateString,
@@ -658,6 +650,37 @@ var (
"OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL": OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL,
"OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL": OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL,
"OpSubgroupAvcSicGetInterRawSadsINTEL": OpSubgroupAvcSicGetInterRawSadsINTEL,
+ "OpVariableLengthArrayINTEL": OpVariableLengthArrayINTEL,
+ "OpSaveMemoryINTEL": OpSaveMemoryINTEL,
+ "OpRestoreMemoryINTEL": OpRestoreMemoryINTEL,
+ "OpLoopControlINTEL": OpLoopControlINTEL,
+ "OpPtrCastToCrossWorkgroupINTEL": OpPtrCastToCrossWorkgroupINTEL,
+ "OpCrossWorkgroupCastToPtrINTEL": OpCrossWorkgroupCastToPtrINTEL,
+ "OpReadPipeBlockingINTEL": OpReadPipeBlockingINTEL,
+ "OpWritePipeBlockingINTEL": OpWritePipeBlockingINTEL,
+ "OpFPGARegINTEL": OpFPGARegINTEL,
+ "OpRayQueryGetRayTMinKHR": OpRayQueryGetRayTMinKHR,
+ "OpRayQueryGetRayFlagsKHR": OpRayQueryGetRayFlagsKHR,
+ "OpRayQueryGetIntersectionTKHR": OpRayQueryGetIntersectionTKHR,
+ "OpRayQueryGetIntersectionInstanceCustomIndexKHR": OpRayQueryGetIntersectionInstanceCustomIndexKHR,
+ "OpRayQueryGetIntersectionInstanceIdKHR": OpRayQueryGetIntersectionInstanceIdKHR,
+ "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR": OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR,
+ "OpRayQueryGetIntersectionGeometryIndexKHR": OpRayQueryGetIntersectionGeometryIndexKHR,
+ "OpRayQueryGetIntersectionPrimitiveIndexKHR": OpRayQueryGetIntersectionPrimitiveIndexKHR,
+ "OpRayQueryGetIntersectionBarycentricsKHR": OpRayQueryGetIntersectionBarycentricsKHR,
+ "OpRayQueryGetIntersectionFrontFaceKHR": OpRayQueryGetIntersectionFrontFaceKHR,
+ "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR": OpRayQueryGetIntersectionCandidateAABBOpaqueKHR,
+ "OpRayQueryGetIntersectionObjectRayDirectionKHR": OpRayQueryGetIntersectionObjectRayDirectionKHR,
+ "OpRayQueryGetIntersectionObjectRayOriginKHR": OpRayQueryGetIntersectionObjectRayOriginKHR,
+ "OpRayQueryGetWorldRayDirectionKHR": OpRayQueryGetWorldRayDirectionKHR,
+ "OpRayQueryGetWorldRayOriginKHR": OpRayQueryGetWorldRayOriginKHR,
+ "OpRayQueryGetIntersectionObjectToWorldKHR": OpRayQueryGetIntersectionObjectToWorldKHR,
+ "OpRayQueryGetIntersectionWorldToObjectKHR": OpRayQueryGetIntersectionWorldToObjectKHR,
+ "OpAtomicFAddEXT": OpAtomicFAddEXT,
+ "OpTypeBufferSurfaceINTEL": OpTypeBufferSurfaceINTEL,
+ "OpTypeStructContinuedINTEL": OpTypeStructContinuedINTEL,
+ "OpConstantCompositeContinuedINTEL": OpConstantCompositeContinuedINTEL,
+ "OpSpecConstantCompositeContinuedINTEL": OpSpecConstantCompositeContinuedINTEL,
}
// ExtOpcodes is a map of extension name to Opcode description list.
@@ -10022,6 +10045,13 @@ var (
},
},
}
+ OpTerminateInvocation = &Opcode {
+ Opname: "OpTerminateInvocation",
+ Class: "Control-Flow",
+ Opcode: 4416,
+ Operands: []Operand {
+ },
+ }
OpSubgroupBallotKHR = &Opcode {
Opname: "OpSubgroupBallotKHR",
Class: "Group",
@@ -10159,455 +10189,89 @@ var (
},
},
}
- OpGroupIAddNonUniformAMD = &Opcode {
- Opname: "OpGroupIAddNonUniformAMD",
- Class: "Group",
- Opcode: 5000,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdScope,
- Name: "'Execution'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindGroupOperation,
- Name: "'Operation'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'X'",
- Quantifier: "",
- },
- },
- }
- OpGroupFAddNonUniformAMD = &Opcode {
- Opname: "OpGroupFAddNonUniformAMD",
- Class: "Group",
- Opcode: 5001,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdScope,
- Name: "'Execution'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindGroupOperation,
- Name: "'Operation'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'X'",
- Quantifier: "",
- },
- },
- }
- OpGroupFMinNonUniformAMD = &Opcode {
- Opname: "OpGroupFMinNonUniformAMD",
- Class: "Group",
- Opcode: 5002,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdScope,
- Name: "'Execution'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindGroupOperation,
- Name: "'Operation'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'X'",
- Quantifier: "",
- },
- },
- }
- OpGroupUMinNonUniformAMD = &Opcode {
- Opname: "OpGroupUMinNonUniformAMD",
- Class: "Group",
- Opcode: 5003,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdScope,
- Name: "'Execution'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindGroupOperation,
- Name: "'Operation'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'X'",
- Quantifier: "",
- },
- },
- }
- OpGroupSMinNonUniformAMD = &Opcode {
- Opname: "OpGroupSMinNonUniformAMD",
- Class: "Group",
- Opcode: 5004,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdScope,
- Name: "'Execution'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindGroupOperation,
- Name: "'Operation'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'X'",
- Quantifier: "",
- },
- },
- }
- OpGroupFMaxNonUniformAMD = &Opcode {
- Opname: "OpGroupFMaxNonUniformAMD",
- Class: "Group",
- Opcode: 5005,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdScope,
- Name: "'Execution'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindGroupOperation,
- Name: "'Operation'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'X'",
- Quantifier: "",
- },
- },
- }
- OpGroupUMaxNonUniformAMD = &Opcode {
- Opname: "OpGroupUMaxNonUniformAMD",
- Class: "Group",
- Opcode: 5006,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdScope,
- Name: "'Execution'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindGroupOperation,
- Name: "'Operation'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'X'",
- Quantifier: "",
- },
- },
- }
- OpGroupSMaxNonUniformAMD = &Opcode {
- Opname: "OpGroupSMaxNonUniformAMD",
- Class: "Group",
- Opcode: 5007,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdScope,
- Name: "'Execution'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindGroupOperation,
- Name: "'Operation'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'X'",
- Quantifier: "",
- },
- },
- }
- OpFragmentMaskFetchAMD = &Opcode {
- Opname: "OpFragmentMaskFetchAMD",
+ OpTraceRayKHR = &Opcode {
+ Opname: "OpTraceRayKHR",
Class: "Reserved",
- Opcode: 5011,
+ Opcode: 4445,
Operands: []Operand {
Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Image'",
- Quantifier: "",
- },
- Operand {
Kind: OperandKindIdRef,
- Name: "'Coordinate'",
- Quantifier: "",
- },
- },
- }
- OpFragmentFetchAMD = &Opcode {
- Opname: "OpFragmentFetchAMD",
- Class: "Reserved",
- Opcode: 5012,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
+ Name: "'Accel'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Image'",
+ Name: "'Ray Flags'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Coordinate'",
+ Name: "'Cull Mask'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Fragment Index'",
- Quantifier: "",
- },
- },
- }
- OpReadClockKHR = &Opcode {
- Opname: "OpReadClockKHR",
- Class: "Reserved",
- Opcode: 5056,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdScope,
- Name: "'Execution'",
- Quantifier: "",
- },
- },
- }
- OpImageSampleFootprintNV = &Opcode {
- Opname: "OpImageSampleFootprintNV",
- Class: "Image",
- Opcode: 5283,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
+ Name: "'SBT Offset'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Sampled Image'",
+ Name: "'SBT Stride'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Coordinate'",
+ Name: "'Miss Index'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Granularity'",
+ Name: "'Ray Origin'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Coarse'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindImageOperands,
- Name: "",
- Quantifier: "?",
- },
- },
- }
- OpGroupNonUniformPartitionNV = &Opcode {
- Opname: "OpGroupNonUniformPartitionNV",
- Class: "Non-Uniform",
- Opcode: 5296,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
+ Name: "'Ray Tmin'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Value'",
+ Name: "'Ray Direction'",
Quantifier: "",
},
- },
- }
- OpWritePackedPrimitiveIndices4x8NV = &Opcode {
- Opname: "OpWritePackedPrimitiveIndices4x8NV",
- Class: "Reserved",
- Opcode: 5299,
- Operands: []Operand {
Operand {
Kind: OperandKindIdRef,
- Name: "'Index Offset'",
+ Name: "'Ray Tmax'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Packed Indices'",
+ Name: "'Payload'",
Quantifier: "",
},
},
}
- OpReportIntersectionNV = &Opcode {
- Opname: "OpReportIntersectionNV",
+ OpExecuteCallableKHR = &Opcode {
+ Opname: "OpExecuteCallableKHR",
Class: "Reserved",
- Opcode: 5334,
+ Opcode: 4446,
Operands: []Operand {
Operand {
- Kind: OperandKindIdResultType,
- Name: "",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- Operand {
Kind: OperandKindIdRef,
- Name: "'Hit'",
+ Name: "'SBT Index'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'HitKind'",
+ Name: "'Callable Data'",
Quantifier: "",
},
},
}
- OpReportIntersectionKHR = &Opcode {
- Opname: "OpReportIntersectionKHR",
+ OpConvertUToAccelerationStructureKHR = &Opcode {
+ Opname: "OpConvertUToAccelerationStructureKHR",
Class: "Reserved",
- Opcode: 5334,
+ Opcode: 4447,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -10621,192 +10285,25 @@ var (
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Hit'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'HitKind'",
+ Name: "'Accel'",
Quantifier: "",
},
},
}
- OpIgnoreIntersectionNV = &Opcode {
- Opname: "OpIgnoreIntersectionNV",
- Class: "Reserved",
- Opcode: 5335,
- Operands: []Operand {
- },
- }
OpIgnoreIntersectionKHR = &Opcode {
Opname: "OpIgnoreIntersectionKHR",
Class: "Reserved",
- Opcode: 5335,
- Operands: []Operand {
- },
- }
- OpTerminateRayNV = &Opcode {
- Opname: "OpTerminateRayNV",
- Class: "Reserved",
- Opcode: 5336,
+ Opcode: 4448,
Operands: []Operand {
},
}
OpTerminateRayKHR = &Opcode {
Opname: "OpTerminateRayKHR",
Class: "Reserved",
- Opcode: 5336,
+ Opcode: 4449,
Operands: []Operand {
},
}
- OpTraceNV = &Opcode {
- Opname: "OpTraceNV",
- Class: "Reserved",
- Opcode: 5337,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Accel'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Ray Flags'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Cull Mask'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'SBT Offset'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'SBT Stride'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Miss Index'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Ray Origin'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Ray Tmin'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Ray Direction'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Ray Tmax'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'PayloadId'",
- Quantifier: "",
- },
- },
- }
- OpTraceRayKHR = &Opcode {
- Opname: "OpTraceRayKHR",
- Class: "Reserved",
- Opcode: 5337,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Accel'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Ray Flags'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Cull Mask'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'SBT Offset'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'SBT Stride'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Miss Index'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Ray Origin'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Ray Tmin'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Ray Direction'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'Ray Tmax'",
- Quantifier: "",
- },
- Operand {
- Kind: OperandKindIdRef,
- Name: "'PayloadId'",
- Quantifier: "",
- },
- },
- }
- OpTypeAccelerationStructureNV = &Opcode {
- Opname: "OpTypeAccelerationStructureNV",
- Class: "Reserved",
- Opcode: 5341,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- },
- }
- OpTypeAccelerationStructureKHR = &Opcode {
- Opname: "OpTypeAccelerationStructureKHR",
- Class: "Reserved",
- Opcode: 5341,
- Operands: []Operand {
- Operand {
- Kind: OperandKindIdResult,
- Name: "",
- Quantifier: "",
- },
- },
- }
OpTypeRayQueryKHR = &Opcode {
Opname: "OpTypeRayQueryKHR",
Class: "Reserved",
@@ -10956,10 +10453,10 @@ var (
},
},
}
- OpRayQueryGetRayTMinKHR = &Opcode {
- Opname: "OpRayQueryGetRayTMinKHR",
- Class: "Reserved",
- Opcode: 6016,
+ OpGroupIAddNonUniformAMD = &Opcode {
+ Opname: "OpGroupIAddNonUniformAMD",
+ Class: "Group",
+ Opcode: 5000,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -10972,16 +10469,26 @@ var (
Quantifier: "",
},
Operand {
+ Kind: OperandKindIdScope,
+ Name: "'Execution'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindGroupOperation,
+ Name: "'Operation'",
+ Quantifier: "",
+ },
+ Operand {
Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Name: "'X'",
Quantifier: "",
},
},
}
- OpRayQueryGetRayFlagsKHR = &Opcode {
- Opname: "OpRayQueryGetRayFlagsKHR",
- Class: "Reserved",
- Opcode: 6017,
+ OpGroupFAddNonUniformAMD = &Opcode {
+ Opname: "OpGroupFAddNonUniformAMD",
+ Class: "Group",
+ Opcode: 5001,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -10994,16 +10501,26 @@ var (
Quantifier: "",
},
Operand {
+ Kind: OperandKindIdScope,
+ Name: "'Execution'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindGroupOperation,
+ Name: "'Operation'",
+ Quantifier: "",
+ },
+ Operand {
Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Name: "'X'",
Quantifier: "",
},
},
}
- OpRayQueryGetIntersectionTKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionTKHR",
- Class: "Reserved",
- Opcode: 6018,
+ OpGroupFMinNonUniformAMD = &Opcode {
+ Opname: "OpGroupFMinNonUniformAMD",
+ Class: "Group",
+ Opcode: 5002,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11016,21 +10533,26 @@ var (
Quantifier: "",
},
Operand {
- Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Kind: OperandKindIdScope,
+ Name: "'Execution'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindGroupOperation,
+ Name: "'Operation'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Intersection'",
+ Name: "'X'",
Quantifier: "",
},
},
}
- OpRayQueryGetIntersectionInstanceCustomIndexKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionInstanceCustomIndexKHR",
- Class: "Reserved",
- Opcode: 6019,
+ OpGroupUMinNonUniformAMD = &Opcode {
+ Opname: "OpGroupUMinNonUniformAMD",
+ Class: "Group",
+ Opcode: 5003,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11043,21 +10565,26 @@ var (
Quantifier: "",
},
Operand {
- Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Kind: OperandKindIdScope,
+ Name: "'Execution'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindGroupOperation,
+ Name: "'Operation'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Intersection'",
+ Name: "'X'",
Quantifier: "",
},
},
}
- OpRayQueryGetIntersectionInstanceIdKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionInstanceIdKHR",
- Class: "Reserved",
- Opcode: 6020,
+ OpGroupSMinNonUniformAMD = &Opcode {
+ Opname: "OpGroupSMinNonUniformAMD",
+ Class: "Group",
+ Opcode: 5004,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11070,21 +10597,26 @@ var (
Quantifier: "",
},
Operand {
- Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Kind: OperandKindIdScope,
+ Name: "'Execution'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindGroupOperation,
+ Name: "'Operation'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Intersection'",
+ Name: "'X'",
Quantifier: "",
},
},
}
- OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR",
- Class: "Reserved",
- Opcode: 6021,
+ OpGroupFMaxNonUniformAMD = &Opcode {
+ Opname: "OpGroupFMaxNonUniformAMD",
+ Class: "Group",
+ Opcode: 5005,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11097,21 +10629,26 @@ var (
Quantifier: "",
},
Operand {
- Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Kind: OperandKindIdScope,
+ Name: "'Execution'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindGroupOperation,
+ Name: "'Operation'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Intersection'",
+ Name: "'X'",
Quantifier: "",
},
},
}
- OpRayQueryGetIntersectionGeometryIndexKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionGeometryIndexKHR",
- Class: "Reserved",
- Opcode: 6022,
+ OpGroupUMaxNonUniformAMD = &Opcode {
+ Opname: "OpGroupUMaxNonUniformAMD",
+ Class: "Group",
+ Opcode: 5006,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11124,21 +10661,26 @@ var (
Quantifier: "",
},
Operand {
- Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Kind: OperandKindIdScope,
+ Name: "'Execution'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindGroupOperation,
+ Name: "'Operation'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Intersection'",
+ Name: "'X'",
Quantifier: "",
},
},
}
- OpRayQueryGetIntersectionPrimitiveIndexKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionPrimitiveIndexKHR",
- Class: "Reserved",
- Opcode: 6023,
+ OpGroupSMaxNonUniformAMD = &Opcode {
+ Opname: "OpGroupSMaxNonUniformAMD",
+ Class: "Group",
+ Opcode: 5007,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11151,21 +10693,26 @@ var (
Quantifier: "",
},
Operand {
- Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Kind: OperandKindIdScope,
+ Name: "'Execution'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindGroupOperation,
+ Name: "'Operation'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Intersection'",
+ Name: "'X'",
Quantifier: "",
},
},
}
- OpRayQueryGetIntersectionBarycentricsKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionBarycentricsKHR",
+ OpFragmentMaskFetchAMD = &Opcode {
+ Opname: "OpFragmentMaskFetchAMD",
Class: "Reserved",
- Opcode: 6024,
+ Opcode: 5011,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11179,20 +10726,20 @@ var (
},
Operand {
Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Name: "'Image'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Intersection'",
+ Name: "'Coordinate'",
Quantifier: "",
},
},
}
- OpRayQueryGetIntersectionFrontFaceKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionFrontFaceKHR",
+ OpFragmentFetchAMD = &Opcode {
+ Opname: "OpFragmentFetchAMD",
Class: "Reserved",
- Opcode: 6025,
+ Opcode: 5012,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11206,20 +10753,25 @@ var (
},
Operand {
Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Name: "'Image'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Intersection'",
+ Name: "'Coordinate'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Fragment Index'",
Quantifier: "",
},
},
}
- OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR",
+ OpReadClockKHR = &Opcode {
+ Opname: "OpReadClockKHR",
Class: "Reserved",
- Opcode: 6026,
+ Opcode: 5056,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11232,16 +10784,16 @@ var (
Quantifier: "",
},
Operand {
- Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Kind: OperandKindIdScope,
+ Name: "'Execution'",
Quantifier: "",
},
},
}
- OpRayQueryGetIntersectionObjectRayDirectionKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionObjectRayDirectionKHR",
- Class: "Reserved",
- Opcode: 6027,
+ OpImageSampleFootprintNV = &Opcode {
+ Opname: "OpImageSampleFootprintNV",
+ Class: "Image",
+ Opcode: 5283,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11255,20 +10807,35 @@ var (
},
Operand {
Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Name: "'Sampled Image'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Intersection'",
+ Name: "'Coordinate'",
Quantifier: "",
},
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Granularity'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Coarse'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindImageOperands,
+ Name: "",
+ Quantifier: "?",
+ },
},
}
- OpRayQueryGetIntersectionObjectRayOriginKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionObjectRayOriginKHR",
- Class: "Reserved",
- Opcode: 6028,
+ OpGroupNonUniformPartitionNV = &Opcode {
+ Opname: "OpGroupNonUniformPartitionNV",
+ Class: "Non-Uniform",
+ Opcode: 5296,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11282,20 +10849,32 @@ var (
},
Operand {
Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Name: "'Value'",
Quantifier: "",
},
+ },
+ }
+ OpWritePackedPrimitiveIndices4x8NV = &Opcode {
+ Opname: "OpWritePackedPrimitiveIndices4x8NV",
+ Class: "Reserved",
+ Opcode: 5299,
+ Operands: []Operand {
Operand {
Kind: OperandKindIdRef,
- Name: "'Intersection'",
+ Name: "'Index Offset'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Packed Indices'",
Quantifier: "",
},
},
}
- OpRayQueryGetWorldRayDirectionKHR = &Opcode {
- Opname: "OpRayQueryGetWorldRayDirectionKHR",
+ OpReportIntersectionNV = &Opcode {
+ Opname: "OpReportIntersectionNV",
Class: "Reserved",
- Opcode: 6029,
+ Opcode: 5334,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11309,15 +10888,20 @@ var (
},
Operand {
Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Name: "'Hit'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'HitKind'",
Quantifier: "",
},
},
}
- OpRayQueryGetWorldRayOriginKHR = &Opcode {
- Opname: "OpRayQueryGetWorldRayOriginKHR",
+ OpReportIntersectionKHR = &Opcode {
+ Opname: "OpReportIntersectionKHR",
Class: "Reserved",
- Opcode: 6030,
+ Opcode: 5334,
Operands: []Operand {
Operand {
Kind: OperandKindIdResultType,
@@ -11331,84 +10915,118 @@ var (
},
Operand {
Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Name: "'Hit'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'HitKind'",
Quantifier: "",
},
},
}
- OpRayQueryGetIntersectionObjectToWorldKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionObjectToWorldKHR",
+ OpIgnoreIntersectionNV = &Opcode {
+ Opname: "OpIgnoreIntersectionNV",
Class: "Reserved",
- Opcode: 6031,
+ Opcode: 5335,
+ Operands: []Operand {
+ },
+ }
+ OpTerminateRayNV = &Opcode {
+ Opname: "OpTerminateRayNV",
+ Class: "Reserved",
+ Opcode: 5336,
+ Operands: []Operand {
+ },
+ }
+ OpTraceNV = &Opcode {
+ Opname: "OpTraceNV",
+ Class: "Reserved",
+ Opcode: 5337,
Operands: []Operand {
Operand {
- Kind: OperandKindIdResultType,
- Name: "",
+ Kind: OperandKindIdRef,
+ Name: "'Accel'",
Quantifier: "",
},
Operand {
- Kind: OperandKindIdResult,
- Name: "",
+ Kind: OperandKindIdRef,
+ Name: "'Ray Flags'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Name: "'Cull Mask'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Intersection'",
+ Name: "'SBT Offset'",
Quantifier: "",
},
- },
- }
- OpRayQueryGetIntersectionWorldToObjectKHR = &Opcode {
- Opname: "OpRayQueryGetIntersectionWorldToObjectKHR",
- Class: "Reserved",
- Opcode: 6032,
- Operands: []Operand {
Operand {
- Kind: OperandKindIdResultType,
- Name: "",
+ Kind: OperandKindIdRef,
+ Name: "'SBT Stride'",
Quantifier: "",
},
Operand {
- Kind: OperandKindIdResult,
- Name: "",
+ Kind: OperandKindIdRef,
+ Name: "'Miss Index'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'RayQuery'",
+ Name: "'Ray Origin'",
Quantifier: "",
},
Operand {
Kind: OperandKindIdRef,
- Name: "'Intersection'",
+ Name: "'Ray Tmin'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Ray Direction'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Ray Tmax'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'PayloadId'",
Quantifier: "",
},
},
}
- OpExecuteCallableNV = &Opcode {
- Opname: "OpExecuteCallableNV",
+ OpTypeAccelerationStructureNV = &Opcode {
+ Opname: "OpTypeAccelerationStructureNV",
Class: "Reserved",
- Opcode: 5344,
+ Opcode: 5341,
Operands: []Operand {
Operand {
- Kind: OperandKindIdRef,
- Name: "'SBT Index'",
+ Kind: OperandKindIdResult,
+ Name: "",
Quantifier: "",
},
+ },
+ }
+ OpTypeAccelerationStructureKHR = &Opcode {
+ Opname: "OpTypeAccelerationStructureKHR",
+ Class: "Reserved",
+ Opcode: 5341,
+ Operands: []Operand {
Operand {
- Kind: OperandKindIdRef,
- Name: "'Callable DataId'",
+ Kind: OperandKindIdResult,
+ Name: "",
Quantifier: "",
},
},
}
- OpExecuteCallableKHR = &Opcode {
- Opname: "OpExecuteCallableKHR",
+ OpExecuteCallableNV = &Opcode {
+ Opname: "OpExecuteCallableNV",
Class: "Reserved",
Opcode: 5344,
Operands: []Operand {
@@ -12260,6 +11878,210 @@ var (
},
},
}
+ OpConstFunctionPointerINTEL = &Opcode {
+ Opname: "OpConstFunctionPointerINTEL",
+ Class: "@exclude",
+ Opcode: 5600,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Function'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpFunctionPointerCallINTEL = &Opcode {
+ Opname: "OpFunctionPointerCallINTEL",
+ Class: "@exclude",
+ Opcode: 5601,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Operand 1'",
+ Quantifier: "*",
+ },
+ },
+ }
+ OpAsmTargetINTEL = &Opcode {
+ Opname: "OpAsmTargetINTEL",
+ Class: "@exclude",
+ Opcode: 5609,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindLiteralString,
+ Name: "'Asm target'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpAsmINTEL = &Opcode {
+ Opname: "OpAsmINTEL",
+ Class: "@exclude",
+ Opcode: 5610,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Asm type'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Target'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindLiteralString,
+ Name: "'Asm instructions'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindLiteralString,
+ Name: "'Constraints'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpAsmCallINTEL = &Opcode {
+ Opname: "OpAsmCallINTEL",
+ Class: "@exclude",
+ Opcode: 5611,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Asm'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Argument 0'",
+ Quantifier: "*",
+ },
+ },
+ }
+ OpAtomicFMinEXT = &Opcode {
+ Opname: "OpAtomicFMinEXT",
+ Class: "Atomic",
+ Opcode: 5614,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Pointer'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdScope,
+ Name: "'Memory'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdMemorySemantics,
+ Name: "'Semantics'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Value'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpAtomicFMaxEXT = &Opcode {
+ Opname: "OpAtomicFMaxEXT",
+ Class: "Atomic",
+ Opcode: 5615,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Pointer'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdScope,
+ Name: "'Memory'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdMemorySemantics,
+ Name: "'Semantics'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Value'",
+ Quantifier: "",
+ },
+ },
+ }
OpDecorateString = &Opcode {
Opname: "OpDecorateString",
Class: "Annotation",
@@ -15439,6 +15261,713 @@ var (
},
},
}
+ OpVariableLengthArrayINTEL = &Opcode {
+ Opname: "OpVariableLengthArrayINTEL",
+ Class: "@exclude",
+ Opcode: 5818,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Lenght'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpSaveMemoryINTEL = &Opcode {
+ Opname: "OpSaveMemoryINTEL",
+ Class: "@exclude",
+ Opcode: 5819,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRestoreMemoryINTEL = &Opcode {
+ Opname: "OpRestoreMemoryINTEL",
+ Class: "@exclude",
+ Opcode: 5820,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Ptr'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpLoopControlINTEL = &Opcode {
+ Opname: "OpLoopControlINTEL",
+ Class: "Reserved",
+ Opcode: 5887,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindLiteralInteger,
+ Name: "'Loop Control Parameters'",
+ Quantifier: "*",
+ },
+ },
+ }
+ OpPtrCastToCrossWorkgroupINTEL = &Opcode {
+ Opname: "OpPtrCastToCrossWorkgroupINTEL",
+ Class: "@exclude",
+ Opcode: 5934,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Pointer'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpCrossWorkgroupCastToPtrINTEL = &Opcode {
+ Opname: "OpCrossWorkgroupCastToPtrINTEL",
+ Class: "@exclude",
+ Opcode: 5938,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Pointer'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpReadPipeBlockingINTEL = &Opcode {
+ Opname: "OpReadPipeBlockingINTEL",
+ Class: "Pipe",
+ Opcode: 5946,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Packet Size'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Packet Alignment'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpWritePipeBlockingINTEL = &Opcode {
+ Opname: "OpWritePipeBlockingINTEL",
+ Class: "Pipe",
+ Opcode: 5947,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Packet Size'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Packet Alignment'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpFPGARegINTEL = &Opcode {
+ Opname: "OpFPGARegINTEL",
+ Class: "Reserved",
+ Opcode: 5949,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Result'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Input'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetRayTMinKHR = &Opcode {
+ Opname: "OpRayQueryGetRayTMinKHR",
+ Class: "Reserved",
+ Opcode: 6016,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetRayFlagsKHR = &Opcode {
+ Opname: "OpRayQueryGetRayFlagsKHR",
+ Class: "Reserved",
+ Opcode: 6017,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionTKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionTKHR",
+ Class: "Reserved",
+ Opcode: 6018,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Intersection'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionInstanceCustomIndexKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionInstanceCustomIndexKHR",
+ Class: "Reserved",
+ Opcode: 6019,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Intersection'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionInstanceIdKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionInstanceIdKHR",
+ Class: "Reserved",
+ Opcode: 6020,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Intersection'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR",
+ Class: "Reserved",
+ Opcode: 6021,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Intersection'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionGeometryIndexKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionGeometryIndexKHR",
+ Class: "Reserved",
+ Opcode: 6022,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Intersection'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionPrimitiveIndexKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionPrimitiveIndexKHR",
+ Class: "Reserved",
+ Opcode: 6023,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Intersection'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionBarycentricsKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionBarycentricsKHR",
+ Class: "Reserved",
+ Opcode: 6024,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Intersection'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionFrontFaceKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionFrontFaceKHR",
+ Class: "Reserved",
+ Opcode: 6025,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Intersection'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR",
+ Class: "Reserved",
+ Opcode: 6026,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionObjectRayDirectionKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionObjectRayDirectionKHR",
+ Class: "Reserved",
+ Opcode: 6027,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Intersection'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionObjectRayOriginKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionObjectRayOriginKHR",
+ Class: "Reserved",
+ Opcode: 6028,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Intersection'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetWorldRayDirectionKHR = &Opcode {
+ Opname: "OpRayQueryGetWorldRayDirectionKHR",
+ Class: "Reserved",
+ Opcode: 6029,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetWorldRayOriginKHR = &Opcode {
+ Opname: "OpRayQueryGetWorldRayOriginKHR",
+ Class: "Reserved",
+ Opcode: 6030,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionObjectToWorldKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionObjectToWorldKHR",
+ Class: "Reserved",
+ Opcode: 6031,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Intersection'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpRayQueryGetIntersectionWorldToObjectKHR = &Opcode {
+ Opname: "OpRayQueryGetIntersectionWorldToObjectKHR",
+ Class: "Reserved",
+ Opcode: 6032,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'RayQuery'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Intersection'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpAtomicFAddEXT = &Opcode {
+ Opname: "OpAtomicFAddEXT",
+ Class: "Atomic",
+ Opcode: 6035,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResultType,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Pointer'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdScope,
+ Name: "'Memory'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdMemorySemantics,
+ Name: "'Semantics'",
+ Quantifier: "",
+ },
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Value'",
+ Quantifier: "",
+ },
+ },
+ }
+ OpTypeBufferSurfaceINTEL = &Opcode {
+ Opname: "OpTypeBufferSurfaceINTEL",
+ Class: "Type-Declaration",
+ Opcode: 6086,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdResult,
+ Name: "",
+ Quantifier: "",
+ },
+ },
+ }
+ OpTypeStructContinuedINTEL = &Opcode {
+ Opname: "OpTypeStructContinuedINTEL",
+ Class: "Type-Declaration",
+ Opcode: 6090,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Member 0 type', + 'member 1 type', + ...",
+ Quantifier: "*",
+ },
+ },
+ }
+ OpConstantCompositeContinuedINTEL = &Opcode {
+ Opname: "OpConstantCompositeContinuedINTEL",
+ Class: "Constant-Creation",
+ Opcode: 6091,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Constituents'",
+ Quantifier: "*",
+ },
+ },
+ }
+ OpSpecConstantCompositeContinuedINTEL = &Opcode {
+ Opname: "OpSpecConstantCompositeContinuedINTEL",
+ Class: "Constant-Creation",
+ Opcode: 6092,
+ Operands: []Operand {
+ Operand {
+ Kind: OperandKindIdRef,
+ Name: "'Constituents'",
+ Quantifier: "*",
+ },
+ },
+ }
GLSLStd450_Round = &Opcode {
Opname: "Round",
@@ -19788,6 +20317,20 @@ var (
Parameters: []Parameter{},
Version: "",
},
+ Enumerant{
+ Enumerant: "AllowContractFastINTEL",
+ Value: 0x10000,
+ Capabilities: []string{"FPFastMathModeINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "AllowReassocINTEL",
+ Value: 0x20000,
+ Capabilities: []string{"FPFastMathModeINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
},
Bases: []*OperandKind {},
}
@@ -19893,6 +20436,62 @@ var (
Parameters: []Parameter{{OperandKindLiteralInteger, ""},},
Version: "1.4",
},
+ Enumerant{
+ Enumerant: "InitiationIntervalINTEL",
+ Value: 0x10000,
+ Capabilities: []string{"FPGALoopControlsINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, ""},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "MaxConcurrencyINTEL",
+ Value: 0x20000,
+ Capabilities: []string{"FPGALoopControlsINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, ""},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "DependencyArrayINTEL",
+ Value: 0x40000,
+ Capabilities: []string{"FPGALoopControlsINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, ""},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "PipelineEnableINTEL",
+ Value: 0x80000,
+ Capabilities: []string{"FPGALoopControlsINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, ""},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "LoopCoalesceINTEL",
+ Value: 0x100000,
+ Capabilities: []string{"FPGALoopControlsINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, ""},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "MaxInterleavingINTEL",
+ Value: 0x200000,
+ Capabilities: []string{"FPGALoopControlsINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, ""},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "SpeculatedIterationsINTEL",
+ Value: 0x400000,
+ Capabilities: []string{"FPGALoopControlsINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, ""},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "NoFusionINTEL",
+ Value: 0x800000,
+ Capabilities: []string{"FPGALoopControlsINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, ""},},
+ Version: "None",
+ },
},
Bases: []*OperandKind {},
}
@@ -20185,77 +20784,112 @@ var (
Value: 0x0000,
Capabilities: []string{"RayQueryKHR","RayTracingKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "OpaqueKHR",
Value: 0x0001,
Capabilities: []string{"RayQueryKHR","RayTracingKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "NoOpaqueKHR",
Value: 0x0002,
Capabilities: []string{"RayQueryKHR","RayTracingKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "TerminateOnFirstHitKHR",
Value: 0x0004,
Capabilities: []string{"RayQueryKHR","RayTracingKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "SkipClosestHitShaderKHR",
Value: 0x0008,
Capabilities: []string{"RayQueryKHR","RayTracingKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "CullBackFacingTrianglesKHR",
Value: 0x0010,
Capabilities: []string{"RayQueryKHR","RayTracingKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "CullFrontFacingTrianglesKHR",
Value: 0x0020,
Capabilities: []string{"RayQueryKHR","RayTracingKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "CullOpaqueKHR",
Value: 0x0040,
Capabilities: []string{"RayQueryKHR","RayTracingKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "CullNoOpaqueKHR",
Value: 0x0080,
Capabilities: []string{"RayQueryKHR","RayTracingKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "SkipTrianglesKHR",
Value: 0x0100,
Capabilities: []string{"RayTraversalPrimitiveCullingKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "SkipAABBsKHR",
Value: 0x0200,
Capabilities: []string{"RayTraversalPrimitiveCullingKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
+ },
+ },
+ Bases: []*OperandKind {},
+ }
+ OperandKindFragmentShadingRate = &OperandKind {
+ Kind: "FragmentShadingRate",
+ Category: "BitEnum",
+ Enumerants: []Enumerant {
+ Enumerant{
+ Enumerant: "Vertical2Pixels",
+ Value: 0x0001,
+ Capabilities: []string{"FragmentShadingRateKHR",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "Vertical4Pixels",
+ Value: 0x0002,
+ Capabilities: []string{"FragmentShadingRateKHR",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "Horizontal2Pixels",
+ Value: 0x0004,
+ Capabilities: []string{"FragmentShadingRateKHR",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "Horizontal4Pixels",
+ Value: 0x0008,
+ Capabilities: []string{"FragmentShadingRateKHR",},
+ Parameters: []Parameter{},
+ Version: "None",
},
},
Bases: []*OperandKind {},
@@ -20943,6 +21577,76 @@ var (
Parameters: []Parameter{},
Version: "None",
},
+ Enumerant{
+ Enumerant: "SharedLocalMemorySizeINTEL",
+ Value: 5618,
+ Capabilities: []string{"VectorComputeINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Size'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "RoundingModeRTPINTEL",
+ Value: 5620,
+ Capabilities: []string{"RoundToInfinityINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Target Width'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "RoundingModeRTNINTEL",
+ Value: 5621,
+ Capabilities: []string{"RoundToInfinityINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Target Width'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FloatingPointModeALTINTEL",
+ Value: 5622,
+ Capabilities: []string{"RoundToInfinityINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Target Width'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FloatingPointModeIEEEINTEL",
+ Value: 5623,
+ Capabilities: []string{"RoundToInfinityINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Target Width'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "MaxWorkgroupSizeINTEL",
+ Value: 5893,
+ Capabilities: []string{"KernelAttributesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'max_x_size'"},{OperandKindLiteralInteger, "'max_y_size'"},{OperandKindLiteralInteger, "'max_z_size'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "MaxWorkDimINTEL",
+ Value: 5894,
+ Capabilities: []string{"KernelAttributesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'max_dimensions'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "NoGlobalOffsetINTEL",
+ Value: 5895,
+ Capabilities: []string{"KernelAttributesINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "NumSIMDWorkitemsINTEL",
+ Value: 5896,
+ Capabilities: []string{"FPGAKernelAttributesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'vector_width'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "SchedulerTargetFmaxMhzINTEL",
+ Value: 5903,
+ Capabilities: []string{"FPGAKernelAttributesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'target_fmax'"},},
+ Version: "None",
+ },
},
Bases: []*OperandKind {},
}
@@ -21139,6 +21843,27 @@ var (
Parameters: []Parameter{},
Version: "1.5",
},
+ Enumerant{
+ Enumerant: "CodeSectionINTEL",
+ Value: 5605,
+ Capabilities: []string{"FunctionPointersINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "DeviceOnlyINTEL",
+ Value: 5936,
+ Capabilities: []string{"USMStorageClassesINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "HostOnlyINTEL",
+ Value: 5937,
+ Capabilities: []string{"USMStorageClassesINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
},
Bases: []*OperandKind {},
}
@@ -21545,6 +22270,20 @@ var (
Parameters: []Parameter{},
Version: "",
},
+ Enumerant{
+ Enumerant: "R64ui",
+ Value: 40,
+ Capabilities: []string{"Int64ImageEXT",},
+ Parameters: []Parameter{},
+ Version: "",
+ },
+ Enumerant{
+ Enumerant: "R64i",
+ Value: 41,
+ Capabilities: []string{"Int64ImageEXT",},
+ Parameters: []Parameter{},
+ Version: "",
+ },
},
Bases: []*OperandKind {},
}
@@ -21856,6 +22595,48 @@ var (
},
Bases: []*OperandKind {},
}
+ OperandKindFPDenormMode = &OperandKind {
+ Kind: "FPDenormMode",
+ Category: "ValueEnum",
+ Enumerants: []Enumerant {
+ Enumerant{
+ Enumerant: "Preserve",
+ Value: 0,
+ Capabilities: []string{"FunctionFloatControlINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FlushToZero",
+ Value: 1,
+ Capabilities: []string{"FunctionFloatControlINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ },
+ Bases: []*OperandKind {},
+ }
+ OperandKindFPOperationMode = &OperandKind {
+ Kind: "FPOperationMode",
+ Category: "ValueEnum",
+ Enumerants: []Enumerant {
+ Enumerant{
+ Enumerant: "IEEE",
+ Value: 0,
+ Capabilities: []string{"FunctionFloatControlINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "ALT",
+ Value: 1,
+ Capabilities: []string{"FunctionFloatControlINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ },
+ Bases: []*OperandKind {},
+ }
OperandKindLinkageType = &OperandKind {
Kind: "LinkageType",
Category: "ValueEnum",
@@ -22421,6 +23202,69 @@ var (
Version: "1.5",
},
Enumerant{
+ Enumerant: "SIMTCallINTEL",
+ Value: 5599,
+ Capabilities: []string{"VectorComputeINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'N'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "ReferencedIndirectlyINTEL",
+ Value: 5602,
+ Capabilities: []string{"IndirectReferencesINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "ClobberINTEL",
+ Value: 5607,
+ Capabilities: []string{"AsmINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralString, "'Register'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "SideEffectsINTEL",
+ Value: 5608,
+ Capabilities: []string{"AsmINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "VectorComputeVariableINTEL",
+ Value: 5624,
+ Capabilities: []string{"VectorComputeINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FuncParamIOKindINTEL",
+ Value: 5625,
+ Capabilities: []string{"VectorComputeINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Kind'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "VectorComputeFunctionINTEL",
+ Value: 5626,
+ Capabilities: []string{"VectorComputeINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "StackCallINTEL",
+ Value: 5627,
+ Capabilities: []string{"VectorComputeINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "GlobalVariableOffsetINTEL",
+ Value: 5628,
+ Capabilities: []string{"VectorComputeINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Offset'"},},
+ Version: "None",
+ },
+ Enumerant{
Enumerant: "CounterBuffer",
Value: 5634,
Capabilities: []string{},
@@ -22455,6 +23299,181 @@ var (
Parameters: []Parameter{{OperandKindLiteralString, "'User Type'"},},
Version: "None",
},
+ Enumerant{
+ Enumerant: "FunctionRoundingModeINTEL",
+ Value: 5822,
+ Capabilities: []string{"FunctionFloatControlINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Target Width'"},{OperandKindFPRoundingMode, "'FP Rounding Mode'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FunctionDenormModeINTEL",
+ Value: 5823,
+ Capabilities: []string{"FunctionFloatControlINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Target Width'"},{OperandKindFPDenormMode, "'FP Denorm Mode'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "RegisterINTEL",
+ Value: 5825,
+ Capabilities: []string{"FPGAMemoryAttributesINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "MemoryINTEL",
+ Value: 5826,
+ Capabilities: []string{"FPGAMemoryAttributesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralString, "'Memory Type'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "NumbanksINTEL",
+ Value: 5827,
+ Capabilities: []string{"FPGAMemoryAttributesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Banks'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "BankwidthINTEL",
+ Value: 5828,
+ Capabilities: []string{"FPGAMemoryAttributesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Bank Width'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "MaxPrivateCopiesINTEL",
+ Value: 5829,
+ Capabilities: []string{"FPGAMemoryAttributesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Maximum Copies'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "SinglepumpINTEL",
+ Value: 5830,
+ Capabilities: []string{"FPGAMemoryAttributesINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "DoublepumpINTEL",
+ Value: 5831,
+ Capabilities: []string{"FPGAMemoryAttributesINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "MaxReplicatesINTEL",
+ Value: 5832,
+ Capabilities: []string{"FPGAMemoryAttributesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Maximum Replicates'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "SimpleDualPortINTEL",
+ Value: 5833,
+ Capabilities: []string{"FPGAMemoryAttributesINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "MergeINTEL",
+ Value: 5834,
+ Capabilities: []string{"FPGAMemoryAttributesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralString, "'Merge Key'"},{OperandKindLiteralString, "'Merge Type'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "BankBitsINTEL",
+ Value: 5835,
+ Capabilities: []string{"FPGAMemoryAttributesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Bank Bits'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "ForcePow2DepthINTEL",
+ Value: 5836,
+ Capabilities: []string{"FPGAMemoryAttributesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Force Key'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "BurstCoalesceINTEL",
+ Value: 5899,
+ Capabilities: []string{"FPGAMemoryAccessesINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "CacheSizeINTEL",
+ Value: 5900,
+ Capabilities: []string{"FPGAMemoryAccessesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Cache Size in bytes'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "DontStaticallyCoalesceINTEL",
+ Value: 5901,
+ Capabilities: []string{"FPGAMemoryAccessesINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "PrefetchINTEL",
+ Value: 5902,
+ Capabilities: []string{"FPGAMemoryAccessesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Prefetcher Size in bytes'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "StallEnableINTEL",
+ Value: 5905,
+ Capabilities: []string{"FPGAClusterAttributesINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FuseLoopsInFunctionINTEL",
+ Value: 5907,
+ Capabilities: []string{"LoopFuseINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "BufferLocationINTEL",
+ Value: 5921,
+ Capabilities: []string{"FPGABufferLocationINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Buffer Location ID'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "IOPipeStorageINTEL",
+ Value: 5944,
+ Capabilities: []string{"IOPipesINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'IO Pipe ID'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FunctionFloatingPointModeINTEL",
+ Value: 6080,
+ Capabilities: []string{"FunctionFloatControlINTEL",},
+ Parameters: []Parameter{{OperandKindLiteralInteger, "'Target Width'"},{OperandKindFPOperationMode, "'FP Operation Mode'"},},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "SingleElementVectorINTEL",
+ Value: 6085,
+ Capabilities: []string{"VectorComputeINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "VectorComputeCallableFunctionINTEL",
+ Value: 6087,
+ Capabilities: []string{"VectorComputeINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
},
Bases: []*OperandKind {},
}
@@ -22507,7 +23526,7 @@ var (
Enumerant{
Enumerant: "PrimitiveId",
Value: 7,
- Capabilities: []string{"Geometry","Tessellation","RayTracingNV","RayTracingKHR",},
+ Capabilities: []string{"Geometry","Tessellation","RayTracingNV","RayTracingKHR","MeshShadingNV",},
Parameters: []Parameter{},
Version: "",
},
@@ -22521,14 +23540,14 @@ var (
Enumerant{
Enumerant: "Layer",
Value: 9,
- Capabilities: []string{"Geometry","ShaderLayer","ShaderViewportIndexLayerEXT",},
+ Capabilities: []string{"Geometry","ShaderLayer","ShaderViewportIndexLayerEXT","MeshShadingNV",},
Parameters: []Parameter{},
Version: "",
},
Enumerant{
Enumerant: "ViewportIndex",
Value: 10,
- Capabilities: []string{"MultiViewport","ShaderViewportIndex","ShaderViewportIndexLayerEXT",},
+ Capabilities: []string{"MultiViewport","ShaderViewportIndex","ShaderViewportIndexLayerEXT","MeshShadingNV",},
Parameters: []Parameter{},
Version: "",
},
@@ -22757,57 +23776,57 @@ var (
Version: "1.3",
},
Enumerant{
- Enumerant: "SubgroupGeMask",
- Value: 4417,
+ Enumerant: "SubgroupEqMaskKHR",
+ Value: 4416,
Capabilities: []string{"SubgroupBallotKHR","GroupNonUniformBallot",},
Parameters: []Parameter{},
Version: "1.3",
},
Enumerant{
- Enumerant: "SubgroupGtMask",
- Value: 4418,
+ Enumerant: "SubgroupGeMask",
+ Value: 4417,
Capabilities: []string{"SubgroupBallotKHR","GroupNonUniformBallot",},
Parameters: []Parameter{},
Version: "1.3",
},
Enumerant{
- Enumerant: "SubgroupLeMask",
- Value: 4419,
+ Enumerant: "SubgroupGeMaskKHR",
+ Value: 4417,
Capabilities: []string{"SubgroupBallotKHR","GroupNonUniformBallot",},
Parameters: []Parameter{},
Version: "1.3",
},
Enumerant{
- Enumerant: "SubgroupLtMask",
- Value: 4420,
+ Enumerant: "SubgroupGtMask",
+ Value: 4418,
Capabilities: []string{"SubgroupBallotKHR","GroupNonUniformBallot",},
Parameters: []Parameter{},
Version: "1.3",
},
Enumerant{
- Enumerant: "SubgroupEqMaskKHR",
- Value: 4416,
+ Enumerant: "SubgroupGtMaskKHR",
+ Value: 4418,
Capabilities: []string{"SubgroupBallotKHR","GroupNonUniformBallot",},
Parameters: []Parameter{},
Version: "1.3",
},
Enumerant{
- Enumerant: "SubgroupGeMaskKHR",
- Value: 4417,
+ Enumerant: "SubgroupLeMask",
+ Value: 4419,
Capabilities: []string{"SubgroupBallotKHR","GroupNonUniformBallot",},
Parameters: []Parameter{},
Version: "1.3",
},
Enumerant{
- Enumerant: "SubgroupGtMaskKHR",
- Value: 4418,
+ Enumerant: "SubgroupLeMaskKHR",
+ Value: 4419,
Capabilities: []string{"SubgroupBallotKHR","GroupNonUniformBallot",},
Parameters: []Parameter{},
Version: "1.3",
},
Enumerant{
- Enumerant: "SubgroupLeMaskKHR",
- Value: 4419,
+ Enumerant: "SubgroupLtMask",
+ Value: 4420,
Capabilities: []string{"SubgroupBallotKHR","GroupNonUniformBallot",},
Parameters: []Parameter{},
Version: "1.3",
@@ -22841,6 +23860,13 @@ var (
Version: "1.3",
},
Enumerant{
+ Enumerant: "PrimitiveShadingRateKHR",
+ Value: 4432,
+ Capabilities: []string{"FragmentShadingRateKHR",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
Enumerant: "DeviceIndex",
Value: 4438,
Capabilities: []string{"DeviceGroup",},
@@ -22855,6 +23881,13 @@ var (
Version: "1.3",
},
Enumerant{
+ Enumerant: "ShadingRateKHR",
+ Value: 4444,
+ Capabilities: []string{"FragmentShadingRateKHR",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
Enumerant: "BaryCoordNoPerspAMD",
Value: 4992,
Capabilities: []string{},
@@ -23207,14 +24240,7 @@ var (
Enumerant{
Enumerant: "HitTNV",
Value: 5332,
- Capabilities: []string{"RayTracingNV","RayTracingKHR",},
- Parameters: []Parameter{},
- Version: "None",
- },
- Enumerant{
- Enumerant: "HitTKHR",
- Value: 5332,
- Capabilities: []string{"RayTracingNV","RayTracingKHR",},
+ Capabilities: []string{"RayTracingNV",},
Parameters: []Parameter{},
Version: "None",
},
@@ -23342,7 +24368,7 @@ var (
Value: 6,
Capabilities: []string{"RayTracingKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
},
Bases: []*OperandKind {},
@@ -23919,6 +24945,13 @@ var (
Version: "1.5",
},
Enumerant{
+ Enumerant: "FragmentShadingRateKHR",
+ Value: 4422,
+ Capabilities: []string{"Shader",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
Enumerant: "SubgroupBallotKHR",
Value: 4423,
Capabilities: []string{},
@@ -23933,6 +24966,27 @@ var (
Version: "1.3",
},
Enumerant{
+ Enumerant: "WorkgroupMemoryExplicitLayoutKHR",
+ Value: 4428,
+ Capabilities: []string{"Shader",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "WorkgroupMemoryExplicitLayout8BitAccessKHR",
+ Value: 4429,
+ Capabilities: []string{"WorkgroupMemoryExplicitLayoutKHR",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "WorkgroupMemoryExplicitLayout16BitAccessKHR",
+ Value: 4430,
+ Capabilities: []string{"Shader",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
Enumerant: "SubgroupVoteKHR",
Value: 4431,
Capabilities: []string{},
@@ -24080,13 +25134,20 @@ var (
Version: "1.4",
},
Enumerant{
- Enumerant: "RayQueryKHR",
+ Enumerant: "RayQueryProvisionalKHR",
Value: 4471,
Capabilities: []string{"Shader",},
Parameters: []Parameter{},
Version: "None",
},
Enumerant{
+ Enumerant: "RayQueryKHR",
+ Value: 4472,
+ Capabilities: []string{"Shader",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
Enumerant: "RayTraversalPrimitiveCullingKHR",
Value: 4478,
Capabilities: []string{"RayQueryKHR","RayTracingKHR",},
@@ -24094,6 +25155,13 @@ var (
Version: "None",
},
Enumerant{
+ Enumerant: "RayTracingKHR",
+ Value: 4479,
+ Capabilities: []string{"Shader",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
Enumerant: "Float16ImageAMD",
Value: 5008,
Capabilities: []string{"Shader",},
@@ -24129,6 +25197,13 @@ var (
Version: "None",
},
Enumerant{
+ Enumerant: "Int64ImageEXT",
+ Value: 5016,
+ Capabilities: []string{"Shader",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
Enumerant: "ShaderClockKHR",
Value: 5055,
Capabilities: []string{"Shader",},
@@ -24465,7 +25540,7 @@ var (
Version: "None",
},
Enumerant{
- Enumerant: "RayTracingKHR",
+ Enumerant: "RayTracingProvisionalKHR",
Value: 5353,
Capabilities: []string{"Shader",},
Parameters: []Parameter{},
@@ -24542,6 +25617,20 @@ var (
Version: "None",
},
Enumerant{
+ Enumerant: "RoundToInfinityINTEL",
+ Value: 5582,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FloatingPointModeINTEL",
+ Value: 5583,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
Enumerant: "IntegerFunctions2INTEL",
Value: 5584,
Capabilities: []string{"Shader",},
@@ -24549,6 +25638,62 @@ var (
Version: "None",
},
Enumerant{
+ Enumerant: "FunctionPointersINTEL",
+ Value: 5603,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "IndirectReferencesINTEL",
+ Value: 5604,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "AsmINTEL",
+ Value: 5606,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "AtomicFloat32MinMaxEXT",
+ Value: 5612,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "AtomicFloat64MinMaxEXT",
+ Value: 5613,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "AtomicFloat16MinMaxEXT",
+ Value: 5616,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "VectorComputeINTEL",
+ Value: 5617,
+ Capabilities: []string{"VectorAnyINTEL",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "VectorAnyINTEL",
+ Value: 5619,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
Enumerant: "SubgroupAvcMotionEstimationINTEL",
Value: 5696,
Capabilities: []string{},
@@ -24569,6 +25714,146 @@ var (
Parameters: []Parameter{},
Version: "None",
},
+ Enumerant{
+ Enumerant: "VariableLengthArrayINTEL",
+ Value: 5817,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FunctionFloatControlINTEL",
+ Value: 5821,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FPGAMemoryAttributesINTEL",
+ Value: 5824,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FPFastMathModeINTEL",
+ Value: 5837,
+ Capabilities: []string{"Kernel",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "ArbitraryPrecisionIntegersINTEL",
+ Value: 5844,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "UnstructuredLoopControlsINTEL",
+ Value: 5886,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FPGALoopControlsINTEL",
+ Value: 5888,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "KernelAttributesINTEL",
+ Value: 5892,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FPGAKernelAttributesINTEL",
+ Value: 5897,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FPGAMemoryAccessesINTEL",
+ Value: 5898,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FPGAClusterAttributesINTEL",
+ Value: 5904,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "LoopFuseINTEL",
+ Value: 5906,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FPGABufferLocationINTEL",
+ Value: 5920,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "USMStorageClassesINTEL",
+ Value: 5935,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "IOPipesINTEL",
+ Value: 5943,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "BlockingPipesINTEL",
+ Value: 5945,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "FPGARegINTEL",
+ Value: 5948,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "AtomicFloat32AddEXT",
+ Value: 6033,
+ Capabilities: []string{"Shader",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "AtomicFloat64AddEXT",
+ Value: 6034,
+ Capabilities: []string{"Shader",},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
+ Enumerant{
+ Enumerant: "LongConstantCompositeINTEL",
+ Value: 6089,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "None",
+ },
},
Bases: []*OperandKind {},
}
@@ -24581,14 +25866,14 @@ var (
Value: 0,
Capabilities: []string{"RayQueryKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "RayQueryCommittedIntersectionKHR",
Value: 1,
Capabilities: []string{"RayQueryKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
},
Bases: []*OperandKind {},
@@ -24602,21 +25887,21 @@ var (
Value: 0,
Capabilities: []string{"RayQueryKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "RayQueryCommittedIntersectionTriangleKHR",
Value: 1,
Capabilities: []string{"RayQueryKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "RayQueryCommittedIntersectionGeneratedKHR",
Value: 2,
Capabilities: []string{"RayQueryKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
},
Bases: []*OperandKind {},
@@ -24630,14 +25915,14 @@ var (
Value: 0,
Capabilities: []string{"RayQueryKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
Enumerant{
Enumerant: "RayQueryCandidateIntersectionAABBKHR",
Value: 1,
Capabilities: []string{"RayQueryKHR",},
Parameters: []Parameter{},
- Version: "",
+ Version: "None",
},
},
Bases: []*OperandKind {},
@@ -24738,6 +26023,13 @@ var (
Category: "BitEnum",
Enumerants: []Enumerant {
Enumerant{
+ Enumerant: "None",
+ Value: 0x0000,
+ Capabilities: []string{},
+ Parameters: []Parameter{},
+ Version: "",
+ },
+ Enumerant{
Enumerant: "FlagIsProtected",
Value: 0x01,
Capabilities: []string{},
diff --git a/utils/vscode/src/tools/gen-grammar.go b/utils/vscode/src/tools/gen-grammar.go
index 200f6959..a1289ef9 100644
--- a/utils/vscode/src/tools/gen-grammar.go
+++ b/utils/vscode/src/tools/gen-grammar.go
@@ -31,7 +31,7 @@ import (
"github.com/pkg/errors"
- "../grammar"
+ "github.com/KhronosGroup/SPIRV-Tools/utils/vscode/src/grammar"
)
type grammarDefinition struct {
@@ -54,7 +54,7 @@ var (
url: "https://raw.githubusercontent.com/KhronosGroup/SPIRV-Headers/master/include/spirv/unified1/extinst.opencl.std.100.grammar.json",
}, {
name: "OpenCL.DebugInfo.100",
- url: "https://raw.githubusercontent.com/KhronosGroup/SPIRV-Tools/master/source/extinst.opencl.debuginfo.100.grammar.json",
+ url: "https://raw.githubusercontent.com/KhronosGroup/SPIRV-Headers/master/include/spirv/unified1/extinst.opencl.debuginfo.100.grammar.json",
},
}
@@ -106,7 +106,7 @@ func run() error {
for _, ext := range extensionGrammars {
root, err := parseGrammar(ext)
if err != nil {
- return errors.Wrap(err, "Failed to parse extension grammar file")
+ return errors.Wrap(err, "Failed to parse extension grammar file: "+ext.name)
}
args.Extensions = append(args.Extensions, extension{Root: root, Name: ext.name})
args.All.Instructions = append(args.All.Instructions, root.Instructions...)