transformation_add_local_variable.cpp 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // Copyright (c) 2020 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_add_local_variable.h"
  15. #include "source/fuzz/fuzzer_util.h"
  16. namespace spvtools {
  17. namespace fuzz {
  18. TransformationAddLocalVariable::TransformationAddLocalVariable(
  19. const spvtools::fuzz::protobufs::TransformationAddLocalVariable& message)
  20. : message_(message) {}
  21. TransformationAddLocalVariable::TransformationAddLocalVariable(
  22. uint32_t fresh_id, uint32_t type_id, uint32_t function_id,
  23. uint32_t initializer_id, bool value_is_irrelevant) {
  24. message_.set_fresh_id(fresh_id);
  25. message_.set_type_id(type_id);
  26. message_.set_function_id(function_id);
  27. message_.set_initializer_id(initializer_id);
  28. message_.set_value_is_irrelevant(value_is_irrelevant);
  29. }
  30. bool TransformationAddLocalVariable::IsApplicable(
  31. opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
  32. // The provided id must be fresh.
  33. if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
  34. return false;
  35. }
  36. // The pointer type id must indeed correspond to a pointer, and it must have
  37. // function storage class.
  38. auto type_instruction =
  39. ir_context->get_def_use_mgr()->GetDef(message_.type_id());
  40. if (!type_instruction || type_instruction->opcode() != SpvOpTypePointer ||
  41. type_instruction->GetSingleWordInOperand(0) != SpvStorageClassFunction) {
  42. return false;
  43. }
  44. // The initializer must...
  45. auto initializer_instruction =
  46. ir_context->get_def_use_mgr()->GetDef(message_.initializer_id());
  47. // ... exist, ...
  48. if (!initializer_instruction) {
  49. return false;
  50. }
  51. // ... be a constant, ...
  52. if (!spvOpcodeIsConstant(initializer_instruction->opcode())) {
  53. return false;
  54. }
  55. // ... and have the same type as the pointee type.
  56. if (initializer_instruction->type_id() !=
  57. type_instruction->GetSingleWordInOperand(1)) {
  58. return false;
  59. }
  60. // The function to which the local variable is to be added must exist.
  61. return fuzzerutil::FindFunction(ir_context, message_.function_id());
  62. }
  63. void TransformationAddLocalVariable::Apply(
  64. opt::IRContext* ir_context,
  65. TransformationContext* transformation_context) const {
  66. fuzzerutil::AddLocalVariable(ir_context, message_.fresh_id(),
  67. message_.type_id(), message_.function_id(),
  68. message_.initializer_id());
  69. if (message_.value_is_irrelevant()) {
  70. transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
  71. message_.fresh_id());
  72. }
  73. ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
  74. }
  75. protobufs::Transformation TransformationAddLocalVariable::ToMessage() const {
  76. protobufs::Transformation result;
  77. *result.mutable_add_local_variable() = message_;
  78. return result;
  79. }
  80. } // namespace fuzz
  81. } // namespace spvtools