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