transformation_swap_function_variables.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright (c) 2021 Mostafa Ashraf
  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/transformation_swap_function_variables.h"
  15. #include "source/fuzz/fuzzer_util.h"
  16. namespace spvtools {
  17. namespace fuzz {
  18. TransformationSwapFunctionVariables::TransformationSwapFunctionVariables(
  19. protobufs::TransformationSwapFunctionVariables message)
  20. : message_(std::move(message)) {}
  21. TransformationSwapFunctionVariables::TransformationSwapFunctionVariables(
  22. uint32_t result_id1, uint32_t result_id2) {
  23. message_.set_result_id1(result_id1);
  24. message_.set_result_id2(result_id2);
  25. }
  26. bool TransformationSwapFunctionVariables::IsApplicable(
  27. opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
  28. uint32_t result_id1 = message_.result_id1();
  29. uint32_t result_id2 = message_.result_id2();
  30. assert((result_id1 != result_id2) && "Two results ids are equal");
  31. // The result ids used in the message must refer to instructions.
  32. auto instruction1 = ir_context->get_def_use_mgr()->GetDef(result_id1);
  33. auto instruction2 = ir_context->get_def_use_mgr()->GetDef(result_id2);
  34. if (instruction1 == nullptr || instruction2 == nullptr) {
  35. return false;
  36. }
  37. // Both instructions must be variables.
  38. if (instruction1->opcode() != spv::Op::OpVariable ||
  39. instruction2->opcode() != spv::Op::OpVariable) {
  40. return false;
  41. }
  42. // Both variable instructions must be in some basic block (as they are
  43. // function-local variables), and they must be in the same block (as they need
  44. // to be variables of the same function).
  45. auto* block_1 = ir_context->get_instr_block(result_id1);
  46. auto* block_2 = ir_context->get_instr_block(result_id2);
  47. if (block_1 == nullptr || block_2 == nullptr) {
  48. return false;
  49. }
  50. return block_1 == block_2;
  51. }
  52. void TransformationSwapFunctionVariables::Apply(
  53. opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
  54. // The result ids used in the message must refer to instructions.
  55. auto instruction1 =
  56. ir_context->get_def_use_mgr()->GetDef(message_.result_id1());
  57. auto instruction2 =
  58. ir_context->get_def_use_mgr()->GetDef(message_.result_id2());
  59. std::unique_ptr<opt::Instruction> temp_instruction =
  60. MakeUnique<opt::Instruction>();
  61. temp_instruction->InsertBefore(instruction1);
  62. instruction1->InsertAfter(instruction2);
  63. instruction2->InsertAfter(temp_instruction.get());
  64. temp_instruction->RemoveFromList();
  65. }
  66. protobufs::Transformation TransformationSwapFunctionVariables::ToMessage()
  67. const {
  68. protobufs::Transformation result;
  69. *result.mutable_swap_function_variables() = message_;
  70. return result;
  71. }
  72. std::unordered_set<uint32_t> TransformationSwapFunctionVariables::GetFreshIds()
  73. const {
  74. return std::unordered_set<uint32_t>();
  75. }
  76. } // namespace fuzz
  77. } // namespace spvtools