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

#include "source/fuzz/call_graph.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/instruction_descriptor.h"

namespace spvtools {
namespace fuzz {

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

TransformationFunctionCall::TransformationFunctionCall(
    uint32_t fresh_id, uint32_t callee_id,
    const std::vector<uint32_t>& argument_id,
    const protobufs::InstructionDescriptor& instruction_to_insert_before) {
  message_.set_fresh_id(fresh_id);
  message_.set_callee_id(callee_id);
  for (auto argument : argument_id) {
    message_.add_argument_id(argument);
  }
  *message_.mutable_instruction_to_insert_before() =
      instruction_to_insert_before;
}

bool TransformationFunctionCall::IsApplicable(
    opt::IRContext* context,
    const spvtools::fuzz::FactManager& fact_manager) const {
  // The result id must be fresh
  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
    return false;
  }

  // The function must exist
  auto callee_inst = context->get_def_use_mgr()->GetDef(message_.callee_id());
  if (!callee_inst || callee_inst->opcode() != SpvOpFunction) {
    return false;
  }

  // The function must not be an entry point
  if (fuzzerutil::FunctionIsEntryPoint(context, message_.callee_id())) {
    return false;
  }

  auto callee_type_inst = context->get_def_use_mgr()->GetDef(
      callee_inst->GetSingleWordInOperand(1));
  assert(callee_type_inst->opcode() == SpvOpTypeFunction &&
         "Bad function type.");

  // The number of expected function arguments must match the number of given
  // arguments.  The number of expected arguments is one less than the function
  // type's number of input operands, as one operand is for the return type.
  if (callee_type_inst->NumInOperands() - 1 !=
      static_cast<uint32_t>(message_.argument_id().size())) {
    return false;
  }

  // The instruction descriptor must refer to a position where it is valid to
  // insert the call
  auto insert_before =
      FindInstruction(message_.instruction_to_insert_before(), context);
  if (!insert_before) {
    return false;
  }
  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpFunctionCall,
                                                    insert_before)) {
    return false;
  }

  auto block = context->get_instr_block(insert_before);
  auto enclosing_function = block->GetParent();

  // If the block is not dead, the function must be livesafe
  bool block_is_dead = fact_manager.BlockIsDead(block->id());
  if (!block_is_dead &&
      !fact_manager.FunctionIsLivesafe(message_.callee_id())) {
    return false;
  }

  // The ids must all match and have the right types and satisfy rules on
  // pointers.  If the block is not dead, pointers must be arbitrary.
  for (uint32_t arg_index = 0;
       arg_index < static_cast<uint32_t>(message_.argument_id().size());
       arg_index++) {
    opt::Instruction* arg_inst =
        context->get_def_use_mgr()->GetDef(message_.argument_id(arg_index));
    if (!arg_inst) {
      // The given argument does not correspond to an instruction.
      return false;
    }
    if (!arg_inst->type_id()) {
      // The given argument does not have a type; it is thus not suitable.
    }
    if (arg_inst->type_id() !=
        callee_type_inst->GetSingleWordInOperand(arg_index + 1)) {
      // Argument type mismatch.
      return false;
    }
    opt::Instruction* arg_type_inst =
        context->get_def_use_mgr()->GetDef(arg_inst->type_id());
    if (arg_type_inst->opcode() == SpvOpTypePointer) {
      switch (arg_inst->opcode()) {
        case SpvOpFunctionParameter:
        case SpvOpVariable:
          // These are OK
          break;
        default:
          // Other pointer ids cannot be passed as parameters
          return false;
      }
      if (!block_is_dead &&
          !fact_manager.PointeeValueIsIrrelevant(arg_inst->result_id())) {
        // This is not a dead block, so pointer parameters passed to the called
        // function might really have their contents modified. We thus require
        // such pointers to be to arbitrary-valued variables, which this is not.
        return false;
      }
    }

    // The argument id needs to be available (according to dominance rules) at
    // the point where the call will occur.
    if (!fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before,
                                                    arg_inst->result_id())) {
      return false;
    }
  }

  // Introducing the call must not lead to recursion.
  if (message_.callee_id() == enclosing_function->result_id()) {
    // This would be direct recursion.
    return false;
  }
  // Ensure the call would not lead to indirect recursion.
  return !CallGraph(context)
              .GetIndirectCallees(message_.callee_id())
              .count(block->GetParent()->result_id());
}

void TransformationFunctionCall::Apply(
    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
  // Update the module's bound to reflect the fresh id for the result of the
  // function call.
  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
  // Get the return type of the function being called.
  uint32_t return_type =
      context->get_def_use_mgr()->GetDef(message_.callee_id())->type_id();
  // Populate the operands to the call instruction, with the function id and the
  // arguments.
  opt::Instruction::OperandList operands;
  operands.push_back({SPV_OPERAND_TYPE_ID, {message_.callee_id()}});
  for (auto arg : message_.argument_id()) {
    operands.push_back({SPV_OPERAND_TYPE_ID, {arg}});
  }
  // Insert the function call before the instruction specified in the message.
  FindInstruction(message_.instruction_to_insert_before(), context)
      ->InsertBefore(
          MakeUnique<opt::Instruction>(context, SpvOpFunctionCall, return_type,
                                       message_.fresh_id(), operands));
  // Invalidate all analyses since we have changed the module.
  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
}

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

}  // namespace fuzz
}  // namespace spvtools
