• 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          SpvMemoryAccessVolatileMask,
107          {PREFIX0},
108          {PREFIX0}},
109         // Aligned has one literal number operand.
110         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
111          SpvMemoryAccessAlignedMask,
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          SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask,
117          {PREFIX1},
118          {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}},
119         // Newer masks are not tested
120     }));
121 #undef PREFIX0
122 #undef PREFIX1
123 
124 // Returns a vector of all operand types that can be used in a pattern.
allOperandTypes()125 std::vector<spv_operand_type_t> allOperandTypes() {
126   std::vector<spv_operand_type_t> result;
127   for (int i = 0; i < SPV_OPERAND_TYPE_NUM_OPERAND_TYPES; i++) {
128     result.push_back(spv_operand_type_t(i));
129   }
130   return result;
131 }
132 
133 using MatchableOperandExpansionTest =
134     ::testing::TestWithParam<spv_operand_type_t>;
135 
TEST_P(MatchableOperandExpansionTest,MatchableOperandsDontExpand)136 TEST_P(MatchableOperandExpansionTest, MatchableOperandsDontExpand) {
137   const spv_operand_type_t type = GetParam();
138   if (!spvOperandIsVariable(type)) {
139     spv_operand_pattern_t pattern;
140     const bool did_expand = spvExpandOperandSequenceOnce(type, &pattern);
141     EXPECT_FALSE(did_expand);
142     EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{}));
143   }
144 }
145 
146 INSTANTIATE_TEST_SUITE_P(MatchableOperandExpansion,
147                          MatchableOperandExpansionTest,
148                          ::testing::ValuesIn(allOperandTypes()));
149 
150 using VariableOperandExpansionTest =
151     ::testing::TestWithParam<spv_operand_type_t>;
152 
TEST_P(VariableOperandExpansionTest,NonMatchableOperandsExpand)153 TEST_P(VariableOperandExpansionTest, NonMatchableOperandsExpand) {
154   const spv_operand_type_t type = GetParam();
155   if (spvOperandIsVariable(type)) {
156     spv_operand_pattern_t pattern;
157     const bool did_expand = spvExpandOperandSequenceOnce(type, &pattern);
158     EXPECT_TRUE(did_expand);
159     EXPECT_FALSE(pattern.empty());
160     // For the existing rules, the first expansion of a zero-or-more operand
161     // type yields a matchable operand type.  This isn't strictly necessary.
162     EXPECT_FALSE(spvOperandIsVariable(pattern.back()));
163   }
164 }
165 
166 INSTANTIATE_TEST_SUITE_P(NonMatchableOperandExpansion,
167                          VariableOperandExpansionTest,
168                          ::testing::ValuesIn(allOperandTypes()));
169 
TEST(AlternatePatternFollowingImmediate,Empty)170 TEST(AlternatePatternFollowingImmediate, Empty) {
171   EXPECT_THAT(spvAlternatePatternFollowingImmediate({}),
172               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
173 }
174 
TEST(AlternatePatternFollowingImmediate,SingleElement)175 TEST(AlternatePatternFollowingImmediate, SingleElement) {
176   // Spot-check a random selection of types.
177   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
178                   {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER}),
179               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
180   EXPECT_THAT(
181       spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_CAPABILITY}),
182       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
183   EXPECT_THAT(
184       spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_LOOP_CONTROL}),
185       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
186   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
187                   {SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER}),
188               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
189   EXPECT_THAT(spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_ID}),
190               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
191 }
192 
TEST(AlternatePatternFollowingImmediate,SingleResultId)193 TEST(AlternatePatternFollowingImmediate, SingleResultId) {
194   EXPECT_THAT(
195       spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_RESULT_ID}),
196       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
197                                SPV_OPERAND_TYPE_RESULT_ID}));
198 }
199 
TEST(AlternatePatternFollowingImmediate,MultipleNonResultIds)200 TEST(AlternatePatternFollowingImmediate, MultipleNonResultIds) {
201   EXPECT_THAT(
202       spvAlternatePatternFollowingImmediate(
203           {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER,
204            SPV_OPERAND_TYPE_CAPABILITY, SPV_OPERAND_TYPE_LOOP_CONTROL,
205            SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID}),
206       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
207 }
208 
TEST(AlternatePatternFollowingImmediate,ResultIdFront)209 TEST(AlternatePatternFollowingImmediate, ResultIdFront) {
210   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
211                   {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}),
212               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
213                                        SPV_OPERAND_TYPE_RESULT_ID,
214                                        SPV_OPERAND_TYPE_OPTIONAL_CIV}));
215   EXPECT_THAT(
216       spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_RESULT_ID,
217                                              SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
218                                              SPV_OPERAND_TYPE_ID}),
219       Eq(spv_operand_pattern_t{
220           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
221           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV}));
222   EXPECT_THAT(
223       spvAlternatePatternFollowingImmediate(
224           {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_DIMENSIONALITY,
225            SPV_OPERAND_TYPE_LINKAGE_TYPE,
226            SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
227            SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
228            SPV_OPERAND_TYPE_VARIABLE_ID}),
229       Eq(spv_operand_pattern_t{
230           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
231           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
232           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
233           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV}));
234 }
235 
TEST(AlternatePatternFollowingImmediate,ResultIdMiddle)236 TEST(AlternatePatternFollowingImmediate, ResultIdMiddle) {
237   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
238                   {SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
239                    SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}),
240               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
241                                        SPV_OPERAND_TYPE_RESULT_ID,
242                                        SPV_OPERAND_TYPE_OPTIONAL_CIV}));
243   EXPECT_THAT(
244       spvAlternatePatternFollowingImmediate(
245           {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE,
246            SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
247            SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
248            SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}),
249       Eq(spv_operand_pattern_t{
250           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
251           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
252           SPV_OPERAND_TYPE_OPTIONAL_CIV}));
253 }
254 
TEST(AlternatePatternFollowingImmediate,ResultIdBack)255 TEST(AlternatePatternFollowingImmediate, ResultIdBack) {
256   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
257                   {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}),
258               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
259                                        SPV_OPERAND_TYPE_RESULT_ID}));
260   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
261                   {SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
262                    SPV_OPERAND_TYPE_RESULT_ID}),
263               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
264                                        SPV_OPERAND_TYPE_RESULT_ID}));
265   EXPECT_THAT(
266       spvAlternatePatternFollowingImmediate(
267           {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE,
268            SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
269            SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
270            SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_RESULT_ID}),
271       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
272                                SPV_OPERAND_TYPE_RESULT_ID}));
273 }
274 
275 }  // namespace
276 }  // namespace spvtools
277