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 } GetChanceOfAddingAtomicLoad()145 uint32_t GetChanceOfAddingAtomicLoad() const { 146 return chance_of_adding_atomic_load_; 147 } GetChanceOfAddingAtomicStore()148 uint32_t GetChanceOfAddingAtomicStore() const { 149 return chance_of_adding_atomic_store_; 150 } GetChanceOfAddingBitInstructionSynonym()151 uint32_t GetChanceOfAddingBitInstructionSynonym() const { 152 return chance_of_adding_bit_instruction_synonym_; 153 } GetChanceOfAddingBothBranchesWhenReplacingOpSelect()154 uint32_t GetChanceOfAddingBothBranchesWhenReplacingOpSelect() const { 155 return chance_of_adding_both_branches_when_replacing_opselect_; 156 } GetChanceOfAddingCompositeExtract()157 uint32_t GetChanceOfAddingCompositeExtract() const { 158 return chance_of_adding_composite_extract_; 159 } GetChanceOfAddingCompositeInsert()160 uint32_t GetChanceOfAddingCompositeInsert() const { 161 return chance_of_adding_composite_insert_; 162 } GetChanceOfAddingCopyMemory()163 uint32_t GetChanceOfAddingCopyMemory() const { 164 return chance_of_adding_copy_memory_; 165 } GetChanceOfAddingDeadBlock()166 uint32_t GetChanceOfAddingDeadBlock() const { 167 return chance_of_adding_dead_block_; 168 } GetChanceOfAddingDeadBreak()169 uint32_t GetChanceOfAddingDeadBreak() const { 170 return chance_of_adding_dead_break_; 171 } GetChanceOfAddingDeadContinue()172 uint32_t GetChanceOfAddingDeadContinue() const { 173 return chance_of_adding_dead_continue_; 174 } GetChanceOfAddingEquationInstruction()175 uint32_t GetChanceOfAddingEquationInstruction() const { 176 return chance_of_adding_equation_instruction_; 177 } GetChanceOfAddingGlobalVariable()178 uint32_t GetChanceOfAddingGlobalVariable() const { 179 return chance_of_adding_global_variable_; 180 } GetChanceOfAddingImageSampleUnusedComponents()181 uint32_t GetChanceOfAddingImageSampleUnusedComponents() const { 182 return chance_of_adding_image_sample_unused_components_; 183 } GetChanceOfAddingLoad()184 uint32_t GetChanceOfAddingLoad() const { return chance_of_adding_load_; } GetChanceOfAddingLocalVariable()185 uint32_t GetChanceOfAddingLocalVariable() const { 186 return chance_of_adding_local_variable_; 187 } GetChanceOfAddingLoopPreheader()188 uint32_t GetChanceOfAddingLoopPreheader() const { 189 return chance_of_adding_loop_preheader_; 190 } GetChanceOfAddingMatrixType()191 uint32_t GetChanceOfAddingMatrixType() const { 192 return chance_of_adding_matrix_type_; 193 } GetChanceOfAddingNoContractionDecoration()194 uint32_t GetChanceOfAddingNoContractionDecoration() const { 195 return chance_of_adding_no_contraction_decoration_; 196 } GetChanceOfAddingOpPhiSynonym()197 uint32_t GetChanceOfAddingOpPhiSynonym() const { 198 return chance_of_adding_opphi_synonym_; 199 } GetChanceOfAddingParameters()200 uint32_t GetChanceOfAddingParameters() const { 201 return chance_of_adding_parameters; 202 } GetChanceOfAddingRelaxedDecoration()203 uint32_t GetChanceOfAddingRelaxedDecoration() const { 204 return chance_of_adding_relaxed_decoration_; 205 } GetChanceOfAddingStore()206 uint32_t GetChanceOfAddingStore() const { return chance_of_adding_store_; } GetChanceOfAddingSynonyms()207 uint32_t GetChanceOfAddingSynonyms() const { 208 return chance_of_adding_synonyms_; 209 } GetChanceOfAddingTrueBranchWhenReplacingOpSelect()210 uint32_t GetChanceOfAddingTrueBranchWhenReplacingOpSelect() const { 211 return chance_of_adding_true_branch_when_replacing_opselect_; 212 } GetChanceOfAddingVectorShuffle()213 uint32_t GetChanceOfAddingVectorShuffle() const { 214 return chance_of_adding_vector_shuffle_; 215 } GetChanceOfAddingVectorType()216 uint32_t GetChanceOfAddingVectorType() const { 217 return chance_of_adding_vector_type_; 218 } GetChanceOfAdjustingBranchWeights()219 uint32_t GetChanceOfAdjustingBranchWeights() const { 220 return chance_of_adjusting_branch_weights_; 221 } GetChanceOfAdjustingFunctionControl()222 uint32_t GetChanceOfAdjustingFunctionControl() const { 223 return chance_of_adjusting_function_control_; 224 } GetChanceOfAdjustingLoopControl()225 uint32_t GetChanceOfAdjustingLoopControl() const { 226 return chance_of_adjusting_loop_control_; 227 } GetChanceOfAdjustingMemoryOperandsMask()228 uint32_t GetChanceOfAdjustingMemoryOperandsMask() const { 229 return chance_of_adjusting_memory_operands_mask_; 230 } GetChanceOfAdjustingSelectionControl()231 uint32_t GetChanceOfAdjustingSelectionControl() const { 232 return chance_of_adjusting_selection_control_; 233 } GetChanceOfCallingFunction()234 uint32_t GetChanceOfCallingFunction() const { 235 return chance_of_calling_function_; 236 } GetChanceOfChoosingStructTypeVsArrayType()237 uint32_t GetChanceOfChoosingStructTypeVsArrayType() const { 238 return chance_of_choosing_struct_type_vs_array_type_; 239 } GetChanceOfChoosingWorkgroupStorageClass()240 uint32_t GetChanceOfChoosingWorkgroupStorageClass() const { 241 return chance_of_choosing_workgroup_storage_class_; 242 } GetChanceOfConstructingComposite()243 uint32_t GetChanceOfConstructingComposite() const { 244 return chance_of_constructing_composite_; 245 } GetChanceOfCopyingObject()246 uint32_t GetChanceOfCopyingObject() const { 247 return chance_of_copying_object_; 248 } GetChanceOfCreatingIntSynonymsUsingLoops()249 uint32_t GetChanceOfCreatingIntSynonymsUsingLoops() const { 250 return chance_of_creating_int_synonyms_using_loops_; 251 } GetChanceOfDonatingAdditionalModule()252 uint32_t GetChanceOfDonatingAdditionalModule() const { 253 return chance_of_donating_additional_module_; 254 } GetChanceOfDuplicatingRegionWithSelection()255 uint32_t GetChanceOfDuplicatingRegionWithSelection() const { 256 return chance_of_duplicating_region_with_selection_; 257 } GetChanceOfExpandingVectorReduction()258 uint32_t GetChanceOfExpandingVectorReduction() const { 259 return chance_of_expanding_vector_reduction_; 260 } GetChanceOfFlatteningConditionalBranch()261 uint32_t GetChanceOfFlatteningConditionalBranch() const { 262 return chance_of_flattening_conditional_branch_; 263 } GetChanceOfGoingDeeperToExtractComposite()264 uint32_t GetChanceOfGoingDeeperToExtractComposite() const { 265 return chance_of_going_deeper_to_extract_composite_; 266 } GetChanceOfGoingDeeperToInsertInComposite()267 uint32_t GetChanceOfGoingDeeperToInsertInComposite() const { 268 return chance_of_going_deeper_to_insert_in_composite_; 269 } GetChanceOfGoingDeeperWhenMakingAccessChain()270 uint32_t GetChanceOfGoingDeeperWhenMakingAccessChain() const { 271 return chance_of_going_deeper_when_making_access_chain_; 272 } GetChanceOfHavingTwoBlocksInLoopToCreateIntSynonym()273 uint32_t GetChanceOfHavingTwoBlocksInLoopToCreateIntSynonym() const { 274 return chance_of_having_two_blocks_in_loop_to_create_int_synonym_; 275 } GetChanceOfInliningFunction()276 uint32_t GetChanceOfInliningFunction() const { 277 return chance_of_inlining_function_; 278 } GetChanceOfInterchangingSignednessOfIntegerOperands()279 uint32_t GetChanceOfInterchangingSignednessOfIntegerOperands() const { 280 return chance_of_interchanging_signedness_of_integer_operands_; 281 } GetChanceOfInterchangingZeroLikeConstants()282 uint32_t GetChanceOfInterchangingZeroLikeConstants() const { 283 return chance_of_interchanging_zero_like_constants_; 284 } GetChanceOfInvertingComparisonOperators()285 uint32_t GetChanceOfInvertingComparisonOperators() const { 286 return chance_of_inverting_comparison_operators_; 287 } ChanceOfMakingDonorLivesafe()288 uint32_t ChanceOfMakingDonorLivesafe() const { 289 return chance_of_making_donor_livesafe_; 290 } GetChanceOfMakingVectorOperationDynamic()291 uint32_t GetChanceOfMakingVectorOperationDynamic() const { 292 return chance_of_making_vector_operation_dynamic_; 293 } GetChanceOfMergingBlocks()294 uint32_t GetChanceOfMergingBlocks() const { 295 return chance_of_merging_blocks_; 296 } GetChanceOfMergingFunctionReturns()297 uint32_t GetChanceOfMergingFunctionReturns() const { 298 return chance_of_merging_function_returns_; 299 } GetChanceOfMovingBlockDown()300 uint32_t GetChanceOfMovingBlockDown() const { 301 return chance_of_moving_block_down_; 302 } GetChanceOfMutatingPointer()303 uint32_t GetChanceOfMutatingPointer() const { 304 return chance_of_mutating_pointer_; 305 } GetChanceOfObfuscatingConstant()306 uint32_t GetChanceOfObfuscatingConstant() const { 307 return chance_of_obfuscating_constant_; 308 } GetChanceOfOutliningFunction()309 uint32_t GetChanceOfOutliningFunction() const { 310 return chance_of_outlining_function_; 311 } GetChanceOfPermutingFunctionVariables()312 uint32_t GetChanceOfPermutingFunctionVariables() const { 313 return chance_of_permuting_function_variables_; 314 } GetChanceOfPermutingInstructions()315 uint32_t GetChanceOfPermutingInstructions() const { 316 return chance_of_permuting_instructions_; 317 } GetChanceOfPermutingParameters()318 uint32_t GetChanceOfPermutingParameters() const { 319 return chance_of_permuting_parameters_; 320 } GetChanceOfPermutingPhiOperands()321 uint32_t GetChanceOfPermutingPhiOperands() const { 322 return chance_of_permuting_phi_operands_; 323 } GetChanceOfPropagatingInstructionsDown()324 uint32_t GetChanceOfPropagatingInstructionsDown() const { 325 return chance_of_propagating_instructions_down_; 326 } GetChanceOfPropagatingInstructionsUp()327 uint32_t GetChanceOfPropagatingInstructionsUp() const { 328 return chance_of_propagating_instructions_up_; 329 } GetChanceOfPushingIdThroughVariable()330 uint32_t GetChanceOfPushingIdThroughVariable() const { 331 return chance_of_pushing_id_through_variable_; 332 } GetChanceOfReplacingAddSubMulWithCarryingExtended()333 uint32_t GetChanceOfReplacingAddSubMulWithCarryingExtended() const { 334 return chance_of_replacing_add_sub_mul_with_carrying_extended_; 335 } GetChanceOfReplacingBranchFromDeadBlockWithExit()336 uint32_t GetChanceOfReplacingBranchFromDeadBlockWithExit() const { 337 return chance_of_replacing_branch_from_dead_block_with_exit_; 338 } GetChanceOfReplacingCopyMemoryWithLoadStore()339 uint32_t GetChanceOfReplacingCopyMemoryWithLoadStore() const { 340 return chance_of_replacing_copy_memory_with_load_store_; 341 } GetChanceOfReplacingCopyObjectWithStoreLoad()342 uint32_t GetChanceOfReplacingCopyObjectWithStoreLoad() const { 343 return chance_of_replacing_copyobject_with_store_load_; 344 } GetChanceOfReplacingIdWithSynonym()345 uint32_t GetChanceOfReplacingIdWithSynonym() const { 346 return chance_of_replacing_id_with_synonym_; 347 } GetChanceOfReplacingIrrelevantId()348 uint32_t GetChanceOfReplacingIrrelevantId() const { 349 return chance_of_replacing_irrelevant_id_; 350 } GetChanceOfReplacingLinearAlgebraInstructions()351 uint32_t GetChanceOfReplacingLinearAlgebraInstructions() const { 352 return chance_of_replacing_linear_algebra_instructions_; 353 } GetChanceOfReplacingLoadStoreWithCopyMemory()354 uint32_t GetChanceOfReplacingLoadStoreWithCopyMemory() const { 355 return chance_of_replacing_load_store_with_copy_memory_; 356 } GetChanceOfReplacingOpPhiIdFromDeadPredecessor()357 uint32_t GetChanceOfReplacingOpPhiIdFromDeadPredecessor() const { 358 return chance_of_replacing_opphi_id_from_dead_predecessor_; 359 } GetChanceOfReplacingOpselectWithConditionalBranch()360 uint32_t GetChanceOfReplacingOpselectWithConditionalBranch() const { 361 return chance_of_replacing_opselect_with_conditional_branch_; 362 } GetChanceOfReplacingParametersWithGlobals()363 uint32_t GetChanceOfReplacingParametersWithGlobals() const { 364 return chance_of_replacing_parameters_with_globals_; 365 } GetChanceOfReplacingParametersWithStruct()366 uint32_t GetChanceOfReplacingParametersWithStruct() const { 367 return chance_of_replacing_parameters_with_struct_; 368 } GetChanceOfSplittingBlock()369 uint32_t GetChanceOfSplittingBlock() const { 370 return chance_of_splitting_block_; 371 } GetChanceOfSwappingAnotherPairOfFunctionVariables()372 uint32_t GetChanceOfSwappingAnotherPairOfFunctionVariables() const { 373 return chance_of_swapping_another_pair_of_function_variables_; 374 } GetChanceOfSwappingConditionalBranchOperands()375 uint32_t GetChanceOfSwappingConditionalBranchOperands() const { 376 return chance_of_swapping_conditional_branch_operands_; 377 } 378 GetChanceOfSwappingFunctions()379 uint32_t GetChanceOfSwappingFunctions() const { 380 return chance_of_swapping_functions_; 381 } 382 GetChanceOfTogglingAccessChainInstruction()383 uint32_t GetChanceOfTogglingAccessChainInstruction() const { 384 return chance_of_toggling_access_chain_instruction_; 385 } GetChanceOfWrappingRegionInSelection()386 uint32_t GetChanceOfWrappingRegionInSelection() const { 387 return chance_of_wrapping_region_in_selection_; 388 } 389 GetChanceOfWrappingVectorSynonym()390 uint32_t GetChanceOfWrappingVectorSynonym() const { 391 return chance_of_wrapping_vector_synonym_; 392 } 393 394 // Other functions to control transformations. Keep them in alphabetical 395 // order. GetMaximumEquivalenceClassSizeForDataSynonymFactClosure()396 uint32_t GetMaximumEquivalenceClassSizeForDataSynonymFactClosure() const { 397 return max_equivalence_class_size_for_data_synonym_fact_closure_; 398 } GetMaximumNumberOfFunctionParameters()399 uint32_t GetMaximumNumberOfFunctionParameters() const { 400 return max_number_of_function_parameters_; 401 } GetMaximumNumberOfParametersReplacedWithStruct()402 uint32_t GetMaximumNumberOfParametersReplacedWithStruct() const { 403 return max_number_of_parameters_replaced_with_struct_; 404 } GetRandomBranchWeights()405 std::pair<uint32_t, uint32_t> GetRandomBranchWeights() { 406 std::pair<uint32_t, uint32_t> branch_weights = {0, 0}; 407 408 while (branch_weights.first == 0 && branch_weights.second == 0) { 409 // Using INT32_MAX to do not overflow UINT32_MAX when the branch weights 410 // are added together. 411 branch_weights.first = random_generator_->RandomUint32(INT32_MAX); 412 branch_weights.second = random_generator_->RandomUint32(INT32_MAX); 413 } 414 415 return branch_weights; 416 } GetRandomComponentsForVectorShuffle(uint32_t max_component_index)417 std::vector<uint32_t> GetRandomComponentsForVectorShuffle( 418 uint32_t max_component_index) { 419 // Component count must be in range [2, 4]. 420 std::vector<uint32_t> components(random_generator_->RandomUint32(2) + 2); 421 422 for (uint32_t& component : components) { 423 component = random_generator_->RandomUint32(max_component_index); 424 } 425 426 return components; 427 } GetRandomCompositeExtractIndex(uint32_t number_of_members)428 uint32_t GetRandomCompositeExtractIndex(uint32_t number_of_members) { 429 assert(number_of_members > 0 && "Composite object must have some members"); 430 return ChooseBetweenMinAndMax({0, number_of_members - 1}); 431 } GetRandomIndexForAccessChain(uint32_t composite_size_bound)432 uint32_t GetRandomIndexForAccessChain(uint32_t composite_size_bound) { 433 return random_generator_->RandomUint32(composite_size_bound); 434 } GetRandomIndexForCompositeInsert(uint32_t number_of_components)435 uint32_t GetRandomIndexForCompositeInsert(uint32_t number_of_components) { 436 return random_generator_->RandomUint32(number_of_components); 437 } GetRandomIndexForWrappingVector(uint32_t vector_width)438 uint32_t GetRandomIndexForWrappingVector(uint32_t vector_width) { 439 return random_generator_->RandomUint32(vector_width); 440 } GetRandomValueForStepConstantInLoop()441 int64_t GetRandomValueForStepConstantInLoop() { 442 return random_generator_->RandomUint64(UINT64_MAX); 443 } GetRandomLoopControlPartialCount()444 uint32_t GetRandomLoopControlPartialCount() { 445 return random_generator_->RandomUint32(max_loop_control_partial_count_); 446 } GetRandomLoopControlPeelCount()447 uint32_t GetRandomLoopControlPeelCount() { 448 return random_generator_->RandomUint32(max_loop_control_peel_count_); 449 } GetRandomLoopLimit()450 uint32_t GetRandomLoopLimit() { 451 return random_generator_->RandomUint32(max_loop_limit_); 452 } GetRandomNumberOfLoopIterations(uint32_t max_num_iterations)453 uint32_t GetRandomNumberOfLoopIterations(uint32_t max_num_iterations) { 454 return ChooseBetweenMinAndMax({1, max_num_iterations}); 455 } GetRandomNumberOfNewParameters(uint32_t num_of_params)456 uint32_t GetRandomNumberOfNewParameters(uint32_t num_of_params) { 457 assert(num_of_params < GetMaximumNumberOfFunctionParameters()); 458 return ChooseBetweenMinAndMax( 459 {1, std::min(max_number_of_new_parameters_, 460 GetMaximumNumberOfFunctionParameters() - num_of_params)}); 461 } GetRandomNumberOfParametersReplacedWithStruct(uint32_t num_params)462 uint32_t GetRandomNumberOfParametersReplacedWithStruct(uint32_t num_params) { 463 assert(num_params != 0 && "A function must have parameters to replace"); 464 return ChooseBetweenMinAndMax( 465 {1, std::min(num_params, 466 GetMaximumNumberOfParametersReplacedWithStruct())}); 467 } GetRandomSizeForNewArray()468 uint32_t GetRandomSizeForNewArray() { 469 // Ensure that the array size is non-zero. 470 return random_generator_->RandomUint32(max_new_array_size_limit_ - 1) + 1; 471 } 472 protobufs::TransformationAddSynonym::SynonymType GetRandomSynonymType(); GetRandomUnusedComponentCountForImageSample(uint32_t max_unused_component_count)473 uint32_t GetRandomUnusedComponentCountForImageSample( 474 uint32_t max_unused_component_count) { 475 // Ensure that the number of unused components is non-zero. 476 return random_generator_->RandomUint32(max_unused_component_count) + 1; 477 } GetWidthOfWrappingVector()478 uint32_t GetWidthOfWrappingVector() { 479 return 2 + random_generator_->RandomUint32(3); 480 } GoDeeperInConstantObfuscation(uint32_t depth)481 bool GoDeeperInConstantObfuscation(uint32_t depth) { 482 return go_deeper_in_constant_obfuscation_(depth, random_generator_.get()); 483 } 484 485 private: 486 // The source of randomness. 487 std::unique_ptr<RandomGenerator> random_generator_; 488 // The next fresh id to be issued. 489 uint32_t next_fresh_id_; 490 491 // True if all transformations should be compatible with WGSL spec. 492 bool is_wgsl_compatible_; 493 494 // Probabilities associated with applying various transformations. 495 // Keep them in alphabetical order. 496 uint32_t chance_of_accepting_repeated_pass_recommendation_; 497 uint32_t chance_of_adding_access_chain_; 498 uint32_t chance_of_adding_another_pass_to_pass_loop_; 499 uint32_t chance_of_adding_another_struct_field_; 500 uint32_t chance_of_adding_array_or_struct_type_; 501 uint32_t chance_of_adding_atomic_load_; 502 uint32_t chance_of_adding_atomic_store_; 503 uint32_t chance_of_adding_bit_instruction_synonym_; 504 uint32_t chance_of_adding_both_branches_when_replacing_opselect_; 505 uint32_t chance_of_adding_composite_extract_; 506 uint32_t chance_of_adding_composite_insert_; 507 uint32_t chance_of_adding_copy_memory_; 508 uint32_t chance_of_adding_dead_block_; 509 uint32_t chance_of_adding_dead_break_; 510 uint32_t chance_of_adding_dead_continue_; 511 uint32_t chance_of_adding_equation_instruction_; 512 uint32_t chance_of_adding_global_variable_; 513 uint32_t chance_of_adding_image_sample_unused_components_; 514 uint32_t chance_of_adding_load_; 515 uint32_t chance_of_adding_local_variable_; 516 uint32_t chance_of_adding_loop_preheader_; 517 uint32_t chance_of_adding_matrix_type_; 518 uint32_t chance_of_adding_no_contraction_decoration_; 519 uint32_t chance_of_adding_opphi_synonym_; 520 uint32_t chance_of_adding_parameters; 521 uint32_t chance_of_adding_relaxed_decoration_; 522 uint32_t chance_of_adding_store_; 523 uint32_t chance_of_adding_synonyms_; 524 uint32_t chance_of_adding_true_branch_when_replacing_opselect_; 525 uint32_t chance_of_adding_vector_shuffle_; 526 uint32_t chance_of_adding_vector_type_; 527 uint32_t chance_of_adjusting_branch_weights_; 528 uint32_t chance_of_adjusting_function_control_; 529 uint32_t chance_of_adjusting_loop_control_; 530 uint32_t chance_of_adjusting_memory_operands_mask_; 531 uint32_t chance_of_adjusting_selection_control_; 532 uint32_t chance_of_calling_function_; 533 uint32_t chance_of_choosing_struct_type_vs_array_type_; 534 uint32_t chance_of_choosing_workgroup_storage_class_; 535 uint32_t chance_of_constructing_composite_; 536 uint32_t chance_of_copying_object_; 537 uint32_t chance_of_creating_int_synonyms_using_loops_; 538 uint32_t chance_of_donating_additional_module_; 539 uint32_t chance_of_duplicating_region_with_selection_; 540 uint32_t chance_of_expanding_vector_reduction_; 541 uint32_t chance_of_flattening_conditional_branch_; 542 uint32_t chance_of_going_deeper_to_extract_composite_; 543 uint32_t chance_of_going_deeper_to_insert_in_composite_; 544 uint32_t chance_of_going_deeper_when_making_access_chain_; 545 uint32_t chance_of_having_two_blocks_in_loop_to_create_int_synonym_; 546 uint32_t chance_of_inlining_function_; 547 uint32_t chance_of_interchanging_signedness_of_integer_operands_; 548 uint32_t chance_of_interchanging_zero_like_constants_; 549 uint32_t chance_of_inverting_comparison_operators_; 550 uint32_t chance_of_making_donor_livesafe_; 551 uint32_t chance_of_making_vector_operation_dynamic_; 552 uint32_t chance_of_merging_blocks_; 553 uint32_t chance_of_merging_function_returns_; 554 uint32_t chance_of_moving_block_down_; 555 uint32_t chance_of_mutating_pointer_; 556 uint32_t chance_of_obfuscating_constant_; 557 uint32_t chance_of_outlining_function_; 558 uint32_t chance_of_permuting_function_variables_; 559 uint32_t chance_of_permuting_instructions_; 560 uint32_t chance_of_permuting_parameters_; 561 uint32_t chance_of_permuting_phi_operands_; 562 uint32_t chance_of_propagating_instructions_down_; 563 uint32_t chance_of_propagating_instructions_up_; 564 uint32_t chance_of_pushing_id_through_variable_; 565 uint32_t chance_of_replacing_add_sub_mul_with_carrying_extended_; 566 uint32_t chance_of_replacing_branch_from_dead_block_with_exit_; 567 uint32_t chance_of_replacing_copy_memory_with_load_store_; 568 uint32_t chance_of_replacing_copyobject_with_store_load_; 569 uint32_t chance_of_replacing_id_with_synonym_; 570 uint32_t chance_of_replacing_irrelevant_id_; 571 uint32_t chance_of_replacing_linear_algebra_instructions_; 572 uint32_t chance_of_replacing_load_store_with_copy_memory_; 573 uint32_t chance_of_replacing_opphi_id_from_dead_predecessor_; 574 uint32_t chance_of_replacing_opselect_with_conditional_branch_; 575 uint32_t chance_of_replacing_parameters_with_globals_; 576 uint32_t chance_of_replacing_parameters_with_struct_; 577 uint32_t chance_of_splitting_block_; 578 uint32_t chance_of_swapping_another_pair_of_function_variables_; 579 uint32_t chance_of_swapping_conditional_branch_operands_; 580 uint32_t chance_of_swapping_functions_; 581 uint32_t chance_of_toggling_access_chain_instruction_; 582 uint32_t chance_of_wrapping_region_in_selection_; 583 uint32_t chance_of_wrapping_vector_synonym_; 584 585 // Limits associated with various quantities for which random values are 586 // chosen during fuzzing. 587 // Keep them in alphabetical order. 588 uint32_t max_equivalence_class_size_for_data_synonym_fact_closure_; 589 uint32_t max_loop_control_partial_count_; 590 uint32_t max_loop_control_peel_count_; 591 uint32_t max_loop_limit_; 592 uint32_t max_new_array_size_limit_; 593 uint32_t max_number_of_function_parameters_; 594 uint32_t max_number_of_new_parameters_; 595 uint32_t max_number_of_parameters_replaced_with_struct_; 596 597 // Functions to determine with what probability to go deeper when generating 598 // or mutating constructs recursively. 599 const std::function<bool(uint32_t, RandomGenerator*)>& 600 go_deeper_in_constant_obfuscation_; 601 602 // Requires |min_max.first| <= |min_max.second|, and returns a value in the 603 // range [ |min_max.first|, |min_max.second| ] 604 uint32_t ChooseBetweenMinAndMax(const std::pair<uint32_t, uint32_t>& min_max); 605 }; 606 607 } // namespace fuzz 608 } // namespace spvtools 609 610 #endif // SOURCE_FUZZ_FUZZER_CONTEXT_H_ 611