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

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

namespace spvtools {
namespace fuzz {

FuzzerPassAddVectorShuffleInstructions::FuzzerPassAddVectorShuffleInstructions(
    opt::IRContext* ir_context, TransformationContext* transformation_context,
    FuzzerContext* fuzzer_context,
    protobufs::TransformationSequence* transformations,
    bool ignore_inapplicable_transformations)
    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
                 transformations, ignore_inapplicable_transformations) {}

void FuzzerPassAddVectorShuffleInstructions::Apply() {
  ForEachInstructionWithInstructionDescriptor(
      [this](opt::Function* function, opt::BasicBlock* block,
             opt::BasicBlock::iterator instruction_iterator,
             const protobufs::InstructionDescriptor& instruction_descriptor)
          -> void {
        assert(instruction_iterator->opcode() ==
                   instruction_descriptor.target_instruction_opcode() &&
               "The opcode of the instruction we might insert before must be "
               "the same as the opcode in the descriptor for the instruction");

        // Randomly decide whether to try adding an OpVectorShuffle instruction.
        if (!GetFuzzerContext()->ChoosePercentage(
                GetFuzzerContext()->GetChanceOfAddingVectorShuffle())) {
          return;
        }

        // It must be valid to insert an OpVectorShuffle instruction
        // before |instruction_iterator|.
        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
                SpvOpVectorShuffle, instruction_iterator)) {
          return;
        }

        // Looks for vectors that we might consider to use as OpVectorShuffle
        // operands.
        std::vector<opt::Instruction*> vector_instructions =
            FindAvailableInstructions(
                function, block, instruction_iterator,
                [this, instruction_descriptor](
                    opt::IRContext* ir_context,
                    opt::Instruction* instruction) -> bool {
                  if (!instruction->result_id() || !instruction->type_id()) {
                    return false;
                  }

                  if (!ir_context->get_type_mgr()
                           ->GetType(instruction->type_id())
                           ->AsVector()) {
                    return false;
                  }

                  if (!GetTransformationContext()
                           ->GetFactManager()
                           ->IdIsIrrelevant(instruction->result_id()) &&
                      !fuzzerutil::CanMakeSynonymOf(ir_context,
                                                    *GetTransformationContext(),
                                                    *instruction)) {
                    // If the id is irrelevant, we can use it since it will not
                    // participate in DataSynonym fact. Otherwise, we should be
                    // able to produce a synonym out of the id.
                    return false;
                  }

                  return fuzzerutil::IdIsAvailableBeforeInstruction(
                      ir_context,
                      FindInstruction(instruction_descriptor, ir_context),
                      instruction->result_id());
                });

        // If there are no vector instructions, then return.
        if (vector_instructions.empty()) {
          return;
        }

        auto vector_1_instruction =
            vector_instructions[GetFuzzerContext()->RandomIndex(
                vector_instructions)];
        auto vector_1_type = GetIRContext()
                                 ->get_type_mgr()
                                 ->GetType(vector_1_instruction->type_id())
                                 ->AsVector();

        auto vector_2_instruction =
            GetFuzzerContext()->RemoveAtRandomIndex(&vector_instructions);
        auto vector_2_type = GetIRContext()
                                 ->get_type_mgr()
                                 ->GetType(vector_2_instruction->type_id())
                                 ->AsVector();

        // |vector_1| and |vector_2| must have the same element type as each
        // other. The loop is guaranteed to terminate because each iteration
        // removes on possible choice for |vector_2|, and there is at least one
        // choice that will cause the loop to exit - namely |vector_1|.
        while (vector_1_type->element_type() != vector_2_type->element_type()) {
          vector_2_instruction =
              GetFuzzerContext()->RemoveAtRandomIndex(&vector_instructions);
          vector_2_type = GetIRContext()
                              ->get_type_mgr()
                              ->GetType(vector_2_instruction->type_id())
                              ->AsVector();
        }

        // Gets components and creates the appropriate result vector type.
        std::vector<uint32_t> components =
            GetFuzzerContext()->GetRandomComponentsForVectorShuffle(
                vector_1_type->element_count() +
                vector_2_type->element_count());
        FindOrCreateVectorType(GetIRContext()->get_type_mgr()->GetId(
                                   vector_1_type->element_type()),
                               static_cast<uint32_t>(components.size()));

        // Applies the vector shuffle transformation.
        ApplyTransformation(TransformationVectorShuffle(
            instruction_descriptor, GetFuzzerContext()->GetFreshId(),
            vector_1_instruction->result_id(),
            vector_2_instruction->result_id(), components));
      });
}

}  // namespace fuzz
}  // namespace spvtools
