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 
20 namespace spvtools {
21 namespace {
22 
23 using ::testing::HasSubstr;
24 
25 class EntryPointsAmountTest : public spvtest::LinkerTest {
26  public:
EntryPointsAmountTest()27   EntryPointsAmountTest() { binaries.reserve(0xFFFF); }
28 
SetUp()29   void SetUp() override {
30     binaries.push_back({SpvMagicNumber,
31                         SpvVersion,
32                         SPV_GENERATOR_CODEPLAY,
33                         10u,  // NOTE: Bound
34                         0u,   // NOTE: Schema; reserved
35 
36                         3u << SpvWordCountShift | SpvOpTypeFloat,
37                         1u,   // NOTE: Result ID
38                         32u,  // NOTE: Width
39 
40                         4u << SpvWordCountShift | SpvOpTypePointer,
41                         2u,  // NOTE: Result ID
42                         SpvStorageClassInput,
43                         1u,  // NOTE: Type ID
44 
45                         2u << SpvWordCountShift | SpvOpTypeVoid,
46                         3u,  // NOTE: Result ID
47 
48                         3u << SpvWordCountShift | SpvOpTypeFunction,
49                         4u,  // NOTE: Result ID
50                         3u,  // NOTE: Return type
51 
52                         5u << SpvWordCountShift | SpvOpFunction,
53                         3u,  // NOTE: Result type
54                         5u,  // NOTE: Result ID
55                         SpvFunctionControlMaskNone,
56                         4u,  // NOTE: Function type
57 
58                         2u << SpvWordCountShift | SpvOpLabel,
59                         6u,  // NOTE: Result ID
60 
61                         4u << SpvWordCountShift | SpvOpVariable,
62                         2u,  // NOTE: Type ID
63                         7u,  // NOTE: Result ID
64                         SpvStorageClassFunction,
65 
66                         4u << SpvWordCountShift | SpvOpVariable,
67                         2u,  // NOTE: Type ID
68                         8u,  // NOTE: Result ID
69                         SpvStorageClassFunction,
70 
71                         4u << SpvWordCountShift | SpvOpVariable,
72                         2u,  // NOTE: Type ID
73                         9u,  // NOTE: Result ID
74                         SpvStorageClassFunction,
75 
76                         1u << SpvWordCountShift | SpvOpReturn,
77 
78                         1u << SpvWordCountShift | SpvOpFunctionEnd});
79     for (size_t i = 0u; i < 2u; ++i) {
80       spvtest::Binary binary = {
81           SpvMagicNumber,
82           SpvVersion,
83           SPV_GENERATOR_CODEPLAY,
84           103u,  // NOTE: Bound
85           0u,    // NOTE: Schema; reserved
86 
87           3u << SpvWordCountShift | SpvOpTypeFloat,
88           1u,   // NOTE: Result ID
89           32u,  // NOTE: Width
90 
91           4u << SpvWordCountShift | SpvOpTypePointer,
92           2u,  // NOTE: Result ID
93           SpvStorageClassInput,
94           1u  // NOTE: Type ID
95       };
96 
97       for (uint32_t j = 0u; j < 0xFFFFu / 2u; ++j) {
98         binary.push_back(4u << SpvWordCountShift | SpvOpVariable);
99         binary.push_back(2u);      // NOTE: Type ID
100         binary.push_back(j + 3u);  // NOTE: Result ID
101         binary.push_back(SpvStorageClassInput);
102       }
103       binaries.push_back(binary);
104     }
105   }
TearDown()106   void TearDown() override { binaries.clear(); }
107 
108   spvtest::Binaries binaries;
109 };
110 
TEST_F(EntryPointsAmountTest,UnderLimit)111 TEST_F(EntryPointsAmountTest, UnderLimit) {
112   spvtest::Binary linked_binary;
113 
114   EXPECT_EQ(SPV_SUCCESS, Link(binaries, &linked_binary));
115   EXPECT_THAT(GetErrorMessage(), std::string());
116 }
117 
TEST_F(EntryPointsAmountTest,OverLimit)118 TEST_F(EntryPointsAmountTest, OverLimit) {
119   binaries.push_back({SpvMagicNumber,
120                       SpvVersion,
121                       SPV_GENERATOR_CODEPLAY,
122                       5u,  // NOTE: Bound
123                       0u,  // NOTE: Schema; reserved
124 
125                       3u << SpvWordCountShift | SpvOpTypeFloat,
126                       1u,   // NOTE: Result ID
127                       32u,  // NOTE: Width
128 
129                       4u << SpvWordCountShift | SpvOpTypePointer,
130                       2u,  // NOTE: Result ID
131                       SpvStorageClassInput,
132                       1u,  // NOTE: Type ID
133 
134                       4u << SpvWordCountShift | SpvOpVariable,
135                       2u,  // NOTE: Type ID
136                       3u,  // NOTE: Result ID
137                       SpvStorageClassInput,
138 
139                       4u << SpvWordCountShift | SpvOpVariable,
140                       2u,  // NOTE: Type ID
141                       4u,  // NOTE: Result ID
142                       SpvStorageClassInput});
143 
144   spvtest::Binary linked_binary;
145 
146   EXPECT_EQ(SPV_ERROR_INTERNAL, Link(binaries, &linked_binary));
147   EXPECT_THAT(GetErrorMessage(),
148               HasSubstr("The limit of global values, 65535, was exceeded; "
149                         "65536 global values were found."));
150 }
151 
152 }  // namespace
153 }  // namespace spvtools
154