// Copyright (c) 2018 Google LLC.
// Copyright (c) 2019 NVIDIA Corporation
//
// 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/val/validate.h"

#include "source/opcode.h"
#include "source/spirv_target_env.h"
#include "source/val/instruction.h"
#include "source/val/validate_scopes.h"
#include "source/val/validation_state.h"

namespace spvtools {
namespace val {
namespace {

spv_result_t ValidateUndef(ValidationState_t& _, const Instruction* inst) {
  if (_.IsVoidType(inst->type_id())) {
    return _.diag(SPV_ERROR_INVALID_ID, inst)
           << "Cannot create undefined values with void type";
  }
  if (_.HasCapability(SpvCapabilityShader) &&
      _.ContainsLimitedUseIntOrFloatType(inst->type_id()) &&
      !_.IsPointerType(inst->type_id())) {
    return _.diag(SPV_ERROR_INVALID_ID, inst)
           << "Cannot create undefined values with 8- or 16-bit types";
  }

  return SPV_SUCCESS;
}

spv_result_t ValidateShaderClock(ValidationState_t& _,
                                 const Instruction* inst) {
  const uint32_t scope = inst->GetOperandAs<uint32_t>(2);
  if (auto error = ValidateScope(_, inst, scope)) {
    return error;
  }

  bool is_int32 = false, is_const_int32 = false;
  uint32_t value = 0;
  std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope);
  if (is_const_int32 && value != SpvScopeSubgroup && value != SpvScopeDevice) {
    return _.diag(SPV_ERROR_INVALID_DATA, inst)
           << _.VkErrorID(4652) << "Scope must be Subgroup or Device";
  }

  // Result Type must be a 64 - bit unsigned integer type or
  // a vector of two - components of 32 -
  // bit unsigned integer type
  const uint32_t result_type = inst->type_id();
  if (!(_.IsUnsignedIntScalarType(result_type) &&
        _.GetBitWidth(result_type) == 64) &&
      !(_.IsUnsignedIntVectorType(result_type) &&
        _.GetDimension(result_type) == 2 && _.GetBitWidth(result_type) == 32)) {
    return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Expected Value to be a "
                                                   "vector of two components"
                                                   " of unsigned integer"
                                                   " or 64bit unsigned integer";
  }

  return SPV_SUCCESS;
}

spv_result_t ValidateAssumeTrue(ValidationState_t& _, const Instruction* inst) {
  const auto operand_type_id = _.GetOperandTypeId(inst, 0);
  if (!operand_type_id || !_.IsBoolScalarType(operand_type_id)) {
    return _.diag(SPV_ERROR_INVALID_ID, inst)
           << "Value operand of OpAssumeTrueKHR must be a boolean scalar";
  }
  return SPV_SUCCESS;
}

spv_result_t ValidateExpect(ValidationState_t& _, const Instruction* inst) {
  const auto result_type = inst->type_id();
  if (!_.IsBoolScalarOrVectorType(result_type) &&
      !_.IsIntScalarOrVectorType(result_type)) {
    return _.diag(SPV_ERROR_INVALID_ID, inst)
           << "Result of OpExpectKHR must be a scalar or vector of integer "
              "type or boolean type";
  }

  if (_.GetOperandTypeId(inst, 2) != result_type) {
    return _.diag(SPV_ERROR_INVALID_ID, inst)
           << "Type of Value operand of OpExpectKHR does not match the result "
              "type ";
  }
  if (_.GetOperandTypeId(inst, 3) != result_type) {
    return _.diag(SPV_ERROR_INVALID_ID, inst)
           << "Type of ExpectedValue operand of OpExpectKHR does not match the "
              "result type ";
  }
  return SPV_SUCCESS;
}

}  // namespace

spv_result_t MiscPass(ValidationState_t& _, const Instruction* inst) {
  switch (inst->opcode()) {
    case SpvOpUndef:
      if (auto error = ValidateUndef(_, inst)) return error;
      break;
    default:
      break;
  }
  switch (inst->opcode()) {
    case SpvOpBeginInvocationInterlockEXT:
    case SpvOpEndInvocationInterlockEXT:
      _.function(inst->function()->id())
          ->RegisterExecutionModelLimitation(
              SpvExecutionModelFragment,
              "OpBeginInvocationInterlockEXT/OpEndInvocationInterlockEXT "
              "require Fragment execution model");

      _.function(inst->function()->id())
          ->RegisterLimitation([](const ValidationState_t& state,
                                  const Function* entry_point,
                                  std::string* message) {
            const auto* execution_modes =
                state.GetExecutionModes(entry_point->id());

            auto find_interlock = [](const SpvExecutionMode& mode) {
              switch (mode) {
                case SpvExecutionModePixelInterlockOrderedEXT:
                case SpvExecutionModePixelInterlockUnorderedEXT:
                case SpvExecutionModeSampleInterlockOrderedEXT:
                case SpvExecutionModeSampleInterlockUnorderedEXT:
                case SpvExecutionModeShadingRateInterlockOrderedEXT:
                case SpvExecutionModeShadingRateInterlockUnorderedEXT:
                  return true;
                default:
                  return false;
              }
            };

            bool found = false;
            if (execution_modes) {
              auto i = std::find_if(execution_modes->begin(),
                                    execution_modes->end(), find_interlock);
              found = (i != execution_modes->end());
            }

            if (!found) {
              *message =
                  "OpBeginInvocationInterlockEXT/OpEndInvocationInterlockEXT "
                  "require a fragment shader interlock execution mode.";
              return false;
            }
            return true;
          });
      break;
    case SpvOpDemoteToHelperInvocationEXT:
      _.function(inst->function()->id())
          ->RegisterExecutionModelLimitation(
              SpvExecutionModelFragment,
              "OpDemoteToHelperInvocationEXT requires Fragment execution "
              "model");
      break;
    case SpvOpIsHelperInvocationEXT: {
      const uint32_t result_type = inst->type_id();
      _.function(inst->function()->id())
          ->RegisterExecutionModelLimitation(
              SpvExecutionModelFragment,
              "OpIsHelperInvocationEXT requires Fragment execution model");
      if (!_.IsBoolScalarType(result_type))
        return _.diag(SPV_ERROR_INVALID_DATA, inst)
               << "Expected bool scalar type as Result Type: "
               << spvOpcodeString(inst->opcode());
      break;
    }
    case SpvOpReadClockKHR:
      if (auto error = ValidateShaderClock(_, inst)) {
        return error;
      }
      break;
    case SpvOpAssumeTrueKHR:
      if (auto error = ValidateAssumeTrue(_, inst)) {
        return error;
      }
      break;
    case SpvOpExpectKHR:
      if (auto error = ValidateExpect(_, inst)) {
        return error;
      }
      break;
    default:
      break;
  }

  return SPV_SUCCESS;
}

}  // namespace val
}  // namespace spvtools
