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 #ifndef SOURCE_FUZZ_FUZZER_CONTEXT_H_ 16 #define SOURCE_FUZZ_FUZZER_CONTEXT_H_ 17 18 #include <functional> 19 #include <utility> 20 21 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h" 22 #include "source/fuzz/random_generator.h" 23 #include "source/opt/function.h" 24 #include "source/opt/ir_context.h" 25 26 namespace spvtools { 27 namespace fuzz { 28 29 // Encapsulates all parameters that control the fuzzing process, such as the 30 // source of randomness and the probabilities with which transformations are 31 // applied. 32 class FuzzerContext { 33 public: 34 // Constructs a fuzzer context with a given random generator and the minimum 35 // value that can be used for fresh ids. 36 FuzzerContext(std::unique_ptr<RandomGenerator> random_generator, 37 uint32_t min_fresh_id, bool is_wgsl_compatible); 38 39 ~FuzzerContext(); 40 41 // Returns a random boolean. 42 bool ChooseEven(); 43 44 // Returns true if and only if a randomly-chosen integer in the range [0, 100] 45 // is less than |percentage_chance|. 46 bool ChoosePercentage(uint32_t percentage_chance); 47 48 // Returns a random index into |sequence|, which is expected to have a 'size' 49 // method, and which must be non-empty. Typically 'HasSizeMethod' will be an 50 // std::vector. 51 template <typename HasSizeMethod> RandomIndex(const HasSizeMethod & sequence)52 uint32_t RandomIndex(const HasSizeMethod& sequence) const { 53 assert(sequence.size() > 0); 54 return random_generator_->RandomUint32( 55 static_cast<uint32_t>(sequence.size())); 56 } 57 58 // Selects a random index into |sequence|, removes the element at that index 59 // and returns it. 60 template <typename T> RemoveAtRandomIndex(std::vector<T> * sequence)61 T RemoveAtRandomIndex(std::vector<T>* sequence) const { 62 uint32_t index = RandomIndex(*sequence); 63 T result = sequence->at(index); 64 sequence->erase(sequence->begin() + index); 65 return result; 66 } 67 68 // Randomly shuffles a |sequence| between |lo| and |hi| indices inclusively. 69 // |lo| and |hi| must be valid indices to the |sequence|. 70 template <typename T> Shuffle(std::vector<T> * sequence,size_t lo,size_t hi)71 void Shuffle(std::vector<T>* sequence, size_t lo, size_t hi) const { 72 auto& array = *sequence; 73 74 if (array.empty()) { 75 return; 76 } 77 78 assert(lo <= hi && hi < array.size() && "lo and/or hi indices are invalid"); 79 80 // i > lo to account for potential infinite loop when lo == 0 81 for (size_t i = hi; i > lo; --i) { 82 auto index = 83 random_generator_->RandomUint32(static_cast<uint32_t>(i - lo + 1)); 84 85 if (lo + index != i) { 86 // Introduce std::swap to the scope but don't use it 87 // directly since there might be a better overload 88 using std::swap; 89 swap(array[lo + index], array[i]); 90 } 91 } 92 } 93 94 // Randomly shuffles a |sequence|. 95 template <typename T> Shuffle(std::vector<T> * sequence)96 void Shuffle(std::vector<T>* sequence) const { 97 if (!sequence->empty()) { 98 Shuffle(sequence, 0, sequence->size() - 1); 99 } 100 } 101 102 // Yields an id that is guaranteed not to be used in the module being fuzzed, 103 // or to have been issued before. 104 uint32_t GetFreshId(); 105 106 // Returns a vector of |count| fresh ids. 107 std::vector<uint32_t> GetFreshIds(uint32_t count); 108 109 // A suggested limit on the id bound for the module being fuzzed. This is 110 // useful for deciding when to stop the overall fuzzing process. Furthermore, 111 // fuzzer passes that run the risk of spiralling out of control can 112 // periodically check this limit and terminate early if it has been reached. 113 uint32_t GetIdBoundLimit() const; 114 115 // A suggested limit on the number of transformations that should be applied. 116 // Also useful to control the overall fuzzing process and rein in individual 117 // fuzzer passes. 118 uint32_t GetTransformationLimit() const; 119 120 // Returns the minimum fresh id that can be used given the |ir_context|. 121 static uint32_t GetMinFreshId(opt::IRContext* ir_context); 122 123 // Returns true if all transformations should be compatible with WGSL. IsWgslCompatible()124 bool IsWgslCompatible() const { 125 return is_wgsl_compatible_; 126 } 127 128 // Probabilities associated with applying various transformations. 129 // Keep them in alphabetical order. GetChanceOfAcceptingRepeatedPassRecommendation()130 uint32_t GetChanceOfAcceptingRepeatedPassRecommendation() const { 131 return chance_of_accepting_repeated_pass_recommendation_; 132 } GetChanceOfAddingAccessChain()133 uint32_t GetChanceOfAddingAccessChain() const { 134 return chance_of_adding_access_chain_; 135 } GetChanceOfAddingAnotherPassToPassLoop()136 uint32_t GetChanceOfAddingAnotherPassToPassLoop() const { 137 return chance_of_adding_another_pass_to_pass_loop_; 138 } GetChanceOfAddingAnotherStructField()139 uint32_t GetChanceOfAddingAnotherStructField() const { 140 return chance_of_adding_another_struct_field_; 141 } GetChanceOfAddingArrayOrStructType()142 uint32_t GetChanceOfAddingArrayOrStructType() const { 143 return chance_of_adding_array_or_struct_type_; 144 } GetChanceOfAddingBitInstructionSynonym()145 uint32_t GetChanceOfAddingBitInstructionSynonym() const { 146 return chance_of_adding_bit_instruction_synonym_; 147 } GetChanceOfAddingBothBranchesWhenReplacingOpSelect()148 uint32_t GetChanceOfAddingBothBranchesWhenReplacingOpSelect() const { 149 return chance_of_adding_both_branches_when_replacing_opselect_; 150 } GetChanceOfAddingCompositeExtract()151 uint32_t GetChanceOfAddingCompositeExtract() const { 152 return chance_of_adding_composite_extract_; 153 } GetChanceOfAddingCompositeInsert()154 uint32_t GetChanceOfAddingCompositeInsert() const { 155 return chance_of_adding_composite_insert_; 156 } GetChanceOfAddingCopyMemory()157 uint32_t GetChanceOfAddingCopyMemory() const { 158 return chance_of_adding_copy_memory_; 159 } GetChanceOfAddingDeadBlock()160 uint32_t GetChanceOfAddingDeadBlock() const { 161 return chance_of_adding_dead_block_; 162 } GetChanceOfAddingDeadBreak()163 uint32_t GetChanceOfAddingDeadBreak() const { 164 return chance_of_adding_dead_break_; 165 } GetChanceOfAddingDeadContinue()166 uint32_t GetChanceOfAddingDeadContinue() const { 167 return chance_of_adding_dead_continue_; 168 } GetChanceOfAddingEquationInstruction()169 uint32_t GetChanceOfAddingEquationInstruction() const { 170 return chance_of_adding_equation_instruction_; 171 } GetChanceOfAddingGlobalVariable()172 uint32_t GetChanceOfAddingGlobalVariable() const { 173 return chance_of_adding_global_variable_; 174 } GetChanceOfAddingImageSampleUnusedComponents()175 uint32_t GetChanceOfAddingImageSampleUnusedComponents() const { 176 return chance_of_adding_image_sample_unused_components_; 177 } GetChanceOfAddingLoad()178 uint32_t GetChanceOfAddingLoad() const { return chance_of_adding_load_; } GetChanceOfAddingLocalVariable()179 uint32_t GetChanceOfAddingLocalVariable() const { 180 return chance_of_adding_local_variable_; 181 } GetChanceOfAddingLoopPreheader()182 uint32_t GetChanceOfAddingLoopPreheader() const { 183 return chance_of_adding_loop_preheader_; 184 } GetChanceOfAddingMatrixType()185 uint32_t GetChanceOfAddingMatrixType() const { 186 return chance_of_adding_matrix_type_; 187 } GetChanceOfAddingNoContractionDecoration()188 uint32_t GetChanceOfAddingNoContractionDecoration() const { 189 return chance_of_adding_no_contraction_decoration_; 190 } GetChanceOfAddingOpPhiSynonym()191 uint32_t GetChanceOfAddingOpPhiSynonym() const { 192 return chance_of_adding_opphi_synonym_; 193 } GetChanceOfAddingParameters()194 uint32_t GetChanceOfAddingParameters() const { 195 return chance_of_adding_parameters; 196 } GetChanceOfAddingRelaxedDecoration()197 uint32_t GetChanceOfAddingRelaxedDecoration() const { 198 return chance_of_adding_relaxed_decoration_; 199 } GetChanceOfAddingStore()200 uint32_t GetChanceOfAddingStore() const { return chance_of_adding_store_; } GetChanceOfAddingSynonyms()201 uint32_t GetChanceOfAddingSynonyms() const { 202 return chance_of_adding_synonyms_; 203 } GetChanceOfAddingTrueBranchWhenReplacingOpSelect()204 uint32_t GetChanceOfAddingTrueBranchWhenReplacingOpSelect() const { 205 return chance_of_adding_true_branch_when_replacing_opselect_; 206 } GetChanceOfAddingVectorShuffle()207 uint32_t GetChanceOfAddingVectorShuffle() const { 208 return chance_of_adding_vector_shuffle_; 209 } GetChanceOfAddingVectorType()210 uint32_t GetChanceOfAddingVectorType() const { 211 return chance_of_adding_vector_type_; 212 } GetChanceOfAdjustingBranchWeights()213 uint32_t GetChanceOfAdjustingBranchWeights() const { 214 return chance_of_adjusting_branch_weights_; 215 } GetChanceOfAdjustingFunctionControl()216 uint32_t GetChanceOfAdjustingFunctionControl() const { 217 return chance_of_adjusting_function_control_; 218 } GetChanceOfAdjustingLoopControl()219 uint32_t GetChanceOfAdjustingLoopControl() const { 220 return chance_of_adjusting_loop_control_; 221 } GetChanceOfAdjustingMemoryOperandsMask()222 uint32_t GetChanceOfAdjustingMemoryOperandsMask() const { 223 return chance_of_adjusting_memory_operands_mask_; 224 } GetChanceOfAdjustingSelectionControl()225 uint32_t GetChanceOfAdjustingSelectionControl() const { 226 return chance_of_adjusting_selection_control_; 227 } GetChanceOfCallingFunction()228 uint32_t GetChanceOfCallingFunction() const { 229 return chance_of_calling_function_; 230 } GetChanceOfChoosingStructTypeVsArrayType()231 uint32_t GetChanceOfChoosingStructTypeVsArrayType() const { 232 return chance_of_choosing_struct_type_vs_array_type_; 233 } GetChanceOfChoosingWorkgroupStorageClass()234 uint32_t GetChanceOfChoosingWorkgroupStorageClass() const { 235 return chance_of_choosing_workgroup_storage_class_; 236 } GetChanceOfConstructingComposite()237 uint32_t GetChanceOfConstructingComposite() const { 238 return chance_of_constructing_composite_; 239 } GetChanceOfCopyingObject()240 uint32_t GetChanceOfCopyingObject() const { 241 return chance_of_copying_object_; 242 } GetChanceOfCreatingIntSynonymsUsingLoops()243 uint32_t GetChanceOfCreatingIntSynonymsUsingLoops() const { 244 return chance_of_creating_int_synonyms_using_loops_; 245 } GetChanceOfDonatingAdditionalModule()246 uint32_t GetChanceOfDonatingAdditionalModule() const { 247 return chance_of_donating_additional_module_; 248 } GetChanceOfDuplicatingRegionWithSelection()249 uint32_t GetChanceOfDuplicatingRegionWithSelection() const { 250 return chance_of_duplicating_region_with_selection_; 251 } GetChanceOfExpandingVectorReduction()252 uint32_t GetChanceOfExpandingVectorReduction() const { 253 return chance_of_expanding_vector_reduction_; 254 } GetChanceOfFlatteningConditionalBranch()255 uint32_t GetChanceOfFlatteningConditionalBranch() const { 256 return chance_of_flattening_conditional_branch_; 257 } GetChanceOfGoingDeeperToExtractComposite()258 uint32_t GetChanceOfGoingDeeperToExtractComposite() const { 259 return chance_of_going_deeper_to_extract_composite_; 260 } GetChanceOfGoingDeeperToInsertInComposite()261 uint32_t GetChanceOfGoingDeeperToInsertInComposite() const { 262 return chance_of_going_deeper_to_insert_in_composite_; 263 } GetChanceOfGoingDeeperWhenMakingAccessChain()264 uint32_t GetChanceOfGoingDeeperWhenMakingAccessChain() const { 265 return chance_of_going_deeper_when_making_access_chain_; 266 } GetChanceOfHavingTwoBlocksInLoopToCreateIntSynonym()267 uint32_t GetChanceOfHavingTwoBlocksInLoopToCreateIntSynonym() const { 268 return chance_of_having_two_blocks_in_loop_to_create_int_synonym_; 269 } GetChanceOfInliningFunction()270 uint32_t GetChanceOfInliningFunction() const { 271 return chance_of_inlining_function_; 272 } GetChanceOfInterchangingSignednessOfIntegerOperands()273 uint32_t GetChanceOfInterchangingSignednessOfIntegerOperands() const { 274 return chance_of_interchanging_signedness_of_integer_operands_; 275 } GetChanceOfInterchangingZeroLikeConstants()276 uint32_t GetChanceOfInterchangingZeroLikeConstants() const { 277 return chance_of_interchanging_zero_like_constants_; 278 } GetChanceOfInvertingComparisonOperators()279 uint32_t GetChanceOfInvertingComparisonOperators() const { 280 return chance_of_inverting_comparison_operators_; 281 } ChanceOfMakingDonorLivesafe()282 uint32_t ChanceOfMakingDonorLivesafe() const { 283 return chance_of_making_donor_livesafe_; 284 } GetChanceOfMakingVectorOperationDynamic()285 uint32_t GetChanceOfMakingVectorOperationDynamic() const { 286 return chance_of_making_vector_operation_dynamic_; 287 } GetChanceOfMergingBlocks()288 uint32_t GetChanceOfMergingBlocks() const { 289 return chance_of_merging_blocks_; 290 } GetChanceOfMergingFunctionReturns()291 uint32_t GetChanceOfMergingFunctionReturns() const { 292 return chance_of_merging_function_returns_; 293 } GetChanceOfMovingBlockDown()294 uint32_t GetChanceOfMovingBlockDown() const { 295 return chance_of_moving_block_down_; 296 } GetChanceOfMutatingPointer()297 uint32_t GetChanceOfMutatingPointer() const { 298 return chance_of_mutating_pointer_; 299 } GetChanceOfObfuscatingConstant()300 uint32_t GetChanceOfObfuscatingConstant() const { 301 return chance_of_obfuscating_constant_; 302 } GetChanceOfOutliningFunction()303 uint32_t GetChanceOfOutliningFunction() const { 304 return chance_of_outlining_function_; 305 } GetChanceOfPermutingInstructions()306 uint32_t GetChanceOfPermutingInstructions() const { 307 return chance_of_permuting_instructions_; 308 } GetChanceOfPermutingParameters()309 uint32_t GetChanceOfPermutingParameters() const { 310 return chance_of_permuting_parameters_; 311 } GetChanceOfPermutingPhiOperands()312 uint32_t GetChanceOfPermutingPhiOperands() const { 313 return chance_of_permuting_phi_operands_; 314 } GetChanceOfPropagatingInstructionsDown()315 uint32_t GetChanceOfPropagatingInstructionsDown() const { 316 return chance_of_propagating_instructions_down_; 317 } GetChanceOfPropagatingInstructionsUp()318 uint32_t GetChanceOfPropagatingInstructionsUp() const { 319 return chance_of_propagating_instructions_up_; 320 } GetChanceOfPushingIdThroughVariable()321 uint32_t GetChanceOfPushingIdThroughVariable() const { 322 return chance_of_pushing_id_through_variable_; 323 } GetChanceOfReplacingAddSubMulWithCarryingExtended()324 uint32_t GetChanceOfReplacingAddSubMulWithCarryingExtended() const { 325 return chance_of_replacing_add_sub_mul_with_carrying_extended_; 326 } GetChanceOfReplacingBranchFromDeadBlockWithExit()327 uint32_t GetChanceOfReplacingBranchFromDeadBlockWithExit() const { 328 return chance_of_replacing_branch_from_dead_block_with_exit_; 329 } GetChanceOfReplacingCopyMemoryWithLoadStore()330 uint32_t GetChanceOfReplacingCopyMemoryWithLoadStore() const { 331 return chance_of_replacing_copy_memory_with_load_store_; 332 } GetChanceOfReplacingCopyObjectWithStoreLoad()333 uint32_t GetChanceOfReplacingCopyObjectWithStoreLoad() const { 334 return chance_of_replacing_copyobject_with_store_load_; 335 } GetChanceOfReplacingIdWithSynonym()336 uint32_t GetChanceOfReplacingIdWithSynonym() const { 337 return chance_of_replacing_id_with_synonym_; 338 } GetChanceOfReplacingIrrelevantId()339 uint32_t GetChanceOfReplacingIrrelevantId() const { 340 return chance_of_replacing_irrelevant_id_; 341 } GetChanceOfReplacingLinearAlgebraInstructions()342 uint32_t GetChanceOfReplacingLinearAlgebraInstructions() const { 343 return chance_of_replacing_linear_algebra_instructions_; 344 } GetChanceOfReplacingLoadStoreWithCopyMemory()345 uint32_t GetChanceOfReplacingLoadStoreWithCopyMemory() const { 346 return chance_of_replacing_load_store_with_copy_memory_; 347 } GetChanceOfReplacingOpPhiIdFromDeadPredecessor()348 uint32_t GetChanceOfReplacingOpPhiIdFromDeadPredecessor() const { 349 return chance_of_replacing_opphi_id_from_dead_predecessor_; 350 } GetChanceOfReplacingOpselectWithConditionalBranch()351 uint32_t GetChanceOfReplacingOpselectWithConditionalBranch() const { 352 return chance_of_replacing_opselect_with_conditional_branch_; 353 } GetChanceOfReplacingParametersWithGlobals()354 uint32_t GetChanceOfReplacingParametersWithGlobals() const { 355 return chance_of_replacing_parameters_with_globals_; 356 } GetChanceOfReplacingParametersWithStruct()357 uint32_t GetChanceOfReplacingParametersWithStruct() const { 358 return chance_of_replacing_parameters_with_struct_; 359 } GetChanceOfSplittingBlock()360 uint32_t GetChanceOfSplittingBlock() const { 361 return chance_of_splitting_block_; 362 } GetChanceOfSwappingConditionalBranchOperands()363 uint32_t GetChanceOfSwappingConditionalBranchOperands() const { 364 return chance_of_swapping_conditional_branch_operands_; 365 } GetChanceOfTogglingAccessChainInstruction()366 uint32_t GetChanceOfTogglingAccessChainInstruction() const { 367 return chance_of_toggling_access_chain_instruction_; 368 } GetChanceOfWrappingRegionInSelection()369 uint32_t GetChanceOfWrappingRegionInSelection() const { 370 return chance_of_wrapping_region_in_selection_; 371 } 372 373 // Other functions to control transformations. Keep them in alphabetical 374 // order. GetMaximumEquivalenceClassSizeForDataSynonymFactClosure()375 uint32_t GetMaximumEquivalenceClassSizeForDataSynonymFactClosure() const { 376 return max_equivalence_class_size_for_data_synonym_fact_closure_; 377 } GetMaximumNumberOfFunctionParameters()378 uint32_t GetMaximumNumberOfFunctionParameters() const { 379 return max_number_of_function_parameters_; 380 } GetMaximumNumberOfParametersReplacedWithStruct()381 uint32_t GetMaximumNumberOfParametersReplacedWithStruct() const { 382 return max_number_of_parameters_replaced_with_struct_; 383 } GetRandomBranchWeights()384 std::pair<uint32_t, uint32_t> GetRandomBranchWeights() { 385 std::pair<uint32_t, uint32_t> branch_weights = {0, 0}; 386 387 while (branch_weights.first == 0 && branch_weights.second == 0) { 388 // Using INT32_MAX to do not overflow UINT32_MAX when the branch weights 389 // are added together. 390 branch_weights.first = random_generator_->RandomUint32(INT32_MAX); 391 branch_weights.second = random_generator_->RandomUint32(INT32_MAX); 392 } 393 394 return branch_weights; 395 } GetRandomComponentsForVectorShuffle(uint32_t max_component_index)396 std::vector<uint32_t> GetRandomComponentsForVectorShuffle( 397 uint32_t max_component_index) { 398 // Component count must be in range [2, 4]. 399 std::vector<uint32_t> components(random_generator_->RandomUint32(2) + 2); 400 401 for (uint32_t& component : components) { 402 component = random_generator_->RandomUint32(max_component_index); 403 } 404 405 return components; 406 } GetRandomCompositeExtractIndex(uint32_t number_of_members)407 uint32_t GetRandomCompositeExtractIndex(uint32_t number_of_members) { 408 assert(number_of_members > 0 && "Composite object must have some members"); 409 return ChooseBetweenMinAndMax({0, number_of_members - 1}); 410 } GetRandomIndexForAccessChain(uint32_t composite_size_bound)411 uint32_t GetRandomIndexForAccessChain(uint32_t composite_size_bound) { 412 return random_generator_->RandomUint32(composite_size_bound); 413 } GetRandomIndexForCompositeInsert(uint32_t number_of_components)414 uint32_t GetRandomIndexForCompositeInsert(uint32_t number_of_components) { 415 return random_generator_->RandomUint32(number_of_components); 416 } GetRandomValueForStepConstantInLoop()417 int64_t GetRandomValueForStepConstantInLoop() { 418 return random_generator_->RandomUint64(UINT64_MAX); 419 } GetRandomLoopControlPartialCount()420 uint32_t GetRandomLoopControlPartialCount() { 421 return random_generator_->RandomUint32(max_loop_control_partial_count_); 422 } GetRandomLoopControlPeelCount()423 uint32_t GetRandomLoopControlPeelCount() { 424 return random_generator_->RandomUint32(max_loop_control_peel_count_); 425 } GetRandomLoopLimit()426 uint32_t GetRandomLoopLimit() { 427 return random_generator_->RandomUint32(max_loop_limit_); 428 } GetRandomNumberOfLoopIterations(uint32_t max_num_iterations)429 uint32_t GetRandomNumberOfLoopIterations(uint32_t max_num_iterations) { 430 return ChooseBetweenMinAndMax({1, max_num_iterations}); 431 } GetRandomNumberOfNewParameters(uint32_t num_of_params)432 uint32_t GetRandomNumberOfNewParameters(uint32_t num_of_params) { 433 assert(num_of_params < GetMaximumNumberOfFunctionParameters()); 434 return ChooseBetweenMinAndMax( 435 {1, std::min(max_number_of_new_parameters_, 436 GetMaximumNumberOfFunctionParameters() - num_of_params)}); 437 } GetRandomNumberOfParametersReplacedWithStruct(uint32_t num_params)438 uint32_t GetRandomNumberOfParametersReplacedWithStruct(uint32_t num_params) { 439 assert(num_params != 0 && "A function must have parameters to replace"); 440 return ChooseBetweenMinAndMax( 441 {1, std::min(num_params, 442 GetMaximumNumberOfParametersReplacedWithStruct())}); 443 } GetRandomSizeForNewArray()444 uint32_t GetRandomSizeForNewArray() { 445 // Ensure that the array size is non-zero. 446 return random_generator_->RandomUint32(max_new_array_size_limit_ - 1) + 1; 447 } 448 protobufs::TransformationAddSynonym::SynonymType GetRandomSynonymType(); GetRandomUnusedComponentCountForImageSample(uint32_t max_unused_component_count)449 uint32_t GetRandomUnusedComponentCountForImageSample( 450 uint32_t max_unused_component_count) { 451 // Ensure that the number of unused components is non-zero. 452 return random_generator_->RandomUint32(max_unused_component_count) + 1; 453 } GoDeeperInConstantObfuscation(uint32_t depth)454 bool GoDeeperInConstantObfuscation(uint32_t depth) { 455 return go_deeper_in_constant_obfuscation_(depth, random_generator_.get()); 456 } 457 458 private: 459 // The source of randomness. 460 std::unique_ptr<RandomGenerator> random_generator_; 461 // The next fresh id to be issued. 462 uint32_t next_fresh_id_; 463 464 // True if all transformations should be compatible with WGSL spec. 465 bool is_wgsl_compatible_; 466 467 // Probabilities associated with applying various transformations. 468 // Keep them in alphabetical order. 469 uint32_t chance_of_accepting_repeated_pass_recommendation_; 470 uint32_t chance_of_adding_access_chain_; 471 uint32_t chance_of_adding_another_pass_to_pass_loop_; 472 uint32_t chance_of_adding_another_struct_field_; 473 uint32_t chance_of_adding_array_or_struct_type_; 474 uint32_t chance_of_adding_bit_instruction_synonym_; 475 uint32_t chance_of_adding_both_branches_when_replacing_opselect_; 476 uint32_t chance_of_adding_composite_extract_; 477 uint32_t chance_of_adding_composite_insert_; 478 uint32_t chance_of_adding_copy_memory_; 479 uint32_t chance_of_adding_dead_block_; 480 uint32_t chance_of_adding_dead_break_; 481 uint32_t chance_of_adding_dead_continue_; 482 uint32_t chance_of_adding_equation_instruction_; 483 uint32_t chance_of_adding_global_variable_; 484 uint32_t chance_of_adding_image_sample_unused_components_; 485 uint32_t chance_of_adding_load_; 486 uint32_t chance_of_adding_local_variable_; 487 uint32_t chance_of_adding_loop_preheader_; 488 uint32_t chance_of_adding_matrix_type_; 489 uint32_t chance_of_adding_no_contraction_decoration_; 490 uint32_t chance_of_adding_opphi_synonym_; 491 uint32_t chance_of_adding_parameters; 492 uint32_t chance_of_adding_relaxed_decoration_; 493 uint32_t chance_of_adding_store_; 494 uint32_t chance_of_adding_synonyms_; 495 uint32_t chance_of_adding_true_branch_when_replacing_opselect_; 496 uint32_t chance_of_adding_vector_shuffle_; 497 uint32_t chance_of_adding_vector_type_; 498 uint32_t chance_of_adjusting_branch_weights_; 499 uint32_t chance_of_adjusting_function_control_; 500 uint32_t chance_of_adjusting_loop_control_; 501 uint32_t chance_of_adjusting_memory_operands_mask_; 502 uint32_t chance_of_adjusting_selection_control_; 503 uint32_t chance_of_calling_function_; 504 uint32_t chance_of_choosing_struct_type_vs_array_type_; 505 uint32_t chance_of_choosing_workgroup_storage_class_; 506 uint32_t chance_of_constructing_composite_; 507 uint32_t chance_of_copying_object_; 508 uint32_t chance_of_creating_int_synonyms_using_loops_; 509 uint32_t chance_of_donating_additional_module_; 510 uint32_t chance_of_duplicating_region_with_selection_; 511 uint32_t chance_of_expanding_vector_reduction_; 512 uint32_t chance_of_flattening_conditional_branch_; 513 uint32_t chance_of_going_deeper_to_extract_composite_; 514 uint32_t chance_of_going_deeper_to_insert_in_composite_; 515 uint32_t chance_of_going_deeper_when_making_access_chain_; 516 uint32_t chance_of_having_two_blocks_in_loop_to_create_int_synonym_; 517 uint32_t chance_of_inlining_function_; 518 uint32_t chance_of_interchanging_signedness_of_integer_operands_; 519 uint32_t chance_of_interchanging_zero_like_constants_; 520 uint32_t chance_of_inverting_comparison_operators_; 521 uint32_t chance_of_making_donor_livesafe_; 522 uint32_t chance_of_making_vector_operation_dynamic_; 523 uint32_t chance_of_merging_blocks_; 524 uint32_t chance_of_merging_function_returns_; 525 uint32_t chance_of_moving_block_down_; 526 uint32_t chance_of_mutating_pointer_; 527 uint32_t chance_of_obfuscating_constant_; 528 uint32_t chance_of_outlining_function_; 529 uint32_t chance_of_permuting_instructions_; 530 uint32_t chance_of_permuting_parameters_; 531 uint32_t chance_of_permuting_phi_operands_; 532 uint32_t chance_of_propagating_instructions_down_; 533 uint32_t chance_of_propagating_instructions_up_; 534 uint32_t chance_of_pushing_id_through_variable_; 535 uint32_t chance_of_replacing_add_sub_mul_with_carrying_extended_; 536 uint32_t chance_of_replacing_branch_from_dead_block_with_exit_; 537 uint32_t chance_of_replacing_copy_memory_with_load_store_; 538 uint32_t chance_of_replacing_copyobject_with_store_load_; 539 uint32_t chance_of_replacing_id_with_synonym_; 540 uint32_t chance_of_replacing_irrelevant_id_; 541 uint32_t chance_of_replacing_linear_algebra_instructions_; 542 uint32_t chance_of_replacing_load_store_with_copy_memory_; 543 uint32_t chance_of_replacing_opphi_id_from_dead_predecessor_; 544 uint32_t chance_of_replacing_opselect_with_conditional_branch_; 545 uint32_t chance_of_replacing_parameters_with_globals_; 546 uint32_t chance_of_replacing_parameters_with_struct_; 547 uint32_t chance_of_splitting_block_; 548 uint32_t chance_of_swapping_conditional_branch_operands_; 549 uint32_t chance_of_toggling_access_chain_instruction_; 550 uint32_t chance_of_wrapping_region_in_selection_; 551 552 // Limits associated with various quantities for which random values are 553 // chosen during fuzzing. 554 // Keep them in alphabetical order. 555 uint32_t max_equivalence_class_size_for_data_synonym_fact_closure_; 556 uint32_t max_loop_control_partial_count_; 557 uint32_t max_loop_control_peel_count_; 558 uint32_t max_loop_limit_; 559 uint32_t max_new_array_size_limit_; 560 uint32_t max_number_of_function_parameters_; 561 uint32_t max_number_of_new_parameters_; 562 uint32_t max_number_of_parameters_replaced_with_struct_; 563 564 // Functions to determine with what probability to go deeper when generating 565 // or mutating constructs recursively. 566 const std::function<bool(uint32_t, RandomGenerator*)>& 567 go_deeper_in_constant_obfuscation_; 568 569 // Requires |min_max.first| <= |min_max.second|, and returns a value in the 570 // range [ |min_max.first|, |min_max.second| ] 571 uint32_t ChooseBetweenMinAndMax(const std::pair<uint32_t, uint32_t>& min_max); 572 }; 573 574 } // namespace fuzz 575 } // namespace spvtools 576 577 #endif // SOURCE_FUZZ_FUZZER_CONTEXT_H_ 578