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