fuzzer_pass_outline_functions.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. #include "source/fuzz/fuzzer_pass_outline_functions.h"
  15. #include <vector>
  16. #include "source/fuzz/fuzzer_util.h"
  17. #include "source/fuzz/transformation_outline_function.h"
  18. namespace spvtools {
  19. namespace fuzz {
  20. FuzzerPassOutlineFunctions::FuzzerPassOutlineFunctions(
  21. opt::IRContext* ir_context, TransformationContext* transformation_context,
  22. FuzzerContext* fuzzer_context,
  23. protobufs::TransformationSequence* transformations)
  24. : FuzzerPass(ir_context, transformation_context, fuzzer_context,
  25. transformations) {}
  26. FuzzerPassOutlineFunctions::~FuzzerPassOutlineFunctions() = default;
  27. void FuzzerPassOutlineFunctions::Apply() {
  28. std::vector<opt::Function*> original_functions;
  29. for (auto& function : *GetIRContext()->module()) {
  30. original_functions.push_back(&function);
  31. }
  32. for (auto& function : original_functions) {
  33. if (!GetFuzzerContext()->ChoosePercentage(
  34. GetFuzzerContext()->GetChanceOfOutliningFunction())) {
  35. continue;
  36. }
  37. std::vector<opt::BasicBlock*> blocks;
  38. for (auto& block : *function) {
  39. blocks.push_back(&block);
  40. }
  41. auto entry_block = blocks[GetFuzzerContext()->RandomIndex(blocks)];
  42. auto dominator_analysis = GetIRContext()->GetDominatorAnalysis(function);
  43. auto postdominator_analysis =
  44. GetIRContext()->GetPostDominatorAnalysis(function);
  45. std::vector<opt::BasicBlock*> candidate_exit_blocks;
  46. for (auto postdominates_entry_block = entry_block;
  47. postdominates_entry_block != nullptr;
  48. postdominates_entry_block = postdominator_analysis->ImmediateDominator(
  49. postdominates_entry_block)) {
  50. if (dominator_analysis->Dominates(entry_block,
  51. postdominates_entry_block)) {
  52. candidate_exit_blocks.push_back(postdominates_entry_block);
  53. }
  54. }
  55. if (candidate_exit_blocks.empty()) {
  56. continue;
  57. }
  58. auto exit_block = candidate_exit_blocks[GetFuzzerContext()->RandomIndex(
  59. candidate_exit_blocks)];
  60. auto region_blocks = TransformationOutlineFunction::GetRegionBlocks(
  61. GetIRContext(), entry_block, exit_block);
  62. std::map<uint32_t, uint32_t> input_id_to_fresh_id;
  63. for (auto id : TransformationOutlineFunction::GetRegionInputIds(
  64. GetIRContext(), region_blocks, exit_block)) {
  65. input_id_to_fresh_id[id] = GetFuzzerContext()->GetFreshId();
  66. }
  67. std::map<uint32_t, uint32_t> output_id_to_fresh_id;
  68. for (auto id : TransformationOutlineFunction::GetRegionOutputIds(
  69. GetIRContext(), region_blocks, exit_block)) {
  70. output_id_to_fresh_id[id] = GetFuzzerContext()->GetFreshId();
  71. }
  72. TransformationOutlineFunction transformation(
  73. entry_block->id(), exit_block->id(),
  74. /*new_function_struct_return_type_id*/
  75. GetFuzzerContext()->GetFreshId(),
  76. /*new_function_type_id*/ GetFuzzerContext()->GetFreshId(),
  77. /*new_function_id*/ GetFuzzerContext()->GetFreshId(),
  78. /*new_function_region_entry_block*/
  79. GetFuzzerContext()->GetFreshId(),
  80. /*new_caller_result_id*/ GetFuzzerContext()->GetFreshId(),
  81. /*new_callee_result_id*/ GetFuzzerContext()->GetFreshId(),
  82. /*input_id_to_fresh_id*/ std::move(input_id_to_fresh_id),
  83. /*output_id_to_fresh_id*/ std::move(output_id_to_fresh_id));
  84. if (transformation.IsApplicable(GetIRContext(),
  85. *GetTransformationContext())) {
  86. transformation.Apply(GetIRContext(), GetTransformationContext());
  87. *GetTransformations()->add_transformation() = transformation.ToMessage();
  88. }
  89. }
  90. }
  91. } // namespace fuzz
  92. } // namespace spvtools