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 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 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 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 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. 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 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 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 164 TEST(AlternatePatternFollowingImmediate, Empty) { 165 EXPECT_THAT(spvAlternatePatternFollowingImmediate({}), 166 Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV})); 167 } 168 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 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 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 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 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 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