id_use_descriptor.cpp 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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/id_use_descriptor.h"
  15. namespace spvtools {
  16. namespace fuzz {
  17. opt::Instruction* transformation::FindInstruction(
  18. const protobufs::IdUseDescriptor& descriptor,
  19. spvtools::opt::IRContext* context) {
  20. for (auto& function : *context->module()) {
  21. for (auto& block : function) {
  22. bool found_base = block.id() == descriptor.base_instruction_result_id();
  23. uint32_t num_ignored = 0;
  24. for (auto& instruction : block) {
  25. if (instruction.HasResultId() &&
  26. instruction.result_id() ==
  27. descriptor.base_instruction_result_id()) {
  28. assert(!found_base &&
  29. "It should not be possible to find the base instruction "
  30. "multiple times.");
  31. found_base = true;
  32. assert(num_ignored == 0 &&
  33. "The skipped instruction count should only be incremented "
  34. "after the instruction base has been found.");
  35. }
  36. if (found_base &&
  37. instruction.opcode() == descriptor.target_instruction_opcode()) {
  38. if (num_ignored == descriptor.num_opcodes_to_ignore()) {
  39. if (descriptor.in_operand_index() >= instruction.NumInOperands()) {
  40. return nullptr;
  41. }
  42. auto in_operand =
  43. instruction.GetInOperand(descriptor.in_operand_index());
  44. if (in_operand.type != SPV_OPERAND_TYPE_ID) {
  45. return nullptr;
  46. }
  47. if (in_operand.words[0] != descriptor.id_of_interest()) {
  48. return nullptr;
  49. }
  50. return &instruction;
  51. }
  52. num_ignored++;
  53. }
  54. }
  55. if (found_base) {
  56. // We found the base instruction, but did not find the target
  57. // instruction in the same block.
  58. return nullptr;
  59. }
  60. }
  61. }
  62. return nullptr;
  63. }
  64. protobufs::IdUseDescriptor transformation::MakeIdUseDescriptor(
  65. uint32_t id_of_interest, SpvOp target_instruction_opcode,
  66. uint32_t in_operand_index, uint32_t base_instruction_result_id,
  67. uint32_t num_opcodes_to_ignore) {
  68. protobufs::IdUseDescriptor result;
  69. result.set_id_of_interest(id_of_interest);
  70. result.set_target_instruction_opcode(target_instruction_opcode);
  71. result.set_in_operand_index(in_operand_index);
  72. result.set_base_instruction_result_id(base_instruction_result_id);
  73. result.set_num_opcodes_to_ignore(num_opcodes_to_ignore);
  74. return result;
  75. }
  76. } // namespace fuzz
  77. } // namespace spvtools