// Copyright (c) 2020 Vasyl Teliman
//
// 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 <utility>

#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/transformation_add_spec_constant_op.h"

namespace spvtools {
namespace fuzz {

TransformationAddSpecConstantOp::TransformationAddSpecConstantOp(
    spvtools::fuzz::protobufs::TransformationAddSpecConstantOp message)
    : message_(std::move(message)) {}

TransformationAddSpecConstantOp::TransformationAddSpecConstantOp(
    uint32_t fresh_id, uint32_t type_id, SpvOp opcode,
    const opt::Instruction::OperandList& operands) {
  message_.set_fresh_id(fresh_id);
  message_.set_type_id(type_id);
  message_.set_opcode(opcode);
  for (const auto& operand : operands) {
    auto* op = message_.add_operand();
    op->set_operand_type(operand.type);
    for (auto word : operand.words) {
      op->add_operand_data(word);
    }
  }
}

bool TransformationAddSpecConstantOp::IsApplicable(
    opt::IRContext* ir_context,
    const TransformationContext& transformation_context) const {
  auto clone = fuzzerutil::CloneIRContext(ir_context);
  ApplyImpl(clone.get());
  return fuzzerutil::IsValid(clone.get(),
                             transformation_context.GetValidatorOptions());
}

void TransformationAddSpecConstantOp::Apply(
    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
  ApplyImpl(ir_context);
  ir_context->InvalidateAnalysesExceptFor(
      opt::IRContext::Analysis::kAnalysisNone);
}

void TransformationAddSpecConstantOp::ApplyImpl(
    opt::IRContext* ir_context) const {
  opt::Instruction::OperandList operands = {
      {SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER, {message_.opcode()}}};

  for (const auto& operand : message_.operand()) {
    std::vector<uint32_t> words(operand.operand_data().begin(),
                                operand.operand_data().end());
    operands.push_back({static_cast<spv_operand_type_t>(operand.operand_type()),
                        std::move(words)});
  }

  ir_context->AddGlobalValue(MakeUnique<opt::Instruction>(
      ir_context, SpvOpSpecConstantOp, message_.type_id(), message_.fresh_id(),
      std::move(operands)));

  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
}

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

}  // namespace fuzz
}  // namespace spvtools
