// Copyright (c) 2020 André Perez Maselco
//
// 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_expand_vector_reduction.h"

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

namespace spvtools {
namespace fuzz {

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

TransformationExpandVectorReduction::TransformationExpandVectorReduction(
    const uint32_t instruction_result_id,
    const std::vector<uint32_t>& fresh_ids) {
  message_.set_instruction_result_id(instruction_result_id);
  *message_.mutable_fresh_ids() =
      google::protobuf::RepeatedField<google::protobuf::uint32>(
          fresh_ids.begin(), fresh_ids.end());
}

bool TransformationExpandVectorReduction::IsApplicable(
    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
  auto* instruction =
      ir_context->get_def_use_mgr()->GetDef(message_.instruction_result_id());

  // |instruction| must be defined.
  if (!instruction) {
    return false;
  }

  // |instruction| must be OpAny or OpAll.
  if (instruction->opcode() != SpvOpAny && instruction->opcode() != SpvOpAll) {
    return false;
  }

  // |message_.fresh_ids.size| must have the exact number of fresh ids required
  // to apply the transformation.
  if (static_cast<uint32_t>(message_.fresh_ids().size()) !=
      GetRequiredFreshIdCount(ir_context, instruction)) {
    return false;
  }

  std::set<uint32_t> ids_used_by_this_transformation;
  for (uint32_t fresh_id : message_.fresh_ids()) {
    // All ids in |message_.fresh_ids| must be fresh.
    if (!fuzzerutil::IsFreshId(ir_context, fresh_id)) {
      return false;
    }

    // All fresh ids need to be distinct.
    if (!CheckIdIsFreshAndNotUsedByThisTransformation(
            fresh_id, ir_context, &ids_used_by_this_transformation)) {
      return false;
    }
  }

  return true;
}

void TransformationExpandVectorReduction::Apply(
    opt::IRContext* ir_context,
    TransformationContext* transformation_context) const {
  auto* instruction =
      ir_context->get_def_use_mgr()->GetDef(message_.instruction_result_id());
  auto* vector = ir_context->get_def_use_mgr()->GetDef(
      instruction->GetSingleWordInOperand(0));
  uint32_t vector_component_count = ir_context->get_type_mgr()
                                        ->GetType(vector->type_id())
                                        ->AsVector()
                                        ->element_count();

  // Fresh id iterator.
  auto fresh_id = message_.fresh_ids().begin();

  // |vector_components| are the ids of the extracted components from |vector|.
  std::vector<uint32_t> vector_components;

  for (uint32_t i = 0; i < vector_component_count; i++) {
    // Extracts the i-th |vector| component.
    auto vector_component = opt::Instruction(
        ir_context, SpvOpCompositeExtract, instruction->type_id(), *fresh_id++,
        {{SPV_OPERAND_TYPE_ID, {vector->result_id()}},
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}});
    instruction->InsertBefore(MakeUnique<opt::Instruction>(vector_component));
    fuzzerutil::UpdateModuleIdBound(ir_context, vector_component.result_id());
    vector_components.push_back(vector_component.result_id());
  }

  // The first two |vector| components are used in the first logical operation.
  auto logical_instruction = opt::Instruction(
      ir_context,
      instruction->opcode() == SpvOpAny ? SpvOpLogicalOr : SpvOpLogicalAnd,
      instruction->type_id(), *fresh_id++,
      {{SPV_OPERAND_TYPE_ID, {vector_components[0]}},
       {SPV_OPERAND_TYPE_ID, {vector_components[1]}}});
  instruction->InsertBefore(MakeUnique<opt::Instruction>(logical_instruction));
  fuzzerutil::UpdateModuleIdBound(ir_context, logical_instruction.result_id());

  // Evaluates the remaining components.
  for (uint32_t i = 2; i < vector_components.size(); i++) {
    logical_instruction = opt::Instruction(
        ir_context, logical_instruction.opcode(), instruction->type_id(),
        *fresh_id++,
        {{SPV_OPERAND_TYPE_ID, {vector_components[i]}},
         {SPV_OPERAND_TYPE_ID, {logical_instruction.result_id()}}});
    instruction->InsertBefore(
        MakeUnique<opt::Instruction>(logical_instruction));
    fuzzerutil::UpdateModuleIdBound(ir_context,
                                    logical_instruction.result_id());
  }

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

  // If it's possible to make a synonym of |instruction|, then add the fact that
  // the last |logical_instruction| is a synonym of |instruction|.
  if (fuzzerutil::CanMakeSynonymOf(ir_context, *transformation_context,
                                   *instruction)) {
    transformation_context->GetFactManager()->AddFactDataSynonym(
        MakeDataDescriptor(logical_instruction.result_id(), {}),
        MakeDataDescriptor(instruction->result_id(), {}));
  }
}

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

uint32_t TransformationExpandVectorReduction::GetRequiredFreshIdCount(
    opt::IRContext* ir_context, opt::Instruction* instruction) {
  // For each vector component, 1 OpCompositeExtract and 1 OpLogical* (except
  // for the first component) instructions will be inserted.
  return 2 * ir_context->get_type_mgr()
                 ->GetType(ir_context->get_def_use_mgr()
                               ->GetDef(instruction->GetSingleWordInOperand(0))
                               ->type_id())
                 ->AsVector()
                 ->element_count() -
         1;
}

std::unordered_set<uint32_t> TransformationExpandVectorReduction::GetFreshIds()
    const {
  std::unordered_set<uint32_t> result;
  for (auto id : message_.fresh_ids()) {
    result.insert(id);
  }
  return result;
}

}  // namespace fuzz
}  // namespace spvtools
