• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2015-2016 The Khronos Group Inc.
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 <vector>
16 
17 #include "gmock/gmock.h"
18 #include "source/operand.h"
19 #include "test/unit_spirv.h"
20 
21 namespace spvtools {
22 namespace {
23 
24 using ::testing::Eq;
25 
TEST(OperandPattern,InitiallyEmpty)26 TEST(OperandPattern, InitiallyEmpty) {
27   spv_operand_pattern_t empty;
28   EXPECT_THAT(empty, Eq(spv_operand_pattern_t{}));
29   EXPECT_EQ(0u, empty.size());
30   EXPECT_TRUE(empty.empty());
31 }
32 
TEST(OperandPattern,PushBacksAreOnTheRight)33 TEST(OperandPattern, PushBacksAreOnTheRight) {
34   spv_operand_pattern_t pattern;
35 
36   pattern.push_back(SPV_OPERAND_TYPE_ID);
37   EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID}));
38   EXPECT_EQ(1u, pattern.size());
39   EXPECT_TRUE(!pattern.empty());
40   EXPECT_EQ(SPV_OPERAND_TYPE_ID, pattern.back());
41 
42   pattern.push_back(SPV_OPERAND_TYPE_NONE);
43   EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID,
44                                                 SPV_OPERAND_TYPE_NONE}));
45   EXPECT_EQ(2u, pattern.size());
46   EXPECT_TRUE(!pattern.empty());
47   EXPECT_EQ(SPV_OPERAND_TYPE_NONE, pattern.back());
48 }
49 
TEST(OperandPattern,PopBacksAreOnTheRight)50 TEST(OperandPattern, PopBacksAreOnTheRight) {
51   spv_operand_pattern_t pattern{SPV_OPERAND_TYPE_ID,
52                                 SPV_OPERAND_TYPE_LITERAL_INTEGER};
53 
54   pattern.pop_back();
55   EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID}));
56 
57   pattern.pop_back();
58   EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{}));
59 }
60 
61 // A test case for typed mask expansion
62 struct MaskExpansionCase {
63   spv_operand_type_t type;
64   uint32_t mask;
65   spv_operand_pattern_t initial;
66   spv_operand_pattern_t expected;
67 };
68 
69 using MaskExpansionTest = ::testing::TestWithParam<MaskExpansionCase>;
70 
TEST_P(MaskExpansionTest,Sample)71 TEST_P(MaskExpansionTest, Sample) {
72   spv_operand_table operandTable = nullptr;
73   auto env = SPV_ENV_UNIVERSAL_1_0;
74   ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable, env));
75 
76   spv_operand_pattern_t pattern(GetParam().initial);
77   spvPushOperandTypesForMask(env, operandTable, GetParam().type,
78                              GetParam().mask, &pattern);
79   EXPECT_THAT(pattern, Eq(GetParam().expected));
80 }
81 
82 // These macros let us write non-trivial examples without too much text.
83 #define PREFIX0 SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE
84 #define PREFIX1                                                         \
85   SPV_OPERAND_TYPE_STORAGE_CLASS, SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE, \
86       SPV_OPERAND_TYPE_ID
87 INSTANTIATE_TEST_SUITE_P(
88     OperandPattern, MaskExpansionTest,
89     ::testing::ValuesIn(std::vector<MaskExpansionCase>{
90         // No bits means no change.
91         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, 0, {PREFIX0}, {PREFIX0}},
92         // Unknown bits means no change.  Use all bits that aren't in the
93         // grammar.
94         // The used mask bits are:
95         //          1 through...
96         //       0x20 SpvMemoryAccessNonPrivatePointerMask
97         // also
98         //    0x10000 SpvMemoryAccessAliasScopeINTELMaskShift
99         //    0x20000 SpvMemoryAccessNoAliasINTELMaskMask
100         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
101          0xffffffc0 ^ (0x10000) ^ (0x20000),
102          {PREFIX1},
103          {PREFIX1}},
104         // Volatile has no operands.
105         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
106          uint32_t(spv::MemoryAccessMask::Volatile),
107          {PREFIX0},
108          {PREFIX0}},
109         // Aligned has one literal number operand.
110         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
111          uint32_t(spv::MemoryAccessMask::Aligned),
112          {PREFIX1},
113          {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}},
114         // Volatile with Aligned still has just one literal number operand.
115         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
116          uint32_t(spv::MemoryAccessMask::Volatile |
117                   spv::MemoryAccessMask::Aligned),
118          {PREFIX1},
119          {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}},
120         // Newer masks are not tested
121     }));
122 #undef PREFIX0
123 #undef PREFIX1
124 
125 // Returns a vector of all operand types that can be used in a pattern.
allOperandTypes()126 std::vector<spv_operand_type_t> allOperandTypes() {
127   std::vector<spv_operand_type_t> result;
128   for (int i = 0; i < SPV_OPERAND_TYPE_NUM_OPERAND_TYPES; i++) {
129     result.push_back(spv_operand_type_t(i));
130   }
131   return result;
132 }
133 
134 using MatchableOperandExpansionTest =
135     ::testing::TestWithParam<spv_operand_type_t>;
136 
TEST_P(MatchableOperandExpansionTest,MatchableOperandsDontExpand)137 TEST_P(MatchableOperandExpansionTest, MatchableOperandsDontExpand) {
138   const spv_operand_type_t type = GetParam();
139   if (!spvOperandIsVariable(type)) {
140     spv_operand_pattern_t pattern;
141     const bool did_expand = spvExpandOperandSequenceOnce(type, &pattern);
142     EXPECT_FALSE(did_expand);
143     EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{}));
144   }
145 }
146 
147 INSTANTIATE_TEST_SUITE_P(MatchableOperandExpansion,
148                          MatchableOperandExpansionTest,
149                          ::testing::ValuesIn(allOperandTypes()));
150 
151 using VariableOperandExpansionTest =
152     ::testing::TestWithParam<spv_operand_type_t>;
153 
TEST_P(VariableOperandExpansionTest,NonMatchableOperandsExpand)154 TEST_P(VariableOperandExpansionTest, NonMatchableOperandsExpand) {
155   const spv_operand_type_t type = GetParam();
156   if (spvOperandIsVariable(type)) {
157     spv_operand_pattern_t pattern;
158     const bool did_expand = spvExpandOperandSequenceOnce(type, &pattern);
159     EXPECT_TRUE(did_expand);
160     EXPECT_FALSE(pattern.empty());
161     // For the existing rules, the first expansion of a zero-or-more operand
162     // type yields a matchable operand type.  This isn't strictly necessary.
163     EXPECT_FALSE(spvOperandIsVariable(pattern.back()));
164   }
165 }
166 
167 INSTANTIATE_TEST_SUITE_P(NonMatchableOperandExpansion,
168                          VariableOperandExpansionTest,
169                          ::testing::ValuesIn(allOperandTypes()));
170 
TEST(AlternatePatternFollowingImmediate,Empty)171 TEST(AlternatePatternFollowingImmediate, Empty) {
172   EXPECT_THAT(spvAlternatePatternFollowingImmediate({}),
173               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
174 }
175 
TEST(AlternatePatternFollowingImmediate,SingleElement)176 TEST(AlternatePatternFollowingImmediate, SingleElement) {
177   // Spot-check a random selection of types.
178   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
179                   {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER}),
180               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
181   EXPECT_THAT(
182       spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_CAPABILITY}),
183       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
184   EXPECT_THAT(
185       spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_LOOP_CONTROL}),
186       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
187   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
188                   {SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER}),
189               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
190   EXPECT_THAT(spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_ID}),
191               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
192 }
193 
TEST(AlternatePatternFollowingImmediate,SingleResultId)194 TEST(AlternatePatternFollowingImmediate, SingleResultId) {
195   EXPECT_THAT(
196       spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_RESULT_ID}),
197       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
198                                SPV_OPERAND_TYPE_RESULT_ID}));
199 }
200 
TEST(AlternatePatternFollowingImmediate,MultipleNonResultIds)201 TEST(AlternatePatternFollowingImmediate, MultipleNonResultIds) {
202   EXPECT_THAT(
203       spvAlternatePatternFollowingImmediate(
204           {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER,
205            SPV_OPERAND_TYPE_CAPABILITY, SPV_OPERAND_TYPE_LOOP_CONTROL,
206            SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID}),
207       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
208 }
209 
TEST(AlternatePatternFollowingImmediate,ResultIdFront)210 TEST(AlternatePatternFollowingImmediate, ResultIdFront) {
211   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
212                   {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}),
213               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
214                                        SPV_OPERAND_TYPE_RESULT_ID,
215                                        SPV_OPERAND_TYPE_OPTIONAL_CIV}));
216   EXPECT_THAT(
217       spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_RESULT_ID,
218                                              SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
219                                              SPV_OPERAND_TYPE_ID}),
220       Eq(spv_operand_pattern_t{
221           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
222           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV}));
223   EXPECT_THAT(
224       spvAlternatePatternFollowingImmediate(
225           {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_DIMENSIONALITY,
226            SPV_OPERAND_TYPE_LINKAGE_TYPE,
227            SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
228            SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
229            SPV_OPERAND_TYPE_VARIABLE_ID}),
230       Eq(spv_operand_pattern_t{
231           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
232           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
233           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
234           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV}));
235 }
236 
TEST(AlternatePatternFollowingImmediate,ResultIdMiddle)237 TEST(AlternatePatternFollowingImmediate, ResultIdMiddle) {
238   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
239                   {SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
240                    SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}),
241               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
242                                        SPV_OPERAND_TYPE_RESULT_ID,
243                                        SPV_OPERAND_TYPE_OPTIONAL_CIV}));
244   EXPECT_THAT(
245       spvAlternatePatternFollowingImmediate(
246           {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE,
247            SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
248            SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
249            SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}),
250       Eq(spv_operand_pattern_t{
251           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
252           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
253           SPV_OPERAND_TYPE_OPTIONAL_CIV}));
254 }
255 
TEST(AlternatePatternFollowingImmediate,ResultIdBack)256 TEST(AlternatePatternFollowingImmediate, ResultIdBack) {
257   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
258                   {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}),
259               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
260                                        SPV_OPERAND_TYPE_RESULT_ID}));
261   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
262                   {SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
263                    SPV_OPERAND_TYPE_RESULT_ID}),
264               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
265                                        SPV_OPERAND_TYPE_RESULT_ID}));
266   EXPECT_THAT(
267       spvAlternatePatternFollowingImmediate(
268           {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE,
269            SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
270            SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
271            SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_RESULT_ID}),
272       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
273                                SPV_OPERAND_TYPE_RESULT_ID}));
274 }
275 
276 }  // namespace
277 }  // namespace spvtools
278