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

#include "source/fuzz/call_graph.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/transformation_add_global_variable.h"
#include "source/fuzz/transformation_add_local_variable.h"
#include "source/fuzz/transformation_function_call.h"

namespace spvtools {
namespace fuzz {

FuzzerPassAddFunctionCalls::FuzzerPassAddFunctionCalls(
    opt::IRContext* ir_context, FactManager* fact_manager,
    FuzzerContext* fuzzer_context,
    protobufs::TransformationSequence* transformations)
    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}

FuzzerPassAddFunctionCalls::~FuzzerPassAddFunctionCalls() = default;

void FuzzerPassAddFunctionCalls::Apply() {
  ForEachInstructionWithInstructionDescriptor(
      [this](opt::Function* function, opt::BasicBlock* block,
             opt::BasicBlock::iterator inst_it,
             const protobufs::InstructionDescriptor& instruction_descriptor)
          -> void {
        // Check whether it is legitimate to insert a function call before the
        // instruction.
        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpFunctionCall,
                                                          inst_it)) {
          return;
        }

        // Randomly decide whether to try inserting a function call here.
        if (!GetFuzzerContext()->ChoosePercentage(
                GetFuzzerContext()->GetChanceOfCallingFunction())) {
          return;
        }

        // Compute the module's call graph - we don't cache it since it may
        // change each time we apply a transformation.  If this proves to be
        // a bottleneck the call graph data structure could be made updatable.
        CallGraph call_graph(GetIRContext());

        // Gather all the non-entry point functions different from this
        // function.  It is important to ignore entry points as a function
        // cannot be an entry point and the target of an OpFunctionCall
        // instruction.  We ignore this function to avoid direct recursion.
        std::vector<opt::Function*> candidate_functions;
        for (auto& other_function : *GetIRContext()->module()) {
          if (&other_function != function &&
              !TransformationFunctionCall::FunctionIsEntryPoint(
                  GetIRContext(), other_function.result_id())) {
            candidate_functions.push_back(&other_function);
          }
        }

        // Choose a function to call, at random, by considering candidate
        // functions until a suitable one is found.
        opt::Function* chosen_function = nullptr;
        while (!candidate_functions.empty()) {
          opt::Function* candidate_function =
              GetFuzzerContext()->RemoveAtRandomIndex(&candidate_functions);
          if (!GetFactManager()->BlockIsDead(block->id()) &&
              !GetFactManager()->FunctionIsLivesafe(
                  candidate_function->result_id())) {
            // Unless in a dead block, only livesafe functions can be invoked
            continue;
          }
          if (call_graph.GetIndirectCallees(candidate_function->result_id())
                  .count(function->result_id())) {
            // Calling this function could lead to indirect recursion
            continue;
          }
          chosen_function = candidate_function;
          break;
        }

        if (!chosen_function) {
          // No suitable function was found to call.  (This can happen, for
          // instance, if the current function is the only function in the
          // module.)
          return;
        }

        ApplyTransformation(TransformationFunctionCall(
            GetFuzzerContext()->GetFreshId(), chosen_function->result_id(),
            ChooseFunctionCallArguments(*chosen_function, function, block,
                                        inst_it),
            instruction_descriptor));
      });
}

std::map<uint32_t, std::vector<opt::Instruction*>>
FuzzerPassAddFunctionCalls::GetAvailableInstructionsSuitableForActualParameters(
    opt::Function* function, opt::BasicBlock* block,
    const opt::BasicBlock::iterator& inst_it) {
  // Find all instructions in scope that could potentially be used as actual
  // parameters.  Weed out unsuitable pointer arguments immediately.
  std::vector<opt::Instruction*> potentially_suitable_instructions =
      FindAvailableInstructions(
          function, block, inst_it,
          [this, block](opt::IRContext* context,
                        opt::Instruction* inst) -> bool {
            if (!inst->HasResultId() || !inst->type_id()) {
              // An instruction needs a result id and type in order
              // to be suitable as an actual parameter.
              return false;
            }
            if (context->get_def_use_mgr()->GetDef(inst->type_id())->opcode() ==
                SpvOpTypePointer) {
              switch (inst->opcode()) {
                case SpvOpFunctionParameter:
                case SpvOpVariable:
                  // Function parameters and variables are the only
                  // kinds of pointer that can be used as actual
                  // parameters.
                  break;
                default:
                  return false;
              }
              if (!GetFactManager()->BlockIsDead(block->id()) &&
                  !GetFactManager()->PointeeValueIsIrrelevant(
                      inst->result_id())) {
                // We can only pass a pointer as an actual parameter
                // if the pointee value for the pointer is irrelevant,
                // or if the block from which we would make the
                // function call is dead.
                return false;
              }
            }
            return true;
          });

  // Group all the instructions that are potentially viable as function actual
  // parameters by their result types.
  std::map<uint32_t, std::vector<opt::Instruction*>> result;
  for (auto inst : potentially_suitable_instructions) {
    if (result.count(inst->type_id()) == 0) {
      // This is the first instruction of this type we have seen, so populate
      // the map with an entry.
      result.insert({inst->type_id(), {}});
    }
    // Add the instruction to the sequence of instructions already associated
    // with this type.
    result.at(inst->type_id()).push_back(inst);
  }
  return result;
}

std::vector<uint32_t> FuzzerPassAddFunctionCalls::ChooseFunctionCallArguments(
    const opt::Function& callee, opt::Function* caller_function,
    opt::BasicBlock* caller_block,
    const opt::BasicBlock::iterator& caller_inst_it) {
  auto type_to_available_instructions =
      GetAvailableInstructionsSuitableForActualParameters(
          caller_function, caller_block, caller_inst_it);

  opt::Instruction* function_type = GetIRContext()->get_def_use_mgr()->GetDef(
      callee.DefInst().GetSingleWordInOperand(1));
  assert(function_type->opcode() == SpvOpTypeFunction &&
         "The function type does not have the expected opcode.");
  std::vector<uint32_t> result;
  for (uint32_t arg_index = 1; arg_index < function_type->NumInOperands();
       arg_index++) {
    auto arg_type_id =
        GetIRContext()
            ->get_def_use_mgr()
            ->GetDef(function_type->GetSingleWordInOperand(arg_index))
            ->result_id();
    if (type_to_available_instructions.count(arg_type_id)) {
      std::vector<opt::Instruction*>& candidate_arguments =
          type_to_available_instructions.at(arg_type_id);
      // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3177) The value
      //  selected here is arbitrary.  We should consider adding this
      //  information as a fact so that the passed parameter could be
      //  transformed/changed.
      result.push_back(candidate_arguments[GetFuzzerContext()->RandomIndex(
                                               candidate_arguments)]
                           ->result_id());
    } else {
      // We don't have a suitable id in scope to pass, so we must make
      // something up.
      auto type_instruction =
          GetIRContext()->get_def_use_mgr()->GetDef(arg_type_id);

      if (type_instruction->opcode() == SpvOpTypePointer) {
        // In the case of a pointer, we make a new variable, at function
        // or global scope depending on the storage class of the
        // pointer.

        // Get a fresh id for the new variable.
        uint32_t fresh_variable_id = GetFuzzerContext()->GetFreshId();

        // The id of this variable is what we pass as the parameter to
        // the call.
        result.push_back(fresh_variable_id);

        // Now bring the variable into existence.
        if (type_instruction->GetSingleWordInOperand(0) ==
            SpvStorageClassFunction) {
          // Add a new zero-initialized local variable to the current
          // function, noting that its pointee value is irrelevant.
          ApplyTransformation(TransformationAddLocalVariable(
              fresh_variable_id, arg_type_id, caller_function->result_id(),
              FindOrCreateZeroConstant(
                  type_instruction->GetSingleWordInOperand(1)),
              true));
        } else {
          assert(type_instruction->GetSingleWordInOperand(0) ==
                     SpvStorageClassPrivate &&
                 "Only Function and Private storage classes are "
                 "supported at present.");
          // Add a new zero-initialized global variable to the module,
          // noting that its pointee value is irrelevant.
          ApplyTransformation(TransformationAddGlobalVariable(
              fresh_variable_id, arg_type_id,
              FindOrCreateZeroConstant(
                  type_instruction->GetSingleWordInOperand(1)),
              true));
        }
      } else {
        // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3177): We use
        //  constant zero for the parameter, but could consider adding a fact
        //  to allow further passes to obfuscate it.
        result.push_back(FindOrCreateZeroConstant(arg_type_id));
      }
    }
  }
  return result;
}

}  // namespace fuzz
}  // namespace spvtools
