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

#include <set>

#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/instruction_descriptor.h"
#include "source/fuzz/transformation_add_constant_boolean.h"
#include "source/fuzz/transformation_add_constant_composite.h"
#include "source/fuzz/transformation_add_constant_null.h"
#include "source/fuzz/transformation_add_constant_scalar.h"
#include "source/fuzz/transformation_add_global_undef.h"
#include "source/fuzz/transformation_add_type_boolean.h"
#include "source/fuzz/transformation_add_type_float.h"
#include "source/fuzz/transformation_add_type_function.h"
#include "source/fuzz/transformation_add_type_int.h"
#include "source/fuzz/transformation_add_type_matrix.h"
#include "source/fuzz/transformation_add_type_pointer.h"
#include "source/fuzz/transformation_add_type_struct.h"
#include "source/fuzz/transformation_add_type_vector.h"

namespace spvtools {
namespace fuzz {

FuzzerPass::FuzzerPass(opt::IRContext* ir_context,
                       TransformationContext* transformation_context,
                       FuzzerContext* fuzzer_context,
                       protobufs::TransformationSequence* transformations)
    : ir_context_(ir_context),
      transformation_context_(transformation_context),
      fuzzer_context_(fuzzer_context),
      transformations_(transformations) {}

FuzzerPass::~FuzzerPass() = default;

std::vector<opt::Instruction*> FuzzerPass::FindAvailableInstructions(
    opt::Function* function, opt::BasicBlock* block,
    const opt::BasicBlock::iterator& inst_it,
    std::function<bool(opt::IRContext*, opt::Instruction*)>
        instruction_is_relevant) const {
  // TODO(afd) The following is (relatively) simple, but may end up being
  //  prohibitively inefficient, as it walks the whole dominator tree for
  //  every instruction that is considered.

  std::vector<opt::Instruction*> result;
  // Consider all global declarations
  for (auto& global : GetIRContext()->module()->types_values()) {
    if (instruction_is_relevant(GetIRContext(), &global)) {
      result.push_back(&global);
    }
  }

  // Consider all function parameters
  function->ForEachParam(
      [this, &instruction_is_relevant, &result](opt::Instruction* param) {
        if (instruction_is_relevant(GetIRContext(), param)) {
          result.push_back(param);
        }
      });

  // Consider all previous instructions in this block
  for (auto prev_inst_it = block->begin(); prev_inst_it != inst_it;
       ++prev_inst_it) {
    if (instruction_is_relevant(GetIRContext(), &*prev_inst_it)) {
      result.push_back(&*prev_inst_it);
    }
  }

  // Walk the dominator tree to consider all instructions from dominating
  // blocks
  auto dominator_analysis = GetIRContext()->GetDominatorAnalysis(function);
  for (auto next_dominator = dominator_analysis->ImmediateDominator(block);
       next_dominator != nullptr;
       next_dominator =
           dominator_analysis->ImmediateDominator(next_dominator)) {
    for (auto& dominating_inst : *next_dominator) {
      if (instruction_is_relevant(GetIRContext(), &dominating_inst)) {
        result.push_back(&dominating_inst);
      }
    }
  }
  return result;
}

void FuzzerPass::ForEachInstructionWithInstructionDescriptor(
    std::function<
        void(opt::Function* function, opt::BasicBlock* block,
             opt::BasicBlock::iterator inst_it,
             const protobufs::InstructionDescriptor& instruction_descriptor)>
        action) {
  // Consider every block in every function.
  for (auto& function : *GetIRContext()->module()) {
    for (auto& block : function) {
      // We now consider every instruction in the block, randomly deciding
      // whether to apply a transformation before it.

      // In order for transformations to insert new instructions, they need to
      // be able to identify the instruction to insert before.  We describe an
      // instruction via its opcode, 'opc', a base instruction 'base' that has a
      // result id, and the number of instructions with opcode 'opc' that we
      // should skip when searching from 'base' for the desired instruction.
      // (An instruction that has a result id is represented by its own opcode,
      // itself as 'base', and a skip-count of 0.)
      std::vector<std::tuple<uint32_t, SpvOp, uint32_t>>
          base_opcode_skip_triples;

      // The initial base instruction is the block label.
      uint32_t base = block.id();

      // Counts the number of times we have seen each opcode since we reset the
      // base instruction.
      std::map<SpvOp, uint32_t> skip_count;

      // Consider every instruction in the block.  The label is excluded: it is
      // only necessary to consider it as a base in case the first instruction
      // in the block does not have a result id.
      for (auto inst_it = block.begin(); inst_it != block.end(); ++inst_it) {
        if (inst_it->HasResultId()) {
          // In the case that the instruction has a result id, we use the
          // instruction as its own base, and clear the skip counts we have
          // collected.
          base = inst_it->result_id();
          skip_count.clear();
        }
        const SpvOp opcode = inst_it->opcode();

        // Invoke the provided function, which might apply a transformation.
        action(&function, &block, inst_it,
               MakeInstructionDescriptor(
                   base, opcode,
                   skip_count.count(opcode) ? skip_count.at(opcode) : 0));

        if (!inst_it->HasResultId()) {
          skip_count[opcode] =
              skip_count.count(opcode) ? skip_count.at(opcode) + 1 : 1;
        }
      }
    }
  }
}

uint32_t FuzzerPass::FindOrCreateBoolType() {
  if (auto existing_id = fuzzerutil::MaybeGetBoolType(GetIRContext())) {
    return existing_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddTypeBoolean(result));
  return result;
}

uint32_t FuzzerPass::FindOrCreateIntegerType(uint32_t width, bool is_signed) {
  opt::analysis::Integer int_type(width, is_signed);
  auto existing_id = GetIRContext()->get_type_mgr()->GetId(&int_type);
  if (existing_id) {
    return existing_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddTypeInt(result, width, is_signed));
  return result;
}

uint32_t FuzzerPass::FindOrCreateFloatType(uint32_t width) {
  opt::analysis::Float float_type(width);
  auto existing_id = GetIRContext()->get_type_mgr()->GetId(&float_type);
  if (existing_id) {
    return existing_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddTypeFloat(result, width));
  return result;
}

uint32_t FuzzerPass::FindOrCreateFunctionType(
    uint32_t return_type_id, const std::vector<uint32_t>& argument_id) {
  // FindFunctionType has a sigle argument for OpTypeFunction operands
  // so we will have to copy them all in this vector
  std::vector<uint32_t> type_ids(argument_id.size() + 1);
  type_ids[0] = return_type_id;
  std::copy(argument_id.begin(), argument_id.end(), type_ids.begin() + 1);

  // Check if type exists
  auto existing_id = fuzzerutil::FindFunctionType(GetIRContext(), type_ids);
  if (existing_id) {
    return existing_id;
  }

  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(
      TransformationAddTypeFunction(result, return_type_id, argument_id));
  return result;
}

uint32_t FuzzerPass::FindOrCreateVectorType(uint32_t component_type_id,
                                            uint32_t component_count) {
  assert(component_count >= 2 && component_count <= 4 &&
         "Precondition: component count must be in range [2, 4].");
  opt::analysis::Type* component_type =
      GetIRContext()->get_type_mgr()->GetType(component_type_id);
  assert(component_type && "Precondition: the component type must exist.");
  opt::analysis::Vector vector_type(component_type, component_count);
  auto existing_id = GetIRContext()->get_type_mgr()->GetId(&vector_type);
  if (existing_id) {
    return existing_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(
      TransformationAddTypeVector(result, component_type_id, component_count));
  return result;
}

uint32_t FuzzerPass::FindOrCreateMatrixType(uint32_t column_count,
                                            uint32_t row_count) {
  assert(column_count >= 2 && column_count <= 4 &&
         "Precondition: column count must be in range [2, 4].");
  assert(row_count >= 2 && row_count <= 4 &&
         "Precondition: row count must be in range [2, 4].");
  uint32_t column_type_id =
      FindOrCreateVectorType(FindOrCreateFloatType(32), row_count);
  opt::analysis::Type* column_type =
      GetIRContext()->get_type_mgr()->GetType(column_type_id);
  opt::analysis::Matrix matrix_type(column_type, column_count);
  auto existing_id = GetIRContext()->get_type_mgr()->GetId(&matrix_type);
  if (existing_id) {
    return existing_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(
      TransformationAddTypeMatrix(result, column_type_id, column_count));
  return result;
}

uint32_t FuzzerPass::FindOrCreateStructType(
    const std::vector<uint32_t>& component_type_ids) {
  if (auto existing_id =
          fuzzerutil::MaybeGetStructType(GetIRContext(), component_type_ids)) {
    return existing_id;
  }
  auto new_id = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddTypeStruct(new_id, component_type_ids));
  return new_id;
}

uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id,
                                             SpvStorageClass storage_class) {
  // We do not use the type manager here, due to problems related to isomorphic
  // but distinct structs not being regarded as different.
  auto existing_id = fuzzerutil::MaybeGetPointerType(
      GetIRContext(), base_type_id, storage_class);
  if (existing_id) {
    return existing_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(
      TransformationAddTypePointer(result, storage_class, base_type_id));
  return result;
}

uint32_t FuzzerPass::FindOrCreatePointerToIntegerType(
    uint32_t width, bool is_signed, SpvStorageClass storage_class) {
  return FindOrCreatePointerType(FindOrCreateIntegerType(width, is_signed),
                                 storage_class);
}

uint32_t FuzzerPass::FindOrCreateIntegerConstant(
    const std::vector<uint32_t>& words, uint32_t width, bool is_signed,
    bool is_irrelevant) {
  auto int_type_id = FindOrCreateIntegerType(width, is_signed);
  if (auto constant_id = fuzzerutil::MaybeGetScalarConstant(
          GetIRContext(), *GetTransformationContext(), words, int_type_id,
          is_irrelevant)) {
    return constant_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddConstantScalar(result, int_type_id,
                                                      words, is_irrelevant));
  return result;
}

uint32_t FuzzerPass::FindOrCreateFloatConstant(
    const std::vector<uint32_t>& words, uint32_t width, bool is_irrelevant) {
  auto float_type_id = FindOrCreateFloatType(width);
  opt::analysis::FloatConstant float_constant(
      GetIRContext()->get_type_mgr()->GetType(float_type_id)->AsFloat(), words);
  if (auto constant_id = fuzzerutil::MaybeGetScalarConstant(
          GetIRContext(), *GetTransformationContext(), words, float_type_id,
          is_irrelevant)) {
    return constant_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddConstantScalar(result, float_type_id,
                                                      words, is_irrelevant));
  return result;
}

uint32_t FuzzerPass::FindOrCreateBoolConstant(bool value, bool is_irrelevant) {
  auto bool_type_id = FindOrCreateBoolType();
  if (auto constant_id = fuzzerutil::MaybeGetScalarConstant(
          GetIRContext(), *GetTransformationContext(), {value ? 1u : 0u},
          bool_type_id, is_irrelevant)) {
    return constant_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(
      TransformationAddConstantBoolean(result, value, is_irrelevant));
  return result;
}

uint32_t FuzzerPass::FindOrCreateConstant(const std::vector<uint32_t>& words,
                                          uint32_t type_id,
                                          bool is_irrelevant) {
  assert(type_id && "Constant's type id can't be 0.");

  const auto* type = GetIRContext()->get_type_mgr()->GetType(type_id);
  assert(type && "Type does not exist.");

  if (type->AsBool()) {
    assert(words.size() == 1);
    return FindOrCreateBoolConstant(words[0], is_irrelevant);
  } else if (const auto* integer = type->AsInteger()) {
    return FindOrCreateIntegerConstant(words, integer->width(),
                                       integer->IsSigned(), is_irrelevant);
  } else if (const auto* floating = type->AsFloat()) {
    return FindOrCreateFloatConstant(words, floating->width(), is_irrelevant);
  }

  // This assertion will fail in debug build but not in release build
  // so we return 0 to make compiler happy.
  assert(false && "Constant type is not supported");
  return 0;
}

uint32_t FuzzerPass::FindOrCreateCompositeConstant(
    const std::vector<uint32_t>& component_ids, uint32_t type_id,
    bool is_irrelevant) {
  if (auto existing_constant = fuzzerutil::MaybeGetCompositeConstant(
          GetIRContext(), *GetTransformationContext(), component_ids, type_id,
          is_irrelevant)) {
    return existing_constant;
  }
  uint32_t result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddConstantComposite(
      result, type_id, component_ids, is_irrelevant));
  return result;
}

uint32_t FuzzerPass::FindOrCreateGlobalUndef(uint32_t type_id) {
  for (auto& inst : GetIRContext()->types_values()) {
    if (inst.opcode() == SpvOpUndef && inst.type_id() == type_id) {
      return inst.result_id();
    }
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddGlobalUndef(result, type_id));
  return result;
}

uint32_t FuzzerPass::FindOrCreateNullConstant(uint32_t type_id) {
  // Find existing declaration
  opt::analysis::NullConstant null_constant(
      GetIRContext()->get_type_mgr()->GetType(type_id));
  auto existing_constant =
      GetIRContext()->get_constant_mgr()->FindConstant(&null_constant);

  // Return if found
  if (existing_constant) {
    return GetIRContext()
        ->get_constant_mgr()
        ->GetDefiningInstruction(existing_constant)
        ->result_id();
  }

  // Create new if not found
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddConstantNull(result, type_id));
  return result;
}

std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
FuzzerPass::GetAvailableBasicTypesAndPointers(
    SpvStorageClass storage_class) const {
  // Records all of the basic types available in the module.
  std::set<uint32_t> basic_types;

  // For each basic type, records all the associated pointer types that target
  // the basic type and that have |storage_class| as their storage class.
  std::map<uint32_t, std::vector<uint32_t>> basic_type_to_pointers;

  for (auto& inst : GetIRContext()->types_values()) {
    // For each basic type that we come across, record type, and the fact that
    // we cannot yet have seen any pointers that use the basic type as its
    // pointee type.
    //
    // For pointer types with basic pointee types, associate the pointer type
    // with the basic type.
    switch (inst.opcode()) {
      case SpvOpTypeBool:
      case SpvOpTypeFloat:
      case SpvOpTypeInt:
      case SpvOpTypeMatrix:
      case SpvOpTypeVector:
        // These are all basic types.
        basic_types.insert(inst.result_id());
        basic_type_to_pointers.insert({inst.result_id(), {}});
        break;
      case SpvOpTypeArray:
        // An array type is basic if its base type is basic.
        if (basic_types.count(inst.GetSingleWordInOperand(0))) {
          basic_types.insert(inst.result_id());
          basic_type_to_pointers.insert({inst.result_id(), {}});
        }
        break;
      case SpvOpTypeStruct: {
        // A struct type is basic if all of its members are basic.
        bool all_members_are_basic_types = true;
        for (uint32_t i = 0; i < inst.NumInOperands(); i++) {
          if (!basic_types.count(inst.GetSingleWordInOperand(i))) {
            all_members_are_basic_types = false;
            break;
          }
        }
        if (all_members_are_basic_types) {
          basic_types.insert(inst.result_id());
          basic_type_to_pointers.insert({inst.result_id(), {}});
        }
        break;
      }
      case SpvOpTypePointer: {
        // We are interested in the pointer if its pointee type is basic and it
        // has the right storage class.
        auto pointee_type = inst.GetSingleWordInOperand(1);
        if (inst.GetSingleWordInOperand(0) == storage_class &&
            basic_types.count(pointee_type)) {
          // The pointer has the desired storage class, and its pointee type is
          // a basic type, so we are interested in it.  Associate it with its
          // basic type.
          basic_type_to_pointers.at(pointee_type).push_back(inst.result_id());
        }
        break;
      }
      default:
        break;
    }
  }
  return {{basic_types.begin(), basic_types.end()}, basic_type_to_pointers};
}

uint32_t FuzzerPass::FindOrCreateZeroConstant(
    uint32_t scalar_or_composite_type_id, bool is_irrelevant) {
  auto type_instruction =
      GetIRContext()->get_def_use_mgr()->GetDef(scalar_or_composite_type_id);
  assert(type_instruction && "The type instruction must exist.");
  switch (type_instruction->opcode()) {
    case SpvOpTypeBool:
      return FindOrCreateBoolConstant(false, is_irrelevant);
    case SpvOpTypeFloat: {
      auto width = type_instruction->GetSingleWordInOperand(0);
      auto num_words = (width + 32 - 1) / 32;
      return FindOrCreateFloatConstant(std::vector<uint32_t>(num_words, 0),
                                       width, is_irrelevant);
    }
    case SpvOpTypeInt: {
      auto width = type_instruction->GetSingleWordInOperand(0);
      auto num_words = (width + 32 - 1) / 32;
      return FindOrCreateIntegerConstant(
          std::vector<uint32_t>(num_words, 0), width,
          type_instruction->GetSingleWordInOperand(1), is_irrelevant);
    }
    case SpvOpTypeArray: {
      auto component_type_id = type_instruction->GetSingleWordInOperand(0);
      auto num_components =
          fuzzerutil::GetArraySize(*type_instruction, GetIRContext());
      return FindOrCreateCompositeConstant(
          std::vector<uint32_t>(
              num_components,
              FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
          scalar_or_composite_type_id, is_irrelevant);
    }
    case SpvOpTypeMatrix:
    case SpvOpTypeVector: {
      auto component_type_id = type_instruction->GetSingleWordInOperand(0);
      auto num_components = type_instruction->GetSingleWordInOperand(1);
      return FindOrCreateCompositeConstant(
          std::vector<uint32_t>(
              num_components,
              FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
          scalar_or_composite_type_id, is_irrelevant);
    }
    case SpvOpTypeStruct: {
      std::vector<uint32_t> field_zero_ids;
      for (uint32_t index = 0; index < type_instruction->NumInOperands();
           index++) {
        field_zero_ids.push_back(FindOrCreateZeroConstant(
            type_instruction->GetSingleWordInOperand(index), is_irrelevant));
      }
      return FindOrCreateCompositeConstant(
          field_zero_ids, scalar_or_composite_type_id, is_irrelevant);
    }
    default:
      assert(false && "Unknown type.");
      return 0;
  }
}

}  // namespace fuzz
}  // namespace spvtools
