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 28namespace spvtools { 29namespace { 30 31using spvtest::EnumCase; 32using spvtest::MakeInstruction; 33using utils::MakeVector; 34using spvtest::TextToBinaryTest; 35using ::testing::Combine; 36using ::testing::Eq; 37using ::testing::Values; 38using ::testing::ValuesIn; 39 40// Test OpDecorate 41 42using OpDecorateSimpleTest = 43 spvtest::TextToBinaryTestBase<::testing::TestWithParam< 44 std::tuple<spv_target_env, EnumCase<spv::Decoration>>>>; 45 46TEST_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. 65using OpDecorateSimpleIdTest = 66 spvtest::TextToBinaryTestBase<::testing::TestWithParam< 67 std::tuple<spv_target_env, EnumCase<spv::Decoration>>>>; 68 69TEST_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 88INSTANTIATE_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 135INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleV11, OpDecorateSimpleTest, 136 Combine(Values(SPV_ENV_UNIVERSAL_1_1), 137 Values(EnumCase<spv::Decoration>{ 138 CASE(MaxByteOffset), {128}}))); 139 140INSTANTIATE_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 147INSTANTIATE_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 157TEST_F(OpDecorateSimpleTest, WrongDecoration) { 158 EXPECT_THAT(CompileFailure("OpDecorate %1 xxyyzz"), 159 Eq("Invalid decoration 'xxyyzz'.")); 160} 161 162TEST_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 168TEST_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 174TEST_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. 182struct 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 191using OpDecorateEnumTest = 192 spvtest::TextToBinaryTestBase<::testing::TestWithParam<DecorateEnumCase>>; 193 194TEST_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" } 207INSTANTIATE_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 256TEST_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" } 265INSTANTIATE_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 279TEST_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" } 288INSTANTIATE_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 298TEST_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" } 311INSTANTIATE_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 323TEST_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 336TEST_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 345struct DecorateLinkageCase { 346 uint32_t linkage_type_value; 347 std::string linkage_type_name; 348 std::string external_name; 349}; 350 351using OpDecorateLinkageTest = spvtest::TextToBinaryTestBase< 352 ::testing::TestWithParam<DecorateLinkageCase>>; 353 354TEST_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 373INSTANTIATE_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 383TEST_F(OpDecorateLinkageTest, WrongType) { 384 EXPECT_THAT(CompileFailure("OpDecorate %1 LinkageAttributes \"foo\" xxyyzz"), 385 Eq("Invalid linkage type 'xxyyzz'.")); 386} 387 388// Test OpGroupMemberDecorate 389 390TEST_F(TextToBinaryTest, GroupMemberDecorateGoodOneTarget) { 391 EXPECT_THAT(CompiledInstructions("OpGroupMemberDecorate %group %id0 42"), 392 Eq(MakeInstruction(spv::Op::OpGroupMemberDecorate, {1, 2, 42}))); 393} 394 395TEST_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 401TEST_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 407TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidGroupId) { 408 EXPECT_THAT(CompileFailure("OpGroupMemberDecorate 16"), 409 Eq("Expected id to start with %.")); 410} 411 412TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidTargetId) { 413 EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group 12"), 414 Eq("Expected id to start with %.")); 415} 416 417TEST_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 423TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidTargetMemberNumber) { 424 EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group %id0 %id1"), 425 Eq("Invalid unsigned integer literal: %id1")); 426} 427 428TEST_F(TextToBinaryTest, GroupMemberDecorateInvalidSecondTargetId) { 429 EXPECT_THAT(CompileFailure("OpGroupMemberDecorate %group %id1 42 12"), 430 Eq("Expected id to start with %.")); 431} 432 433TEST_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 439TEST_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 446using OpMemberDecorateSimpleTest = 447 spvtest::TextToBinaryTestBase<::testing::TestWithParam< 448 std::tuple<spv_target_env, EnumCase<spv::Decoration>>>>; 449 450TEST_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 470INSTANTIATE_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 517INSTANTIATE_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 523TEST_F(OpMemberDecorateSimpleTest, WrongDecoration) { 524 EXPECT_THAT(CompileFailure("OpMemberDecorate %1 9 xxyyzz"), 525 Eq("Invalid decoration 'xxyyzz'.")); 526} 527 528TEST_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 534TEST_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 540TEST_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