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

#include "source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.h"

namespace spvtools {
namespace fuzz {

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

FuzzerPassReplaceOpPhiIdsFromDeadPredecessors::
    ~FuzzerPassReplaceOpPhiIdsFromDeadPredecessors() = default;

void FuzzerPassReplaceOpPhiIdsFromDeadPredecessors::Apply() {
  // Keep a vector of the transformations to apply.
  std::vector<TransformationReplaceOpPhiIdFromDeadPredecessor> transformations;

  // Loop through the reachable blocks in the module.
  for (auto& function : *GetIRContext()->module()) {
    GetIRContext()->cfg()->ForEachBlockInPostOrder(
        &*function.begin(),
        [this, &function, &transformations](opt::BasicBlock* block) {
          // Only consider dead blocks.
          if (!GetTransformationContext()->GetFactManager()->BlockIsDead(
                  block->id())) {
            return;
          }

          // Find all the uses of the label id of the block inside OpPhi
          // instructions.
          GetIRContext()->get_def_use_mgr()->ForEachUse(
              block->id(), [this, &function, block, &transformations](
                               opt::Instruction* instruction, uint32_t) {
                // Only consider OpPhi instructions.
                if (instruction->opcode() != SpvOpPhi) {
                  return;
                }

                // Randomly decide whether to consider this use.
                if (!GetFuzzerContext()->ChoosePercentage(
                        GetFuzzerContext()
                            ->GetChanceOfReplacingOpPhiIdFromDeadPredecessor())) {
                  return;
                }

                // Get the current id corresponding to the predecessor.
                uint32_t current_id = 0;
                for (uint32_t i = 1; i < instruction->NumInOperands(); i += 2) {
                  if (instruction->GetSingleWordInOperand(i) == block->id()) {
                    // The corresponding id is at the index of the block - 1.
                    current_id = instruction->GetSingleWordInOperand(i - 1);
                    break;
                  }
                }
                assert(
                    current_id != 0 &&
                    "The predecessor - and corresponding id - should always be "
                    "found.");

                uint32_t type_id = instruction->type_id();

                // Find all the suitable instructions to replace the id.
                const auto& candidates = FindAvailableInstructions(
                    &function, block, block->end(),
                    [type_id, current_id](opt::IRContext* /* unused */,
                                          opt::Instruction* candidate) -> bool {
                      // Only consider instructions with a result id different
                      // from the currently-used one, and with the right type.
                      return candidate->HasResultId() &&
                             candidate->type_id() == type_id &&
                             candidate->result_id() != current_id;
                    });

                // If there is no possible replacement, we cannot apply any
                // transformation.
                if (candidates.empty()) {
                  return;
                }

                // Choose one of the candidates.
                uint32_t replacement_id =
                    candidates[GetFuzzerContext()->RandomIndex(candidates)]
                        ->result_id();

                // Add a new transformation to the list of transformations to
                // apply.
                transformations.emplace_back(
                    TransformationReplaceOpPhiIdFromDeadPredecessor(
                        instruction->result_id(), block->id(), replacement_id));
              });
        });
  }

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

}  // namespace fuzz
}  // namespace spvtools
