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

namespace spvtools {
namespace fuzz {

opt::Instruction* FindInstruction(
    const protobufs::InstructionDescriptor& instruction_descriptor,
    spvtools::opt::IRContext* context) {
  for (auto& function : *context->module()) {
    for (auto& block : function) {
      bool found_base =
          block.id() == instruction_descriptor.base_instruction_result_id();
      uint32_t num_ignored = 0;
      for (auto& instruction : block) {
        if (instruction.HasResultId() &&
            instruction.result_id() ==
                instruction_descriptor.base_instruction_result_id()) {
          assert(!found_base &&
                 "It should not be possible to find the base instruction "
                 "multiple times.");
          found_base = true;
          assert(num_ignored == 0 &&
                 "The skipped instruction count should only be incremented "
                 "after the instruction base has been found.");
        }
        if (found_base &&
            instruction.opcode() ==
                instruction_descriptor.target_instruction_opcode()) {
          if (num_ignored == instruction_descriptor.num_opcodes_to_ignore()) {
            return &instruction;
          }
          num_ignored++;
        }
      }
      if (found_base) {
        // We found the base instruction, but did not find the target
        // instruction in the same block.
        return nullptr;
      }
    }
  }
  return nullptr;
}

protobufs::InstructionDescriptor MakeInstructionDescriptor(
    uint32_t base_instruction_result_id, SpvOp target_instruction_opcode,
    uint32_t num_opcodes_to_ignore) {
  protobufs::InstructionDescriptor result;
  result.set_base_instruction_result_id(base_instruction_result_id);
  result.set_target_instruction_opcode(target_instruction_opcode);
  result.set_num_opcodes_to_ignore(num_opcodes_to_ignore);
  return result;
}

protobufs::InstructionDescriptor MakeInstructionDescriptor(
    const opt::BasicBlock& block,
    const opt::BasicBlock::const_iterator& inst_it) {
  const SpvOp opcode =
      inst_it->opcode();    // The opcode of the instruction being described.
  uint32_t skip_count = 0;  // The number of these opcodes we have skipped when
  // searching backwards.

  // Consider instructions in the block in reverse order, starting from
  // |inst_it|.
  for (opt::BasicBlock::const_iterator backwards_iterator = inst_it;;
       --backwards_iterator) {
    if (backwards_iterator->HasResultId()) {
      // As soon as we find an instruction with a result id, we can return a
      // descriptor for |inst_it|.
      return MakeInstructionDescriptor(backwards_iterator->result_id(), opcode,
                                       skip_count);
    }
    if (backwards_iterator != inst_it &&
        backwards_iterator->opcode() == opcode) {
      // We are skipping over an instruction with the same opcode as |inst_it|;
      // we increase our skip count to reflect this.
      skip_count++;
    }
    if (backwards_iterator == block.begin()) {
      // We exit the loop when we reach the start of the block, but only after
      // we have processed the first instruction in the block.
      break;
    }
  }
  // We did not find an instruction inside the block with a result id, so we use
  // the block's label's id.
  return MakeInstructionDescriptor(block.id(), opcode, skip_count);
}

protobufs::InstructionDescriptor MakeInstructionDescriptor(
    opt::IRContext* context, opt::Instruction* inst) {
  auto block = context->get_instr_block(inst);
  uint32_t base_instruction_result_id = block->id();
  uint32_t num_opcodes_to_ignore = 0;
  for (auto& inst_in_block : *block) {
    if (inst_in_block.HasResultId()) {
      base_instruction_result_id = inst_in_block.result_id();
      num_opcodes_to_ignore = 0;
    }
    if (&inst_in_block == inst) {
      return MakeInstructionDescriptor(base_instruction_result_id,
                                       inst->opcode(), num_opcodes_to_ignore);
    }
    if (inst_in_block.opcode() == inst->opcode()) {
      num_opcodes_to_ignore++;
    }
  }
  assert(false && "No matching instruction was found.");
  return protobufs::InstructionDescriptor();
}

}  // namespace fuzz
}  // namespace spvtools
