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

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

namespace spvtools {
namespace fuzz {

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

FuzzerPassAddStores::~FuzzerPassAddStores() = default;

void FuzzerPassAddStores::Apply() {
  MaybeAddTransformationBeforeEachInstruction(
      [this](opt::Function* function, opt::BasicBlock* block,
             opt::BasicBlock::iterator inst_it,
             const protobufs::InstructionDescriptor& instruction_descriptor)
          -> void {
        assert(inst_it->opcode() ==
                   instruction_descriptor.target_instruction_opcode() &&
               "The opcode of the instruction we might insert before must be "
               "the same as the opcode in the descriptor for the instruction");

        // Check whether it is legitimate to insert a store before this
        // instruction.
        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore,
                                                          inst_it)) {
          return;
        }

        // Randomly decide whether to try inserting a store here.
        if (!GetFuzzerContext()->ChoosePercentage(
                GetFuzzerContext()->GetChanceOfAddingStore())) {
          return;
        }

        // Look for pointers we might consider storing to.
        std::vector<opt::Instruction*> relevant_pointers =
            FindAvailableInstructions(
                function, block, inst_it,
                [this, block](opt::IRContext* context,
                              opt::Instruction* instruction) -> bool {
                  if (!instruction->result_id() || !instruction->type_id()) {
                    return false;
                  }
                  auto type_inst = context->get_def_use_mgr()->GetDef(
                      instruction->type_id());
                  if (type_inst->opcode() != SpvOpTypePointer) {
                    // Not a pointer.
                    return false;
                  }
                  if (type_inst->GetSingleWordInOperand(0) ==
                      SpvStorageClassInput) {
                    // Read-only: cannot store to it.
                    return false;
                  }
                  switch (instruction->result_id()) {
                    case SpvOpConstantNull:
                    case SpvOpUndef:
                      // Do not allow storing to a null or undefined pointer;
                      // this might be OK if the block is dead, but for now we
                      // conservatively avoid it.
                      return false;
                    default:
                      break;
                  }
                  return GetFactManager()->BlockIsDead(block->id()) ||
                         GetFactManager()->PointeeValueIsIrrelevant(
                             instruction->result_id());
                });

        // At this point, |relevant_pointers| contains all the pointers we might
        // think of storing to.
        if (relevant_pointers.empty()) {
          return;
        }

        auto pointer = relevant_pointers[GetFuzzerContext()->RandomIndex(
            relevant_pointers)];

        std::vector<opt::Instruction*> relevant_values =
            FindAvailableInstructions(
                function, block, inst_it,
                [pointer](opt::IRContext* context,
                          opt::Instruction* instruction) -> bool {
                  if (!instruction->result_id() || !instruction->type_id()) {
                    return false;
                  }
                  return instruction->type_id() ==
                         context->get_def_use_mgr()
                             ->GetDef(pointer->type_id())
                             ->GetSingleWordInOperand(1);
                });

        if (relevant_values.empty()) {
          return;
        }

        // Choose a value at random, and create and apply a storing
        // transformation based on it and the pointer.
        ApplyTransformation(TransformationStore(
            pointer->result_id(),
            relevant_values[GetFuzzerContext()->RandomIndex(relevant_values)]
                ->result_id(),
            instruction_descriptor));
      });
}

}  // namespace fuzz
}  // namespace spvtools
