// Copyright (c) 2015-2016 The Khronos Group Inc.
//
// 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 <unordered_set>
#include <vector>

#include "source/instruction.h"
#include "source/opcode.h"
#include "source/operand.h"
#include "source/val/function.h"
#include "source/val/validate.h"
#include "source/val/validation_state.h"
#include "spirv-tools/libspirv.h"

namespace spvtools {
namespace val {

spv_result_t UpdateIdUse(ValidationState_t& _, const Instruction* inst) {
  for (auto& operand : inst->operands()) {
    const spv_operand_type_t& type = operand.type;
    const uint32_t operand_id = inst->word(operand.offset);
    if (spvIsIdType(type) && type != SPV_OPERAND_TYPE_RESULT_ID) {
      if (auto def = _.FindDef(operand_id))
        def->RegisterUse(inst, operand.offset);
    }
  }

  return SPV_SUCCESS;
}

/// This function checks all ID definitions dominate their use in the CFG.
///
/// This function will iterate over all ID definitions that are defined in the
/// functions of a module and make sure that the definitions appear in a
/// block that dominates their use.
///
/// NOTE: This function does NOT check module scoped functions which are
/// checked during the initial binary parse in the IdPass below
spv_result_t CheckIdDefinitionDominateUse(ValidationState_t& _) {
  std::vector<const Instruction*> phi_instructions;
  std::unordered_set<uint32_t> phi_ids;
  for (const auto& inst : _.ordered_instructions()) {
    if (inst.id() == 0) continue;
    if (const Function* func = inst.function()) {
      if (const BasicBlock* block = inst.block()) {
        // If the Id is defined within a block then make sure all references to
        // that Id appear in a blocks that are dominated by the defining block
        for (auto& use_index_pair : inst.uses()) {
          const Instruction* use = use_index_pair.first;
          if (const BasicBlock* use_block = use->block()) {
            if (use_block->reachable() == false) continue;
            if (use->opcode() == spv::Op::OpPhi) {
              if (phi_ids.insert(use->id()).second) {
                phi_instructions.push_back(use);
              }
            } else if (!block->dominates(*use->block())) {
              return _.diag(SPV_ERROR_INVALID_ID, use_block->label())
                     << "ID " << _.getIdName(inst.id()) << " defined in block "
                     << _.getIdName(block->id())
                     << " does not dominate its use in block "
                     << _.getIdName(use_block->id());
            }
          }
        }
      } else {
        // If the Ids defined within a function but not in a block(i.e. function
        // parameters, block ids), then make sure all references to that Id
        // appear within the same function
        for (auto use : inst.uses()) {
          const Instruction* user = use.first;
          if (user->function() && user->function() != func) {
            return _.diag(SPV_ERROR_INVALID_ID, _.FindDef(func->id()))
                   << "ID " << _.getIdName(inst.id()) << " used in function "
                   << _.getIdName(user->function()->id())
                   << " is used outside of it's defining function "
                   << _.getIdName(func->id());
          }
        }
      }
    }
    // NOTE: Ids defined outside of functions must appear before they are used
    // This check is being performed in the IdPass function
  }

  // Check all OpPhi parent blocks are dominated by the variable's defining
  // blocks
  for (const Instruction* phi : phi_instructions) {
    if (phi->block()->reachable() == false) continue;
    for (size_t i = 3; i < phi->operands().size(); i += 2) {
      const Instruction* variable = _.FindDef(phi->word(i));
      const BasicBlock* parent =
          phi->function()->GetBlock(phi->word(i + 1)).first;
      if (variable->block() && parent->reachable() &&
          !variable->block()->dominates(*parent)) {
        return _.diag(SPV_ERROR_INVALID_ID, phi)
               << "In OpPhi instruction " << _.getIdName(phi->id()) << ", ID "
               << _.getIdName(variable->id())
               << " definition does not dominate its parent "
               << _.getIdName(parent->id());
      }
    }
  }

  return SPV_SUCCESS;
}

bool InstructionCanHaveTypeOperand(const Instruction* inst) {
  static std::unordered_set<spv::Op> instruction_allow_set{
      spv::Op::OpSizeOf,
      spv::Op::OpCooperativeMatrixLengthNV,
      spv::Op::OpCooperativeMatrixLengthKHR,
      spv::Op::OpUntypedArrayLengthKHR,
      spv::Op::OpFunction,
      spv::Op::OpAsmINTEL,
      spv::Op::OpConstantSizeOfEXT,
      spv::Op::OpBufferPointerEXT,
      spv::Op::OpUntypedImageTexelPointerEXT,
      spv::Op::OpAbortKHR,
  };
  const auto opcode = inst->opcode();
  bool type_instruction = spvOpcodeGeneratesType(opcode);
  bool debug_instruction = spvOpcodeIsDebug(opcode) || inst->IsDebugInfo();
  bool coop_matrix_spec_constant_op_length =
      (opcode == spv::Op::OpSpecConstantOp) &&
      (spv::Op(inst->word(3)) == spv::Op::OpCooperativeMatrixLengthNV ||
       spv::Op(inst->word(3)) == spv::Op::OpCooperativeMatrixLengthKHR);
  return type_instruction || debug_instruction || inst->IsNonSemantic() ||
         spvOpcodeIsDecoration(opcode) || instruction_allow_set.count(opcode) ||
         spvOpcodeGeneratesUntypedPointer(opcode) ||
         coop_matrix_spec_constant_op_length;
}

bool InstructionRequiresTypeOperand(const Instruction* inst) {
  static std::unordered_set<spv::Op> instruction_deny_set{
      spv::Op::OpExtInst,
      spv::Op::OpExtInstWithForwardRefsKHR,
      spv::Op::OpExtInstImport,
      spv::Op::OpSelectionMerge,
      spv::Op::OpLoopMerge,
      spv::Op::OpFunction,
      spv::Op::OpSizeOf,
      spv::Op::OpCooperativeMatrixLengthNV,
      spv::Op::OpCooperativeMatrixLengthKHR,
      spv::Op::OpPhi,
      spv::Op::OpUntypedArrayLengthKHR,
      spv::Op::OpAsmINTEL,
      spv::Op::OpAliasScopeDeclINTEL,
      spv::Op::OpAliasScopeListDeclINTEL,
      spv::Op::OpAbortKHR,
  };
  const auto opcode = inst->opcode();
  bool debug_instruction = spvOpcodeIsDebug(opcode) || inst->IsDebugInfo();
  bool coop_matrix_spec_constant_op_length =
      opcode == spv::Op::OpSpecConstantOp &&
      (spv::Op(inst->word(3)) == spv::Op::OpCooperativeMatrixLengthNV ||
       spv::Op(inst->word(3)) == spv::Op::OpCooperativeMatrixLengthKHR);

  return !debug_instruction && !inst->IsNonSemantic() &&
         !spvOpcodeIsDecoration(opcode) && !spvOpcodeIsBranch(opcode) &&
         !instruction_deny_set.count(opcode) &&
         !spvOpcodeGeneratesUntypedPointer(opcode) &&
         !coop_matrix_spec_constant_op_length;
}

// Performs SSA validation on the IDs of an instruction. The
// can_have_forward_declared_ids  functor should return true if the
// instruction operand's ID can be forward referenced.
spv_result_t IdPass(ValidationState_t& _, Instruction* inst) {
  auto can_have_forward_declared_ids =
      spvIsExtendedInstruction(inst->opcode()) &&
              spvExtInstIsDebugInfo(inst->ext_inst_type())
          ? spvDbgInfoExtOperandCanBeForwardDeclaredFunction(
                inst->opcode(), inst->ext_inst_type(), inst->word(4))
          : spvOperandCanBeForwardDeclaredFunction(inst->opcode());

  // Keep track of a result id defined by this instruction.  0 means it
  // does not define an id.
  uint32_t result_id = 0;
  bool has_forward_declared_ids = false;

  for (unsigned i = 0; i < inst->operands().size(); i++) {
    const spv_parsed_operand_t& operand = inst->operand(i);
    const spv_operand_type_t& type = operand.type;
    // We only care about Id operands, which are a single word.
    const uint32_t operand_word = inst->word(operand.offset);

    auto ret = SPV_ERROR_INTERNAL;
    switch (type) {
      case SPV_OPERAND_TYPE_RESULT_ID:
        // NOTE: Multiple Id definitions are being checked by the binary parser.
        //
        // Defer undefined-forward-reference removal until after we've analyzed
        // the remaining operands to this instruction.  Deferral only matters
        // for OpPhi since it's the only case where it defines its own forward
        // reference.  Other instructions that can have forward references
        // either don't define a value or the forward reference is to a function
        // Id (and hence defined outside of a function body).
        result_id = operand_word;
        // NOTE: The result Id is added (in RegisterInstruction) *after* all of
        // the other Ids have been checked to avoid premature use in the same
        // instruction.
        ret = SPV_SUCCESS;
        break;
      case SPV_OPERAND_TYPE_ID:
      case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
      case SPV_OPERAND_TYPE_SCOPE_ID:
        if (const auto def = _.FindDef(operand_word)) {
          if (spvOpcodeGeneratesType(def->opcode()) &&
              !InstructionCanHaveTypeOperand(inst)) {
            return _.diag(SPV_ERROR_INVALID_ID, inst)
                   << "Operand " << _.getIdName(operand_word)
                   << " cannot be a type";
          } else if (def->type_id() == 0 &&
                     !spvOpcodeGeneratesType(def->opcode()) &&
                     InstructionRequiresTypeOperand(inst) &&
                     InstructionRequiresTypeOperand(def)) {
            return _.diag(SPV_ERROR_INVALID_ID, inst)
                   << "Operand " << _.getIdName(operand_word)
                   << " requires a type";
          } else if (def->IsNonSemantic() && !inst->IsNonSemantic()) {
            return _.diag(SPV_ERROR_INVALID_ID, inst)
                   << "Operand " << _.getIdName(operand_word)
                   << " in semantic instruction cannot be a non-semantic "
                      "instruction";
          } else {
            ret = SPV_SUCCESS;
          }
        } else if (can_have_forward_declared_ids(i)) {
          has_forward_declared_ids = true;
          if (spvOpcodeGeneratesType(inst->opcode()) &&
              !_.IsForwardPointer(operand_word)) {
            ret = _.diag(SPV_ERROR_INVALID_ID, inst)
                  << "Operand " << _.getIdName(operand_word)
                  << " requires a previous definition";
          } else {
            ret = _.ForwardDeclareId(operand_word);
          }
        } else {
          ret = _.diag(SPV_ERROR_INVALID_ID, inst)
                << "ID " << _.getIdName(operand_word)
                << " has not been defined";
        }
        break;
      case SPV_OPERAND_TYPE_TYPE_ID:
        if (_.IsDefinedId(operand_word)) {
          auto* def = _.FindDef(operand_word);
          if (!spvOpcodeGeneratesType(def->opcode())) {
            ret = _.diag(SPV_ERROR_INVALID_ID, inst)
                  << "ID " << _.getIdName(operand_word) << " is not a type id";
          } else {
            ret = SPV_SUCCESS;
          }
        } else {
          ret = _.diag(SPV_ERROR_INVALID_ID, inst)
                << "ID " << _.getIdName(operand_word)
                << " has not been defined";
        }
        break;
      case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
        // Ideally, this check would live in validate_extensions.cpp. But since
        // forward references are only allowed on non-semantic instructions, and
        // ID validation is done first, we would fail with a "ID had not been
        // defined" error before we could give a more helpful message. For this
        // reason, this test is done here, so we can be more helpful to the
        // user.
        if (inst->opcode() == spv::Op::OpExtInstWithForwardRefsKHR &&
            !inst->IsNonSemantic())
          return _.diag(SPV_ERROR_INVALID_DATA, inst)
                 << "OpExtInstWithForwardRefsKHR is only allowed with "
                    "non-semantic instructions.";
        ret = SPV_SUCCESS;
        break;
      default:
        ret = SPV_SUCCESS;
        break;
    }
    if (SPV_SUCCESS != ret) return ret;
  }
  const bool must_have_forward_declared_ids =
      inst->opcode() == spv::Op::OpExtInstWithForwardRefsKHR;
  if (must_have_forward_declared_ids && !has_forward_declared_ids) {
    return _.diag(SPV_ERROR_INVALID_ID, inst)
           << "Opcode OpExtInstWithForwardRefsKHR must have at least one "
              "forward "
              "declared ID.";
  }

  if (result_id) _.RemoveIfForwardDeclared(result_id);

  return SPV_SUCCESS;
}

}  // namespace val
}  // namespace spvtools
