// Copyright (c) 2019 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_id_with_synonym.h"

#include <algorithm>

#include "source/fuzz/data_descriptor.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/id_use_descriptor.h"
#include "source/opt/types.h"
#include "source/util/make_unique.h"

namespace spvtools {
namespace fuzz {

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

TransformationReplaceIdWithSynonym::TransformationReplaceIdWithSynonym(
    protobufs::IdUseDescriptor id_use_descriptor, uint32_t synonymous_id) {
  *message_.mutable_id_use_descriptor() = std::move(id_use_descriptor);
  message_.set_synonymous_id(synonymous_id);
}

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

  // Does the fact manager know about the synonym?
  auto data_descriptor_for_synonymous_id =
      MakeDataDescriptor(message_.synonymous_id(), {});
  if (!transformation_context.GetFactManager()->IsSynonymous(
          MakeDataDescriptor(id_of_interest, {}),
          data_descriptor_for_synonymous_id)) {
    return false;
  }

  // Does the id use descriptor in the transformation identify an instruction?
  auto use_instruction =
      FindInstructionContainingUse(message_.id_use_descriptor(), ir_context);
  if (!use_instruction) {
    return false;
  }

  uint32_t type_id_of_interest =
      ir_context->get_def_use_mgr()->GetDef(id_of_interest)->type_id();
  uint32_t type_id_synonym = ir_context->get_def_use_mgr()
                                 ->GetDef(message_.synonymous_id())
                                 ->type_id();

  // If the id of interest and the synonym are scalar or vector integer
  // constants with different signedness, their use can only be swapped if the
  // instruction is agnostic to the signedness of the operand.
  if (!TypesAreCompatible(ir_context, use_instruction->opcode(),
                          message_.id_use_descriptor().in_operand_index(),
                          type_id_of_interest, type_id_synonym)) {
    return false;
  }

  // Is the use suitable for being replaced in principle?
  if (!fuzzerutil::IdUseCanBeReplaced(
          ir_context, transformation_context, use_instruction,
          message_.id_use_descriptor().in_operand_index())) {
    return false;
  }

  // The transformation is applicable if the synonymous id is available at the
  // use point.
  return fuzzerutil::IdIsAvailableAtUse(
      ir_context, use_instruction,
      message_.id_use_descriptor().in_operand_index(),
      message_.synonymous_id());
}

void TransformationReplaceIdWithSynonym::Apply(
    spvtools::opt::IRContext* ir_context,
    TransformationContext* /*unused*/) const {
  auto instruction_to_change =
      FindInstructionContainingUse(message_.id_use_descriptor(), ir_context);
  instruction_to_change->SetInOperand(
      message_.id_use_descriptor().in_operand_index(),
      {message_.synonymous_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 TransformationReplaceIdWithSynonym::ToMessage()
    const {
  protobufs::Transformation result;
  *result.mutable_replace_id_with_synonym() = message_;
  return result;
}

// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3582): Add all
//  opcodes that are agnostic to signedness of operands to function.
//  This is not exhaustive yet.
bool TransformationReplaceIdWithSynonym::IsAgnosticToSignednessOfOperand(
    SpvOp opcode, uint32_t use_in_operand_index) {
  switch (opcode) {
    case SpvOpSNegate:
    case SpvOpNot:
    case SpvOpIAdd:
    case SpvOpISub:
    case SpvOpIMul:
    case SpvOpSDiv:
    case SpvOpSRem:
    case SpvOpSMod:
    case SpvOpShiftRightLogical:
    case SpvOpShiftRightArithmetic:
    case SpvOpShiftLeftLogical:
    case SpvOpBitwiseOr:
    case SpvOpBitwiseXor:
    case SpvOpBitwiseAnd:
    case SpvOpIEqual:
    case SpvOpINotEqual:
    case SpvOpULessThan:
    case SpvOpSLessThan:
    case SpvOpUGreaterThan:
    case SpvOpSGreaterThan:
    case SpvOpULessThanEqual:
    case SpvOpSLessThanEqual:
    case SpvOpUGreaterThanEqual:
    case SpvOpSGreaterThanEqual:
      return true;

    case SpvOpAtomicStore:
    case SpvOpAtomicExchange:
    case SpvOpAtomicIAdd:
    case SpvOpAtomicISub:
    case SpvOpAtomicSMin:
    case SpvOpAtomicUMin:
    case SpvOpAtomicSMax:
    case SpvOpAtomicUMax:
    case SpvOpAtomicAnd:
    case SpvOpAtomicOr:
    case SpvOpAtomicXor:
    case SpvOpAtomicFAddEXT:  // Capability AtomicFloat32AddEXT,
                              // AtomicFloat64AddEXT.
      assert(use_in_operand_index != 0 &&
             "Signedness check should not occur on a pointer operand.");
      return use_in_operand_index == 1 || use_in_operand_index == 2;

    case SpvOpAtomicCompareExchange:
    case SpvOpAtomicCompareExchangeWeak:  // Capability Kernel.
      assert(use_in_operand_index != 0 &&
             "Signedness check should not occur on a pointer operand.");
      return use_in_operand_index >= 1 && use_in_operand_index <= 3;

    case SpvOpAtomicLoad:
    case SpvOpAtomicIIncrement:
    case SpvOpAtomicIDecrement:
    case SpvOpAtomicFlagTestAndSet:  // Capability Kernel.
    case SpvOpAtomicFlagClear:       // Capability Kernel.
      assert(use_in_operand_index != 0 &&
             "Signedness check should not occur on a pointer operand.");
      return use_in_operand_index >= 1;

    case SpvOpAccessChain:
      // The signedness of indices does not matter.
      return use_in_operand_index > 0;

    default:
      // Conservatively assume that the id cannot be swapped in other
      // instructions.
      return false;
  }
}

bool TransformationReplaceIdWithSynonym::TypesAreCompatible(
    opt::IRContext* ir_context, SpvOp opcode, uint32_t use_in_operand_index,
    uint32_t type_id_1, uint32_t type_id_2) {
  assert(ir_context->get_type_mgr()->GetType(type_id_1) &&
         ir_context->get_type_mgr()->GetType(type_id_2) &&
         "Type ids are invalid");

  return type_id_1 == type_id_2 ||
         (IsAgnosticToSignednessOfOperand(opcode, use_in_operand_index) &&
          fuzzerutil::TypesAreEqualUpToSign(ir_context, type_id_1, type_id_2));
}

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

}  // namespace fuzz
}  // namespace spvtools
