transformation_set_function_control.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. const spvtools::fuzz::protobufs::TransformationSetFunctionControl& message)
  19. : message_(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* context, const FactManager& /*unused*/) const {
  27. opt::Instruction* function_def_instruction =
  28. FindFunctionDefInstruction(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 =
  38. SpvFunctionControlInlineMask | SpvFunctionControlDontInlineMask |
  39. SpvFunctionControlPureMask | SpvFunctionControlConstMask;
  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() & SpvFunctionControlInlineMask) &&
  48. (message_.function_control() & SpvFunctionControlDontInlineMask)) &&
  49. "It is not OK to set both the 'Inline' and 'DontInline' bits of a "
  50. "function control mask");
  51. // Check that Const and Pure are only present if they were present on the
  52. // original function
  53. for (auto mask_bit :
  54. {SpvFunctionControlPureMask, SpvFunctionControlConstMask}) {
  55. if ((message_.function_control() & mask_bit) &&
  56. !(existing_function_control_mask & mask_bit)) {
  57. return false;
  58. }
  59. }
  60. return true;
  61. }
  62. void TransformationSetFunctionControl::Apply(opt::IRContext* context,
  63. FactManager* /*unused*/) const {
  64. opt::Instruction* function_def_instruction =
  65. FindFunctionDefInstruction(context);
  66. function_def_instruction->SetInOperand(0, {message_.function_control()});
  67. }
  68. protobufs::Transformation TransformationSetFunctionControl::ToMessage() const {
  69. protobufs::Transformation result;
  70. *result.mutable_set_function_control() = message_;
  71. return result;
  72. }
  73. opt::Instruction* TransformationSetFunctionControl ::FindFunctionDefInstruction(
  74. opt::IRContext* context) const {
  75. // Look through all functions for a function whose defining instruction's
  76. // result id matches |message_.function_id|, returning the defining
  77. // instruction if found.
  78. for (auto& function : *context->module()) {
  79. if (function.DefInst().result_id() == message_.function_id()) {
  80. return &function.DefInst();
  81. }
  82. }
  83. // A nullptr result indicates that no match was found.
  84. return nullptr;
  85. }
  86. } // namespace fuzz
  87. } // namespace spvtools