// Copyright (c) 2021 Shiyu Liu
//
// 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_wrap_vector_synonym.h"
#include "source/fuzz/fuzzer_context.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/transformation_composite_construct.h"
#include "source/fuzz/transformation_wrap_vector_synonym.h"

namespace spvtools {
namespace fuzz {

FuzzerPassWrapVectorSynonym::FuzzerPassWrapVectorSynonym(
    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 FuzzerPassWrapVectorSynonym::Apply() {
  ForEachInstructionWithInstructionDescriptor(
      [this](opt::Function* /*unused*/, opt::BasicBlock* /*unused*/,
             opt::BasicBlock::iterator instruction_iterator,
             const protobufs::InstructionDescriptor& instruction_descriptor)
          -> void {

        // Randomly decide whether to wrap it to a vector operation.
        if (!GetFuzzerContext()->ChoosePercentage(
                GetFuzzerContext()->GetChanceOfWrappingVectorSynonym())) {
          return;
        }

        // The transformation is not applicable if the instruction has missing
        // result id, type id, or is not supported type.
        if (!TransformationWrapVectorSynonym::IsInstructionSupported(
                GetIRContext(), *instruction_iterator)) {
          return;
        }

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

        // Get the scalar operands from the original instruction.
        opt::Instruction* operand1 = GetIRContext()->get_def_use_mgr()->GetDef(
            instruction_iterator->GetSingleWordInOperand(0));
        opt::Instruction* operand2 = GetIRContext()->get_def_use_mgr()->GetDef(
            instruction_iterator->GetSingleWordInOperand(1));

        // We need to be able to make a synonym of the scalar operation's result
        // id, as well as the operand ids (for example, they cannot be
        // irrelevant).
        if (!fuzzerutil::CanMakeSynonymOf(GetIRContext(),
                                          *GetTransformationContext(),
                                          *instruction_iterator)) {
          return;
        }
        if (!fuzzerutil::CanMakeSynonymOf(
                GetIRContext(), *GetTransformationContext(), *operand1)) {
          return;
        }
        if (!fuzzerutil::CanMakeSynonymOf(
                GetIRContext(), *GetTransformationContext(), *operand2)) {
          return;
        }

        // Get a random vector size from 2 to 4.
        uint32_t vector_size = GetFuzzerContext()->GetWidthOfWrappingVector();

        // Randomly choose a position that target ids should be placed at.
        // The position is in range [0, n - 1], where n is the size of the
        // vector.
        uint32_t position =
            GetFuzzerContext()->GetRandomIndexForWrappingVector(vector_size);

        // Stores the ids of scalar constants.
        std::vector<uint32_t> vec1_components;
        std::vector<uint32_t> vec2_components;

        // Populate components based on vector type and size.
        for (uint32_t i = 0; i < vector_size; ++i) {
          if (i == position) {
            vec1_components.emplace_back(operand1->result_id());
            vec2_components.emplace_back(operand2->result_id());
          } else {
            vec1_components.emplace_back(
                FindOrCreateZeroConstant(operand1->type_id(), true));
            vec2_components.emplace_back(
                FindOrCreateZeroConstant(operand2->type_id(), true));
          }
        }

        // Add two OpCompositeConstruct to the module with result id returned.
        // The added vectors may have different types, for instance if the
        // scalar instruction operates on integers with differing sign.

        // Add the first OpCompositeConstruct that wraps the id of the first
        // operand.
        uint32_t result_id1 = GetFuzzerContext()->GetFreshId();
        ApplyTransformation(TransformationCompositeConstruct(
            FindOrCreateVectorType(operand1->type_id(), vector_size),
            vec1_components, instruction_descriptor, result_id1));

        // Add the second OpCompositeConstruct that wraps the id of the second
        // operand.
        uint32_t result_id2 = GetFuzzerContext()->GetFreshId();
        ApplyTransformation(TransformationCompositeConstruct(
            FindOrCreateVectorType(operand2->type_id(), vector_size),
            vec2_components, instruction_descriptor, result_id2));

        // The result of the vector instruction that
        // TransformationWrapVectorSynonym will create should be a vector of the
        // right size, with the scalar instruction's result type as its element
        // type. This can be distinct from the types of the operands, if the
        // scalar instruction adds two signed integers and stores the result in
        // an unsigned id, for example. A transformation is applied to add the
        // right type to the module.
        FindOrCreateVectorType(instruction_iterator->type_id(), vector_size);

        // Apply transformation to do vector operation and add synonym between
        // the result vector id and the id of the original instruction.
        ApplyTransformation(TransformationWrapVectorSynonym(
            instruction_iterator->result_id(), result_id1, result_id2,
            GetFuzzerContext()->GetFreshId(), position));
      });
}

}  // namespace fuzz
}  // namespace spvtools
