// Copyright (c) 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "source/fuzz/transformation_replace_copy_memory_with_load_store.h"

#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/instruction_descriptor.h"

namespace spvtools {
namespace fuzz {

TransformationReplaceCopyMemoryWithLoadStore::
    TransformationReplaceCopyMemoryWithLoadStore(
        const spvtools::fuzz::protobufs::
            TransformationReplaceCopyMemoryWithLoadStore& message)
    : message_(message) {}

TransformationReplaceCopyMemoryWithLoadStore::
    TransformationReplaceCopyMemoryWithLoadStore(
        uint32_t fresh_id, const protobufs::InstructionDescriptor&
                               copy_memory_instruction_descriptor) {
  message_.set_fresh_id(fresh_id);
  *message_.mutable_copy_memory_instruction_descriptor() =
      copy_memory_instruction_descriptor;
}

bool TransformationReplaceCopyMemoryWithLoadStore::IsApplicable(
    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
  // |message_.fresh_id| must be fresh.
  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
    return false;
  }
  // The instruction to be replaced must be defined and have opcode
  // OpCopyMemory.
  auto copy_memory_instruction = FindInstruction(
      message_.copy_memory_instruction_descriptor(), ir_context);
  if (!copy_memory_instruction ||
      copy_memory_instruction->opcode() != SpvOpCopyMemory) {
    return false;
  }
  return true;
}

void TransformationReplaceCopyMemoryWithLoadStore::Apply(
    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
  auto copy_memory_instruction = FindInstruction(
      message_.copy_memory_instruction_descriptor(), ir_context);
  // |copy_memory_instruction| must be defined.
  assert(copy_memory_instruction &&
         copy_memory_instruction->opcode() == SpvOpCopyMemory &&
         "The required OpCopyMemory instruction must be defined.");

  // Integrity check: Both operands must be pointers.

  // Get types of ids used as a source and target of |copy_memory_instruction|.
  auto target = ir_context->get_def_use_mgr()->GetDef(
      copy_memory_instruction->GetSingleWordInOperand(0));
  auto source = ir_context->get_def_use_mgr()->GetDef(
      copy_memory_instruction->GetSingleWordInOperand(1));
  auto target_type_opcode =
      ir_context->get_def_use_mgr()->GetDef(target->type_id())->opcode();
  auto source_type_opcode =
      ir_context->get_def_use_mgr()->GetDef(source->type_id())->opcode();

  // Keep release-mode compilers happy. (No unused variables.)
  (void)target;
  (void)source;
  (void)target_type_opcode;
  (void)source_type_opcode;

  assert(target_type_opcode == SpvOpTypePointer &&
         source_type_opcode == SpvOpTypePointer &&
         "Operands must be of type OpTypePointer");

  // Integrity check: |source| and |target| must point to the same type.
  uint32_t target_pointee_type = fuzzerutil::GetPointeeTypeIdFromPointerType(
      ir_context, target->type_id());
  uint32_t source_pointee_type = fuzzerutil::GetPointeeTypeIdFromPointerType(
      ir_context, source->type_id());

  // Keep release-mode compilers happy. (No unused variables.)
  (void)target_pointee_type;
  (void)source_pointee_type;

  assert(target_pointee_type == source_pointee_type &&
         "Operands must have the same type to which they point to.");

  // First, insert the OpStore instruction before the OpCopyMemory instruction
  // and then insert the OpLoad instruction before the OpStore instruction.
  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
  FindInstruction(message_.copy_memory_instruction_descriptor(), ir_context)
      ->InsertBefore(MakeUnique<opt::Instruction>(
          ir_context, SpvOpStore, 0, 0,
          opt::Instruction::OperandList(
              {{SPV_OPERAND_TYPE_ID, {target->result_id()}},
               {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}})))
      ->InsertBefore(MakeUnique<opt::Instruction>(
          ir_context, SpvOpLoad, target_pointee_type, message_.fresh_id(),
          opt::Instruction::OperandList(
              {{SPV_OPERAND_TYPE_ID, {source->result_id()}}})));

  // Remove the OpCopyMemory instruction.
  ir_context->KillInst(copy_memory_instruction);

  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
}

protobufs::Transformation
TransformationReplaceCopyMemoryWithLoadStore::ToMessage() const {
  protobufs::Transformation result;
  *result.mutable_replace_copy_memory_with_load_store() = message_;
  return result;
}

std::unordered_set<uint32_t>
TransformationReplaceCopyMemoryWithLoadStore::GetFreshIds() const {
  return {message_.fresh_id()};
}

}  // namespace fuzz
}  // namespace spvtools
