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