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

#include <vector>

#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/instruction_descriptor.h"
#include "source/fuzz/transformation_outline_function.h"
#include "source/fuzz/transformation_split_block.h"

namespace spvtools {
namespace fuzz {

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

FuzzerPassOutlineFunctions::~FuzzerPassOutlineFunctions() = default;

void FuzzerPassOutlineFunctions::Apply() {
  std::vector<opt::Function*> original_functions;
  for (auto& function : *GetIRContext()->module()) {
    original_functions.push_back(&function);
  }
  for (auto& function : original_functions) {
    if (!GetFuzzerContext()->ChoosePercentage(
            GetFuzzerContext()->GetChanceOfOutliningFunction())) {
      continue;
    }
    std::vector<opt::BasicBlock*> blocks;
    for (auto& block : *function) {
      blocks.push_back(&block);
    }
    auto entry_block = MaybeGetEntryBlockSuitableForOutlining(
        blocks[GetFuzzerContext()->RandomIndex(blocks)]);

    if (!entry_block) {
      // The chosen block is not suitable to be the entry block of a region that
      // will be outlined.
      continue;
    }

    auto dominator_analysis = GetIRContext()->GetDominatorAnalysis(function);
    auto postdominator_analysis =
        GetIRContext()->GetPostDominatorAnalysis(function);
    std::vector<opt::BasicBlock*> candidate_exit_blocks;
    for (auto postdominates_entry_block = entry_block;
         postdominates_entry_block != nullptr;
         postdominates_entry_block = postdominator_analysis->ImmediateDominator(
             postdominates_entry_block)) {
      // Consider the block if it is dominated by the entry block, ignore it if
      // it is a continue target.
      if (dominator_analysis->Dominates(entry_block,
                                        postdominates_entry_block) &&
          !GetIRContext()->GetStructuredCFGAnalysis()->IsContinueBlock(
              postdominates_entry_block->id())) {
        candidate_exit_blocks.push_back(postdominates_entry_block);
      }
    }
    if (candidate_exit_blocks.empty()) {
      continue;
    }
    auto exit_block = MaybeGetExitBlockSuitableForOutlining(
        candidate_exit_blocks[GetFuzzerContext()->RandomIndex(
            candidate_exit_blocks)]);

    if (!exit_block) {
      // The block chosen is not suitable
      continue;
    }

    auto region_blocks = TransformationOutlineFunction::GetRegionBlocks(
        GetIRContext(), entry_block, exit_block);
    std::map<uint32_t, uint32_t> input_id_to_fresh_id;
    for (auto id : TransformationOutlineFunction::GetRegionInputIds(
             GetIRContext(), region_blocks, exit_block)) {
      input_id_to_fresh_id[id] = GetFuzzerContext()->GetFreshId();
    }
    std::map<uint32_t, uint32_t> output_id_to_fresh_id;
    for (auto id : TransformationOutlineFunction::GetRegionOutputIds(
             GetIRContext(), region_blocks, exit_block)) {
      output_id_to_fresh_id[id] = GetFuzzerContext()->GetFreshId();
    }
    TransformationOutlineFunction transformation(
        entry_block->id(), exit_block->id(),
        /*new_function_struct_return_type_id*/
        GetFuzzerContext()->GetFreshId(),
        /*new_function_type_id*/ GetFuzzerContext()->GetFreshId(),
        /*new_function_id*/ GetFuzzerContext()->GetFreshId(),
        /*new_function_region_entry_block*/
        GetFuzzerContext()->GetFreshId(),
        /*new_caller_result_id*/ GetFuzzerContext()->GetFreshId(),
        /*new_callee_result_id*/ GetFuzzerContext()->GetFreshId(),
        /*input_id_to_fresh_id*/ std::move(input_id_to_fresh_id),
        /*output_id_to_fresh_id*/ std::move(output_id_to_fresh_id));
    MaybeApplyTransformation(transformation);
  }
}

opt::BasicBlock*
FuzzerPassOutlineFunctions::MaybeGetEntryBlockSuitableForOutlining(
    opt::BasicBlock* entry_block) {
  // If the entry block is a loop header, we need to get or create its
  // preheader and make it the entry block, if possible.
  if (entry_block->IsLoopHeader()) {
    auto predecessors =
        GetIRContext()->cfg()->preds(entry_block->GetLabel()->result_id());

    if (predecessors.size() < 2) {
      // The header only has one predecessor (the back-edge block) and thus
      // it is unreachable. The block cannot be adjusted to be suitable for
      // outlining.
      return nullptr;
    }

    // Get or create a suitable preheader and make it become the entry block.
    entry_block =
        GetOrCreateSimpleLoopPreheader(entry_block->GetLabel()->result_id());
  }

  assert(!entry_block->IsLoopHeader() &&
         "The entry block cannot be a loop header at this point.");

  // If the entry block starts with OpPhi or OpVariable, try to split it.
  if (entry_block->begin()->opcode() == SpvOpPhi ||
      entry_block->begin()->opcode() == SpvOpVariable) {
    // Find the first non-OpPhi and non-OpVariable instruction.
    auto non_phi_or_var_inst = &*entry_block->begin();
    while (non_phi_or_var_inst->opcode() == SpvOpPhi ||
           non_phi_or_var_inst->opcode() == SpvOpVariable) {
      non_phi_or_var_inst = non_phi_or_var_inst->NextNode();
    }

    // Split the block.
    uint32_t new_block_id = GetFuzzerContext()->GetFreshId();
    ApplyTransformation(TransformationSplitBlock(
        MakeInstructionDescriptor(GetIRContext(), non_phi_or_var_inst),
        new_block_id));

    // The new entry block is the newly-created block.
    entry_block = &*entry_block->GetParent()->FindBlock(new_block_id);
  }

  return entry_block;
}

opt::BasicBlock*
FuzzerPassOutlineFunctions::MaybeGetExitBlockSuitableForOutlining(
    opt::BasicBlock* exit_block) {
  // The exit block must not be a continue target.
  assert(!GetIRContext()->GetStructuredCFGAnalysis()->IsContinueBlock(
             exit_block->id()) &&
         "A candidate exit block cannot be a continue target.");

  // If the exit block is a merge block, try to split it and return the second
  // block in the pair as the exit block.
  if (GetIRContext()->GetStructuredCFGAnalysis()->IsMergeBlock(
          exit_block->id())) {
    uint32_t new_block_id = GetFuzzerContext()->GetFreshId();

    // Find the first non-OpPhi instruction, after which to split.
    auto split_before = &*exit_block->begin();
    while (split_before->opcode() == SpvOpPhi) {
      split_before = split_before->NextNode();
    }

    if (!MaybeApplyTransformation(TransformationSplitBlock(
            MakeInstructionDescriptor(GetIRContext(), split_before),
            new_block_id))) {
      return nullptr;
    }

    return &*exit_block->GetParent()->FindBlock(new_block_id);
  }

  return exit_block;
}

}  // namespace fuzz
}  // namespace spvtools
