// Copyright (c) 2018 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 <memory>

#include "gtest/gtest.h"
#include "source/opt/build_module.h"
#include "source/opt/constants.h"
#include "source/opt/ir_context.h"

namespace spvtools {
namespace opt {
namespace analysis {
namespace {

using ConstantManagerTest = ::testing::Test;

TEST_F(ConstantManagerTest, GetDefiningInstruction) {
  const std::string text = R"(
%int = OpTypeInt 32 0
%1 = OpTypeStruct %int
%2 = OpTypeStruct %int
  )";

  std::unique_ptr<IRContext> context =
      BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text,
                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  ASSERT_NE(context, nullptr);

  Type* struct_type_1 = context->get_type_mgr()->GetType(1);
  StructConstant struct_const_1(struct_type_1->AsStruct());
  Instruction* const_inst_1 =
      context->get_constant_mgr()->GetDefiningInstruction(&struct_const_1, 1);
  EXPECT_EQ(const_inst_1->type_id(), 1);

  Type* struct_type_2 = context->get_type_mgr()->GetType(2);
  StructConstant struct_const_2(struct_type_2->AsStruct());
  Instruction* const_inst_2 =
      context->get_constant_mgr()->GetDefiningInstruction(&struct_const_2, 2);
  EXPECT_EQ(const_inst_2->type_id(), 2);
}

TEST_F(ConstantManagerTest, GetDefiningInstruction2) {
  const std::string text = R"(
%int = OpTypeInt 32 0
%1 = OpTypeStruct %int
%2 = OpTypeStruct %int
%3 = OpConstantNull %1
%4 = OpConstantNull %2
  )";

  std::unique_ptr<IRContext> context =
      BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text,
                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  ASSERT_NE(context, nullptr);

  Type* struct_type_1 = context->get_type_mgr()->GetType(1);
  NullConstant struct_const_1(struct_type_1->AsStruct());
  Instruction* const_inst_1 =
      context->get_constant_mgr()->GetDefiningInstruction(&struct_const_1, 1);
  EXPECT_EQ(const_inst_1->type_id(), 1);
  EXPECT_EQ(const_inst_1->result_id(), 3);

  Type* struct_type_2 = context->get_type_mgr()->GetType(2);
  NullConstant struct_const_2(struct_type_2->AsStruct());
  Instruction* const_inst_2 =
      context->get_constant_mgr()->GetDefiningInstruction(&struct_const_2, 2);
  EXPECT_EQ(const_inst_2->type_id(), 2);
  EXPECT_EQ(const_inst_2->result_id(), 4);
}

TEST_F(ConstantManagerTest, GetDefiningInstructionIdOverflow) {
  const std::string text = R"(
%1 = OpTypeInt 32 0
%3 = OpConstant %1 1
%4 = OpConstant %1 2
  )";

  std::unique_ptr<IRContext> context =
      BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text,
                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  ASSERT_NE(context, nullptr);

  // Set the id bound to the max, so the new constant cannot be generated.
  context->module()->SetIdBound(context->max_id_bound());

  Type* int_type = context->get_type_mgr()->GetType(1);
  IntConstant int_constant(int_type->AsInteger(), {3});
  Instruction* inst =
      context->get_constant_mgr()->GetDefiningInstruction(&int_constant, 1);
  EXPECT_EQ(inst, nullptr);
}

TEST_F(ConstantManagerTest, ConstantCompositeReplicateExtMapping) {
  const std::string text = R"(
OpCapability Shader
OpCapability ReplicatedCompositesEXT
OpExtension "SPV_EXT_replicated_composites"
OpMemoryModel Logical Simple
%1 = OpTypeInt 32 1
%2 = OpTypeVector %1 4
%3 = OpConstant %1 0
%4 = OpConstantCompositeReplicateEXT %2 %3
%5 = OpSpecConstantCompositeReplicateEXT %2 %3
  )";

  std::unique_ptr<IRContext> context =
      BuildModule(SPV_ENV_UNIVERSAL_1_5, nullptr, text,
                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  ASSERT_NE(context, nullptr);

  ConstantManager* const_mgr = context->get_constant_mgr();
  const Constant* base_constant = const_mgr->FindDeclaredConstant(3);
  ASSERT_NE(base_constant, nullptr);

  const Constant* composite_constant = const_mgr->FindDeclaredConstant(4);
  ASSERT_NE(composite_constant, nullptr);
  const Vector* vector_type = composite_constant->type()->AsVector();
  ASSERT_NE(vector_type, nullptr);

  const CompositeConstant* composite =
      composite_constant->AsCompositeConstant();
  ASSERT_NE(composite, nullptr);
  ASSERT_EQ(composite->GetComponents().size(),
            static_cast<size_t>(vector_type->element_count()));
  ASSERT_FALSE(composite->GetComponents().empty());
  for (const Constant* component : composite->GetComponents()) {
    EXPECT_EQ(component, base_constant);
  }

  const Constant* spec_composite_constant = const_mgr->FindDeclaredConstant(5);
  ASSERT_NE(spec_composite_constant, nullptr);
  const Vector* spec_vector_type = spec_composite_constant->type()->AsVector();
  ASSERT_NE(spec_vector_type, nullptr);

  const CompositeConstant* spec_composite =
      spec_composite_constant->AsCompositeConstant();
  ASSERT_NE(spec_composite, nullptr);
  ASSERT_EQ(spec_composite->GetComponents().size(),
            static_cast<size_t>(spec_vector_type->element_count()));
  ASSERT_FALSE(spec_composite->GetComponents().empty());
  for (const Constant* component : spec_composite->GetComponents()) {
    EXPECT_EQ(component, base_constant);
  }
}

}  // namespace
}  // namespace analysis
}  // namespace opt
}  // namespace spvtools
