// 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_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
