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

#include "source/fuzz/instruction_descriptor.h"
#include "source/fuzz/transformation_set_memory_operands_mask.h"

namespace spvtools {
namespace fuzz {

FuzzerPassAdjustMemoryOperandsMasks::FuzzerPassAdjustMemoryOperandsMasks(
    opt::IRContext* ir_context, FactManager* fact_manager,
    FuzzerContext* fuzzer_context,
    protobufs::TransformationSequence* transformations)
    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}

FuzzerPassAdjustMemoryOperandsMasks::~FuzzerPassAdjustMemoryOperandsMasks() =
    default;

void FuzzerPassAdjustMemoryOperandsMasks::Apply() {
  // Consider every block in every function.
  for (auto& function : *GetIRContext()->module()) {
    for (auto& block : function) {
      // Consider every instruction in this block, using an explicit iterator so
      // that when we find an instruction of interest we can search backwards to
      // create an id descriptor for it.
      for (auto inst_it = block.cbegin(); inst_it != block.cend(); ++inst_it) {
        if (!TransformationSetMemoryOperandsMask::IsMemoryAccess(*inst_it)) {
          // We are only interested in memory access instructions.
          continue;
        }

        std::vector<uint32_t> indices_of_available_masks_to_adjust;
        // All memory instructions have at least one memory operands mask.
        indices_of_available_masks_to_adjust.push_back(0);
        // From SPIR-V 1.4 onwards, OpCopyMemory and OpCopyMemorySized have a
        // second mask.
        switch (inst_it->opcode()) {
          case SpvOpCopyMemory:
          case SpvOpCopyMemorySized:
            if (TransformationSetMemoryOperandsMask::
                    MultipleMemoryOperandMasksAreSupported(GetIRContext())) {
              indices_of_available_masks_to_adjust.push_back(1);
            }
            break;
          default:
            break;
        }

        // Consider the available masks
        for (auto mask_index : indices_of_available_masks_to_adjust) {
          // Randomly decide whether to adjust this mask.
          if (!GetFuzzerContext()->ChoosePercentage(
                  GetFuzzerContext()
                      ->GetChanceOfAdjustingMemoryOperandsMask())) {
            continue;
          }
          // Get the existing mask, using None if there was no mask present at
          // all.
          auto existing_mask_in_operand_index =
              TransformationSetMemoryOperandsMask::GetInOperandIndexForMask(
                  *inst_it, mask_index);
          auto existing_mask =
              existing_mask_in_operand_index < inst_it->NumInOperands()
                  ? inst_it->GetSingleWordOperand(
                        existing_mask_in_operand_index)
                  : static_cast<uint32_t>(SpvMemoryAccessMaskNone);

          // There are two things we can do to a mask:
          // - add Volatile if not already present
          // - toggle Nontemporal
          // The following ensures that we do at least one of these
          bool add_volatile = !(existing_mask & SpvMemoryAccessVolatileMask) &&
                              GetFuzzerContext()->ChooseEven();
          bool toggle_nontemporal =
              !add_volatile || GetFuzzerContext()->ChooseEven();

          // These bitwise operations use '|' to add Volatile if desired, and
          // '^' to toggle Nontemporal if desired.
          uint32_t new_mask =
              (existing_mask | (add_volatile ? SpvMemoryAccessVolatileMask
                                             : SpvMemoryAccessMaskNone)) ^
              (toggle_nontemporal ? SpvMemoryAccessNontemporalMask
                                  : SpvMemoryAccessMaskNone);

          TransformationSetMemoryOperandsMask transformation(
              MakeInstructionDescriptor(block, inst_it), new_mask, mask_index);
          assert(
              transformation.IsApplicable(GetIRContext(), *GetFactManager()) &&
              "Transformation should be applicable by construction.");
          transformation.Apply(GetIRContext(), GetFactManager());
          *GetTransformations()->add_transformation() =
              transformation.ToMessage();
        }
      }
    }
  }
}

}  // namespace fuzz
}  // namespace spvtools
