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

#include "source/fuzz/fuzzer_util.h"

namespace spvtools {
namespace fuzz {

TransformationReplaceBranchFromDeadBlockWithExit::
    TransformationReplaceBranchFromDeadBlockWithExit(
        const spvtools::fuzz::protobufs::
            TransformationReplaceBranchFromDeadBlockWithExit& message)
    : message_(message) {}

TransformationReplaceBranchFromDeadBlockWithExit::
    TransformationReplaceBranchFromDeadBlockWithExit(uint32_t block_id,
                                                     SpvOp opcode,
                                                     uint32_t return_value_id) {
  message_.set_block_id(block_id);
  message_.set_opcode(opcode);
  message_.set_return_value_id(return_value_id);
}

bool TransformationReplaceBranchFromDeadBlockWithExit::IsApplicable(
    opt::IRContext* ir_context,
    const TransformationContext& transformation_context) const {
  // The block whose terminator is to be changed must exist.
  auto block = ir_context->get_instr_block(message_.block_id());
  if (!block) {
    return false;
  }
  if (!BlockIsSuitable(ir_context, transformation_context, *block)) {
    return false;
  }
  auto function_return_type_id = block->GetParent()->type_id();
  switch (message_.opcode()) {
    case SpvOpKill:
      for (auto& entry_point : ir_context->module()->entry_points()) {
        if (entry_point.GetSingleWordInOperand(0) !=
            SpvExecutionModelFragment) {
          // OpKill is only allowed in a fragment shader.  This is a
          // conservative check: if the module contains a non-fragment entry
          // point then adding an OpKill might lead to OpKill being used in a
          // non-fragment shader.
          return false;
        }
      }
      break;
    case SpvOpReturn:
      if (ir_context->get_def_use_mgr()
              ->GetDef(function_return_type_id)
              ->opcode() != SpvOpTypeVoid) {
        // OpReturn is only allowed in a function with void return type.
        return false;
      }
      break;
    case SpvOpReturnValue: {
      // If the terminator is to be changed to OpReturnValue, with
      // |message_.return_value_id| being the value that will be returned, then
      // |message_.return_value_id| must have a compatible type and be available
      // at the block terminator.
      auto return_value =
          ir_context->get_def_use_mgr()->GetDef(message_.return_value_id());
      if (!return_value || return_value->type_id() != function_return_type_id) {
        return false;
      }
      if (!fuzzerutil::IdIsAvailableBeforeInstruction(
              ir_context, block->terminator(), message_.return_value_id())) {
        return false;
      }
      break;
    }
    default:
      assert(message_.opcode() == SpvOpUnreachable &&
             "Invalid early exit opcode.");
      break;
  }
  return true;
}

void TransformationReplaceBranchFromDeadBlockWithExit::Apply(
    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
  // If the successor block has OpPhi instructions then arguments related to
  // |message_.block_id| need to be removed from these instruction.
  auto block = ir_context->get_instr_block(message_.block_id());
  assert(block->terminator()->opcode() == SpvOpBranch &&
         "Precondition: the block must end with OpBranch.");
  auto successor = ir_context->get_instr_block(
      block->terminator()->GetSingleWordInOperand(0));
  successor->ForEachPhiInst([block](opt::Instruction* phi_inst) {
    opt::Instruction::OperandList new_phi_in_operands;
    for (uint32_t i = 0; i < phi_inst->NumInOperands(); i += 2) {
      if (phi_inst->GetSingleWordInOperand(i + 1) == block->id()) {
        continue;
      }
      new_phi_in_operands.emplace_back(phi_inst->GetInOperand(i));
      new_phi_in_operands.emplace_back(phi_inst->GetInOperand(i + 1));
    }
    assert(new_phi_in_operands.size() == phi_inst->NumInOperands() - 2);
    phi_inst->SetInOperands(std::move(new_phi_in_operands));
  });

  // Rewrite the terminator of |message_.block_id|.
  opt::Instruction::OperandList new_terminator_in_operands;
  if (message_.opcode() == SpvOpReturnValue) {
    new_terminator_in_operands.push_back(
        {SPV_OPERAND_TYPE_ID, {message_.return_value_id()}});
  }
  auto terminator = block->terminator();
  terminator->SetOpcode(static_cast<SpvOp>(message_.opcode()));
  terminator->SetInOperands(std::move(new_terminator_in_operands));
  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
}

std::unordered_set<uint32_t>
TransformationReplaceBranchFromDeadBlockWithExit::GetFreshIds() const {
  return std::unordered_set<uint32_t>();
}

protobufs::Transformation
TransformationReplaceBranchFromDeadBlockWithExit::ToMessage() const {
  protobufs::Transformation result;
  *result.mutable_replace_branch_from_dead_block_with_exit() = message_;
  return result;
}

bool TransformationReplaceBranchFromDeadBlockWithExit::BlockIsSuitable(
    opt::IRContext* ir_context,
    const TransformationContext& transformation_context,
    const opt::BasicBlock& block) {
  // The block must be dead.
  if (!transformation_context.GetFactManager()->BlockIsDead(block.id())) {
    return false;
  }
  // The block's terminator must be OpBranch.
  if (block.terminator()->opcode() != SpvOpBranch) {
    return false;
  }
  if (ir_context->GetStructuredCFGAnalysis()->IsInContinueConstruct(
          block.id())) {
    // Early exits from continue constructs are not allowed as they would break
    // the SPIR-V structured control flow rules.
    return false;
  }
  // We only allow changing OpBranch to an early terminator if the target of the
  // OpBranch has at least one other predecessor.
  auto successor = ir_context->get_instr_block(
      block.terminator()->GetSingleWordInOperand(0));
  if (ir_context->cfg()->preds(successor->id()).size() < 2) {
    return false;
  }
  return true;
}

}  // namespace fuzz
}  // namespace spvtools
