1// Copyright (c) 2017 Pierre Moreau 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include <string> 16 17#include "gmock/gmock.h" 18#include "test/link/linker_fixture.h" 19 20namespace spvtools { 21namespace { 22 23using ::testing::HasSubstr; 24 25const uint32_t binary_count = 2u; 26 27class EntryPointsAmountTest : public spvtest::LinkerTest { 28 public: 29 EntryPointsAmountTest() { binaries.reserve(binary_count + 1u); } 30 31 void SetUp() override { 32 const uint32_t global_variable_count_per_binary = 33 (SPV_LIMIT_GLOBAL_VARIABLES_MAX - 1u) / binary_count; 34 35 spvtest::Binary common_binary = { 36 // clang-format off 37 static_cast<uint32_t>(spv::MagicNumber), 38 static_cast<uint32_t>(spv::Version), 39 SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0), 40 3u + global_variable_count_per_binary, // NOTE: Bound 41 0u, // NOTE: Schema; reserved 42 43 static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift, 44 static_cast<uint32_t>(spv::Capability::Shader), 45 46 static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift, 47 static_cast<uint32_t>(spv::AddressingModel::Logical), 48 static_cast<uint32_t>(spv::MemoryModel::Simple), 49 50 static_cast<uint32_t>(spv::Op::OpTypeFloat) | 3u << spv::WordCountShift, 51 1u, // NOTE: Result ID 52 32u, // NOTE: Width 53 54 static_cast<uint32_t>(spv::Op::OpTypePointer) | 4u << spv::WordCountShift, 55 2u, // NOTE: Result ID 56 static_cast<uint32_t>(spv::StorageClass::Input), 57 1u // NOTE: Type ID 58 // clang-format on 59 }; 60 61 binaries.push_back({}); 62 spvtest::Binary& binary = binaries.back(); 63 binary.reserve(common_binary.size() + global_variable_count_per_binary * 4); 64 binary.insert(binary.end(), common_binary.cbegin(), common_binary.cend()); 65 66 for (uint32_t i = 0u; i < global_variable_count_per_binary; ++i) { 67 binary.push_back(static_cast<uint32_t>(spv::Op::OpVariable) | 68 4u << spv::WordCountShift); 69 binary.push_back(2u); // NOTE: Type ID 70 binary.push_back(3u + i); // NOTE: Result ID 71 binary.push_back(static_cast<uint32_t>(spv::StorageClass::Input)); 72 } 73 74 for (uint32_t i = 0u; i < binary_count - 1u; ++i) { 75 binaries.push_back(binaries.back()); 76 } 77 } 78 void TearDown() override { binaries.clear(); } 79 80 spvtest::Binaries binaries; 81}; 82 83TEST_F(EntryPointsAmountTest, UnderLimit) { 84 spvtest::Binary linked_binary; 85 86 ASSERT_EQ(SPV_SUCCESS, Link(binaries, &linked_binary)) << GetErrorMessage(); 87 EXPECT_THAT(GetErrorMessage(), std::string()); 88} 89 90TEST_F(EntryPointsAmountTest, OverLimit) { 91 binaries.push_back({ 92 // clang-format off 93 static_cast<uint32_t>(spv::MagicNumber), 94 static_cast<uint32_t>(spv::Version), 95 SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0), 96 5u, // NOTE: Bound 97 0u, // NOTE: Schema; reserved 98 99 static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift, 100 static_cast<uint32_t>(spv::Capability::Shader), 101 102 static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift, 103 static_cast<uint32_t>(spv::AddressingModel::Logical), 104 static_cast<uint32_t>(spv::MemoryModel::Simple), 105 106 static_cast<uint32_t>(spv::Op::OpTypeFloat) | 3u << spv::WordCountShift, 107 1u, // NOTE: Result ID 108 32u, // NOTE: Width 109 110 static_cast<uint32_t>(spv::Op::OpTypePointer) | 4u << spv::WordCountShift, 111 2u, // NOTE: Result ID 112 static_cast<uint32_t>(spv::StorageClass::Input), 113 1u, // NOTE: Type ID 114 115 static_cast<uint32_t>(spv::Op::OpVariable) | 4u << spv::WordCountShift, 116 2u, // NOTE: Type ID 117 3u, // NOTE: Result ID 118 static_cast<uint32_t>(spv::StorageClass::Input), 119 120 static_cast<uint32_t>(spv::Op::OpVariable) | 4u << spv::WordCountShift, 121 2u, // NOTE: Type ID 122 4u, // NOTE: Result ID 123 static_cast<uint32_t>(spv::StorageClass::Input) 124 // clang-format on 125 }); 126 127 spvtest::Binary linked_binary; 128 ASSERT_EQ(SPV_SUCCESS, Link(binaries, &linked_binary)) << GetErrorMessage(); 129 EXPECT_THAT( 130 GetErrorMessage(), 131 HasSubstr("The minimum limit of global values, 65535, was exceeded; " 132 "65536 global values were found.")); 133} 134 135} // namespace 136} // namespace spvtools 137