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

#include "source/fuzz/instruction_message.h"
#include "source/fuzz/replayer.h"
#include "source/fuzz/transformation_add_function.h"
#include "source/opt/build_module.h"
#include "source/opt/ir_context.h"
#include "source/reduce/reducer.h"

namespace spvtools {
namespace fuzz {

AddedFunctionReducer::AddedFunctionReducer(
    spv_target_env target_env, MessageConsumer consumer,
    const std::vector<uint32_t>& binary_in,
    const protobufs::FactSequence& initial_facts,
    const protobufs::TransformationSequence& transformation_sequence_in,
    uint32_t index_of_add_function_transformation,
    const Shrinker::InterestingnessFunction& shrinker_interestingness_function,
    bool validate_during_replay, spv_validator_options validator_options,
    uint32_t shrinker_step_limit, uint32_t num_existing_shrink_attempts)
    : target_env_(target_env),
      consumer_(std::move(consumer)),
      binary_in_(binary_in),
      initial_facts_(initial_facts),
      transformation_sequence_in_(transformation_sequence_in),
      index_of_add_function_transformation_(
          index_of_add_function_transformation),
      shrinker_interestingness_function_(shrinker_interestingness_function),
      validate_during_replay_(validate_during_replay),
      validator_options_(validator_options),
      shrinker_step_limit_(shrinker_step_limit),
      num_existing_shrink_attempts_(num_existing_shrink_attempts),
      num_reducer_interestingness_function_invocations_(0) {}

AddedFunctionReducer::~AddedFunctionReducer() = default;

AddedFunctionReducer::AddedFunctionReducerResult AddedFunctionReducer::Run() {
  // Replay all transformations before the AddFunction transformation, then
  // add the raw function associated with the AddFunction transformation.
  std::vector<uint32_t> binary_to_reduce;
  std::unordered_set<uint32_t> irrelevant_pointee_global_variables;
  ReplayPrefixAndAddFunction(&binary_to_reduce,
                             &irrelevant_pointee_global_variables);

  // Set up spirv-reduce to use our very specific interestingness function.
  reduce::Reducer reducer(target_env_);
  reducer.SetMessageConsumer(consumer_);
  reducer.AddDefaultReductionPasses();
  reducer.SetInterestingnessFunction(
      [this, &irrelevant_pointee_global_variables](
          const std::vector<uint32_t>& binary_under_reduction,
          uint32_t /*unused*/) {
        return InterestingnessFunctionForReducingAddedFunction(
            binary_under_reduction, irrelevant_pointee_global_variables);
      });

  // Instruct spirv-reduce to only target the function with the id associated
  // with the AddFunction transformation that we care about.
  spvtools::ReducerOptions reducer_options;
  reducer_options.set_target_function(GetAddedFunctionId());
  // Bound the number of reduction steps that spirv-reduce can make according
  // to the overall shrinker step limit and the number of shrink attempts that
  // have already been tried.
  assert(shrinker_step_limit_ > num_existing_shrink_attempts_ &&
         "The added function reducer should not have been invoked.");
  reducer_options.set_step_limit(shrinker_step_limit_ -
                                 num_existing_shrink_attempts_);

  // Run spirv-reduce.
  std::vector<uint32_t> reduced_binary;
  auto reducer_result =
      reducer.Run(std::move(binary_to_reduce), &reduced_binary, reducer_options,
                  validator_options_);
  if (reducer_result != reduce::Reducer::kComplete &&
      reducer_result != reduce::Reducer::kReachedStepLimit) {
    return {AddedFunctionReducerResultStatus::kReductionFailed,
            std::vector<uint32_t>(), protobufs::TransformationSequence(), 0};
  }

  // Provide the outer shrinker with an adapted sequence of transformations in
  // which the AddFunction transformation of interest has been simplified to use
  // the version of the added function that appears in |reduced_binary|.
  std::vector<uint32_t> binary_out;
  protobufs::TransformationSequence transformation_sequence_out;
  ReplayAdaptedTransformations(reduced_binary, &binary_out,
                               &transformation_sequence_out);
  // We subtract 1 from |num_reducer_interestingness_function_invocations_| to
  // account for the fact that spirv-reduce invokes its interestingness test
  // once before reduction commences in order to check that the initial module
  // is interesting.
  assert(num_reducer_interestingness_function_invocations_ > 0 &&
         "At a minimum spirv-reduce should have invoked its interestingness "
         "test once.");
  return {AddedFunctionReducerResultStatus::kComplete, std::move(binary_out),
          std::move(transformation_sequence_out),
          num_reducer_interestingness_function_invocations_ - 1};
}

bool AddedFunctionReducer::InterestingnessFunctionForReducingAddedFunction(
    const std::vector<uint32_t>& binary_under_reduction,
    const std::unordered_set<uint32_t>& irrelevant_pointee_global_variables) {
  uint32_t counter_for_shrinker_interestingness_function =
      num_existing_shrink_attempts_ +
      num_reducer_interestingness_function_invocations_;
  num_reducer_interestingness_function_invocations_++;

  // The reduced version of the added function must be limited to accessing
  // global variables appearing in |irrelevant_pointee_global_variables|.  This
  // is to guard against the possibility of spirv-reduce changing a reference
  // to an irrelevant global to a reference to a regular global variable, which
  // could cause the added function to change the semantics of the original
  // module.
  auto ir_context =
      BuildModule(target_env_, consumer_, binary_under_reduction.data(),
                  binary_under_reduction.size());
  assert(ir_context != nullptr && "The binary should be parsable.");
  for (auto& type_or_value : ir_context->module()->types_values()) {
    if (type_or_value.opcode() != SpvOpVariable) {
      continue;
    }
    if (irrelevant_pointee_global_variables.count(type_or_value.result_id())) {
      continue;
    }
    if (!ir_context->get_def_use_mgr()->WhileEachUse(
            &type_or_value,
            [this, &ir_context](opt::Instruction* user,
                                uint32_t /*unused*/) -> bool {
              auto block = ir_context->get_instr_block(user);
              if (block != nullptr &&
                  block->GetParent()->result_id() == GetAddedFunctionId()) {
                return false;
              }
              return true;
            })) {
      return false;
    }
  }

  // For the binary to be deemed interesting, it must be possible to
  // successfully apply all the transformations, with the transformation at
  // index |index_of_add_function_transformation_| simplified to use the version
  // of the added function from |binary_under_reduction|.
  //
  // This might not be the case: spirv-reduce might have removed a chunk of the
  // added function on which future transformations depend.
  //
  // This is an optimization: the assumption is that having already shrunk the
  // transformation sequence down to minimal form, all transformations have a
  // role to play, and it's almost certainly a waste of time to invoke the
  // shrinker's interestingness function if we have eliminated transformations
  // that the shrinker previously tried to -- but could not -- eliminate.
  std::vector<uint32_t> binary_out;
  protobufs::TransformationSequence modified_transformations;
  ReplayAdaptedTransformations(binary_under_reduction, &binary_out,
                               &modified_transformations);
  if (transformation_sequence_in_.transformation_size() !=
      modified_transformations.transformation_size()) {
    return false;
  }

  // The resulting binary must be deemed interesting according to the shrinker's
  // interestingness function.
  return shrinker_interestingness_function_(
      binary_out, counter_for_shrinker_interestingness_function);
}

void AddedFunctionReducer::ReplayPrefixAndAddFunction(
    std::vector<uint32_t>* binary_out,
    std::unordered_set<uint32_t>* irrelevant_pointee_global_variables) const {
  assert(transformation_sequence_in_
             .transformation(index_of_add_function_transformation_)
             .has_add_function() &&
         "A TransformationAddFunction is required at the given index.");

  auto replay_result = Replayer(target_env_, consumer_, binary_in_,
                                initial_facts_, transformation_sequence_in_,
                                index_of_add_function_transformation_,
                                validate_during_replay_, validator_options_)
                           .Run();
  assert(replay_result.status == Replayer::ReplayerResultStatus::kComplete &&
         "Replay should succeed");
  assert(static_cast<uint32_t>(
             replay_result.applied_transformations.transformation_size()) ==
             index_of_add_function_transformation_ &&
         "All requested transformations should have applied.");

  auto* ir_context = replay_result.transformed_module.get();

  for (auto& type_or_value : ir_context->module()->types_values()) {
    if (type_or_value.opcode() != SpvOpVariable) {
      continue;
    }
    if (replay_result.transformation_context->GetFactManager()
            ->PointeeValueIsIrrelevant(type_or_value.result_id())) {
      irrelevant_pointee_global_variables->insert(type_or_value.result_id());
    }
  }

  // Add the function associated with the transformation at
  // |index_of_add_function_transformation| to the module.  By construction this
  // should succeed.
  const protobufs::TransformationAddFunction&
      transformation_add_function_message =
          transformation_sequence_in_
              .transformation(index_of_add_function_transformation_)
              .add_function();
  bool success = TransformationAddFunction(transformation_add_function_message)
                     .TryToAddFunction(ir_context);
  (void)success;  // Keep release mode compilers happy.
  assert(success && "Addition of the function should have succeeded.");

  // Get the binary representation of the module with this function added.
  ir_context->module()->ToBinary(binary_out, false);
}

void AddedFunctionReducer::ReplayAdaptedTransformations(
    const std::vector<uint32_t>& binary_under_reduction,
    std::vector<uint32_t>* binary_out,
    protobufs::TransformationSequence* transformation_sequence_out) const {
  assert(index_of_add_function_transformation_ <
             static_cast<uint32_t>(
                 transformation_sequence_in_.transformation_size()) &&
         "The relevant add function transformation must be present.");
  std::unique_ptr<opt::IRContext> ir_context_under_reduction =
      BuildModule(target_env_, consumer_, binary_under_reduction.data(),
                  binary_under_reduction.size());
  assert(ir_context_under_reduction && "Error building module.");

  protobufs::TransformationSequence modified_transformations;
  for (uint32_t i = 0;
       i <
       static_cast<uint32_t>(transformation_sequence_in_.transformation_size());
       i++) {
    if (i == index_of_add_function_transformation_) {
      protobufs::TransformationAddFunction modified_add_function =
          transformation_sequence_in_
              .transformation(index_of_add_function_transformation_)
              .add_function();
      assert(GetAddedFunctionId() ==
                 modified_add_function.instruction(0).result_id() &&
             "Unexpected result id for added function.");
      modified_add_function.clear_instruction();
      for (auto& function : *ir_context_under_reduction->module()) {
        if (function.result_id() != GetAddedFunctionId()) {
          continue;
        }
        function.ForEachInst(
            [&modified_add_function](const opt::Instruction* instruction) {
              *modified_add_function.add_instruction() =
                  MakeInstructionMessage(instruction);
            });
      }
      assert(modified_add_function.instruction_size() > 0 &&
             "Some instructions for the added function should remain.");
      *modified_transformations.add_transformation()->mutable_add_function() =
          modified_add_function;
    } else {
      *modified_transformations.add_transformation() =
          transformation_sequence_in_.transformation(i);
    }
  }
  assert(
      transformation_sequence_in_.transformation_size() ==
          modified_transformations.transformation_size() &&
      "The original and modified transformations should have the same size.");
  auto replay_result = Replayer(target_env_, consumer_, binary_in_,
                                initial_facts_, modified_transformations,
                                modified_transformations.transformation_size(),
                                validate_during_replay_, validator_options_)
                           .Run();
  assert(replay_result.status == Replayer::ReplayerResultStatus::kComplete &&
         "Replay should succeed.");
  replay_result.transformed_module->module()->ToBinary(binary_out, false);
  *transformation_sequence_out =
      std::move(replay_result.applied_transformations);
}

uint32_t AddedFunctionReducer::GetAddedFunctionId() const {
  return transformation_sequence_in_
      .transformation(index_of_add_function_transformation_)
      .add_function()
      .instruction(0)
      .result_id();
}

}  // namespace fuzz
}  // namespace spvtools
