fuzzer_pass_replace_parameter_with_global.cpp 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Copyright (c) 2020 Vasyl Teliman
  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_replace_parameter_with_global.h"
  15. #include <numeric>
  16. #include <vector>
  17. #include "source/fuzz/fuzzer_context.h"
  18. #include "source/fuzz/fuzzer_util.h"
  19. #include "source/fuzz/transformation_replace_parameter_with_global.h"
  20. namespace spvtools {
  21. namespace fuzz {
  22. FuzzerPassReplaceParameterWithGlobal::FuzzerPassReplaceParameterWithGlobal(
  23. opt::IRContext* ir_context, TransformationContext* transformation_context,
  24. FuzzerContext* fuzzer_context,
  25. protobufs::TransformationSequence* transformations,
  26. bool ignore_inapplicable_transformations)
  27. : FuzzerPass(ir_context, transformation_context, fuzzer_context,
  28. transformations, ignore_inapplicable_transformations) {}
  29. void FuzzerPassReplaceParameterWithGlobal::Apply() {
  30. for (const auto& function : *GetIRContext()->module()) {
  31. if (fuzzerutil::FunctionIsEntryPoint(GetIRContext(),
  32. function.result_id())) {
  33. continue;
  34. }
  35. if (!GetFuzzerContext()->ChoosePercentage(
  36. GetFuzzerContext()->GetChanceOfReplacingParametersWithGlobals())) {
  37. continue;
  38. }
  39. auto params =
  40. fuzzerutil::GetParameters(GetIRContext(), function.result_id());
  41. // Make sure at least one parameter can be replaced. Also checks that the
  42. // function has at least one parameter.
  43. if (std::none_of(params.begin(), params.end(),
  44. [this](const opt::Instruction* param) {
  45. return TransformationReplaceParameterWithGlobal::
  46. IsParameterTypeSupported(GetIRContext(),
  47. param->type_id());
  48. })) {
  49. continue;
  50. }
  51. // Select id of a parameter to replace.
  52. const opt::Instruction* replaced_param;
  53. uint32_t param_type_id;
  54. do {
  55. replaced_param = GetFuzzerContext()->RemoveAtRandomIndex(&params);
  56. param_type_id = replaced_param->type_id();
  57. assert(param_type_id && "Parameter has invalid type");
  58. } while (
  59. !TransformationReplaceParameterWithGlobal::IsParameterTypeSupported(
  60. GetIRContext(), param_type_id));
  61. assert(replaced_param && "Unable to find a parameter to replace");
  62. // Make sure type id for the global variable exists in the module.
  63. FindOrCreatePointerType(replaced_param->type_id(),
  64. spv::StorageClass::Private);
  65. // Make sure initializer for the global variable exists in the module.
  66. FindOrCreateZeroConstant(replaced_param->type_id(), false);
  67. ApplyTransformation(TransformationReplaceParameterWithGlobal(
  68. GetFuzzerContext()->GetFreshId(), replaced_param->result_id(),
  69. GetFuzzerContext()->GetFreshId()));
  70. }
  71. }
  72. } // namespace fuzz
  73. } // namespace spvtools