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

#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/id_use_descriptor.h"
#include "source/fuzz/transformation_record_synonymous_constants.h"
#include "source/fuzz/transformation_replace_id_with_synonym.h"

namespace spvtools {
namespace fuzz {

FuzzerPassInterchangeSignednessOfIntegerOperands::
    FuzzerPassInterchangeSignednessOfIntegerOperands(
        opt::IRContext* ir_context,
        TransformationContext* transformation_context,
        FuzzerContext* fuzzer_context,
        protobufs::TransformationSequence* transformations)
    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
                 transformations) {}

FuzzerPassInterchangeSignednessOfIntegerOperands::
    ~FuzzerPassInterchangeSignednessOfIntegerOperands() = default;

void FuzzerPassInterchangeSignednessOfIntegerOperands::Apply() {
  // Make vector keeping track of all the uses we want to replace.
  // This is a vector of pairs, where the first element is an id use descriptor
  // identifying the use of a constant id and the second is the id that should
  // be used to replace it.
  std::vector<std::pair<protobufs::IdUseDescriptor, uint32_t>> uses_to_replace;

  for (auto constant : GetIRContext()->GetConstants()) {
    uint32_t constant_id = constant->result_id();

    // We want to record the synonymity of an integer constant with another
    // constant with opposite signedness, and this can only be done if they are
    // not irrelevant.
    if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
            constant_id)) {
      continue;
    }

    uint32_t toggled_id =
        FindOrCreateToggledIntegerConstant(constant->result_id());
    if (!toggled_id) {
      // Not an integer constant
      continue;
    }

    assert(!GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
               toggled_id) &&
           "FindOrCreateToggledConstant can't produce an irrelevant id");

    // Record synonymous constants
    ApplyTransformation(
        TransformationRecordSynonymousConstants(constant_id, toggled_id));

    // Find all the uses of the constant and, for each, probabilistically
    // decide whether to replace it.
    GetIRContext()->get_def_use_mgr()->ForEachUse(
        constant_id,
        [this, toggled_id, &uses_to_replace](opt::Instruction* use_inst,
                                             uint32_t use_index) -> void {
          if (GetFuzzerContext()->ChoosePercentage(
                  GetFuzzerContext()
                      ->GetChanceOfInterchangingSignednessOfIntegerOperands())) {
            MaybeAddUseToReplace(use_inst, use_index, toggled_id,
                                 &uses_to_replace);
          }
        });
  }

  // Replace the ids if it is allowed.
  for (auto use_to_replace : uses_to_replace) {
    MaybeApplyTransformation(TransformationReplaceIdWithSynonym(
        use_to_replace.first, use_to_replace.second));
  }
}

uint32_t FuzzerPassInterchangeSignednessOfIntegerOperands::
    FindOrCreateToggledIntegerConstant(uint32_t id) {
  auto constant = GetIRContext()->get_constant_mgr()->FindDeclaredConstant(id);

  // This pass only toggles integer constants.
  if (!constant->AsIntConstant() &&
      (!constant->AsVectorConstant() ||
       !constant->AsVectorConstant()->component_type()->AsInteger())) {
    return 0;
  }

  if (auto integer = constant->AsIntConstant()) {
    auto type = integer->type()->AsInteger();

    // Find or create and return the toggled constant.
    return FindOrCreateIntegerConstant(std::vector<uint32_t>(integer->words()),
                                       type->width(), !type->IsSigned(), false);
  }

  // The constant is an integer vector.

  // Find the component type.
  auto component_type =
      constant->AsVectorConstant()->component_type()->AsInteger();

  // Find or create the toggled component type.
  uint32_t toggled_component_type = FindOrCreateIntegerType(
      component_type->width(), !component_type->IsSigned());

  // Get the information about the toggled components. We need to extract this
  // information now because the analyses might be invalidated, which would make
  // the constant and component_type variables invalid.
  std::vector<std::vector<uint32_t>> component_words;

  for (auto component : constant->AsVectorConstant()->GetComponents()) {
    component_words.push_back(component->AsIntConstant()->words());
  }
  uint32_t width = component_type->width();
  bool is_signed = !component_type->IsSigned();

  std::vector<uint32_t> toggled_components;

  // Find or create the toggled components.
  for (auto words : component_words) {
    toggled_components.push_back(
        FindOrCreateIntegerConstant(words, width, is_signed, false));
  }

  // Find or create the required toggled vector type.
  uint32_t toggled_type = FindOrCreateVectorType(
      toggled_component_type, (uint32_t)toggled_components.size());

  // Find or create and return the toggled vector constant.
  return FindOrCreateCompositeConstant(toggled_components, toggled_type, false);
}

}  // namespace fuzz
}  // namespace spvtools
