transformation_set_function_control.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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/transformation_set_function_control.h"
  15. namespace spvtools {
  16. namespace fuzz {
  17. TransformationSetFunctionControl::TransformationSetFunctionControl(
  18. protobufs::TransformationSetFunctionControl message)
  19. : message_(std::move(message)) {}
  20. TransformationSetFunctionControl::TransformationSetFunctionControl(
  21. uint32_t function_id, uint32_t function_control) {
  22. message_.set_function_id(function_id);
  23. message_.set_function_control(function_control);
  24. }
  25. bool TransformationSetFunctionControl::IsApplicable(
  26. opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
  27. opt::Instruction* function_def_instruction =
  28. FindFunctionDefInstruction(ir_context);
  29. if (!function_def_instruction) {
  30. // The given function id does not correspond to any function.
  31. return false;
  32. }
  33. uint32_t existing_function_control_mask =
  34. function_def_instruction->GetSingleWordInOperand(0);
  35. // Check (via an assertion) that function control mask doesn't have any bad
  36. // bits set.
  37. uint32_t acceptable_function_control_bits = uint32_t(
  38. spv::FunctionControlMask::Inline | spv::FunctionControlMask::DontInline |
  39. spv::FunctionControlMask::Pure | spv::FunctionControlMask::Const);
  40. // The following is to keep release-mode compilers happy as this variable is
  41. // only used in an assertion.
  42. (void)(acceptable_function_control_bits);
  43. assert(!(message_.function_control() & ~acceptable_function_control_bits) &&
  44. "Nonsensical loop control bits were found.");
  45. // Check (via an assertion) that function control mask does not have both
  46. // Inline and DontInline bits set.
  47. assert(!((message_.function_control() &
  48. (uint32_t)spv::FunctionControlMask::Inline) &&
  49. (message_.function_control() &
  50. (uint32_t)spv::FunctionControlMask::DontInline)) &&
  51. "It is not OK to set both the 'Inline' and 'DontInline' bits of a "
  52. "function control mask");
  53. // Check that Const and Pure are only present if they were present on the
  54. // original function
  55. for (auto mask_bit :
  56. {spv::FunctionControlMask::Pure, spv::FunctionControlMask::Const}) {
  57. if ((message_.function_control() & uint32_t(mask_bit)) &&
  58. !(existing_function_control_mask & uint32_t(mask_bit))) {
  59. return false;
  60. }
  61. }
  62. return true;
  63. }
  64. void TransformationSetFunctionControl::Apply(
  65. opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
  66. opt::Instruction* function_def_instruction =
  67. FindFunctionDefInstruction(ir_context);
  68. function_def_instruction->SetInOperand(0, {message_.function_control()});
  69. }
  70. protobufs::Transformation TransformationSetFunctionControl::ToMessage() const {
  71. protobufs::Transformation result;
  72. *result.mutable_set_function_control() = message_;
  73. return result;
  74. }
  75. opt::Instruction* TransformationSetFunctionControl ::FindFunctionDefInstruction(
  76. opt::IRContext* ir_context) const {
  77. // Look through all functions for a function whose defining instruction's
  78. // result id matches |message_.function_id|, returning the defining
  79. // instruction if found.
  80. for (auto& function : *ir_context->module()) {
  81. if (function.DefInst().result_id() == message_.function_id()) {
  82. return &function.DefInst();
  83. }
  84. }
  85. // A nullptr result indicates that no match was found.
  86. return nullptr;
  87. }
  88. std::unordered_set<uint32_t> TransformationSetFunctionControl::GetFreshIds()
  89. const {
  90. return std::unordered_set<uint32_t>();
  91. }
  92. } // namespace fuzz
  93. } // namespace spvtools