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