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