operand_pattern_test.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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. #include <vector>
  15. #include "gmock/gmock.h"
  16. #include "source/operand.h"
  17. #include "test/unit_spirv.h"
  18. namespace spvtools {
  19. namespace {
  20. using ::testing::Eq;
  21. TEST(OperandPattern, InitiallyEmpty) {
  22. spv_operand_pattern_t empty;
  23. EXPECT_THAT(empty, Eq(spv_operand_pattern_t{}));
  24. EXPECT_EQ(0u, empty.size());
  25. EXPECT_TRUE(empty.empty());
  26. }
  27. TEST(OperandPattern, PushBacksAreOnTheRight) {
  28. spv_operand_pattern_t pattern;
  29. pattern.push_back(SPV_OPERAND_TYPE_ID);
  30. EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID}));
  31. EXPECT_EQ(1u, pattern.size());
  32. EXPECT_TRUE(!pattern.empty());
  33. EXPECT_EQ(SPV_OPERAND_TYPE_ID, pattern.back());
  34. pattern.push_back(SPV_OPERAND_TYPE_NONE);
  35. EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID,
  36. SPV_OPERAND_TYPE_NONE}));
  37. EXPECT_EQ(2u, pattern.size());
  38. EXPECT_TRUE(!pattern.empty());
  39. EXPECT_EQ(SPV_OPERAND_TYPE_NONE, pattern.back());
  40. }
  41. TEST(OperandPattern, PopBacksAreOnTheRight) {
  42. spv_operand_pattern_t pattern{SPV_OPERAND_TYPE_ID,
  43. SPV_OPERAND_TYPE_LITERAL_INTEGER};
  44. pattern.pop_back();
  45. EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID}));
  46. pattern.pop_back();
  47. EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{}));
  48. }
  49. // A test case for typed mask expansion
  50. struct MaskExpansionCase {
  51. spv_operand_type_t type;
  52. uint32_t mask;
  53. spv_operand_pattern_t initial;
  54. spv_operand_pattern_t expected;
  55. };
  56. using MaskExpansionTest = ::testing::TestWithParam<MaskExpansionCase>;
  57. TEST_P(MaskExpansionTest, Sample) {
  58. spv_operand_table operandTable = nullptr;
  59. auto env = SPV_ENV_UNIVERSAL_1_0;
  60. ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable, env));
  61. spv_operand_pattern_t pattern(GetParam().initial);
  62. spvPushOperandTypesForMask(env, operandTable, GetParam().type,
  63. GetParam().mask, &pattern);
  64. EXPECT_THAT(pattern, Eq(GetParam().expected));
  65. }
  66. // These macros let us write non-trivial examples without too much text.
  67. #define PREFIX0 SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE
  68. #define PREFIX1 \
  69. SPV_OPERAND_TYPE_STORAGE_CLASS, SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE, \
  70. SPV_OPERAND_TYPE_ID
  71. INSTANTIATE_TEST_SUITE_P(
  72. OperandPattern, MaskExpansionTest,
  73. ::testing::ValuesIn(std::vector<MaskExpansionCase>{
  74. // No bits means no change.
  75. {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, 0, {PREFIX0}, {PREFIX0}},
  76. // Unknown bits means no change. Use all bits that aren't in the
  77. // grammar.
  78. // The used mask bits are:
  79. // 1 through...
  80. // 0x20 SpvMemoryAccessNonPrivatePointerMask
  81. // also
  82. // 0x10000 SpvMemoryAccessAliasScopeINTELMaskShift
  83. // 0x20000 SpvMemoryAccessNoAliasINTELMaskMask
  84. {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
  85. 0xffffffc0 ^ (0x10000) ^ (0x20000),
  86. {PREFIX1},
  87. {PREFIX1}},
  88. // Volatile has no operands.
  89. {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
  90. uint32_t(spv::MemoryAccessMask::Volatile),
  91. {PREFIX0},
  92. {PREFIX0}},
  93. // Aligned has one literal number operand.
  94. {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
  95. uint32_t(spv::MemoryAccessMask::Aligned),
  96. {PREFIX1},
  97. {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}},
  98. // Volatile with Aligned still has just one literal number operand.
  99. {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
  100. uint32_t(spv::MemoryAccessMask::Volatile |
  101. spv::MemoryAccessMask::Aligned),
  102. {PREFIX1},
  103. {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}},
  104. // Newer masks are not tested
  105. }));
  106. #undef PREFIX0
  107. #undef PREFIX1
  108. // Returns a vector of all operand types that can be used in a pattern.
  109. std::vector<spv_operand_type_t> allOperandTypes() {
  110. std::vector<spv_operand_type_t> result;
  111. for (int i = 0; i < SPV_OPERAND_TYPE_NUM_OPERAND_TYPES; i++) {
  112. result.push_back(spv_operand_type_t(i));
  113. }
  114. return result;
  115. }
  116. using MatchableOperandExpansionTest =
  117. ::testing::TestWithParam<spv_operand_type_t>;
  118. TEST_P(MatchableOperandExpansionTest, MatchableOperandsDontExpand) {
  119. const spv_operand_type_t type = GetParam();
  120. if (!spvOperandIsVariable(type)) {
  121. spv_operand_pattern_t pattern;
  122. const bool did_expand = spvExpandOperandSequenceOnce(type, &pattern);
  123. EXPECT_FALSE(did_expand);
  124. EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{}));
  125. }
  126. }
  127. INSTANTIATE_TEST_SUITE_P(MatchableOperandExpansion,
  128. MatchableOperandExpansionTest,
  129. ::testing::ValuesIn(allOperandTypes()));
  130. using VariableOperandExpansionTest =
  131. ::testing::TestWithParam<spv_operand_type_t>;
  132. TEST_P(VariableOperandExpansionTest, NonMatchableOperandsExpand) {
  133. const spv_operand_type_t type = GetParam();
  134. if (spvOperandIsVariable(type)) {
  135. spv_operand_pattern_t pattern;
  136. const bool did_expand = spvExpandOperandSequenceOnce(type, &pattern);
  137. EXPECT_TRUE(did_expand);
  138. EXPECT_FALSE(pattern.empty());
  139. // For the existing rules, the first expansion of a zero-or-more operand
  140. // type yields a matchable operand type. This isn't strictly necessary.
  141. EXPECT_FALSE(spvOperandIsVariable(pattern.back()));
  142. }
  143. }
  144. INSTANTIATE_TEST_SUITE_P(NonMatchableOperandExpansion,
  145. VariableOperandExpansionTest,
  146. ::testing::ValuesIn(allOperandTypes()));
  147. TEST(AlternatePatternFollowingImmediate, Empty) {
  148. EXPECT_THAT(spvAlternatePatternFollowingImmediate({}),
  149. Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
  150. }
  151. TEST(AlternatePatternFollowingImmediate, SingleElement) {
  152. // Spot-check a random selection of types.
  153. EXPECT_THAT(spvAlternatePatternFollowingImmediate(
  154. {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER}),
  155. Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
  156. EXPECT_THAT(
  157. spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_CAPABILITY}),
  158. Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
  159. EXPECT_THAT(
  160. spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_LOOP_CONTROL}),
  161. Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
  162. EXPECT_THAT(spvAlternatePatternFollowingImmediate(
  163. {SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER}),
  164. Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
  165. EXPECT_THAT(spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_ID}),
  166. Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
  167. }
  168. TEST(AlternatePatternFollowingImmediate, SingleResultId) {
  169. EXPECT_THAT(
  170. spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_RESULT_ID}),
  171. Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
  172. SPV_OPERAND_TYPE_RESULT_ID}));
  173. }
  174. TEST(AlternatePatternFollowingImmediate, MultipleNonResultIds) {
  175. EXPECT_THAT(
  176. spvAlternatePatternFollowingImmediate(
  177. {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER,
  178. SPV_OPERAND_TYPE_CAPABILITY, SPV_OPERAND_TYPE_LOOP_CONTROL,
  179. SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID}),
  180. Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
  181. }
  182. TEST(AlternatePatternFollowingImmediate, ResultIdFront) {
  183. EXPECT_THAT(spvAlternatePatternFollowingImmediate(
  184. {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}),
  185. Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
  186. SPV_OPERAND_TYPE_RESULT_ID,
  187. SPV_OPERAND_TYPE_OPTIONAL_CIV}));
  188. EXPECT_THAT(
  189. spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_RESULT_ID,
  190. SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
  191. SPV_OPERAND_TYPE_ID}),
  192. Eq(spv_operand_pattern_t{
  193. SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
  194. SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV}));
  195. EXPECT_THAT(
  196. spvAlternatePatternFollowingImmediate(
  197. {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_DIMENSIONALITY,
  198. SPV_OPERAND_TYPE_LINKAGE_TYPE,
  199. SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
  200. SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
  201. SPV_OPERAND_TYPE_VARIABLE_ID}),
  202. Eq(spv_operand_pattern_t{
  203. SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
  204. SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
  205. SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
  206. SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV}));
  207. }
  208. TEST(AlternatePatternFollowingImmediate, ResultIdMiddle) {
  209. EXPECT_THAT(spvAlternatePatternFollowingImmediate(
  210. {SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
  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(
  217. {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE,
  218. SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
  219. SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
  220. SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}),
  221. Eq(spv_operand_pattern_t{
  222. SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
  223. SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
  224. SPV_OPERAND_TYPE_OPTIONAL_CIV}));
  225. }
  226. TEST(AlternatePatternFollowingImmediate, ResultIdBack) {
  227. EXPECT_THAT(spvAlternatePatternFollowingImmediate(
  228. {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}),
  229. Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
  230. SPV_OPERAND_TYPE_RESULT_ID}));
  231. EXPECT_THAT(spvAlternatePatternFollowingImmediate(
  232. {SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
  233. SPV_OPERAND_TYPE_RESULT_ID}),
  234. Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
  235. SPV_OPERAND_TYPE_RESULT_ID}));
  236. EXPECT_THAT(
  237. spvAlternatePatternFollowingImmediate(
  238. {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE,
  239. SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
  240. SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
  241. SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_RESULT_ID}),
  242. Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
  243. SPV_OPERAND_TYPE_RESULT_ID}));
  244. }
  245. } // namespace
  246. } // namespace spvtools