1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Pierre Moreau 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include <string> 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 18fd4e5da5Sopenharmony_ci#include "test/link/linker_fixture.h" 19fd4e5da5Sopenharmony_ci 20fd4e5da5Sopenharmony_cinamespace spvtools { 21fd4e5da5Sopenharmony_cinamespace { 22fd4e5da5Sopenharmony_ci 23fd4e5da5Sopenharmony_ciusing ::testing::HasSubstr; 24fd4e5da5Sopenharmony_ci 25fd4e5da5Sopenharmony_ciclass IdsLimit : public spvtest::LinkerTest { 26fd4e5da5Sopenharmony_ci public: 27fd4e5da5Sopenharmony_ci IdsLimit() { binaries.reserve(2u); } 28fd4e5da5Sopenharmony_ci 29fd4e5da5Sopenharmony_ci void SetUp() override { 30fd4e5da5Sopenharmony_ci const uint32_t id_bound = SPV_LIMIT_RESULT_ID_BOUND - 1u; 31fd4e5da5Sopenharmony_ci const uint32_t constant_count = 32fd4e5da5Sopenharmony_ci id_bound - 33fd4e5da5Sopenharmony_ci 2u; // One ID is used for TypeBool, and (constant_count + 1) < id_bound 34fd4e5da5Sopenharmony_ci 35fd4e5da5Sopenharmony_ci // This is needed, as otherwise the ID bound will get reset to 1 while 36fd4e5da5Sopenharmony_ci // running the RemoveDuplicates pass. 37fd4e5da5Sopenharmony_ci spvtest::Binary common_binary = { 38fd4e5da5Sopenharmony_ci // clang-format off 39fd4e5da5Sopenharmony_ci spv::MagicNumber, 40fd4e5da5Sopenharmony_ci spv::Version, 41fd4e5da5Sopenharmony_ci SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0), 42fd4e5da5Sopenharmony_ci id_bound, // NOTE: Bound 43fd4e5da5Sopenharmony_ci 0u, // NOTE: Schema; reserved 44fd4e5da5Sopenharmony_ci 45fd4e5da5Sopenharmony_ci static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift, 46fd4e5da5Sopenharmony_ci static_cast<uint32_t>(spv::Capability::Shader), 47fd4e5da5Sopenharmony_ci 48fd4e5da5Sopenharmony_ci static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift, 49fd4e5da5Sopenharmony_ci static_cast<uint32_t>(spv::AddressingModel::Logical), 50fd4e5da5Sopenharmony_ci static_cast<uint32_t>(spv::MemoryModel::Simple), 51fd4e5da5Sopenharmony_ci 52fd4e5da5Sopenharmony_ci static_cast<uint32_t>(spv::Op::OpTypeBool) | 2u << spv::WordCountShift, 53fd4e5da5Sopenharmony_ci 1u // NOTE: Result ID 54fd4e5da5Sopenharmony_ci // clang-format on 55fd4e5da5Sopenharmony_ci }; 56fd4e5da5Sopenharmony_ci 57fd4e5da5Sopenharmony_ci binaries.push_back({}); 58fd4e5da5Sopenharmony_ci spvtest::Binary& binary = binaries.back(); 59fd4e5da5Sopenharmony_ci binary.reserve(common_binary.size() + constant_count * 3u); 60fd4e5da5Sopenharmony_ci binary.insert(binary.end(), common_binary.cbegin(), common_binary.cend()); 61fd4e5da5Sopenharmony_ci 62fd4e5da5Sopenharmony_ci for (uint32_t i = 0u; i < constant_count; ++i) { 63fd4e5da5Sopenharmony_ci binary.push_back(static_cast<uint32_t>(spv::Op::OpConstantTrue) | 64fd4e5da5Sopenharmony_ci 3u << spv::WordCountShift); 65fd4e5da5Sopenharmony_ci binary.push_back(1u); // NOTE: Type ID 66fd4e5da5Sopenharmony_ci binary.push_back(2u + i); // NOTE: Result ID 67fd4e5da5Sopenharmony_ci } 68fd4e5da5Sopenharmony_ci } 69fd4e5da5Sopenharmony_ci void TearDown() override { binaries.clear(); } 70fd4e5da5Sopenharmony_ci 71fd4e5da5Sopenharmony_ci spvtest::Binaries binaries; 72fd4e5da5Sopenharmony_ci}; 73fd4e5da5Sopenharmony_ci 74fd4e5da5Sopenharmony_cispvtest::Binary CreateBinary(uint32_t id_bound) { 75fd4e5da5Sopenharmony_ci return { 76fd4e5da5Sopenharmony_ci // clang-format off 77fd4e5da5Sopenharmony_ci // Header 78fd4e5da5Sopenharmony_ci spv::MagicNumber, 79fd4e5da5Sopenharmony_ci spv::Version, 80fd4e5da5Sopenharmony_ci SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0), 81fd4e5da5Sopenharmony_ci id_bound, // NOTE: Bound 82fd4e5da5Sopenharmony_ci 0u, // NOTE: Schema; reserved 83fd4e5da5Sopenharmony_ci 84fd4e5da5Sopenharmony_ci // OpCapability Shader 85fd4e5da5Sopenharmony_ci static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift, 86fd4e5da5Sopenharmony_ci static_cast<uint32_t>(spv::Capability::Shader), 87fd4e5da5Sopenharmony_ci 88fd4e5da5Sopenharmony_ci // OpMemoryModel Logical Simple 89fd4e5da5Sopenharmony_ci static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift, 90fd4e5da5Sopenharmony_ci static_cast<uint32_t>(spv::AddressingModel::Logical), 91fd4e5da5Sopenharmony_ci static_cast<uint32_t>(spv::MemoryModel::Simple) 92fd4e5da5Sopenharmony_ci // clang-format on 93fd4e5da5Sopenharmony_ci }; 94fd4e5da5Sopenharmony_ci} 95fd4e5da5Sopenharmony_ci 96fd4e5da5Sopenharmony_ciTEST_F(IdsLimit, DISABLED_UnderLimit) { 97fd4e5da5Sopenharmony_ci spvtest::Binary linked_binary; 98fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, Link(binaries, &linked_binary)) << GetErrorMessage(); 99fd4e5da5Sopenharmony_ci EXPECT_THAT(GetErrorMessage(), std::string()); 100fd4e5da5Sopenharmony_ci EXPECT_EQ(0x3FFFFFu, linked_binary[3]); 101fd4e5da5Sopenharmony_ci} 102fd4e5da5Sopenharmony_ci 103fd4e5da5Sopenharmony_ciTEST_F(IdsLimit, DISABLED_OverLimit) { 104fd4e5da5Sopenharmony_ci spvtest::Binary& binary = binaries.back(); 105fd4e5da5Sopenharmony_ci 106fd4e5da5Sopenharmony_ci const uint32_t id_bound = binary[3]; 107fd4e5da5Sopenharmony_ci binary[3] = id_bound + 1u; 108fd4e5da5Sopenharmony_ci 109fd4e5da5Sopenharmony_ci binary.push_back(static_cast<uint32_t>(spv::Op::OpConstantFalse) | 110fd4e5da5Sopenharmony_ci 3u << spv::WordCountShift); 111fd4e5da5Sopenharmony_ci binary.push_back(1u); // NOTE: Type ID 112fd4e5da5Sopenharmony_ci binary.push_back(id_bound); // NOTE: Result ID 113fd4e5da5Sopenharmony_ci 114fd4e5da5Sopenharmony_ci spvtest::Binary linked_binary; 115fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, Link(binaries, &linked_binary)) << GetErrorMessage(); 116fd4e5da5Sopenharmony_ci EXPECT_THAT( 117fd4e5da5Sopenharmony_ci GetErrorMessage(), 118fd4e5da5Sopenharmony_ci HasSubstr("The minimum limit of IDs, 4194303, was exceeded: 4194304 is " 119fd4e5da5Sopenharmony_ci "the current ID bound.")); 120fd4e5da5Sopenharmony_ci EXPECT_EQ(0x400000u, linked_binary[3]); 121fd4e5da5Sopenharmony_ci} 122fd4e5da5Sopenharmony_ci 123fd4e5da5Sopenharmony_ciTEST_F(IdsLimit, DISABLED_Overflow) { 124fd4e5da5Sopenharmony_ci spvtest::Binaries binaries = {CreateBinary(0xFFFFFFFFu), 125fd4e5da5Sopenharmony_ci CreateBinary(0x00000002u)}; 126fd4e5da5Sopenharmony_ci 127fd4e5da5Sopenharmony_ci spvtest::Binary linked_binary; 128fd4e5da5Sopenharmony_ci 129fd4e5da5Sopenharmony_ci EXPECT_EQ(SPV_ERROR_INVALID_DATA, Link(binaries, &linked_binary)); 130fd4e5da5Sopenharmony_ci EXPECT_THAT( 131fd4e5da5Sopenharmony_ci GetErrorMessage(), 132fd4e5da5Sopenharmony_ci HasSubstr("Too many IDs (4294967296): combining all modules would " 133fd4e5da5Sopenharmony_ci "overflow the 32-bit word of the SPIR-V header.")); 134fd4e5da5Sopenharmony_ci} 135fd4e5da5Sopenharmony_ci 136fd4e5da5Sopenharmony_ci} // namespace 137fd4e5da5Sopenharmony_ci} // namespace spvtools 138