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 // Assembler tests for instructions in the "Annotation" section of the
16 // SPIR-V spec.
17 
18 #include <sstream>
19 #include <string>
20 #include <tuple>
21 #include <vector>
22 
23 #include "gmock/gmock.h"
24 #include "source/util/string_utils.h"
25 #include "test/test_fixture.h"
26 #include "test/unit_spirv.h"
27 
28 namespace spvtools {
29 namespace {
30 
31 using spvtest::EnumCase;
32 using spvtest::MakeInstruction;
33 using utils::MakeVector;
34 using spvtest::TextToBinaryTest;
35 using ::testing::Combine;
36 using ::testing::Eq;
37 using ::testing::Values;
38 using ::testing::ValuesIn;
39 
40 // Test OpDecorate
41 
42 using OpDecorateSimpleTest =
43     spvtest::TextToBinaryTestBase<::testing::TestWithParam<
44         std::tuple<spv_target_env, EnumCase<SpvDecoration>>>>;
45 
TEST_P(OpDecorateSimpleTest,AnySimpleDecoration)46 TEST_P(OpDecorateSimpleTest, AnySimpleDecoration) {
47   // This string should assemble, but should not validate.
48   std::stringstream input;
49   input << "OpDecorate %1 " << std::get<1>(GetParam()).name();
50   for (auto operand : std::get<1>(GetParam()).operands())
51     input << " " << operand;
52   input << std::endl;
53   EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())),
54               Eq(MakeInstruction(SpvOpDecorate,
55                                  {1, uint32_t(std::get<1>(GetParam()).value())},
56                                  std::get<1>(GetParam()).operands())));
57   // Also check disassembly.
58   EXPECT_THAT(
59       EncodeAndDecodeSuccessfully(input.str(), SPV_BINARY_TO_TEXT_OPTION_NONE,
60                                   std::get<0>(GetParam())),
61       Eq(input.str()));
62 }
63 
64 // Like above, but parameters to the decoration are IDs.
65 using OpDecorateSimpleIdTest =
66     spvtest::TextToBinaryTestBase<::testing::TestWithParam<
67         std::tuple<spv_target_env, EnumCase<SpvDecoration>>>>;
68 
TEST_P(OpDecorateSimpleIdTest,AnySimpleDecoration)69 TEST_P(OpDecorateSimpleIdTest, AnySimpleDecoration) {
70   // This string should assemble, but should not validate.
71   std::stringstream input;
72   input << "OpDecorateId %1 " << std::get<1>(GetParam()).name();
73   for (auto operand : std::get<1>(GetParam()).operands())
74     input << " %" << operand;
75   input << std::endl;
76   EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())),
77               Eq(MakeInstruction(SpvOpDecorateId,
78                                  {1, uint32_t(std::get<1>(GetParam()).value())},
79                                  std::get<1>(GetParam()).operands())));
80   // Also check disassembly.
81   EXPECT_THAT(
82       EncodeAndDecodeSuccessfully(input.str(), SPV_BINARY_TO_TEXT_OPTION_NONE,
83                                   std::get<0>(GetParam())),
84       Eq(input.str()));
85 }
86 
87 #define CASE(NAME) SpvDecoration##NAME, #NAME
88 INSTANTIATE_TEST_SUITE_P(
89     TextToBinaryDecorateSimple, OpDecorateSimpleTest,
90     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
91             ValuesIn(std::vector<EnumCase<SpvDecoration>>{
92                 // The operand literal values are arbitrarily chosen,
93                 // but there are the right number of them.
94                 {CASE(RelaxedPrecision), {}},
95                 {CASE(SpecId), {100}},
96                 {CASE(Block), {}},
97                 {CASE(BufferBlock), {}},
98                 {CASE(RowMajor), {}},
99                 {CASE(ColMajor), {}},
100                 {CASE(ArrayStride), {4}},
101                 {CASE(MatrixStride), {16}},
102                 {CASE(GLSLShared), {}},
103                 {CASE(GLSLPacked), {}},
104                 {CASE(CPacked), {}},
105                 // Placeholder line for enum value 12
106                 {CASE(NoPerspective), {}},
107                 {CASE(Flat), {}},
108                 {CASE(Patch), {}},
109                 {CASE(Centroid), {}},
110                 {CASE(Sample), {}},
111                 {CASE(Invariant), {}},
112                 {CASE(Restrict), {}},
113                 {CASE(Aliased), {}},
114                 {CASE(Volatile), {}},
115                 {CASE(Constant), {}},
116                 {CASE(Coherent), {}},
117                 {CASE(NonWritable), {}},
118                 {CASE(NonReadable), {}},
119                 {CASE(Uniform), {}},
120                 {CASE(SaturatedConversion), {}},
121                 {CASE(Stream), {2}},
122                 {CASE(Location), {6}},
123                 {CASE(Component), {3}},
124                 {CASE(Index), {14}},
125                 {CASE(Binding), {19}},
126                 {CASE(DescriptorSet), {7}},
127                 {CASE(Offset), {12}},
128                 {CASE(XfbBuffer), {1}},
129                 {CASE(XfbStride), {8}},
130                 {CASE(NoContraction), {}},
131                 {CASE(InputAttachmentIndex), {102}},
132                 {CASE(Alignment), {16}},
133             })));
134 
135 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleV11, OpDecorateSimpleTest,
136                          Combine(Values(SPV_ENV_UNIVERSAL_1_1),
137                                  Values(EnumCase<SpvDecoration>{
138                                      CASE(MaxByteOffset), {128}})));
139 
140 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleV14, OpDecorateSimpleTest,
141                          Combine(Values(SPV_ENV_UNIVERSAL_1_4),
142                                  ValuesIn(std::vector<EnumCase<SpvDecoration>>{
143                                      {CASE(Uniform), {}},
144                                  })));
145 
146 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleIdV14,
147                          OpDecorateSimpleIdTest,
148                          Combine(Values(SPV_ENV_UNIVERSAL_1_4),
149                                  ValuesIn(std::vector<EnumCase<SpvDecoration>>{
150                                      // In 1.4, UniformId decoration takes a
151                                      // scope Id.
152                                      {CASE(UniformId), {1}},
153                                  })));
154 #undef CASE
155 
TEST_F(OpDecorateSimpleTest,WrongDecoration)156 TEST_F(OpDecorateSimpleTest, WrongDecoration) {
157   EXPECT_THAT(CompileFailure("OpDecorate %1 xxyyzz"),
158               Eq("Invalid decoration 'xxyyzz'."));
159 }
160 
TEST_F(OpDecorateSimpleTest,ExtraOperandsOnDecorationExpectingNone)161 TEST_F(OpDecorateSimpleTest, ExtraOperandsOnDecorationExpectingNone) {
162   EXPECT_THAT(CompileFailure("OpDecorate %1 RelaxedPrecision 99"),
163               Eq("Expected <opcode> or <result-id> at the beginning of an "
164                  "instruction, found '99'."));
165 }
166 
TEST_F(OpDecorateSimpleTest,ExtraOperandsOnDecorationExpectingOne)167 TEST_F(OpDecorateSimpleTest, ExtraOperandsOnDecorationExpectingOne) {
168   EXPECT_THAT(CompileFailure("OpDecorate %1 SpecId 99 100"),
169               Eq("Expected <opcode> or <result-id> at the beginning of an "
170                  "instruction, found '100'."));
171 }
172 
TEST_F(OpDecorateSimpleTest,ExtraOperandsOnDecorationExpectingTwo)173 TEST_F(OpDecorateSimpleTest, ExtraOperandsOnDecorationExpectingTwo) {
174   EXPECT_THAT(
175       CompileFailure("OpDecorate %1 LinkageAttributes \"abc\" Import 42"),
176       Eq("Expected <opcode> or <result-id> at the beginning of an "
177          "instruction, found '42'."));
178 }
179 
180 // A single test case for an enum decoration.
181 struct DecorateEnumCase {
182   // Place the enum value first, so it's easier to read the binary dumps when
183   // the test fails.
184   uint32_t value;  // The value within the enum, e.g. Position
185   std::string name;
186   uint32_t enum_value;  // Which enum, e.g. BuiltIn
187   std::string enum_name;
188 };
189 
190 using OpDecorateEnumTest =
191     spvtest::TextToBinaryTestBase<::testing::TestWithParam<DecorateEnumCase>>;
192 
TEST_P(OpDecorateEnumTest,AnyEnumDecoration)193 TEST_P(OpDecorateEnumTest, AnyEnumDecoration) {
194   // This string should assemble, but should not validate.
195   const std::string input =
196       "OpDecorate %1 " + GetParam().enum_name + " " + GetParam().name;
197   EXPECT_THAT(CompiledInstructions(input),
198               Eq(MakeInstruction(SpvOpDecorate, {1, GetParam().enum_value,
199                                                  GetParam().value})));
200 }
201 
202 // Test OpDecorate BuiltIn.
203 // clang-format off
204 #define CASE(NAME) \
205   { SpvBuiltIn##NAME, #NAME, SpvDecorationBuiltIn, "BuiltIn" }
206 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateBuiltIn, OpDecorateEnumTest,
207                         ::testing::ValuesIn(std::vector<DecorateEnumCase>{
208                             CASE(Position),
209                             CASE(PointSize),
210                             CASE(ClipDistance),
211                             CASE(CullDistance),
212                             CASE(VertexId),
213                             CASE(InstanceId),
214                             CASE(PrimitiveId),
215                             CASE(InvocationId),
216                             CASE(Layer),
217                             CASE(ViewportIndex),
218                             CASE(TessLevelOuter),
219                             CASE(TessLevelInner),
220                             CASE(TessCoord),
221                             CASE(PatchVertices),
222                             CASE(FragCoord),
223                             CASE(PointCoord),
224                             CASE(FrontFacing),
225                             CASE(SampleId),
226                             CASE(SamplePosition),
227                             CASE(SampleMask),
228                             // Value 21 intentionally missing.
229                             CASE(FragDepth),
230                             CASE(HelperInvocation),
231                             CASE(NumWorkgroups),
232                             CASE(WorkgroupSize),
233                             CASE(WorkgroupId),
234                             CASE(LocalInvocationId),
235                             CASE(GlobalInvocationId),
236                             CASE(LocalInvocationIndex),
237                             CASE(WorkDim),
238                             CASE(GlobalSize),
239                             CASE(EnqueuedWorkgroupSize),
240                             CASE(GlobalOffset),
241                             CASE(GlobalLinearId),
242                             // Value 35 intentionally missing.
243                             CASE(SubgroupSize),
244                             CASE(SubgroupMaxSize),
245                             CASE(NumSubgroups),
246                             CASE(NumEnqueuedSubgroups),
247                             CASE(SubgroupId),
248                             CASE(SubgroupLocalInvocationId),
249                             CASE(VertexIndex),
250                             CASE(InstanceIndex),
251                         }));
252 #undef CASE
253 // clang-format on
254 
TEST_F(OpDecorateEnumTest,WrongBuiltIn)255 TEST_F(OpDecorateEnumTest, WrongBuiltIn) {
256   EXPECT_THAT(CompileFailure("OpDecorate %1 BuiltIn xxyyzz"),
257               Eq("Invalid built-in 'xxyyzz'."));
258 }
259 
260 // Test OpDecorate FuncParamAttr
261 // clang-format off
262 #define CASE(NAME) \
263   { SpvFunctionParameterAttribute##NAME, #NAME, SpvDecorationFuncParamAttr, "FuncParamAttr" }
264 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateFuncParamAttr, OpDecorateEnumTest,
265                         ::testing::ValuesIn(std::vector<DecorateEnumCase>{
266                             CASE(Zext),
267                             CASE(Sext),
268                             CASE(ByVal),
269                             CASE(Sret),
270                             CASE(NoAlias),
271                             CASE(NoCapture),
272                             CASE(NoWrite),
273                             CASE(NoReadWrite),
274                       }));
275 #undef CASE
276 // clang-format on
277 
TEST_F(OpDecorateEnumTest,WrongFuncParamAttr)278 TEST_F(OpDecorateEnumTest, WrongFuncParamAttr) {
279   EXPECT_THAT(CompileFailure("OpDecorate %1 FuncParamAttr xxyyzz"),
280               Eq("Invalid function parameter attribute 'xxyyzz'."));
281 }
282 
283 // Test OpDecorate FPRoundingMode
284 // clang-format off
285 #define CASE(NAME) \
286   { SpvFPRoundingMode##NAME, #NAME, SpvDecorationFPRoundingMode, "FPRoundingMode" }
287 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateFPRoundingMode, OpDecorateEnumTest,
288                         ::testing::ValuesIn(std::vector<DecorateEnumCase>{
289                             CASE(RTE),
290                             CASE(RTZ),
291                             CASE(RTP),
292                             CASE(RTN),
293                       }));
294 #undef CASE
295 // clang-format on
296 
TEST_F(OpDecorateEnumTest,WrongFPRoundingMode)297 TEST_F(OpDecorateEnumTest, WrongFPRoundingMode) {
298   EXPECT_THAT(CompileFailure("OpDecorate %1 FPRoundingMode xxyyzz"),
299               Eq("Invalid floating-point rounding mode 'xxyyzz'."));
300 }
301 
302 // Test OpDecorate FPFastMathMode.
303 // These can by named enums for the single-bit masks.  However, we don't support
304 // symbolic combinations of the masks.  Rather, they can use !<immediate>
305 // syntax, e.g. !0x3
306 
307 // clang-format off
308 #define CASE(ENUM,NAME) \
309   { SpvFPFastMathMode##ENUM, #NAME, SpvDecorationFPFastMathMode, "FPFastMathMode" }
310 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateFPFastMathMode, OpDecorateEnumTest,
311                         ::testing::ValuesIn(std::vector<DecorateEnumCase>{
312                             CASE(MaskNone, None),
313                             CASE(NotNaNMask, NotNaN),
314                             CASE(NotInfMask, NotInf),
315                             CASE(NSZMask, NSZ),
316                             CASE(AllowRecipMask, AllowRecip),
317                             CASE(FastMask, Fast),
318                       }));
319 #undef CASE
320 // clang-format on
321 
TEST_F(OpDecorateEnumTest,CombinedFPFastMathMask)322 TEST_F(OpDecorateEnumTest, CombinedFPFastMathMask) {
323   // Sample a single combination.  This ensures we've integrated
324   // the instruction parsing logic with spvTextParseMask.
325   const std::string input = "OpDecorate %1 FPFastMathMode NotNaN|NotInf|NSZ";
326   const uint32_t expected_enum = SpvDecorationFPFastMathMode;
327   const uint32_t expected_mask = SpvFPFastMathModeNotNaNMask |
328                                  SpvFPFastMathModeNotInfMask |
329                                  SpvFPFastMathModeNSZMask;
330   EXPECT_THAT(
331       CompiledInstructions(input),
332       Eq(MakeInstruction(SpvOpDecorate, {1, expected_enum, expected_mask})));
333 }
334 
TEST_F(OpDecorateEnumTest,WrongFPFastMathMode)335 TEST_F(OpDecorateEnumTest, WrongFPFastMathMode) {
336   EXPECT_THAT(
337       CompileFailure("OpDecorate %1 FPFastMathMode NotNaN|xxyyzz"),
338       Eq("Invalid floating-point fast math mode operand 'NotNaN|xxyyzz'."));
339 }
340 
341 // Test OpDecorate Linkage
342 
343 // A single test case for a linkage
344 struct DecorateLinkageCase {
345   uint32_t linkage_type_value;
346   std::string linkage_type_name;
347   std::string external_name;
348 };
349 
350 using OpDecorateLinkageTest = spvtest::TextToBinaryTestBase<
351     ::testing::TestWithParam<DecorateLinkageCase>>;
352 
TEST_P(OpDecorateLinkageTest,AnyLinkageDecoration)353 TEST_P(OpDecorateLinkageTest, AnyLinkageDecoration) {
354   // This string should assemble, but should not validate.
355   const std::string input = "OpDecorate %1 LinkageAttributes \"" +
356                             GetParam().external_name + "\" " +
357                             GetParam().linkage_type_name;
358   std::vector<uint32_t> expected_operands{1, SpvDecorationLinkageAttributes};
359   std::vector<uint32_t> encoded_external_name =
360       MakeVector(GetParam().external_name);
361   expected_operands.insert(expected_operands.end(),
362                            encoded_external_name.begin(),
363                            encoded_external_name.end());
364   expected_operands.push_back(GetParam().linkage_type_value);
365   EXPECT_THAT(CompiledInstructions(input),
366               Eq(MakeInstruction(SpvOpDecorate, expected_operands)));
367 }
368 
369 // clang-format off
370 #define CASE(ENUM) SpvLinkageType##ENUM, #ENUM
371 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateLinkage, OpDecorateLinkageTest,
372                         ::testing::ValuesIn(std::vector<DecorateLinkageCase>{
373                             { CASE(Import), "a" },
374                             { CASE(Export), "foo" },
375                             { CASE(Import), "some kind of long name with spaces etc." },
376                             // TODO(dneto): utf-8, escaping, quoting cases.
377                       }));
378 #undef CASE
379 // clang-format on
380 
TEST_F(OpDecorateLinkageTest,WrongType)381 TEST_F(OpDecorateLinkageTest, WrongType) {
382   EXPECT_THAT(CompileFailure("OpDecorate %1 LinkageAttributes \"foo\" xxyyzz"),
383               Eq("Invalid linkage type 'xxyyzz'."));
384 }
385 
386 // Test OpGroupMemberDecorate
387 
TEST_F(TextToBinaryTest,GroupMemberDecorateGoodOneTarget)388 TEST_F(TextToBinaryTest, GroupMemberDecorateGoodOneTarget) {
389   EXPECT_THAT(CompiledInstructions("OpGroupMemberDecorate %group %id0 42"),
390               Eq(MakeInstruction(SpvOpGroupMemberDecorate, {1, 2, 42})));
391 }
392 
TEST_F(TextToBinaryTest,GroupMemberDecorateGoodTwoTargets)393 TEST_F(TextToBinaryTest, GroupMemberDecorateGoodTwoTargets) {
394   EXPECT_THAT(
395       CompiledInstructions("OpGroupMemberDecorate %group %id0 96 %id1 42"),
396       Eq(MakeInstruction(SpvOpGroupMemberDecorate, {1, 2, 96, 3, 42})));
397 }
398 
TEST_F(TextToBinaryTest,GroupMemberDecorateMissingGroupId)399 TEST_F(TextToBinaryTest, GroupMemberDecorateMissingGroupId) {
400   EXPECT_THAT(CompileFailure("OpGroupMemberDecorate"),
401               Eq("Expected operand, found end of stream."));
402 }
403 
TEST_F(TextToBinaryTest,GroupMemberDecorateInvalidGroupId)404 TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidGroupId) {
405   EXPECT_THAT(CompileFailure("OpGroupMemberDecorate 16"),
406               Eq("Expected id to start with %."));
407 }
408 
TEST_F(TextToBinaryTest,GroupMemberDecorateInvalidTargetId)409 TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidTargetId) {
410   EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group 12"),
411               Eq("Expected id to start with %."));
412 }
413 
TEST_F(TextToBinaryTest,GroupMemberDecorateMissingTargetMemberNumber)414 TEST_F(TextToBinaryTest, GroupMemberDecorateMissingTargetMemberNumber) {
415   EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group %id0"),
416               Eq("Expected operand, found end of stream."));
417 }
418 
TEST_F(TextToBinaryTest,GroupMemberDecorateInvalidTargetMemberNumber)419 TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidTargetMemberNumber) {
420   EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group %id0 %id1"),
421               Eq("Invalid unsigned integer literal: %id1"));
422 }
423 
TEST_F(TextToBinaryTest,GroupMemberDecorateInvalidSecondTargetId)424 TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidSecondTargetId) {
425   EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group %id1 42 12"),
426               Eq("Expected id to start with %."));
427 }
428 
TEST_F(TextToBinaryTest,GroupMemberDecorateMissingSecondTargetMemberNumber)429 TEST_F(TextToBinaryTest, GroupMemberDecorateMissingSecondTargetMemberNumber) {
430   EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group %id0 42 %id1"),
431               Eq("Expected operand, found end of stream."));
432 }
433 
TEST_F(TextToBinaryTest,GroupMemberDecorateInvalidSecondTargetMemberNumber)434 TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidSecondTargetMemberNumber) {
435   EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group %id0 42 %id1 %id2"),
436               Eq("Invalid unsigned integer literal: %id2"));
437 }
438 
439 // Test OpMemberDecorate
440 
441 using OpMemberDecorateSimpleTest =
442     spvtest::TextToBinaryTestBase<::testing::TestWithParam<
443         std::tuple<spv_target_env, EnumCase<SpvDecoration>>>>;
444 
TEST_P(OpMemberDecorateSimpleTest,AnySimpleDecoration)445 TEST_P(OpMemberDecorateSimpleTest, AnySimpleDecoration) {
446   // This string should assemble, but should not validate.
447   std::stringstream input;
448   input << "OpMemberDecorate %1 42 " << std::get<1>(GetParam()).name();
449   for (auto operand : std::get<1>(GetParam()).operands())
450     input << " " << operand;
451   input << std::endl;
452   EXPECT_THAT(
453       CompiledInstructions(input.str(), std::get<0>(GetParam())),
454       Eq(MakeInstruction(SpvOpMemberDecorate,
455                          {1, 42, uint32_t(std::get<1>(GetParam()).value())},
456                          std::get<1>(GetParam()).operands())));
457   // Also check disassembly.
458   EXPECT_THAT(
459       EncodeAndDecodeSuccessfully(input.str(), SPV_BINARY_TO_TEXT_OPTION_NONE,
460                                   std::get<0>(GetParam())),
461       Eq(input.str()));
462 }
463 
464 #define CASE(NAME) SpvDecoration##NAME, #NAME
465 INSTANTIATE_TEST_SUITE_P(
466     TextToBinaryDecorateSimple, OpMemberDecorateSimpleTest,
467     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
468             ValuesIn(std::vector<EnumCase<SpvDecoration>>{
469                 // The operand literal values are arbitrarily chosen,
470                 // but there are the right number of them.
471                 {CASE(RelaxedPrecision), {}},
472                 {CASE(SpecId), {100}},
473                 {CASE(Block), {}},
474                 {CASE(BufferBlock), {}},
475                 {CASE(RowMajor), {}},
476                 {CASE(ColMajor), {}},
477                 {CASE(ArrayStride), {4}},
478                 {CASE(MatrixStride), {16}},
479                 {CASE(GLSLShared), {}},
480                 {CASE(GLSLPacked), {}},
481                 {CASE(CPacked), {}},
482                 // Placeholder line for enum value 12
483                 {CASE(NoPerspective), {}},
484                 {CASE(Flat), {}},
485                 {CASE(Patch), {}},
486                 {CASE(Centroid), {}},
487                 {CASE(Sample), {}},
488                 {CASE(Invariant), {}},
489                 {CASE(Restrict), {}},
490                 {CASE(Aliased), {}},
491                 {CASE(Volatile), {}},
492                 {CASE(Constant), {}},
493                 {CASE(Coherent), {}},
494                 {CASE(NonWritable), {}},
495                 {CASE(NonReadable), {}},
496                 {CASE(Uniform), {}},
497                 {CASE(SaturatedConversion), {}},
498                 {CASE(Stream), {2}},
499                 {CASE(Location), {6}},
500                 {CASE(Component), {3}},
501                 {CASE(Index), {14}},
502                 {CASE(Binding), {19}},
503                 {CASE(DescriptorSet), {7}},
504                 {CASE(Offset), {12}},
505                 {CASE(XfbBuffer), {1}},
506                 {CASE(XfbStride), {8}},
507                 {CASE(NoContraction), {}},
508                 {CASE(InputAttachmentIndex), {102}},
509                 {CASE(Alignment), {16}},
510             })));
511 
512 INSTANTIATE_TEST_SUITE_P(
513     TextToBinaryDecorateSimpleV11, OpMemberDecorateSimpleTest,
514     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
515             Values(EnumCase<SpvDecoration>{CASE(MaxByteOffset), {128}})));
516 #undef CASE
517 
TEST_F(OpMemberDecorateSimpleTest,WrongDecoration)518 TEST_F(OpMemberDecorateSimpleTest, WrongDecoration) {
519   EXPECT_THAT(CompileFailure("OpMemberDecorate %1 9 xxyyzz"),
520               Eq("Invalid decoration 'xxyyzz'."));
521 }
522 
TEST_F(OpMemberDecorateSimpleTest,ExtraOperandsOnDecorationExpectingNone)523 TEST_F(OpMemberDecorateSimpleTest, ExtraOperandsOnDecorationExpectingNone) {
524   EXPECT_THAT(CompileFailure("OpMemberDecorate %1 12 RelaxedPrecision 99"),
525               Eq("Expected <opcode> or <result-id> at the beginning of an "
526                  "instruction, found '99'."));
527 }
528 
TEST_F(OpMemberDecorateSimpleTest,ExtraOperandsOnDecorationExpectingOne)529 TEST_F(OpMemberDecorateSimpleTest, ExtraOperandsOnDecorationExpectingOne) {
530   EXPECT_THAT(CompileFailure("OpMemberDecorate %1 0 SpecId 99 100"),
531               Eq("Expected <opcode> or <result-id> at the beginning of an "
532                  "instruction, found '100'."));
533 }
534 
TEST_F(OpMemberDecorateSimpleTest,ExtraOperandsOnDecorationExpectingTwo)535 TEST_F(OpMemberDecorateSimpleTest, ExtraOperandsOnDecorationExpectingTwo) {
536   EXPECT_THAT(CompileFailure(
537                   "OpMemberDecorate %1 1 LinkageAttributes \"abc\" Import 42"),
538               Eq("Expected <opcode> or <result-id> at the beginning of an "
539                  "instruction, found '42'."));
540 }
541 
542 // TODO(dneto): OpMemberDecorate cases for decorations with parameters which
543 // are: not just lists of literal numbers.
544 
545 // TODO(dneto): OpDecorationGroup
546 // TODO(dneto): OpGroupDecorate
547 
548 }  // namespace
549 }  // namespace spvtools
550