// Copyright (c) 2019 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/replayer.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "source/fuzz/counter_overflow_id_source.h"
#include "source/fuzz/fact_manager/fact_manager.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation.h"
#include "source/fuzz/transformation_context.h"
#include "source/opt/build_module.h"
#include "source/util/make_unique.h"

namespace spvtools {
namespace fuzz {

Replayer::Replayer(
    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 num_transformations_to_apply, bool validate_during_replay,
    spv_validator_options validator_options)
    : target_env_(target_env),
      consumer_(std::move(consumer)),
      binary_in_(binary_in),
      initial_facts_(initial_facts),
      transformation_sequence_in_(transformation_sequence_in),
      num_transformations_to_apply_(num_transformations_to_apply),
      validate_during_replay_(validate_during_replay),
      validator_options_(validator_options) {}

Replayer::~Replayer() = default;

Replayer::ReplayerResult Replayer::Run() {
  // Check compatibility between the library version being linked with and the
  // header files being used.
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  if (num_transformations_to_apply_ >
      static_cast<uint32_t>(
          transformation_sequence_in_.transformation_size())) {
    consumer_(SPV_MSG_ERROR, nullptr, {},
              "The number of transformations to be replayed must not "
              "exceed the size of the transformation sequence.");
    return {Replayer::ReplayerResultStatus::kTooManyTransformationsRequested,
            nullptr, nullptr, protobufs::TransformationSequence()};
  }

  spvtools::SpirvTools tools(target_env_);
  if (!tools.IsValid()) {
    consumer_(SPV_MSG_ERROR, nullptr, {},
              "Failed to create SPIRV-Tools interface; stopping.");
    return {Replayer::ReplayerResultStatus::kFailedToCreateSpirvToolsInterface,
            nullptr, nullptr, protobufs::TransformationSequence()};
  }

  // Initial binary should be valid.
  if (!tools.Validate(&binary_in_[0], binary_in_.size(), validator_options_)) {
    consumer_(SPV_MSG_INFO, nullptr, {},
              "Initial binary is invalid; stopping.");
    return {Replayer::ReplayerResultStatus::kInitialBinaryInvalid, nullptr,
            nullptr, protobufs::TransformationSequence()};
  }

  // Build the module from the input binary.
  std::unique_ptr<opt::IRContext> ir_context =
      BuildModule(target_env_, consumer_, binary_in_.data(), binary_in_.size());
  assert(ir_context);

  // For replay validation, we track the last valid SPIR-V binary that was
  // observed. Initially this is the input binary.
  std::vector<uint32_t> last_valid_binary;
  if (validate_during_replay_) {
    last_valid_binary = binary_in_;
  }

  // We find the smallest id that is (a) not in use by the original module, and
  // (b) not used by any transformation in the sequence to be replayed.  This
  // serves as a starting id from which to issue overflow ids if they are
  // required during replay.
  uint32_t first_overflow_id = ir_context->module()->id_bound();
  for (auto& transformation : transformation_sequence_in_.transformation()) {
    auto fresh_ids = Transformation::FromMessage(transformation)->GetFreshIds();
    if (!fresh_ids.empty()) {
      first_overflow_id =
          std::max(first_overflow_id,
                   *std::max_element(fresh_ids.begin(), fresh_ids.end()));
    }
  }

  std::unique_ptr<TransformationContext> transformation_context =
      MakeUnique<TransformationContext>(
          MakeUnique<FactManager>(ir_context.get()), validator_options_,
          MakeUnique<CounterOverflowIdSource>(first_overflow_id));
  transformation_context->GetFactManager()->AddInitialFacts(consumer_,
                                                            initial_facts_);

  // We track the largest id bound observed, to ensure that it only increases
  // as transformations are applied.
  uint32_t max_observed_id_bound = ir_context->module()->id_bound();
  (void)(max_observed_id_bound);  // Keep release-mode compilers happy.

  protobufs::TransformationSequence transformation_sequence_out;

  // Consider the transformation proto messages in turn.
  uint32_t counter = 0;
  for (auto& message : transformation_sequence_in_.transformation()) {
    if (counter >= num_transformations_to_apply_) {
      break;
    }
    counter++;

    auto transformation = Transformation::FromMessage(message);

    // Check whether the transformation can be applied.
    if (transformation->IsApplicable(ir_context.get(),
                                     *transformation_context)) {
      // The transformation is applicable, so apply it, and copy it to the
      // sequence of transformations that were applied.
      transformation->Apply(ir_context.get(), transformation_context.get());
      *transformation_sequence_out.add_transformation() = message;

      assert(ir_context->module()->id_bound() >= max_observed_id_bound &&
             "The module's id bound should only increase due to applying "
             "transformations.");
      max_observed_id_bound = ir_context->module()->id_bound();

      if (validate_during_replay_) {
        std::vector<uint32_t> binary_to_validate;
        ir_context->module()->ToBinary(&binary_to_validate, false);

        // Check whether the latest transformation led to a valid binary.
        if (!tools.Validate(&binary_to_validate[0], binary_to_validate.size(),
                            validator_options_)) {
          consumer_(SPV_MSG_INFO, nullptr, {},
                    "Binary became invalid during replay (set a "
                    "breakpoint to inspect); stopping.");
          return {Replayer::ReplayerResultStatus::kReplayValidationFailure,
                  nullptr, nullptr, protobufs::TransformationSequence()};
        }

        // The binary was valid, so it becomes the latest valid binary.
        last_valid_binary = std::move(binary_to_validate);
      }
    }
  }

  return {Replayer::ReplayerResultStatus::kComplete, std::move(ir_context),
          std::move(transformation_context),
          std::move(transformation_sequence_out)};
}

}  // namespace fuzz
}  // namespace spvtools
