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