// 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_irrelevant_id.h"

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

namespace spvtools {
namespace fuzz {

TransformationReplaceIrrelevantId::TransformationReplaceIrrelevantId(
    protobufs::TransformationReplaceIrrelevantId message)
    : message_(std::move(message)) {}

TransformationReplaceIrrelevantId::TransformationReplaceIrrelevantId(
    const protobufs::IdUseDescriptor& id_use_descriptor,
    uint32_t replacement_id) {
  *message_.mutable_id_use_descriptor() = id_use_descriptor;
  message_.set_replacement_id(replacement_id);
}

bool TransformationReplaceIrrelevantId::IsApplicable(
    opt::IRContext* ir_context,
    const TransformationContext& transformation_context) const {
  auto id_of_interest = message_.id_use_descriptor().id_of_interest();

  // The id must be irrelevant.
  if (!transformation_context.GetFactManager()->IdIsIrrelevant(
          id_of_interest)) {
    return false;
  }

  // Find the instruction containing the id use, which must exist.
  auto use_instruction =
      FindInstructionContainingUse(message_.id_use_descriptor(), ir_context);
  if (!use_instruction) {
    return false;
  }

  // Check that the replacement id exists and retrieve its definition.
  auto replacement_id_def =
      ir_context->get_def_use_mgr()->GetDef(message_.replacement_id());
  if (!replacement_id_def) {
    return false;
  }

  // The type of the id of interest and of the replacement id must be the same.
  uint32_t type_id_of_interest =
      ir_context->get_def_use_mgr()->GetDef(id_of_interest)->type_id();
  uint32_t type_replacement_id = replacement_id_def->type_id();
  if (type_id_of_interest != type_replacement_id) {
    return false;
  }

  // The replacement id must not be the result of an OpFunction instruction.
  if (replacement_id_def->opcode() == SpvOpFunction) {
    return false;
  }

  // Consistency check: an irrelevant id cannot be a pointer.
  assert(
      !ir_context->get_type_mgr()->GetType(type_id_of_interest)->AsPointer() &&
      "An irrelevant id cannot be a pointer");

  uint32_t use_in_operand_index =
      message_.id_use_descriptor().in_operand_index();

  // The id use must be replaceable with any other id of the same type.
  if (!fuzzerutil::IdUseCanBeReplaced(ir_context, transformation_context,
                                      use_instruction, use_in_operand_index)) {
    return false;
  }

  if (AttemptsToReplaceVariableInitializerWithNonConstant(
          *use_instruction, *replacement_id_def)) {
    return false;
  }

  // The id must be available to use at the use point.
  return fuzzerutil::IdIsAvailableAtUse(
      ir_context, use_instruction,
      message_.id_use_descriptor().in_operand_index(),
      message_.replacement_id());
}

void TransformationReplaceIrrelevantId::Apply(
    opt::IRContext* ir_context,
    TransformationContext* /* transformation_context */) const {
  // Find the instruction.
  auto instruction_to_change =
      FindInstructionContainingUse(message_.id_use_descriptor(), ir_context);

  // Replace the instruction.
  instruction_to_change->SetInOperand(
      message_.id_use_descriptor().in_operand_index(),
      {message_.replacement_id()});

  ir_context->get_def_use_mgr()->EraseUseRecordsOfOperandIds(
      instruction_to_change);
  ir_context->get_def_use_mgr()->AnalyzeInstUse(instruction_to_change);

  // No analyses need to be invalidated, since the transformation is local to a
  // block, and the def-use analysis has been updated.
}

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

std::unordered_set<uint32_t> TransformationReplaceIrrelevantId::GetFreshIds()
    const {
  return std::unordered_set<uint32_t>();
}

bool TransformationReplaceIrrelevantId::
    AttemptsToReplaceVariableInitializerWithNonConstant(
        const opt::Instruction& use_instruction,
        const opt::Instruction& replacement_for_use) {
  return use_instruction.opcode() == SpvOpVariable &&
         !spvOpcodeIsConstant(replacement_for_use.opcode());
}

}  // namespace fuzz
}  // namespace spvtools
