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

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

namespace spvtools {
namespace fuzz {

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

TransformationCompositeInsert::TransformationCompositeInsert(
    const protobufs::InstructionDescriptor& instruction_to_insert_before,
    uint32_t fresh_id, uint32_t composite_id, uint32_t object_id,
    const std::vector<uint32_t>& index) {
  *message_.mutable_instruction_to_insert_before() =
      instruction_to_insert_before;
  message_.set_fresh_id(fresh_id);
  message_.set_composite_id(composite_id);
  message_.set_object_id(object_id);
  for (auto an_index : index) {
    message_.add_index(an_index);
  }
}

bool TransformationCompositeInsert::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;
  }

  // |message_.composite_id| must refer to an existing composite value.
  auto composite =
      ir_context->get_def_use_mgr()->GetDef(message_.composite_id());

  if (!IsCompositeInstructionSupported(ir_context, composite)) {
    return false;
  }

  // The indices in |message_.index| must be suitable for indexing into
  // |composite->type_id()|.
  auto component_to_be_replaced_type_id = fuzzerutil::WalkCompositeTypeIndices(
      ir_context, composite->type_id(), message_.index());
  if (component_to_be_replaced_type_id == 0) {
    return false;
  }

  // The instruction having the id of |message_.object_id| must be defined.
  auto object_instruction =
      ir_context->get_def_use_mgr()->GetDef(message_.object_id());
  if (object_instruction == nullptr || object_instruction->type_id() == 0) {
    return false;
  }

  // We ignore pointers for now.
  auto object_instruction_type =
      ir_context->get_type_mgr()->GetType(object_instruction->type_id());
  if (object_instruction_type->AsPointer() != nullptr) {
    return false;
  }

  // The type id of the object having |message_.object_id| and the type id of
  // the component of the composite at index |message_.index| must be the same.
  if (component_to_be_replaced_type_id != object_instruction->type_id()) {
    return false;
  }

  // |message_.instruction_to_insert_before| must be a defined instruction.
  auto instruction_to_insert_before =
      FindInstruction(message_.instruction_to_insert_before(), ir_context);
  if (instruction_to_insert_before == nullptr) {
    return false;
  }

  // |message_.composite_id| and |message_.object_id| must be available before
  // the |message_.instruction_to_insert_before|.
  if (!fuzzerutil::IdIsAvailableBeforeInstruction(
          ir_context, instruction_to_insert_before, message_.composite_id())) {
    return false;
  }
  if (!fuzzerutil::IdIsAvailableBeforeInstruction(
          ir_context, instruction_to_insert_before, message_.object_id())) {
    return false;
  }

  // It must be possible to insert an OpCompositeInsert before this
  // instruction.
  return fuzzerutil::CanInsertOpcodeBeforeInstruction(
      SpvOpCompositeInsert, instruction_to_insert_before);
}

void TransformationCompositeInsert::Apply(
    opt::IRContext* ir_context,
    TransformationContext* transformation_context) const {
  // |message_.struct_fresh_id| must be fresh.
  assert(fuzzerutil::IsFreshId(ir_context, message_.fresh_id()) &&
         "|message_.fresh_id| must be fresh");

  std::vector<uint32_t> index =
      fuzzerutil::RepeatedFieldToVector(message_.index());
  opt::Instruction::OperandList in_operands;
  in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.object_id()}});
  in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.composite_id()}});
  for (auto i : index) {
    in_operands.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}});
  }
  auto composite_type_id =
      fuzzerutil::GetTypeId(ir_context, message_.composite_id());

  FindInstruction(message_.instruction_to_insert_before(), ir_context)
      ->InsertBefore(MakeUnique<opt::Instruction>(
          ir_context, SpvOpCompositeInsert, composite_type_id,
          message_.fresh_id(), std::move(in_operands)));

  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());

  // We have modified the module so most analyzes are now invalid.
  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);

  // Add data synonym facts that arise from the insertion.
  AddDataSynonymFacts(ir_context, transformation_context);
}

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

bool TransformationCompositeInsert::IsCompositeInstructionSupported(
    opt::IRContext* ir_context, opt::Instruction* instruction) {
  if (instruction == nullptr) {
    return false;
  }
  if (instruction->result_id() == 0 || instruction->type_id() == 0) {
    return false;
  }
  auto composite_type =
      ir_context->get_type_mgr()->GetType(instruction->type_id());
  if (!fuzzerutil::IsCompositeType(composite_type)) {
    return false;
  }

  // Empty composites are not supported.
  auto instruction_type_inst =
      ir_context->get_def_use_mgr()->GetDef(instruction->type_id());
  if (fuzzerutil::GetBoundForCompositeIndex(*instruction_type_inst,
                                            ir_context) == 0) {
    return false;
  }
  return true;
}

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

void TransformationCompositeInsert::AddDataSynonymFacts(
    opt::IRContext* ir_context,
    TransformationContext* transformation_context) const {
  // If the result id arising from the insertion is irrelevant then do not add
  // any data synonym facts.  (The result id can be irrelevant if the insertion
  // occurs in a dead block.)
  if (transformation_context->GetFactManager()->IdIsIrrelevant(
          message_.fresh_id())) {
    return;
  }

  // So long as the |message_.composite_id| is suitable for participating in
  // synonyms, every every element of the insertion result except for at the
  // index being inserted into is synonymous with the corresponding element of
  // |message_.composite_id|.  In that case, for every index that is a prefix of
  // |index|, the components different from the one that contains the inserted
  // object are synonymous with corresponding elements in the original
  // composite.
  uint32_t current_node_type_id =
      fuzzerutil::GetTypeId(ir_context, message_.composite_id());
  std::vector<uint32_t> current_index;

  std::vector<uint32_t> index =
      fuzzerutil::RepeatedFieldToVector(message_.index());

  for (uint32_t current_level : index) {
    auto current_node_type_inst =
        ir_context->get_def_use_mgr()->GetDef(current_node_type_id);
    uint32_t index_to_skip = current_level;
    uint32_t num_of_components = fuzzerutil::GetBoundForCompositeIndex(
        *current_node_type_inst, ir_context);

    // Update the current_node_type_id.
    current_node_type_id = fuzzerutil::WalkOneCompositeTypeIndex(
        ir_context, current_node_type_id, index_to_skip);

    for (uint32_t i = 0; i < num_of_components; i++) {
      if (i == index_to_skip) {
        continue;
      }
      current_index.push_back(i);
      if (fuzzerutil::CanMakeSynonymOf(
              ir_context, *transformation_context,
              ir_context->get_def_use_mgr()->GetDef(message_.composite_id()))) {
        transformation_context->GetFactManager()->AddFactDataSynonym(
            MakeDataDescriptor(message_.fresh_id(), current_index),
            MakeDataDescriptor(message_.composite_id(), current_index));
      }
      current_index.pop_back();
    }
    // Store the prefix of the |index|.
    current_index.push_back(current_level);
  }
  // If the object being inserted supports synonym creation then it is
  // synonymous with the result of the insert instruction at the given index.
  if (fuzzerutil::CanMakeSynonymOf(
          ir_context, *transformation_context,
          ir_context->get_def_use_mgr()->GetDef(message_.object_id()))) {
    transformation_context->GetFactManager()->AddFactDataSynonym(
        MakeDataDescriptor(message_.object_id(), {}),
        MakeDataDescriptor(message_.fresh_id(), index));
  }
}

}  // namespace fuzz
}  // namespace spvtools
