transformation_copy_object.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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_copy_object.h"
  15. #include "source/fuzz/data_descriptor.h"
  16. #include "source/fuzz/fuzzer_util.h"
  17. #include "source/fuzz/instruction_descriptor.h"
  18. #include "source/opt/instruction.h"
  19. #include "source/util/make_unique.h"
  20. namespace spvtools {
  21. namespace fuzz {
  22. TransformationCopyObject::TransformationCopyObject(
  23. const protobufs::TransformationCopyObject& message)
  24. : message_(message) {}
  25. TransformationCopyObject::TransformationCopyObject(
  26. uint32_t object,
  27. const protobufs::InstructionDescriptor& instruction_to_insert_before,
  28. uint32_t fresh_id) {
  29. message_.set_object(object);
  30. *message_.mutable_instruction_to_insert_before() =
  31. instruction_to_insert_before;
  32. message_.set_fresh_id(fresh_id);
  33. }
  34. bool TransformationCopyObject::IsApplicable(
  35. opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
  36. if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
  37. // We require the id for the object copy to be unused.
  38. return false;
  39. }
  40. // The id of the object to be copied must exist
  41. auto object_inst = ir_context->get_def_use_mgr()->GetDef(message_.object());
  42. if (!object_inst) {
  43. return false;
  44. }
  45. if (!fuzzerutil::CanMakeSynonymOf(ir_context, object_inst)) {
  46. return false;
  47. }
  48. auto insert_before =
  49. FindInstruction(message_.instruction_to_insert_before(), ir_context);
  50. if (!insert_before) {
  51. // The instruction before which the copy should be inserted was not found.
  52. return false;
  53. }
  54. if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyObject,
  55. insert_before)) {
  56. return false;
  57. }
  58. // |message_object| must be available directly before the point where we want
  59. // to add the copy.
  60. return fuzzerutil::IdIsAvailableBeforeInstruction(ir_context, insert_before,
  61. message_.object());
  62. }
  63. void TransformationCopyObject::Apply(
  64. opt::IRContext* ir_context,
  65. TransformationContext* transformation_context) const {
  66. auto object_inst = ir_context->get_def_use_mgr()->GetDef(message_.object());
  67. assert(object_inst && "The object to be copied must exist.");
  68. auto insert_before_inst =
  69. FindInstruction(message_.instruction_to_insert_before(), ir_context);
  70. auto destination_block = ir_context->get_instr_block(insert_before_inst);
  71. assert(destination_block && "The base instruction must be in a block.");
  72. auto insert_before = fuzzerutil::GetIteratorForInstruction(
  73. destination_block, insert_before_inst);
  74. assert(insert_before != destination_block->end() &&
  75. "There must be an instruction before which the copy can be inserted.");
  76. opt::Instruction::OperandList operands = {
  77. {SPV_OPERAND_TYPE_ID, {message_.object()}}};
  78. insert_before->InsertBefore(MakeUnique<opt::Instruction>(
  79. ir_context, SpvOp::SpvOpCopyObject, object_inst->type_id(),
  80. message_.fresh_id(), operands));
  81. fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
  82. ir_context->InvalidateAnalysesExceptFor(
  83. opt::IRContext::Analysis::kAnalysisNone);
  84. transformation_context->GetFactManager()->AddFactDataSynonym(
  85. MakeDataDescriptor(message_.object(), {}),
  86. MakeDataDescriptor(message_.fresh_id(), {}), ir_context);
  87. if (transformation_context->GetFactManager()->PointeeValueIsIrrelevant(
  88. message_.object())) {
  89. transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
  90. message_.fresh_id());
  91. }
  92. }
  93. protobufs::Transformation TransformationCopyObject::ToMessage() const {
  94. protobufs::Transformation result;
  95. *result.mutable_copy_object() = message_;
  96. return result;
  97. }
  98. } // namespace fuzz
  99. } // namespace spvtools