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

#include <memory>

#include "source/fuzz/available_instructions.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/transformation_composite_construct.h"

namespace spvtools {
namespace fuzz {

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

void FuzzerPassConstructComposites::Apply() {
  // Gather up the ids of all composite types, but skip block-/buffer
  // block-decorated struct types.
  std::vector<uint32_t> composite_type_ids;
  for (auto& inst : GetIRContext()->types_values()) {
    if (fuzzerutil::IsCompositeType(
            GetIRContext()->get_type_mgr()->GetType(inst.result_id())) &&
        !fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(),
                                                     inst.result_id())) {
      composite_type_ids.push_back(inst.result_id());
    }
  }

  if (composite_type_ids.empty()) {
    // There are no composite types, so this fuzzer pass cannot do anything.
    return;
  }

  AvailableInstructions available_composite_constituents(
      GetIRContext(),
      [this](opt::IRContext* ir_context, opt::Instruction* inst) -> bool {
        if (!inst->result_id() || !inst->type_id()) {
          return false;
        }

        // 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 GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
                   inst->result_id()) ||
               fuzzerutil::CanMakeSynonymOf(ir_context,
                                            *GetTransformationContext(), *inst);
      });

  ForEachInstructionWithInstructionDescriptor(
      [this, &available_composite_constituents, &composite_type_ids](
          opt::Function* /*unused*/, opt::BasicBlock* /*unused*/,
          opt::BasicBlock::iterator inst_it,
          const protobufs::InstructionDescriptor& instruction_descriptor)
          -> void {
        // Randomly decide whether to try inserting a composite construction
        // here.
        if (!GetFuzzerContext()->ChoosePercentage(
                GetFuzzerContext()->GetChanceOfConstructingComposite())) {
          return;
        }

        // Check whether it is legitimate to insert a composite construction
        // before the instruction.
        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
                SpvOpCompositeConstruct, inst_it)) {
          return;
        }

        // For each instruction that is available at this program point (i.e. an
        // instruction that is global or whose definition strictly dominates the
        // program point) and suitable for making a synonym of, associate it
        // with the id of its result type.
        TypeIdToInstructions type_id_to_available_instructions;
        auto available_instructions =
            available_composite_constituents.GetAvailableBeforeInstruction(
                &*inst_it);
        for (uint32_t available_instruction_index = 0;
             available_instruction_index < available_instructions.size();
             available_instruction_index++) {
          opt::Instruction* inst =
              available_instructions[available_instruction_index];
          type_id_to_available_instructions[inst->type_id()].push_back(
              inst->result_id());
        }

        // At this point, |composite_type_ids| captures all the composite types
        // we could try to create, while |type_id_to_available_instructions|
        // captures all the available result ids we might use, organized by
        // type.

        // Now we choose a composite type to construct, building it from
        // available constituent components and using zero constants if suitable
        // components are not available.

        std::vector<uint32_t> constructor_arguments;
        uint32_t chosen_composite_type =
            composite_type_ids[GetFuzzerContext()->RandomIndex(
                composite_type_ids)];

        // Construct a composite of this type, using an appropriate helper
        // method depending on the kind of composite type.
        auto composite_type_inst =
            GetIRContext()->get_def_use_mgr()->GetDef(chosen_composite_type);
        switch (composite_type_inst->opcode()) {
          case SpvOpTypeArray:
            constructor_arguments = FindComponentsToConstructArray(
                *composite_type_inst, type_id_to_available_instructions);
            break;
          case SpvOpTypeMatrix:
            constructor_arguments = FindComponentsToConstructMatrix(
                *composite_type_inst, type_id_to_available_instructions);
            break;
          case SpvOpTypeStruct:
            constructor_arguments = FindComponentsToConstructStruct(
                *composite_type_inst, type_id_to_available_instructions);
            break;
          case SpvOpTypeVector:
            constructor_arguments = FindComponentsToConstructVector(
                *composite_type_inst, type_id_to_available_instructions);
            break;
          default:
            assert(false &&
                   "The space of possible composite types should be covered "
                   "by the above cases.");
            break;
        }
        assert(!constructor_arguments.empty());

        // Make and apply a transformation.
        ApplyTransformation(TransformationCompositeConstruct(
            chosen_composite_type, constructor_arguments,
            instruction_descriptor, GetFuzzerContext()->GetFreshId()));
      });
}

std::vector<uint32_t>
FuzzerPassConstructComposites::FindComponentsToConstructArray(
    const opt::Instruction& array_type_instruction,
    const TypeIdToInstructions& type_id_to_available_instructions) {
  assert(array_type_instruction.opcode() == SpvOpTypeArray &&
         "Precondition: instruction must be an array type.");

  // Get the element type for the array.
  auto element_type_id = array_type_instruction.GetSingleWordInOperand(0);

  // Get all instructions at our disposal that compute something of this element
  // type.
  auto available_instructions =
      type_id_to_available_instructions.find(element_type_id);

  uint32_t array_length =
      GetIRContext()
          ->get_def_use_mgr()
          ->GetDef(array_type_instruction.GetSingleWordInOperand(1))
          ->GetSingleWordInOperand(0);

  std::vector<uint32_t> result;
  for (uint32_t index = 0; index < array_length; index++) {
    if (available_instructions == type_id_to_available_instructions.cend()) {
      // No suitable instructions are available, so use a zero constant
      result.push_back(FindOrCreateZeroConstant(element_type_id, true));
    } else {
      result.push_back(
          available_instructions->second[GetFuzzerContext()->RandomIndex(
              available_instructions->second)]);
    }
  }
  return result;
}

std::vector<uint32_t>
FuzzerPassConstructComposites::FindComponentsToConstructMatrix(
    const opt::Instruction& matrix_type_instruction,
    const TypeIdToInstructions& type_id_to_available_instructions) {
  assert(matrix_type_instruction.opcode() == SpvOpTypeMatrix &&
         "Precondition: instruction must be a matrix type.");

  // Get the element type for the matrix.
  auto element_type_id = matrix_type_instruction.GetSingleWordInOperand(0);

  // Get all instructions at our disposal that compute something of this element
  // type.
  auto available_instructions =
      type_id_to_available_instructions.find(element_type_id);

  std::vector<uint32_t> result;
  for (uint32_t index = 0;
       index < matrix_type_instruction.GetSingleWordInOperand(1); index++) {
    if (available_instructions == type_id_to_available_instructions.cend()) {
      // No suitable components are available, so use a zero constant.
      result.push_back(FindOrCreateZeroConstant(element_type_id, true));
    } else {
      result.push_back(
          available_instructions->second[GetFuzzerContext()->RandomIndex(
              available_instructions->second)]);
    }
  }
  return result;
}

std::vector<uint32_t>
FuzzerPassConstructComposites::FindComponentsToConstructStruct(
    const opt::Instruction& struct_type_instruction,
    const TypeIdToInstructions& type_id_to_available_instructions) {
  assert(struct_type_instruction.opcode() == SpvOpTypeStruct &&
         "Precondition: instruction must be a struct type.");
  std::vector<uint32_t> result;
  // Consider the type of each field of the struct.
  for (uint32_t in_operand_index = 0;
       in_operand_index < struct_type_instruction.NumInOperands();
       in_operand_index++) {
    auto element_type_id =
        struct_type_instruction.GetSingleWordInOperand(in_operand_index);
    // Find the instructions at our disposal that compute something of the field
    // type.
    auto available_instructions =
        type_id_to_available_instructions.find(element_type_id);
    if (available_instructions == type_id_to_available_instructions.cend()) {
      // No suitable component is available for this element type, so use a zero
      // constant.
      result.push_back(FindOrCreateZeroConstant(element_type_id, true));
    } else {
      result.push_back(
          available_instructions->second[GetFuzzerContext()->RandomIndex(
              available_instructions->second)]);
    }
  }
  return result;
}

std::vector<uint32_t>
FuzzerPassConstructComposites::FindComponentsToConstructVector(
    const opt::Instruction& vector_type_instruction,
    const TypeIdToInstructions& type_id_to_available_instructions) {
  assert(vector_type_instruction.opcode() == SpvOpTypeVector &&
         "Precondition: instruction must be a vector type.");

  // Get details of the type underlying the vector, and the width of the vector,
  // for convenience.
  auto element_type_id = vector_type_instruction.GetSingleWordInOperand(0);
  auto element_type = GetIRContext()->get_type_mgr()->GetType(element_type_id);
  auto element_count = vector_type_instruction.GetSingleWordInOperand(1);

  // Collect a mapping, from type id to width, for scalar/vector types that are
  // smaller in width than |vector_type|, but that have the same underlying
  // type.  For example, if |vector_type| is vec4, the mapping will be:
  //   { float -> 1, vec2 -> 2, vec3 -> 3 }
  // The mapping will have missing entries if some of these types do not exist.

  std::map<uint32_t, uint32_t> smaller_vector_type_id_to_width;
  // Add the underlying type.  This id must exist, in order for |vector_type| to
  // exist.
  smaller_vector_type_id_to_width[element_type_id] = 1;

  // Now add every vector type with width at least 2, and less than the width of
  // |vector_type|.
  for (uint32_t width = 2; width < element_count; width++) {
    opt::analysis::Vector smaller_vector_type(element_type, width);
    auto smaller_vector_type_id =
        GetIRContext()->get_type_mgr()->GetId(&smaller_vector_type);
    // We might find that there is no declared type of this smaller width.
    // For example, a module can declare vec4 without having declared vec2 or
    // vec3.
    if (smaller_vector_type_id) {
      smaller_vector_type_id_to_width[smaller_vector_type_id] = width;
    }
  }

  // Now we know the types that are available to us, we set about populating a
  // vector of the right length.  We do this by deciding, with no order in mind,
  // which instructions we will use to populate the vector, and subsequently
  // randomly choosing an order.  This is to avoid biasing construction of
  // vectors with smaller vectors to the left and scalars to the right.  That is
  // a concern because, e.g. in the case of populating a vec4, if we populate
  // the constructor instructions left-to-right, we can always choose a vec3 to
  // construct the first three elements, but can only choose a vec3 to construct
  // the last three elements if we chose a float to construct the first element
  // (otherwise there will not be space left for a vec3).

  uint32_t vector_slots_used = 0;

  // The instructions result ids we will use to construct the vector, in no
  // particular order at this stage.
  std::vector<uint32_t> result;

  while (vector_slots_used < element_count) {
    std::vector<uint32_t> instructions_to_choose_from;
    for (auto& entry : smaller_vector_type_id_to_width) {
      if (entry.second >
          std::min(element_count - 1, element_count - vector_slots_used)) {
        continue;
      }
      auto available_instructions =
          type_id_to_available_instructions.find(entry.first);
      if (available_instructions == type_id_to_available_instructions.cend()) {
        continue;
      }
      instructions_to_choose_from.insert(instructions_to_choose_from.end(),
                                         available_instructions->second.begin(),
                                         available_instructions->second.end());
    }
    // If there are no instructions to choose from then use a zero constant,
    // otherwise select one of the instructions at random.
    uint32_t id_of_instruction_to_use =
        instructions_to_choose_from.empty()
            ? FindOrCreateZeroConstant(element_type_id, true)
            : instructions_to_choose_from[GetFuzzerContext()->RandomIndex(
                  instructions_to_choose_from)];
    opt::Instruction* instruction_to_use =
        GetIRContext()->get_def_use_mgr()->GetDef(id_of_instruction_to_use);
    result.push_back(instruction_to_use->result_id());
    auto chosen_type =
        GetIRContext()->get_type_mgr()->GetType(instruction_to_use->type_id());
    if (chosen_type->AsVector()) {
      assert(chosen_type->AsVector()->element_type() == element_type);
      assert(chosen_type->AsVector()->element_count() < element_count);
      assert(chosen_type->AsVector()->element_count() <=
             element_count - vector_slots_used);
      vector_slots_used += chosen_type->AsVector()->element_count();
    } else {
      assert(chosen_type == element_type);
      vector_slots_used += 1;
    }
  }
  assert(vector_slots_used == element_count);

  GetFuzzerContext()->Shuffle(&result);
  return result;
}

}  // namespace fuzz
}  // namespace spvtools
