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

#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/transformation_add_opphi_synonym.h"

namespace spvtools {
namespace fuzz {

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

void FuzzerPassAddOpPhiSynonyms::Apply() {
  // Get a list of synonymous ids with the same type that can be used in the
  // same OpPhi instruction.
  auto equivalence_classes = GetIdEquivalenceClasses();

  // Make a list of references, to avoid copying sets unnecessarily.
  std::vector<std::set<uint32_t>*> equivalence_class_pointers;
  for (auto& set : equivalence_classes) {
    equivalence_class_pointers.push_back(&set);
  }

  // Keep a list of transformations to apply at the end.
  std::vector<TransformationAddOpPhiSynonym> transformations_to_apply;

  for (auto& function : *GetIRContext()->module()) {
    for (auto& block : function) {
      // Randomly decide whether to consider this block.
      if (!GetFuzzerContext()->ChoosePercentage(
              GetFuzzerContext()->GetChanceOfAddingOpPhiSynonym())) {
        continue;
      }

      // The block must not be dead.
      if (GetTransformationContext()->GetFactManager()->BlockIsDead(
              block.id())) {
        continue;
      }

      // The block must have at least one predecessor.
      size_t num_preds = GetIRContext()->cfg()->preds(block.id()).size();
      if (num_preds == 0) {
        continue;
      }

      std::set<uint32_t>* chosen_equivalence_class = nullptr;

      if (num_preds > 1) {
        // If the block has more than one predecessor, prioritise sets with at
        // least 2 ids available at some predecessor.
        chosen_equivalence_class = MaybeFindSuitableEquivalenceClassRandomly(
            equivalence_class_pointers, block.id(), 2);
      }

      // If a set was not already chosen, choose one with at least one available
      // id.
      if (!chosen_equivalence_class) {
        chosen_equivalence_class = MaybeFindSuitableEquivalenceClassRandomly(
            equivalence_class_pointers, block.id(), 1);
      }

      // If no suitable set was found, we cannot apply the transformation to
      // this block.
      if (!chosen_equivalence_class) {
        continue;
      }

      // Initialise the map from predecessor labels to ids.
      std::map<uint32_t, uint32_t> preds_to_ids;

      // Keep track of the ids used and of the id of a predecessor with at least
      // two ids to choose from. This is to ensure that, if possible, at least
      // two distinct ids will be used.
      std::set<uint32_t> ids_chosen;
      uint32_t pred_with_alternatives = 0;

      // Choose an id for each predecessor.
      for (uint32_t pred_id : GetIRContext()->cfg()->preds(block.id())) {
        auto suitable_ids = GetSuitableIds(*chosen_equivalence_class, pred_id);
        assert(!suitable_ids.empty() &&
               "We must be able to find at least one suitable id because the "
               "equivalence class was chosen among suitable ones.");

        // If this predecessor has more than one id to choose from and it is the
        // first one of this kind that we found, remember its id.
        if (suitable_ids.size() > 1 && !pred_with_alternatives) {
          pred_with_alternatives = pred_id;
        }

        uint32_t chosen_id =
            suitable_ids[GetFuzzerContext()->RandomIndex(suitable_ids)];

        // Add this id to the set of ids chosen.
        ids_chosen.emplace(chosen_id);

        // Add the pair (predecessor, chosen id) to the map.
        preds_to_ids[pred_id] = chosen_id;
      }

      // If:
      // - the block has more than one predecessor
      // - at least one predecessor has more than one alternative
      // - the same id has been chosen by all the predecessors
      // then choose another one for the predecessor with more than one
      // alternative.
      if (num_preds > 1 && pred_with_alternatives != 0 &&
          ids_chosen.size() == 1) {
        auto suitable_ids =
            GetSuitableIds(*chosen_equivalence_class, pred_with_alternatives);
        uint32_t chosen_id =
            GetFuzzerContext()->RemoveAtRandomIndex(&suitable_ids);
        if (chosen_id == preds_to_ids[pred_with_alternatives]) {
          chosen_id = GetFuzzerContext()->RemoveAtRandomIndex(&suitable_ids);
        }

        preds_to_ids[pred_with_alternatives] = chosen_id;
      }

      // Add the transformation to the list of transformations to apply.
      transformations_to_apply.emplace_back(block.id(), preds_to_ids,
                                            GetFuzzerContext()->GetFreshId());
    }
  }

  // Apply the transformations.
  for (const auto& transformation : transformations_to_apply) {
    ApplyTransformation(transformation);
  }
}

std::vector<std::set<uint32_t>>
FuzzerPassAddOpPhiSynonyms::GetIdEquivalenceClasses() {
  std::vector<std::set<uint32_t>> id_equivalence_classes;

  // Keep track of all the ids that have already be assigned to a class.
  std::set<uint32_t> already_in_a_class;

  for (const auto& pair : GetIRContext()->get_def_use_mgr()->id_to_defs()) {
    // Exclude ids that have already been assigned to a class.
    if (already_in_a_class.count(pair.first)) {
      continue;
    }

    // Exclude irrelevant ids.
    if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
            pair.first)) {
      continue;
    }

    // Exclude ids having a type that is not allowed by the transformation.
    if (!TransformationAddOpPhiSynonym::CheckTypeIsAllowed(
            GetIRContext(), pair.second->type_id())) {
      continue;
    }

    // Exclude OpFunction and OpUndef instructions, because:
    // - OpFunction does not yield a value;
    // - OpUndef yields an undefined value at each use, so it should never be a
    //   synonym of another id.
    if (pair.second->opcode() == SpvOpFunction ||
        pair.second->opcode() == SpvOpUndef) {
      continue;
    }

    // We need a new equivalence class for this id.
    std::set<uint32_t> new_equivalence_class;

    // Add this id to the class.
    new_equivalence_class.emplace(pair.first);
    already_in_a_class.emplace(pair.first);

    // Add all the synonyms with the same type to this class.
    for (auto synonym :
         GetTransformationContext()->GetFactManager()->GetSynonymsForId(
             pair.first)) {
      // The synonym must be a plain id - it cannot be an indexed access into a
      // composite.
      if (synonym->index_size() > 0) {
        continue;
      }

      // The synonym must not be irrelevant.
      if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
              synonym->object())) {
        continue;
      }

      auto synonym_def =
          GetIRContext()->get_def_use_mgr()->GetDef(synonym->object());
      // The synonym must exist and have the same type as the id we are
      // considering.
      if (!synonym_def || synonym_def->type_id() != pair.second->type_id()) {
        continue;
      }

      // We can add this synonym to the new equivalence class.
      new_equivalence_class.emplace(synonym->object());
      already_in_a_class.emplace(synonym->object());
    }

    // Add the new equivalence class to the list of equivalence classes.
    id_equivalence_classes.emplace_back(std::move(new_equivalence_class));
  }

  return id_equivalence_classes;
}

bool FuzzerPassAddOpPhiSynonyms::EquivalenceClassIsSuitableForBlock(
    const std::set<uint32_t>& equivalence_class, uint32_t block_id,
    uint32_t distinct_ids_required) {
  bool at_least_one_id_for_each_pred = true;

  // Keep a set of the suitable ids found.
  std::set<uint32_t> suitable_ids_found;

  // Loop through all the predecessors of the block.
  for (auto pred_id : GetIRContext()->cfg()->preds(block_id)) {
    // Find the last instruction in the predecessor block.
    auto last_instruction =
        GetIRContext()->get_instr_block(pred_id)->terminator();

    // Initially assume that there is not a suitable id for this predecessor.
    bool at_least_one_suitable_id_found = false;
    for (uint32_t id : equivalence_class) {
      if (fuzzerutil::IdIsAvailableBeforeInstruction(GetIRContext(),
                                                     last_instruction, id)) {
        // We have found a suitable id.
        at_least_one_suitable_id_found = true;
        suitable_ids_found.emplace(id);

        // If we have already found enough distinct suitable ids, we don't need
        // to check the remaining ones for this predecessor.
        if (suitable_ids_found.size() >= distinct_ids_required) {
          break;
        }
      }
    }
    // If no suitable id was found for this predecessor, this equivalence class
    // is not suitable and we don't need to check the other predecessors.
    if (!at_least_one_suitable_id_found) {
      at_least_one_id_for_each_pred = false;
      break;
    }
  }

  // The equivalence class is suitable if at least one suitable id was found for
  // each predecessor and we have found at least |distinct_ids_required|
  // distinct suitable ids in general.
  return at_least_one_id_for_each_pred &&
         suitable_ids_found.size() >= distinct_ids_required;
}

std::vector<uint32_t> FuzzerPassAddOpPhiSynonyms::GetSuitableIds(
    const std::set<uint32_t>& ids, uint32_t pred_id) {
  // Initialise an empty vector of suitable ids.
  std::vector<uint32_t> suitable_ids;

  // Get the predecessor block.
  auto predecessor = fuzzerutil::MaybeFindBlock(GetIRContext(), pred_id);

  // Loop through the ids to find the suitable ones.
  for (uint32_t id : ids) {
    if (fuzzerutil::IdIsAvailableBeforeInstruction(
            GetIRContext(), predecessor->terminator(), id)) {
      suitable_ids.push_back(id);
    }
  }

  return suitable_ids;
}

std::set<uint32_t>*
FuzzerPassAddOpPhiSynonyms::MaybeFindSuitableEquivalenceClassRandomly(
    const std::vector<std::set<uint32_t>*>& candidates, uint32_t block_id,
    uint32_t distinct_ids_required) {
  auto remaining_candidates = candidates;
  while (!remaining_candidates.empty()) {
    // Choose one set randomly and return it if it is suitable.
    auto chosen =
        GetFuzzerContext()->RemoveAtRandomIndex(&remaining_candidates);
    if (EquivalenceClassIsSuitableForBlock(*chosen, block_id,
                                           distinct_ids_required)) {
      return chosen;
    }
  }

  // No suitable sets were found.
  return nullptr;
}

}  // namespace fuzz
}  // namespace spvtools
