// Copyright (c) 2020 Stefano Milizia
// 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_interchange_zero_like_constants.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 {
FuzzerPassInterchangeZeroLikeConstants::FuzzerPassInterchangeZeroLikeConstants(
    opt::IRContext* ir_context, TransformationContext* transformation_context,
    FuzzerContext* fuzzer_context,
    protobufs::TransformationSequence* transformations)
    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
                 transformations) {}

FuzzerPassInterchangeZeroLikeConstants::
    ~FuzzerPassInterchangeZeroLikeConstants() = default;

uint32_t FuzzerPassInterchangeZeroLikeConstants::FindOrCreateToggledConstant(
    opt::Instruction* declaration) {
  auto constant = GetIRContext()->get_constant_mgr()->FindDeclaredConstant(
      declaration->result_id());

  // This pass only toggles zero-like constants
  if (!constant->IsZero()) {
    return 0;
  }

  if (constant->AsScalarConstant()) {
    return FindOrCreateNullConstant(declaration->type_id());
  } else if (constant->AsNullConstant()) {
    // Add declaration of equivalent scalar constant
    auto kind = constant->type()->kind();
    if (kind == opt::analysis::Type::kBool ||
        kind == opt::analysis::Type::kInteger ||
        kind == opt::analysis::Type::kFloat) {
      return FindOrCreateZeroConstant(declaration->type_id(), false);
    }
  }

  return 0;
}

void FuzzerPassInterchangeZeroLikeConstants::MaybeAddUseToReplace(
    opt::Instruction* use_inst, uint32_t use_index, uint32_t replacement_id,
    std::vector<std::pair<protobufs::IdUseDescriptor, uint32_t>>*
        uses_to_replace) {
  // Only consider this use if it is in a block
  if (!GetIRContext()->get_instr_block(use_inst)) {
    return;
  }

  // Get the index of the operand restricted to input operands.
  uint32_t in_operand_index =
      fuzzerutil::InOperandIndexFromOperandIndex(*use_inst, use_index);
  auto id_use_descriptor =
      MakeIdUseDescriptorFromUse(GetIRContext(), use_inst, in_operand_index);
  uses_to_replace->emplace_back(
      std::make_pair(id_use_descriptor, replacement_id));
}

void FuzzerPassInterchangeZeroLikeConstants::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();
    if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
            constant_id)) {
      continue;
    }

    uint32_t toggled_id = FindOrCreateToggledConstant(constant);
    if (!toggled_id) {
      // Not a zero-like 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()
                      ->GetChanceOfInterchangingZeroLikeConstants())) {
            MaybeAddUseToReplace(use_inst, use_index, toggled_id,
                                 &uses_to_replace);
          }
        });
  }

  // Replace the ids
  for (auto use_to_replace : uses_to_replace) {
    MaybeApplyTransformation(TransformationReplaceIdWithSynonym(
        use_to_replace.first, use_to_replace.second));
  }
}
}  // namespace fuzz
}  // namespace spvtools