// 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(
        protobufs::TransformationReplaceBranchFromDeadBlockWithExit message)
    : message_(std::move(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;
  }
  // Make sure that domination rules are satisfied when we remove the branch
  // from the |block| to its |successor|.
  return fuzzerutil::NewTerminatorPreservesDominationRules(
      ir_context, block.id(), {ir_context, SpvOpUnreachable});
}

}  // namespace fuzz
}  // namespace spvtools
