1 // Copyright (c) 2015-2016 The Khronos Group Inc.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include "unit_spirv.h"
17 #include "gmock/gmock.h"
18 #include "source/operand.h"
24 TEST(OperandPattern, InitiallyEmpty) {
25 spv_operand_pattern_t empty;
26 EXPECT_THAT(empty, Eq(spv_operand_pattern_t{}));
27 EXPECT_EQ(0u, empty.size());
28 EXPECT_TRUE(empty.empty());
31 TEST(OperandPattern, PushFrontsAreOnTheLeft) {
32 spv_operand_pattern_t pattern;
34 pattern.push_front(SPV_OPERAND_TYPE_ID);
35 EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID}));
36 EXPECT_EQ(1u, pattern.size());
37 EXPECT_TRUE(!pattern.empty());
38 EXPECT_EQ(SPV_OPERAND_TYPE_ID, pattern.front());
40 pattern.push_front(SPV_OPERAND_TYPE_NONE);
41 EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_NONE,
42 SPV_OPERAND_TYPE_ID}));
43 EXPECT_EQ(2u, pattern.size());
44 EXPECT_TRUE(!pattern.empty());
45 EXPECT_EQ(SPV_OPERAND_TYPE_NONE, pattern.front());
48 TEST(OperandPattern, PopFrontsAreOnTheLeft) {
49 spv_operand_pattern_t pattern{SPV_OPERAND_TYPE_LITERAL_INTEGER,
53 EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID}));
56 EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{}));
59 // A test case for typed mask expansion
60 struct MaskExpansionCase {
61 spv_operand_type_t type;
63 spv_operand_pattern_t initial;
64 spv_operand_pattern_t expected;
67 using MaskExpansionTest = ::testing::TestWithParam<MaskExpansionCase>;
69 TEST_P(MaskExpansionTest, Sample) {
70 spv_operand_table operandTable = nullptr;
71 ASSERT_EQ(SPV_SUCCESS,
72 spvOperandTableGet(&operandTable, SPV_ENV_UNIVERSAL_1_0));
74 spv_operand_pattern_t pattern(GetParam().initial);
75 spvPrependOperandTypesForMask(operandTable, GetParam().type, GetParam().mask,
77 EXPECT_THAT(pattern, Eq(GetParam().expected));
80 // These macros let us write non-trivial examples without too much text.
81 #define SUFFIX0 SPV_OPERAND_TYPE_NONE, SPV_OPERAND_TYPE_ID
83 SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE, \
84 SPV_OPERAND_TYPE_STORAGE_CLASS
85 INSTANTIATE_TEST_CASE_P(
86 OperandPattern, MaskExpansionTest,
87 ::testing::ValuesIn(std::vector<MaskExpansionCase>{
88 // No bits means no change.
89 {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, 0, {SUFFIX0}, {SUFFIX0}},
90 // Unknown bits means no change.
91 {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
95 // Volatile has no operands.
96 {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
97 SpvMemoryAccessVolatileMask,
100 // Aligned has one literal number operand.
101 {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
102 SpvMemoryAccessAlignedMask,
104 {SPV_OPERAND_TYPE_LITERAL_INTEGER, SUFFIX1}},
105 // Volatile with Aligned still has just one literal number operand.
106 {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
107 SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask,
109 {SPV_OPERAND_TYPE_LITERAL_INTEGER, SUFFIX1}},
114 // Returns a vector of all operand types that can be used in a pattern.
115 std::vector<spv_operand_type_t> allOperandTypes() {
116 std::vector<spv_operand_type_t> result;
117 for (int i = 0; i < SPV_OPERAND_TYPE_NUM_OPERAND_TYPES; i++) {
118 result.push_back(spv_operand_type_t(i));
123 using MatchableOperandExpansionTest =
124 ::testing::TestWithParam<spv_operand_type_t>;
126 TEST_P(MatchableOperandExpansionTest, MatchableOperandsDontExpand) {
127 const spv_operand_type_t type = GetParam();
128 if (!spvOperandIsVariable(type)) {
129 spv_operand_pattern_t pattern;
130 const bool did_expand = spvExpandOperandSequenceOnce(type, &pattern);
131 EXPECT_FALSE(did_expand);
132 EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{}));
136 INSTANTIATE_TEST_CASE_P(MatchableOperandExpansion,
137 MatchableOperandExpansionTest,
138 ::testing::ValuesIn(allOperandTypes()), );
140 using VariableOperandExpansionTest =
141 ::testing::TestWithParam<spv_operand_type_t>;
143 TEST_P(VariableOperandExpansionTest, NonMatchableOperandsExpand) {
144 const spv_operand_type_t type = GetParam();
145 if (spvOperandIsVariable(type)) {
146 spv_operand_pattern_t pattern;
147 const bool did_expand = spvExpandOperandSequenceOnce(type, &pattern);
148 EXPECT_TRUE(did_expand);
149 EXPECT_FALSE(pattern.empty());
150 // For the existing rules, the first expansion of a zero-or-more operand
151 // type yields a matchable operand type. This isn't strictly necessary.
152 EXPECT_FALSE(spvOperandIsVariable(pattern.front()));
156 INSTANTIATE_TEST_CASE_P(NonMatchableOperandExpansion,
157 VariableOperandExpansionTest,
158 ::testing::ValuesIn(allOperandTypes()), );
160 TEST(AlternatePatternFollowingImmediate, Empty) {
161 EXPECT_THAT(spvAlternatePatternFollowingImmediate({}),
162 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
165 TEST(AlternatePatternFollowingImmediate, SingleElement) {
166 // Spot-check a random selection of types.
167 EXPECT_THAT(spvAlternatePatternFollowingImmediate(
168 {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER}),
169 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
171 spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_CAPABILITY}),
172 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
174 spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_LOOP_CONTROL}),
175 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
176 EXPECT_THAT(spvAlternatePatternFollowingImmediate(
177 {SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER}),
178 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
179 EXPECT_THAT(spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_ID}),
180 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
183 TEST(AlternatePatternFollowingImmediate, SingleResultId) {
185 spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_RESULT_ID}),
186 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_RESULT_ID,
187 SPV_OPERAND_TYPE_OPTIONAL_CIV}));
190 TEST(AlternatePatternFollowingImmediate, MultipleNonResultIds) {
192 spvAlternatePatternFollowingImmediate(
193 {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER,
194 SPV_OPERAND_TYPE_CAPABILITY, SPV_OPERAND_TYPE_LOOP_CONTROL,
195 SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID}),
196 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
199 TEST(AlternatePatternFollowingImmediate, ResultIdFront) {
200 EXPECT_THAT(spvAlternatePatternFollowingImmediate(
201 {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}),
202 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_RESULT_ID,
203 SPV_OPERAND_TYPE_OPTIONAL_CIV}));
204 EXPECT_THAT(spvAlternatePatternFollowingImmediate(
205 {SPV_OPERAND_TYPE_RESULT_ID,
206 SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID}),
207 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_RESULT_ID,
208 SPV_OPERAND_TYPE_OPTIONAL_CIV}));
209 EXPECT_THAT(spvAlternatePatternFollowingImmediate(
210 {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_DIMENSIONALITY,
211 SPV_OPERAND_TYPE_LINKAGE_TYPE,
212 SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
213 SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
214 SPV_OPERAND_TYPE_VARIABLE_ID}),
215 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_RESULT_ID,
216 SPV_OPERAND_TYPE_OPTIONAL_CIV}));
219 TEST(AlternatePatternFollowingImmediate, ResultIdMiddle) {
220 EXPECT_THAT(spvAlternatePatternFollowingImmediate(
221 {SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
222 SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}),
223 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
224 SPV_OPERAND_TYPE_RESULT_ID,
225 SPV_OPERAND_TYPE_OPTIONAL_CIV}));
227 spvAlternatePatternFollowingImmediate(
228 {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE,
229 SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
230 SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
231 SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}),
232 Eq(spv_operand_pattern_t{
233 SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
234 SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
235 SPV_OPERAND_TYPE_OPTIONAL_CIV}));
238 TEST(AlternatePatternFollowingImmediate, ResultIdBack) {
239 EXPECT_THAT(spvAlternatePatternFollowingImmediate(
240 {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_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(spvAlternatePatternFollowingImmediate(
245 {SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
246 SPV_OPERAND_TYPE_RESULT_ID}),
247 Eq(spv_operand_pattern_t{
248 SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
249 SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_OPTIONAL_CIV}));
251 spvAlternatePatternFollowingImmediate(
252 {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE,
253 SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
254 SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
255 SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_RESULT_ID}),
256 Eq(spv_operand_pattern_t{
257 SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
258 SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
259 SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
260 SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_OPTIONAL_CIV}));
263 } // anonymous namespace