transformation_add_local_variable.cpp 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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* context,
  32. const spvtools::fuzz::FactManager& /*unused*/) const {
  33. // The provided id must be fresh.
  34. if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
  35. return false;
  36. }
  37. // The pointer type id must indeed correspond to a pointer, and it must have
  38. // function storage class.
  39. auto type_instruction =
  40. context->get_def_use_mgr()->GetDef(message_.type_id());
  41. if (!type_instruction || type_instruction->opcode() != SpvOpTypePointer ||
  42. type_instruction->GetSingleWordInOperand(0) != SpvStorageClassFunction) {
  43. return false;
  44. }
  45. // The initializer must...
  46. auto initializer_instruction =
  47. context->get_def_use_mgr()->GetDef(message_.initializer_id());
  48. // ... exist, ...
  49. if (!initializer_instruction) {
  50. return false;
  51. }
  52. // ... be a constant, ...
  53. if (!spvOpcodeIsConstant(initializer_instruction->opcode())) {
  54. return false;
  55. }
  56. // ... and have the same type as the pointee type.
  57. if (initializer_instruction->type_id() !=
  58. type_instruction->GetSingleWordInOperand(1)) {
  59. return false;
  60. }
  61. // The function to which the local variable is to be added must exist.
  62. return fuzzerutil::FindFunction(context, message_.function_id());
  63. }
  64. void TransformationAddLocalVariable::Apply(
  65. opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
  66. fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
  67. fuzzerutil::FindFunction(context, message_.function_id())
  68. ->begin()
  69. ->begin()
  70. ->InsertBefore(MakeUnique<opt::Instruction>(
  71. context, SpvOpVariable, message_.type_id(), message_.fresh_id(),
  72. opt::Instruction::OperandList(
  73. {{SPV_OPERAND_TYPE_STORAGE_CLASS,
  74. {
  75. SpvStorageClassFunction}},
  76. {SPV_OPERAND_TYPE_ID, {message_.initializer_id()}}})));
  77. if (message_.value_is_irrelevant()) {
  78. fact_manager->AddFactValueOfPointeeIsIrrelevant(message_.fresh_id());
  79. }
  80. context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
  81. }
  82. protobufs::Transformation TransformationAddLocalVariable::ToMessage() const {
  83. protobufs::Transformation result;
  84. *result.mutable_add_local_variable() = message_;
  85. return result;
  86. }
  87. } // namespace fuzz
  88. } // namespace spvtools