1 // Copyright (c) 2019 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "source/fuzz/transformation.h" 16 17 #include <cassert> 18 19 #include "source/fuzz/fuzzer_util.h" 20 #include "source/fuzz/transformation_access_chain.h" 21 #include "source/fuzz/transformation_add_bit_instruction_synonym.h" 22 #include "source/fuzz/transformation_add_constant_boolean.h" 23 #include "source/fuzz/transformation_add_constant_composite.h" 24 #include "source/fuzz/transformation_add_constant_null.h" 25 #include "source/fuzz/transformation_add_constant_scalar.h" 26 #include "source/fuzz/transformation_add_copy_memory.h" 27 #include "source/fuzz/transformation_add_dead_block.h" 28 #include "source/fuzz/transformation_add_dead_break.h" 29 #include "source/fuzz/transformation_add_dead_continue.h" 30 #include "source/fuzz/transformation_add_early_terminator_wrapper.h" 31 #include "source/fuzz/transformation_add_function.h" 32 #include "source/fuzz/transformation_add_global_undef.h" 33 #include "source/fuzz/transformation_add_global_variable.h" 34 #include "source/fuzz/transformation_add_image_sample_unused_components.h" 35 #include "source/fuzz/transformation_add_local_variable.h" 36 #include "source/fuzz/transformation_add_loop_preheader.h" 37 #include "source/fuzz/transformation_add_loop_to_create_int_constant_synonym.h" 38 #include "source/fuzz/transformation_add_no_contraction_decoration.h" 39 #include "source/fuzz/transformation_add_opphi_synonym.h" 40 #include "source/fuzz/transformation_add_parameter.h" 41 #include "source/fuzz/transformation_add_relaxed_decoration.h" 42 #include "source/fuzz/transformation_add_spec_constant_op.h" 43 #include "source/fuzz/transformation_add_synonym.h" 44 #include "source/fuzz/transformation_add_type_array.h" 45 #include "source/fuzz/transformation_add_type_boolean.h" 46 #include "source/fuzz/transformation_add_type_float.h" 47 #include "source/fuzz/transformation_add_type_function.h" 48 #include "source/fuzz/transformation_add_type_int.h" 49 #include "source/fuzz/transformation_add_type_matrix.h" 50 #include "source/fuzz/transformation_add_type_pointer.h" 51 #include "source/fuzz/transformation_add_type_struct.h" 52 #include "source/fuzz/transformation_add_type_vector.h" 53 #include "source/fuzz/transformation_adjust_branch_weights.h" 54 #include "source/fuzz/transformation_composite_construct.h" 55 #include "source/fuzz/transformation_composite_extract.h" 56 #include "source/fuzz/transformation_composite_insert.h" 57 #include "source/fuzz/transformation_compute_data_synonym_fact_closure.h" 58 #include "source/fuzz/transformation_duplicate_region_with_selection.h" 59 #include "source/fuzz/transformation_equation_instruction.h" 60 #include "source/fuzz/transformation_expand_vector_reduction.h" 61 #include "source/fuzz/transformation_flatten_conditional_branch.h" 62 #include "source/fuzz/transformation_function_call.h" 63 #include "source/fuzz/transformation_inline_function.h" 64 #include "source/fuzz/transformation_invert_comparison_operator.h" 65 #include "source/fuzz/transformation_load.h" 66 #include "source/fuzz/transformation_make_vector_operation_dynamic.h" 67 #include "source/fuzz/transformation_merge_blocks.h" 68 #include "source/fuzz/transformation_merge_function_returns.h" 69 #include "source/fuzz/transformation_move_block_down.h" 70 #include "source/fuzz/transformation_move_instruction_down.h" 71 #include "source/fuzz/transformation_mutate_pointer.h" 72 #include "source/fuzz/transformation_outline_function.h" 73 #include "source/fuzz/transformation_permute_function_parameters.h" 74 #include "source/fuzz/transformation_permute_phi_operands.h" 75 #include "source/fuzz/transformation_propagate_instruction_down.h" 76 #include "source/fuzz/transformation_propagate_instruction_up.h" 77 #include "source/fuzz/transformation_push_id_through_variable.h" 78 #include "source/fuzz/transformation_record_synonymous_constants.h" 79 #include "source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.h" 80 #include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h" 81 #include "source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h" 82 #include "source/fuzz/transformation_replace_constant_with_uniform.h" 83 #include "source/fuzz/transformation_replace_copy_memory_with_load_store.h" 84 #include "source/fuzz/transformation_replace_copy_object_with_store_load.h" 85 #include "source/fuzz/transformation_replace_id_with_synonym.h" 86 #include "source/fuzz/transformation_replace_irrelevant_id.h" 87 #include "source/fuzz/transformation_replace_linear_algebra_instruction.h" 88 #include "source/fuzz/transformation_replace_load_store_with_copy_memory.h" 89 #include "source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.h" 90 #include "source/fuzz/transformation_replace_opselect_with_conditional_branch.h" 91 #include "source/fuzz/transformation_replace_parameter_with_global.h" 92 #include "source/fuzz/transformation_replace_params_with_struct.h" 93 #include "source/fuzz/transformation_set_function_control.h" 94 #include "source/fuzz/transformation_set_loop_control.h" 95 #include "source/fuzz/transformation_set_memory_operands_mask.h" 96 #include "source/fuzz/transformation_set_selection_control.h" 97 #include "source/fuzz/transformation_split_block.h" 98 #include "source/fuzz/transformation_store.h" 99 #include "source/fuzz/transformation_swap_commutable_operands.h" 100 #include "source/fuzz/transformation_swap_conditional_branch_operands.h" 101 #include "source/fuzz/transformation_toggle_access_chain_instruction.h" 102 #include "source/fuzz/transformation_vector_shuffle.h" 103 #include "source/fuzz/transformation_wrap_early_terminator_in_function.h" 104 #include "source/fuzz/transformation_wrap_region_in_selection.h" 105 #include "source/util/make_unique.h" 106 107 namespace spvtools { 108 namespace fuzz { 109 110 Transformation::~Transformation() = default; 111 FromMessage(const protobufs::Transformation & message)112std::unique_ptr<Transformation> Transformation::FromMessage( 113 const protobufs::Transformation& message) { 114 switch (message.transformation_case()) { 115 case protobufs::Transformation::TransformationCase::kAccessChain: 116 return MakeUnique<TransformationAccessChain>(message.access_chain()); 117 case protobufs::Transformation::TransformationCase:: 118 kAddBitInstructionSynonym: 119 return MakeUnique<TransformationAddBitInstructionSynonym>( 120 message.add_bit_instruction_synonym()); 121 case protobufs::Transformation::TransformationCase::kAddConstantBoolean: 122 return MakeUnique<TransformationAddConstantBoolean>( 123 message.add_constant_boolean()); 124 case protobufs::Transformation::TransformationCase::kAddConstantComposite: 125 return MakeUnique<TransformationAddConstantComposite>( 126 message.add_constant_composite()); 127 case protobufs::Transformation::TransformationCase::kAddConstantNull: 128 return MakeUnique<TransformationAddConstantNull>( 129 message.add_constant_null()); 130 case protobufs::Transformation::TransformationCase::kAddConstantScalar: 131 return MakeUnique<TransformationAddConstantScalar>( 132 message.add_constant_scalar()); 133 case protobufs::Transformation::TransformationCase::kAddCopyMemory: 134 return MakeUnique<TransformationAddCopyMemory>(message.add_copy_memory()); 135 case protobufs::Transformation::TransformationCase::kAddDeadBlock: 136 return MakeUnique<TransformationAddDeadBlock>(message.add_dead_block()); 137 case protobufs::Transformation::TransformationCase::kAddDeadBreak: 138 return MakeUnique<TransformationAddDeadBreak>(message.add_dead_break()); 139 case protobufs::Transformation::TransformationCase::kAddDeadContinue: 140 return MakeUnique<TransformationAddDeadContinue>( 141 message.add_dead_continue()); 142 case protobufs::Transformation::TransformationCase:: 143 kAddEarlyTerminatorWrapper: 144 return MakeUnique<TransformationAddEarlyTerminatorWrapper>( 145 message.add_early_terminator_wrapper()); 146 case protobufs::Transformation::TransformationCase::kAddFunction: 147 return MakeUnique<TransformationAddFunction>(message.add_function()); 148 case protobufs::Transformation::TransformationCase::kAddGlobalUndef: 149 return MakeUnique<TransformationAddGlobalUndef>( 150 message.add_global_undef()); 151 case protobufs::Transformation::TransformationCase::kAddGlobalVariable: 152 return MakeUnique<TransformationAddGlobalVariable>( 153 message.add_global_variable()); 154 case protobufs::Transformation::TransformationCase:: 155 kAddImageSampleUnusedComponents: 156 return MakeUnique<TransformationAddImageSampleUnusedComponents>( 157 message.add_image_sample_unused_components()); 158 case protobufs::Transformation::TransformationCase::kAddLocalVariable: 159 return MakeUnique<TransformationAddLocalVariable>( 160 message.add_local_variable()); 161 case protobufs::Transformation::TransformationCase::kAddLoopPreheader: 162 return MakeUnique<TransformationAddLoopPreheader>( 163 message.add_loop_preheader()); 164 case protobufs::Transformation::TransformationCase:: 165 kAddLoopToCreateIntConstantSynonym: 166 return MakeUnique<TransformationAddLoopToCreateIntConstantSynonym>( 167 message.add_loop_to_create_int_constant_synonym()); 168 case protobufs::Transformation::TransformationCase:: 169 kAddNoContractionDecoration: 170 return MakeUnique<TransformationAddNoContractionDecoration>( 171 message.add_no_contraction_decoration()); 172 case protobufs::Transformation::TransformationCase::kAddOpphiSynonym: 173 return MakeUnique<TransformationAddOpPhiSynonym>( 174 message.add_opphi_synonym()); 175 case protobufs::Transformation::TransformationCase::kAddParameter: 176 return MakeUnique<TransformationAddParameter>(message.add_parameter()); 177 case protobufs::Transformation::TransformationCase::kAddRelaxedDecoration: 178 return MakeUnique<TransformationAddRelaxedDecoration>( 179 message.add_relaxed_decoration()); 180 case protobufs::Transformation::TransformationCase::kAddSpecConstantOp: 181 return MakeUnique<TransformationAddSpecConstantOp>( 182 message.add_spec_constant_op()); 183 case protobufs::Transformation::TransformationCase::kAddSynonym: 184 return MakeUnique<TransformationAddSynonym>(message.add_synonym()); 185 case protobufs::Transformation::TransformationCase::kAddTypeArray: 186 return MakeUnique<TransformationAddTypeArray>(message.add_type_array()); 187 case protobufs::Transformation::TransformationCase::kAddTypeBoolean: 188 return MakeUnique<TransformationAddTypeBoolean>( 189 message.add_type_boolean()); 190 case protobufs::Transformation::TransformationCase::kAddTypeFloat: 191 return MakeUnique<TransformationAddTypeFloat>(message.add_type_float()); 192 case protobufs::Transformation::TransformationCase::kAddTypeFunction: 193 return MakeUnique<TransformationAddTypeFunction>( 194 message.add_type_function()); 195 case protobufs::Transformation::TransformationCase::kAddTypeInt: 196 return MakeUnique<TransformationAddTypeInt>(message.add_type_int()); 197 case protobufs::Transformation::TransformationCase::kAddTypeMatrix: 198 return MakeUnique<TransformationAddTypeMatrix>(message.add_type_matrix()); 199 case protobufs::Transformation::TransformationCase::kAddTypePointer: 200 return MakeUnique<TransformationAddTypePointer>( 201 message.add_type_pointer()); 202 case protobufs::Transformation::TransformationCase::kAddTypeStruct: 203 return MakeUnique<TransformationAddTypeStruct>(message.add_type_struct()); 204 case protobufs::Transformation::TransformationCase::kAddTypeVector: 205 return MakeUnique<TransformationAddTypeVector>(message.add_type_vector()); 206 case protobufs::Transformation::TransformationCase::kAdjustBranchWeights: 207 return MakeUnique<TransformationAdjustBranchWeights>( 208 message.adjust_branch_weights()); 209 case protobufs::Transformation::TransformationCase::kCompositeConstruct: 210 return MakeUnique<TransformationCompositeConstruct>( 211 message.composite_construct()); 212 case protobufs::Transformation::TransformationCase::kCompositeExtract: 213 return MakeUnique<TransformationCompositeExtract>( 214 message.composite_extract()); 215 case protobufs::Transformation::TransformationCase::kCompositeInsert: 216 return MakeUnique<TransformationCompositeInsert>( 217 message.composite_insert()); 218 case protobufs::Transformation::TransformationCase:: 219 kComputeDataSynonymFactClosure: 220 return MakeUnique<TransformationComputeDataSynonymFactClosure>( 221 message.compute_data_synonym_fact_closure()); 222 case protobufs::Transformation::TransformationCase:: 223 kDuplicateRegionWithSelection: 224 return MakeUnique<TransformationDuplicateRegionWithSelection>( 225 message.duplicate_region_with_selection()); 226 case protobufs::Transformation::TransformationCase::kEquationInstruction: 227 return MakeUnique<TransformationEquationInstruction>( 228 message.equation_instruction()); 229 case protobufs::Transformation::TransformationCase::kExpandVectorReduction: 230 return MakeUnique<TransformationExpandVectorReduction>( 231 message.expand_vector_reduction()); 232 case protobufs::Transformation::TransformationCase:: 233 kFlattenConditionalBranch: 234 return MakeUnique<TransformationFlattenConditionalBranch>( 235 message.flatten_conditional_branch()); 236 case protobufs::Transformation::TransformationCase::kFunctionCall: 237 return MakeUnique<TransformationFunctionCall>(message.function_call()); 238 case protobufs::Transformation::TransformationCase::kInlineFunction: 239 return MakeUnique<TransformationInlineFunction>( 240 message.inline_function()); 241 case protobufs::Transformation::TransformationCase:: 242 kInvertComparisonOperator: 243 return MakeUnique<TransformationInvertComparisonOperator>( 244 message.invert_comparison_operator()); 245 case protobufs::Transformation::TransformationCase::kLoad: 246 return MakeUnique<TransformationLoad>(message.load()); 247 case protobufs::Transformation::TransformationCase:: 248 kMakeVectorOperationDynamic: 249 return MakeUnique<TransformationMakeVectorOperationDynamic>( 250 message.make_vector_operation_dynamic()); 251 case protobufs::Transformation::TransformationCase::kMergeBlocks: 252 return MakeUnique<TransformationMergeBlocks>(message.merge_blocks()); 253 case protobufs::Transformation::TransformationCase::kMergeFunctionReturns: 254 return MakeUnique<TransformationMergeFunctionReturns>( 255 message.merge_function_returns()); 256 case protobufs::Transformation::TransformationCase::kMoveBlockDown: 257 return MakeUnique<TransformationMoveBlockDown>(message.move_block_down()); 258 case protobufs::Transformation::TransformationCase::kMoveInstructionDown: 259 return MakeUnique<TransformationMoveInstructionDown>( 260 message.move_instruction_down()); 261 case protobufs::Transformation::TransformationCase::kMutatePointer: 262 return MakeUnique<TransformationMutatePointer>(message.mutate_pointer()); 263 case protobufs::Transformation::TransformationCase::kOutlineFunction: 264 return MakeUnique<TransformationOutlineFunction>( 265 message.outline_function()); 266 case protobufs::Transformation::TransformationCase:: 267 kPermuteFunctionParameters: 268 return MakeUnique<TransformationPermuteFunctionParameters>( 269 message.permute_function_parameters()); 270 case protobufs::Transformation::TransformationCase::kPermutePhiOperands: 271 return MakeUnique<TransformationPermutePhiOperands>( 272 message.permute_phi_operands()); 273 case protobufs::Transformation::TransformationCase:: 274 kPropagateInstructionDown: 275 return MakeUnique<TransformationPropagateInstructionDown>( 276 message.propagate_instruction_down()); 277 case protobufs::Transformation::TransformationCase::kPropagateInstructionUp: 278 return MakeUnique<TransformationPropagateInstructionUp>( 279 message.propagate_instruction_up()); 280 case protobufs::Transformation::TransformationCase::kPushIdThroughVariable: 281 return MakeUnique<TransformationPushIdThroughVariable>( 282 message.push_id_through_variable()); 283 case protobufs::Transformation::TransformationCase:: 284 kRecordSynonymousConstants: 285 return MakeUnique<TransformationRecordSynonymousConstants>( 286 message.record_synonymous_constants()); 287 case protobufs::Transformation::TransformationCase:: 288 kReplaceAddSubMulWithCarryingExtended: 289 return MakeUnique<TransformationReplaceAddSubMulWithCarryingExtended>( 290 message.replace_add_sub_mul_with_carrying_extended()); 291 case protobufs::Transformation::TransformationCase:: 292 kReplaceBooleanConstantWithConstantBinary: 293 return MakeUnique<TransformationReplaceBooleanConstantWithConstantBinary>( 294 message.replace_boolean_constant_with_constant_binary()); 295 case protobufs::Transformation::TransformationCase:: 296 kReplaceBranchFromDeadBlockWithExit: 297 return MakeUnique<TransformationReplaceBranchFromDeadBlockWithExit>( 298 message.replace_branch_from_dead_block_with_exit()); 299 case protobufs::Transformation::TransformationCase:: 300 kReplaceConstantWithUniform: 301 return MakeUnique<TransformationReplaceConstantWithUniform>( 302 message.replace_constant_with_uniform()); 303 case protobufs::Transformation::TransformationCase:: 304 kReplaceCopyMemoryWithLoadStore: 305 return MakeUnique<TransformationReplaceCopyMemoryWithLoadStore>( 306 message.replace_copy_memory_with_load_store()); 307 case protobufs::Transformation::TransformationCase:: 308 kReplaceCopyObjectWithStoreLoad: 309 return MakeUnique<TransformationReplaceCopyObjectWithStoreLoad>( 310 message.replace_copy_object_with_store_load()); 311 case protobufs::Transformation::TransformationCase::kReplaceIdWithSynonym: 312 return MakeUnique<TransformationReplaceIdWithSynonym>( 313 message.replace_id_with_synonym()); 314 case protobufs::Transformation::TransformationCase::kReplaceIrrelevantId: 315 return MakeUnique<TransformationReplaceIrrelevantId>( 316 message.replace_irrelevant_id()); 317 case protobufs::Transformation::TransformationCase:: 318 kReplaceLinearAlgebraInstruction: 319 return MakeUnique<TransformationReplaceLinearAlgebraInstruction>( 320 message.replace_linear_algebra_instruction()); 321 case protobufs::Transformation::TransformationCase:: 322 kReplaceLoadStoreWithCopyMemory: 323 return MakeUnique<TransformationReplaceLoadStoreWithCopyMemory>( 324 message.replace_load_store_with_copy_memory()); 325 case protobufs::Transformation::TransformationCase:: 326 kReplaceOpselectWithConditionalBranch: 327 return MakeUnique<TransformationReplaceOpSelectWithConditionalBranch>( 328 message.replace_opselect_with_conditional_branch()); 329 case protobufs::Transformation::TransformationCase:: 330 kReplaceParameterWithGlobal: 331 return MakeUnique<TransformationReplaceParameterWithGlobal>( 332 message.replace_parameter_with_global()); 333 case protobufs::Transformation::TransformationCase:: 334 kReplaceParamsWithStruct: 335 return MakeUnique<TransformationReplaceParamsWithStruct>( 336 message.replace_params_with_struct()); 337 case protobufs::Transformation::TransformationCase:: 338 kReplaceOpphiIdFromDeadPredecessor: 339 return MakeUnique<TransformationReplaceOpPhiIdFromDeadPredecessor>( 340 message.replace_opphi_id_from_dead_predecessor()); 341 case protobufs::Transformation::TransformationCase::kSetFunctionControl: 342 return MakeUnique<TransformationSetFunctionControl>( 343 message.set_function_control()); 344 case protobufs::Transformation::TransformationCase::kSetLoopControl: 345 return MakeUnique<TransformationSetLoopControl>( 346 message.set_loop_control()); 347 case protobufs::Transformation::TransformationCase::kSetMemoryOperandsMask: 348 return MakeUnique<TransformationSetMemoryOperandsMask>( 349 message.set_memory_operands_mask()); 350 case protobufs::Transformation::TransformationCase::kSetSelectionControl: 351 return MakeUnique<TransformationSetSelectionControl>( 352 message.set_selection_control()); 353 case protobufs::Transformation::TransformationCase::kSplitBlock: 354 return MakeUnique<TransformationSplitBlock>(message.split_block()); 355 case protobufs::Transformation::TransformationCase::kStore: 356 return MakeUnique<TransformationStore>(message.store()); 357 case protobufs::Transformation::TransformationCase::kSwapCommutableOperands: 358 return MakeUnique<TransformationSwapCommutableOperands>( 359 message.swap_commutable_operands()); 360 case protobufs::Transformation::TransformationCase:: 361 kSwapConditionalBranchOperands: 362 return MakeUnique<TransformationSwapConditionalBranchOperands>( 363 message.swap_conditional_branch_operands()); 364 case protobufs::Transformation::TransformationCase:: 365 kToggleAccessChainInstruction: 366 return MakeUnique<TransformationToggleAccessChainInstruction>( 367 message.toggle_access_chain_instruction()); 368 case protobufs::Transformation::TransformationCase::kVectorShuffle: 369 return MakeUnique<TransformationVectorShuffle>(message.vector_shuffle()); 370 case protobufs::Transformation::TransformationCase:: 371 kWrapEarlyTerminatorInFunction: 372 return MakeUnique<TransformationWrapEarlyTerminatorInFunction>( 373 message.wrap_early_terminator_in_function()); 374 case protobufs::Transformation::TransformationCase::kWrapRegionInSelection: 375 return MakeUnique<TransformationWrapRegionInSelection>( 376 message.wrap_region_in_selection()); 377 case protobufs::Transformation::TRANSFORMATION_NOT_SET: 378 assert(false && "An unset transformation was encountered."); 379 return nullptr; 380 } 381 assert(false && "Should be unreachable as all cases must be handled above."); 382 return nullptr; 383 } 384 CheckIdIsFreshAndNotUsedByThisTransformation(uint32_t id,opt::IRContext * ir_context,std::set<uint32_t> * ids_used_by_this_transformation)385bool Transformation::CheckIdIsFreshAndNotUsedByThisTransformation( 386 uint32_t id, opt::IRContext* ir_context, 387 std::set<uint32_t>* ids_used_by_this_transformation) { 388 if (!fuzzerutil::IsFreshId(ir_context, id)) { 389 return false; 390 } 391 if (ids_used_by_this_transformation->count(id) != 0) { 392 return false; 393 } 394 ids_used_by_this_transformation->insert(id); 395 return true; 396 } 397 398 } // namespace fuzz 399 } // namespace spvtools 400