Improve the instruction diagnostic for some access chain errors (#5978)
[KhronosGroup/SPIRV-Tools.git] / test / val / val_id_test.cpp
blobb4c9d78a8fc8d020f9a57b9866b2935836361b78
1 // Copyright (c) 2015-2016 The Khronos Group Inc.
2 // Modifications Copyright (C) 2024 Advanced Micro Devices, Inc. All rights
3 // reserved.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
17 #include <sstream>
18 #include <string>
19 #include <vector>
21 #include "gmock/gmock.h"
22 #include "test/test_fixture.h"
23 #include "test/unit_spirv.h"
24 #include "test/val/val_fixtures.h"
26 // NOTE: The tests in this file are ONLY testing ID usage, there for the input
27 // SPIR-V does not follow the logical layout rules from the spec in all cases in
28 // order to makes the tests smaller. Validation of the whole module is handled
29 // in stages, ID validation is only one of these stages. All validation stages
30 // are stand alone.
32 namespace spvtools {
33 namespace val {
34 namespace {
36 using spvtest::ScopedContext;
37 using ::testing::HasSubstr;
38 using ::testing::ValuesIn;
40 class ValidateIdWithMessage : public spvtest::ValidateBase<bool> {
41 public:
42 ValidateIdWithMessage() {
43 const bool use_friendly_names = GetParam();
44 spvValidatorOptionsSetFriendlyNames(options_, use_friendly_names);
47 std::string make_message(const char* msg);
50 std::string kOpCapabilitySetupWithoutVector16 = R"(
51 OpCapability Shader
52 OpCapability Linkage
53 OpCapability Addresses
54 OpCapability Int8
55 OpCapability Int16
56 OpCapability Int64
57 OpCapability Float64
58 OpCapability LiteralSampler
59 OpCapability Pipes
60 OpCapability DeviceEnqueue
61 )";
63 std::string kOpCapabilitySetup = R"(
64 OpCapability Shader
65 OpCapability Linkage
66 OpCapability Addresses
67 OpCapability Int8
68 OpCapability Int16
69 OpCapability Int64
70 OpCapability Float64
71 OpCapability LiteralSampler
72 OpCapability Pipes
73 OpCapability DeviceEnqueue
74 OpCapability Vector16
75 )";
77 std::string kOpVariablePtrSetUp = R"(
78 OpCapability VariablePointers
79 OpExtension "SPV_KHR_variable_pointers"
80 )";
82 std::string kGLSL450MemoryModel =
83 kOpCapabilitySetup + kOpVariablePtrSetUp + R"(
84 OpMemoryModel Logical GLSL450
85 )";
87 std::string kGLSL450MemoryModelWithoutVector16 =
88 kOpCapabilitySetupWithoutVector16 + kOpVariablePtrSetUp + R"(
89 OpMemoryModel Logical GLSL450
90 )";
92 std::string kNoKernelGLSL450MemoryModel = R"(
93 OpCapability Shader
94 OpCapability Linkage
95 OpCapability Addresses
96 OpCapability Int8
97 OpCapability Int16
98 OpCapability Int64
99 OpCapability Float64
100 OpMemoryModel Logical GLSL450
103 std::string kOpenCLMemoryModel32 = R"(
104 OpCapability Addresses
105 OpCapability Linkage
106 OpCapability Kernel
107 %1 = OpExtInstImport "OpenCL.std"
108 OpMemoryModel Physical32 OpenCL
111 std::string kOpenCLMemoryModel64 = R"(
112 OpCapability Addresses
113 OpCapability Linkage
114 OpCapability Kernel
115 OpCapability Int64
116 %1 = OpExtInstImport "OpenCL.std"
117 OpMemoryModel Physical64 OpenCL
120 std::string sampledImageSetup = R"(
121 %void = OpTypeVoid
122 %typeFuncVoid = OpTypeFunction %void
123 %float = OpTypeFloat 32
124 %v4float = OpTypeVector %float 4
125 %image_type = OpTypeImage %float 2D 0 0 0 1 Unknown
126 %_ptr_UniformConstant_img = OpTypePointer UniformConstant %image_type
127 %tex = OpVariable %_ptr_UniformConstant_img UniformConstant
128 %sampler_type = OpTypeSampler
129 %_ptr_UniformConstant_sam = OpTypePointer UniformConstant %sampler_type
130 %s = OpVariable %_ptr_UniformConstant_sam UniformConstant
131 %sampled_image_type = OpTypeSampledImage %image_type
132 %v2float = OpTypeVector %float 2
133 %float_1 = OpConstant %float 1
134 %float_2 = OpConstant %float 2
135 %const_vec_1_1 = OpConstantComposite %v2float %float_1 %float_1
136 %const_vec_2_2 = OpConstantComposite %v2float %float_2 %float_2
137 %bool_type = OpTypeBool
138 %spec_true = OpSpecConstantTrue %bool_type
139 %main = OpFunction %void None %typeFuncVoid
140 %label_1 = OpLabel
141 %image_inst = OpLoad %image_type %tex
142 %sampler_inst = OpLoad %sampler_type %s
145 std::string BranchConditionalSetup = R"(
146 OpCapability Shader
147 %1 = OpExtInstImport "GLSL.std.450"
148 OpMemoryModel Logical GLSL450
149 OpEntryPoint Fragment %main "main"
150 OpExecutionMode %main OriginUpperLeft
151 OpSource GLSL 140
152 OpName %main "main"
154 ; type definitions
155 %bool = OpTypeBool
156 %uint = OpTypeInt 32 0
157 %int = OpTypeInt 32 1
158 %float = OpTypeFloat 32
159 %v4float = OpTypeVector %float 4
161 ; constants
162 %true = OpConstantTrue %bool
163 %i0 = OpConstant %int 0
164 %i1 = OpConstant %int 1
165 %f0 = OpConstant %float 0
166 %f1 = OpConstant %float 1
169 ; main function header
170 %void = OpTypeVoid
171 %voidfunc = OpTypeFunction %void
172 %main = OpFunction %void None %voidfunc
173 %lmain = OpLabel
176 std::string BranchConditionalTail = R"(
177 %target_t = OpLabel
178 OpNop
179 OpBranch %end
180 %target_f = OpLabel
181 OpNop
182 OpBranch %end
184 %end = OpLabel
186 OpReturn
187 OpFunctionEnd
190 // Transform an expected validation message to either use friendly names (as
191 // provided in the message) or replace the friendly names by the corresponding
192 // id. The same flag used to configure the validator to output friendly names
193 // or not is used here.
194 std::string ValidateIdWithMessage::make_message(const char* msg) {
195 const bool use_friendly_names = GetParam();
196 if (use_friendly_names) {
197 return msg;
200 std::string message(msg);
201 std::ostringstream result;
203 size_t next = 0;
204 while (next < message.size()) {
205 // Parse 'num[%name]'
206 size_t open_quote = message.find('\'', next);
208 if (open_quote == std::string::npos) {
209 break;
212 // Copy up to the first quote
213 result.write(msg + next, open_quote - next);
214 // Handle apostrophes
215 if (!isdigit(message[open_quote + 1])) {
216 result << '\'';
217 next = open_quote + 1;
218 continue;
221 size_t open_bracket = message.find('[', open_quote + 1);
222 assert(open_bracket != std::string::npos);
224 size_t close_bracket = message.find(']', open_bracket + 1);
225 assert(close_bracket != std::string::npos);
227 size_t close_quote = close_bracket + 1;
228 assert(close_quote < message.size() && message[close_quote] == '\'');
230 // Change to 'num[%num]' because friendly names are not being used.
231 result.write(msg + open_quote, open_bracket - open_quote + 1);
232 result << '%';
233 result.write(msg + open_quote + 1, open_bracket - open_quote - 1);
234 result << "]'";
236 // Continue to the next id, or end of string.
237 next = close_quote + 1;
240 return result.str();
243 // TODO: OpUndef
245 TEST_P(ValidateIdWithMessage, OpName) {
246 std::string spirv = kGLSL450MemoryModel + R"(
247 OpName %2 "name"
248 %1 = OpTypeInt 32 0
249 %2 = OpTypePointer UniformConstant %1
250 %3 = OpVariable %2 UniformConstant)";
251 CompileSuccessfully(spirv.c_str());
252 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
255 TEST_P(ValidateIdWithMessage, OpMemberNameGood) {
256 std::string spirv = kGLSL450MemoryModel + R"(
257 OpMemberName %2 0 "foo"
258 %1 = OpTypeInt 32 0
259 %2 = OpTypeStruct %1)";
260 CompileSuccessfully(spirv.c_str());
261 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
263 TEST_P(ValidateIdWithMessage, OpMemberNameTypeBad) {
264 std::string spirv = kGLSL450MemoryModel + R"(
265 OpMemberName %1 0 "foo"
266 %1 = OpTypeInt 32 0)";
267 CompileSuccessfully(spirv.c_str());
268 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
269 EXPECT_THAT(getDiagnosticString(),
270 HasSubstr(make_message(
271 "OpMemberName Type <id> '1[%uint]' is not a struct type.")));
273 TEST_P(ValidateIdWithMessage, OpMemberNameMemberBad) {
274 std::string spirv = kGLSL450MemoryModel + R"(
275 OpMemberName %1 1 "foo"
276 %2 = OpTypeInt 32 0
277 %1 = OpTypeStruct %2)";
278 CompileSuccessfully(spirv.c_str());
279 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
280 EXPECT_THAT(getDiagnosticString(),
281 HasSubstr(make_message(
282 "OpMemberName Member <id> '1[%_struct_1]' index is larger "
283 "than Type <id> '1[%_struct_1]'s member count.")));
286 TEST_P(ValidateIdWithMessage, OpLineGood) {
287 std::string spirv = kGLSL450MemoryModel + R"(
288 %1 = OpString "/path/to/source.file"
289 OpLine %1 0 0
290 %2 = OpTypeInt 32 0
291 %3 = OpTypePointer Input %2
292 %4 = OpVariable %3 Input)";
293 CompileSuccessfully(spirv.c_str());
294 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
297 TEST_P(ValidateIdWithMessage, OpLineFileBad) {
298 std::string spirv = kGLSL450MemoryModel + R"(
299 %1 = OpTypeInt 32 0
300 OpLine %1 0 0
302 CompileSuccessfully(spirv.c_str());
303 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
304 EXPECT_THAT(getDiagnosticString(),
305 HasSubstr(make_message(
306 "OpLine Target <id> '1[%uint]' is not an OpString.")));
309 TEST_P(ValidateIdWithMessage, OpDecorateGood) {
310 std::string spirv = kGLSL450MemoryModel + R"(
311 OpDecorate %2 GLSLShared
312 %1 = OpTypeInt 64 0
313 %2 = OpTypeStruct %1 %1)";
314 CompileSuccessfully(spirv.c_str());
315 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
317 TEST_P(ValidateIdWithMessage, OpDecorateBad) {
318 std::string spirv = kGLSL450MemoryModel + R"(
319 OpDecorate %1 GLSLShared)";
320 CompileSuccessfully(spirv.c_str());
321 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
322 EXPECT_THAT(
323 getDiagnosticString(),
324 HasSubstr(make_message("forward referenced IDs have not been defined")));
327 TEST_P(ValidateIdWithMessage, OpMemberDecorateGood) {
328 std::string spirv = kGLSL450MemoryModel + R"(
329 OpMemberDecorate %2 0 RelaxedPrecision
330 %1 = OpTypeInt 32 0
331 %2 = OpTypeStruct %1 %1)";
332 CompileSuccessfully(spirv.c_str());
333 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
335 TEST_P(ValidateIdWithMessage, OpMemberDecorateBad) {
336 std::string spirv = kGLSL450MemoryModel + R"(
337 OpMemberDecorate %1 0 RelaxedPrecision
338 %1 = OpTypeInt 32 0)";
339 CompileSuccessfully(spirv.c_str());
340 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
341 EXPECT_THAT(getDiagnosticString(),
342 HasSubstr(make_message(
343 "OpMemberDecorate Structure type <id> '1[%uint]' is "
344 "not a struct type.")));
346 TEST_P(ValidateIdWithMessage, OpMemberDecorateMemberBad) {
347 std::string spirv = kGLSL450MemoryModel + R"(
348 OpMemberDecorate %1 3 RelaxedPrecision
349 %int = OpTypeInt 32 0
350 %1 = OpTypeStruct %int %int)";
351 CompileSuccessfully(spirv.c_str());
352 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
353 EXPECT_THAT(getDiagnosticString(),
354 HasSubstr(make_message(
355 "Index 3 provided in OpMemberDecorate for struct <id> "
356 "'1[%_struct_1]' is out of bounds. The structure has 2 "
357 "members. Largest valid index is 1.")));
360 TEST_P(ValidateIdWithMessage, OpGroupDecorateGood) {
361 std::string spirv = kGLSL450MemoryModel + R"(
362 %1 = OpDecorationGroup
363 OpDecorate %1 RelaxedPrecision
364 OpDecorate %1 GLSLShared
365 OpGroupDecorate %1 %3 %4
366 %2 = OpTypeInt 32 0
367 %3 = OpConstant %2 42
368 %4 = OpConstant %2 23)";
369 CompileSuccessfully(spirv.c_str());
370 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
372 TEST_P(ValidateIdWithMessage, OpDecorationGroupBad) {
373 std::string spirv = kGLSL450MemoryModel + R"(
374 %1 = OpDecorationGroup
375 OpDecorate %1 RelaxedPrecision
376 OpDecorate %1 GLSLShared
377 OpMemberDecorate %1 0 Constant
379 CompileSuccessfully(spirv.c_str());
380 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
381 EXPECT_THAT(getDiagnosticString(),
382 HasSubstr(make_message(
383 "Result id of OpDecorationGroup can only "
384 "be targeted by OpName, OpGroupDecorate, "
385 "OpDecorate, OpDecorateId, and OpGroupMemberDecorate")));
387 TEST_P(ValidateIdWithMessage, OpGroupDecorateDecorationGroupBad) {
388 std::string spirv = R"(
389 OpCapability Shader
390 OpCapability Linkage
391 %1 = OpExtInstImport "GLSL.std.450"
392 OpMemoryModel Logical GLSL450
393 OpGroupDecorate %1 %2 %3
394 %2 = OpTypeInt 32 0
395 %3 = OpConstant %2 42)";
396 CompileSuccessfully(spirv.c_str());
397 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
398 EXPECT_THAT(getDiagnosticString(),
399 HasSubstr(make_message(
400 "OpGroupDecorate Decoration group <id> '1[%1]' is not "
401 "a decoration group.")));
403 TEST_P(ValidateIdWithMessage, OpGroupDecorateTargetBad) {
404 std::string spirv = kGLSL450MemoryModel + R"(
405 %1 = OpDecorationGroup
406 OpDecorate %1 RelaxedPrecision
407 OpDecorate %1 GLSLShared
408 OpGroupDecorate %1 %3
409 %2 = OpTypeInt 32 0)";
410 CompileSuccessfully(spirv.c_str());
411 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
412 EXPECT_THAT(
413 getDiagnosticString(),
414 HasSubstr(make_message("forward referenced IDs have not been defined")));
416 TEST_P(ValidateIdWithMessage, OpGroupMemberDecorateDecorationGroupBad) {
417 std::string spirv = R"(
418 OpCapability Shader
419 OpCapability Linkage
420 %1 = OpExtInstImport "GLSL.std.450"
421 OpMemoryModel Logical GLSL450
422 OpGroupMemberDecorate %1 %2 0
423 %2 = OpTypeInt 32 0)";
424 CompileSuccessfully(spirv.c_str());
425 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
426 EXPECT_THAT(getDiagnosticString(),
427 HasSubstr(make_message(
428 "OpGroupMemberDecorate Decoration group <id> '1[%1]' "
429 "is not a decoration group.")));
431 TEST_P(ValidateIdWithMessage, OpGroupMemberDecorateIdNotStructBad) {
432 std::string spirv = kGLSL450MemoryModel + R"(
433 %1 = OpDecorationGroup
434 OpGroupMemberDecorate %1 %2 0
435 %2 = OpTypeInt 32 0)";
436 CompileSuccessfully(spirv.c_str());
437 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
438 EXPECT_THAT(getDiagnosticString(),
439 HasSubstr(make_message(
440 "OpGroupMemberDecorate Structure type <id> '2[%uint]' "
441 "is not a struct type.")));
443 TEST_P(ValidateIdWithMessage, OpGroupMemberDecorateIndexOutOfBoundBad) {
444 std::string spirv = kGLSL450MemoryModel + R"(
445 OpDecorate %1 Offset 0
446 %1 = OpDecorationGroup
447 OpGroupMemberDecorate %1 %struct 3
448 %float = OpTypeFloat 32
449 %struct = OpTypeStruct %float %float %float
451 CompileSuccessfully(spirv.c_str());
452 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
453 EXPECT_THAT(getDiagnosticString(),
454 HasSubstr(make_message(
455 "Index 3 provided in OpGroupMemberDecorate for struct "
456 "<id> '2[%_struct_2]' is out of bounds. The structure "
457 "has 3 members. Largest valid index is 2.")));
460 // TODO: OpExtInst
462 TEST_P(ValidateIdWithMessage, OpEntryPointGood) {
463 std::string spirv = kGLSL450MemoryModel + R"(
464 OpEntryPoint GLCompute %3 ""
465 %1 = OpTypeVoid
466 %2 = OpTypeFunction %1
467 %3 = OpFunction %1 None %2
468 %4 = OpLabel
469 OpReturn
470 OpFunctionEnd
472 CompileSuccessfully(spirv.c_str());
473 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
475 TEST_P(ValidateIdWithMessage, OpEntryPointFunctionBad) {
476 std::string spirv = kGLSL450MemoryModel + R"(
477 OpEntryPoint GLCompute %1 ""
478 %1 = OpTypeVoid)";
479 CompileSuccessfully(spirv.c_str());
480 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
481 EXPECT_THAT(getDiagnosticString(),
482 HasSubstr(make_message(
483 "OpEntryPoint Entry Point <id> '1[%void]' is not a "
484 "function.")));
486 TEST_P(ValidateIdWithMessage, OpEntryPointParameterCountBad) {
487 std::string spirv = kGLSL450MemoryModel + R"(
488 OpEntryPoint GLCompute %1 ""
489 %2 = OpTypeVoid
490 %3 = OpTypeFunction %2 %2
491 %1 = OpFunction %2 None %3
492 %4 = OpLabel
493 OpReturn
494 OpFunctionEnd)";
495 CompileSuccessfully(spirv.c_str());
496 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
497 EXPECT_THAT(
498 getDiagnosticString(),
499 HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
500 "parameter count is not zero")));
502 TEST_P(ValidateIdWithMessage, OpEntryPointReturnTypeBad) {
503 std::string spirv = kGLSL450MemoryModel + R"(
504 OpEntryPoint GLCompute %1 ""
505 %2 = OpTypeInt 32 0
506 %ret = OpConstant %2 0
507 %3 = OpTypeFunction %2
508 %1 = OpFunction %2 None %3
509 %4 = OpLabel
510 OpReturnValue %ret
511 OpFunctionEnd)";
512 CompileSuccessfully(spirv.c_str());
513 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
514 EXPECT_THAT(
515 getDiagnosticString(),
516 HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
517 "return type is not void.")));
519 TEST_P(ValidateIdWithMessage, OpEntryPointParameterCountBadInVulkan) {
520 std::string spirv = R"(
521 OpCapability Shader
522 OpMemoryModel Logical GLSL450
523 OpEntryPoint GLCompute %1 ""
524 %2 = OpTypeVoid
525 %3 = OpTypeFunction %2 %2
526 %1 = OpFunction %2 None %3
527 %4 = OpLabel
528 OpReturn
529 OpFunctionEnd)";
530 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
531 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
532 EXPECT_THAT(getDiagnosticString(),
533 AnyVUID("VUID-StandaloneSpirv-None-04633"));
534 EXPECT_THAT(
535 getDiagnosticString(),
536 HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
537 "parameter count is not zero")));
539 TEST_P(ValidateIdWithMessage, OpEntryPointReturnTypeBadInVulkan) {
540 std::string spirv = R"(
541 OpCapability Shader
542 OpMemoryModel Logical GLSL450
543 OpEntryPoint GLCompute %1 ""
544 %2 = OpTypeInt 32 0
545 %ret = OpConstant %2 0
546 %3 = OpTypeFunction %2
547 %1 = OpFunction %2 None %3
548 %4 = OpLabel
549 OpReturnValue %ret
550 OpFunctionEnd)";
551 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
552 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
553 EXPECT_THAT(getDiagnosticString(),
554 AnyVUID("VUID-StandaloneSpirv-None-04633"));
555 EXPECT_THAT(
556 getDiagnosticString(),
557 HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
558 "return type is not void.")));
561 TEST_P(ValidateIdWithMessage, OpEntryPointInterfaceIsNotVariableTypeBad) {
562 std::string spirv = R"(
563 OpCapability Shader
564 OpCapability Geometry
565 OpMemoryModel Logical GLSL450
566 OpEntryPoint Geometry %main "main" %ptr_builtin_1
567 OpExecutionMode %main InputPoints
568 OpExecutionMode %main OutputPoints
569 OpMemberDecorate %struct_1 0 BuiltIn InvocationId
570 %int = OpTypeInt 32 1
571 %void = OpTypeVoid
572 %func = OpTypeFunction %void
573 %struct_1 = OpTypeStruct %int
574 %ptr_builtin_1 = OpTypePointer Input %struct_1
575 %main = OpFunction %void None %func
576 %5 = OpLabel
577 OpReturn
578 OpFunctionEnd
580 CompileSuccessfully(spirv);
581 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
582 EXPECT_THAT(getDiagnosticString(),
583 HasSubstr("Interfaces passed to OpEntryPoint must be variables. "
584 "Found OpTypePointer."));
587 TEST_P(ValidateIdWithMessage, OpEntryPointInterfaceStorageClassBad) {
588 std::string spirv = R"(
589 OpCapability Shader
590 OpCapability Geometry
591 OpMemoryModel Logical GLSL450
592 OpEntryPoint Geometry %main "main" %in_1
593 OpExecutionMode %main InputPoints
594 OpExecutionMode %main OutputPoints
595 OpMemberDecorate %struct_1 0 BuiltIn InvocationId
596 %int = OpTypeInt 32 1
597 %void = OpTypeVoid
598 %func = OpTypeFunction %void
599 %struct_1 = OpTypeStruct %int
600 %ptr_builtin_1 = OpTypePointer Uniform %struct_1
601 %in_1 = OpVariable %ptr_builtin_1 Uniform
602 %main = OpFunction %void None %func
603 %5 = OpLabel
604 OpReturn
605 OpFunctionEnd
607 CompileSuccessfully(spirv);
608 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
609 EXPECT_THAT(getDiagnosticString(),
610 HasSubstr(make_message(
611 "OpEntryPoint interfaces must be OpVariables with "
612 "Storage Class of Input(1) or Output(3). Found Storage "
613 "Class 2 for Entry Point id 1.")));
616 TEST_P(ValidateIdWithMessage, OpExecutionModeGood) {
617 std::string spirv = kGLSL450MemoryModel + R"(
618 OpEntryPoint GLCompute %3 ""
619 OpExecutionMode %3 LocalSize 1 1 1
620 %1 = OpTypeVoid
621 %2 = OpTypeFunction %1
622 %3 = OpFunction %1 None %2
623 %4 = OpLabel
624 OpReturn
625 OpFunctionEnd)";
626 CompileSuccessfully(spirv.c_str());
627 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
630 TEST_P(ValidateIdWithMessage, OpExecutionModeEntryPointMissing) {
631 std::string spirv = kGLSL450MemoryModel + R"(
632 OpExecutionMode %3 LocalSize 1 1 1
633 %1 = OpTypeVoid
634 %2 = OpTypeFunction %1
635 %3 = OpFunction %1 None %2
636 %4 = OpLabel
637 OpReturn
638 OpFunctionEnd)";
639 CompileSuccessfully(spirv.c_str());
640 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
641 EXPECT_THAT(getDiagnosticString(),
642 HasSubstr(make_message(
643 "OpExecutionMode Entry Point <id> '1[%1]' is not the "
644 "Entry Point operand of an OpEntryPoint.")));
647 TEST_P(ValidateIdWithMessage, OpExecutionModeEntryPointBad) {
648 std::string spirv = kGLSL450MemoryModel + R"(
649 OpEntryPoint GLCompute %3 "" %a
650 OpExecutionMode %a LocalSize 1 1 1
651 %void = OpTypeVoid
652 %ptr = OpTypePointer Input %void
653 %a = OpVariable %ptr Input
654 %2 = OpTypeFunction %void
655 %3 = OpFunction %void None %2
656 %4 = OpLabel
657 OpReturn
658 OpFunctionEnd)";
659 CompileSuccessfully(spirv.c_str());
660 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
661 EXPECT_THAT(getDiagnosticString(),
662 HasSubstr(make_message(
663 "OpExecutionMode Entry Point <id> '2[%2]' is not the "
664 "Entry Point operand of an OpEntryPoint.")));
667 TEST_P(ValidateIdWithMessage, OpTypeVectorFloat) {
668 std::string spirv = kGLSL450MemoryModel + R"(
669 %1 = OpTypeFloat 32
670 %2 = OpTypeVector %1 4)";
671 CompileSuccessfully(spirv.c_str());
672 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
675 TEST_P(ValidateIdWithMessage, OpTypeVectorInt) {
676 std::string spirv = kGLSL450MemoryModel + R"(
677 %1 = OpTypeInt 32 0
678 %2 = OpTypeVector %1 4)";
679 CompileSuccessfully(spirv.c_str());
680 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
683 TEST_P(ValidateIdWithMessage, OpTypeVectorUInt) {
684 std::string spirv = kGLSL450MemoryModel + R"(
685 %1 = OpTypeInt 64 0
686 %2 = OpTypeVector %1 4)";
687 CompileSuccessfully(spirv.c_str());
688 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
691 TEST_P(ValidateIdWithMessage, OpTypeVectorBool) {
692 std::string spirv = kGLSL450MemoryModel + R"(
693 %1 = OpTypeBool
694 %2 = OpTypeVector %1 4)";
695 CompileSuccessfully(spirv.c_str());
696 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
699 TEST_P(ValidateIdWithMessage, OpTypeVectorComponentTypeBad) {
700 std::string spirv = kGLSL450MemoryModel + R"(
701 %1 = OpTypeFloat 32
702 %2 = OpTypePointer UniformConstant %1
703 %3 = OpTypeVector %2 4)";
704 CompileSuccessfully(spirv.c_str());
705 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
706 EXPECT_THAT(getDiagnosticString(),
707 HasSubstr(make_message(
708 "OpTypeVector Component Type <id> "
709 "'2[%_ptr_UniformConstant_float]' is not a scalar type.")));
712 TEST_P(ValidateIdWithMessage, OpTypeVectorColumnCountLessThanTwoBad) {
713 std::string spirv = kGLSL450MemoryModel + R"(
714 %1 = OpTypeFloat 32
715 %2 = OpTypeVector %1 1)";
716 CompileSuccessfully(spirv.c_str());
717 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
718 EXPECT_THAT(
719 getDiagnosticString(),
720 HasSubstr(make_message(
721 "Illegal number of components (1) for TypeVector\n %v1float = "
722 "OpTypeVector %float 1\n")));
725 TEST_P(ValidateIdWithMessage, OpTypeVectorColumnCountGreaterThanFourBad) {
726 std::string spirv = kGLSL450MemoryModel + R"(
727 %1 = OpTypeFloat 32
728 %2 = OpTypeVector %1 5)";
729 CompileSuccessfully(spirv.c_str());
730 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
731 EXPECT_THAT(
732 getDiagnosticString(),
733 HasSubstr(make_message(
734 "Illegal number of components (5) for TypeVector\n %v5float = "
735 "OpTypeVector %float 5\n")));
738 TEST_P(ValidateIdWithMessage, OpTypeVectorColumnCountEightWithoutVector16Bad) {
739 std::string spirv = kGLSL450MemoryModelWithoutVector16 + R"(
740 %1 = OpTypeFloat 32
741 %2 = OpTypeVector %1 8)";
743 CompileSuccessfully(spirv.c_str());
744 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
745 EXPECT_THAT(getDiagnosticString(),
746 HasSubstr(make_message(
747 "Having 8 components for TypeVector requires the Vector16 "
748 "capability\n %v8float = OpTypeVector %float 8\n")));
751 TEST_P(ValidateIdWithMessage,
752 OpTypeVectorColumnCountSixteenWithoutVector16Bad) {
753 std::string spirv = kGLSL450MemoryModelWithoutVector16 + R"(
754 %1 = OpTypeFloat 32
755 %2 = OpTypeVector %1 16)";
757 CompileSuccessfully(spirv.c_str());
758 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
759 EXPECT_THAT(getDiagnosticString(),
760 HasSubstr(make_message(
761 "Having 16 components for TypeVector requires the Vector16 "
762 "capability\n %v16float = OpTypeVector %float 16\n")));
765 TEST_P(ValidateIdWithMessage, OpTypeVectorColumnCountOfEightWithVector16Good) {
766 std::string spirv = kGLSL450MemoryModel + R"(
767 %1 = OpTypeFloat 32
768 %2 = OpTypeVector %1 8)";
769 CompileSuccessfully(spirv.c_str());
770 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
773 TEST_P(ValidateIdWithMessage,
774 OpTypeVectorColumnCountOfSixteenWithVector16Good) {
775 std::string spirv = kGLSL450MemoryModel + R"(
776 %1 = OpTypeFloat 32
777 %2 = OpTypeVector %1 16)";
778 CompileSuccessfully(spirv.c_str());
779 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
782 TEST_P(ValidateIdWithMessage, OpTypeMatrixGood) {
783 std::string spirv = kGLSL450MemoryModel + R"(
784 %1 = OpTypeFloat 32
785 %2 = OpTypeVector %1 2
786 %3 = OpTypeMatrix %2 3)";
787 CompileSuccessfully(spirv.c_str());
788 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
791 TEST_P(ValidateIdWithMessage, OpTypeMatrixColumnTypeNonVectorBad) {
792 std::string spirv = kGLSL450MemoryModel + R"(
793 %1 = OpTypeFloat 32
794 %2 = OpTypeMatrix %1 3)";
795 CompileSuccessfully(spirv.c_str());
796 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
797 EXPECT_THAT(getDiagnosticString(),
798 HasSubstr(make_message(
799 "olumns in a matrix must be of type vector.\n %mat3float = "
800 "OpTypeMatrix %float 3\n")));
803 TEST_P(ValidateIdWithMessage, OpTypeMatrixVectorTypeNonFloatBad) {
804 std::string spirv = kGLSL450MemoryModel + R"(
805 %1 = OpTypeInt 16 0
806 %2 = OpTypeVector %1 2
807 %3 = OpTypeMatrix %2 2)";
808 CompileSuccessfully(spirv.c_str());
809 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
810 EXPECT_THAT(getDiagnosticString(),
811 HasSubstr(make_message(
812 "Matrix types can only be parameterized with floating-point "
813 "types.\n %mat2v2ushort = OpTypeMatrix %v2ushort 2\n")));
816 TEST_P(ValidateIdWithMessage, OpTypeMatrixColumnCountLessThanTwoBad) {
817 std::string spirv = kGLSL450MemoryModel + R"(
818 %1 = OpTypeFloat 32
819 %2 = OpTypeVector %1 2
820 %3 = OpTypeMatrix %2 1)";
821 CompileSuccessfully(spirv.c_str());
822 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
823 EXPECT_THAT(
824 getDiagnosticString(),
825 HasSubstr(make_message(
826 "Matrix types can only be parameterized as having only 2, 3, "
827 "or 4 columns.\n %mat1v2float = OpTypeMatrix %v2float 1\n")));
830 TEST_P(ValidateIdWithMessage, OpTypeMatrixColumnCountGreaterThanFourBad) {
831 std::string spirv = kGLSL450MemoryModel + R"(
832 %1 = OpTypeFloat 32
833 %2 = OpTypeVector %1 2
834 %3 = OpTypeMatrix %2 8)";
835 CompileSuccessfully(spirv.c_str());
836 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
837 EXPECT_THAT(
838 getDiagnosticString(),
839 HasSubstr(make_message(
840 "Matrix types can only be parameterized as having only 2, 3, "
841 "or 4 columns.\n %mat8v2float = OpTypeMatrix %v2float 8\n")));
844 TEST_P(ValidateIdWithMessage, OpTypeSamplerGood) {
845 // In Rev31, OpTypeSampler takes no arguments.
846 std::string spirv = kGLSL450MemoryModel + R"(
847 %s = OpTypeSampler)";
848 CompileSuccessfully(spirv.c_str());
849 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
852 TEST_P(ValidateIdWithMessage, OpTypeArrayGood) {
853 std::string spirv = kGLSL450MemoryModel + R"(
854 %1 = OpTypeInt 32 0
855 %2 = OpConstant %1 1
856 %3 = OpTypeArray %1 %2)";
857 CompileSuccessfully(spirv.c_str());
858 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
861 TEST_P(ValidateIdWithMessage, OpTypeArrayElementTypeBad) {
862 std::string spirv = kGLSL450MemoryModel + R"(
863 %1 = OpTypeInt 32 0
864 %2 = OpConstant %1 1
865 %3 = OpTypeArray %2 %2)";
866 CompileSuccessfully(spirv.c_str());
867 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
868 EXPECT_THAT(getDiagnosticString(),
869 HasSubstr(make_message(
870 "OpTypeArray Element Type <id> '2[%uint_1]' is not a "
871 "type.")));
874 // Signed or unsigned.
875 enum Signed { kSigned, kUnsigned };
877 // Creates an assembly module declaring OpTypeArray with the given length.
878 std::string MakeArrayLength(const std::string& len, Signed isSigned, int width,
879 int max_int_width = 64,
880 bool use_vulkan_memory_model = false) {
881 std::ostringstream ss;
882 ss << R"(
883 OpCapability Shader
885 if (use_vulkan_memory_model) {
886 ss << " OpCapability VulkanMemoryModel\n";
888 if (width == 16) {
889 ss << " OpCapability Int16\n";
891 if (max_int_width > 32) {
892 ss << "\n OpCapability Int64\n";
894 if (use_vulkan_memory_model) {
895 ss << " OpExtension \"SPV_KHR_vulkan_memory_model\"\n";
896 ss << "OpMemoryModel Logical Vulkan\n";
897 } else {
898 ss << "OpMemoryModel Logical GLSL450\n";
900 ss << "OpEntryPoint GLCompute %main \"main\"\n";
901 ss << "OpExecutionMode %main LocalSize 1 1 1\n";
902 ss << " %t = OpTypeInt " << width << (isSigned == kSigned ? " 1" : " 0");
903 ss << " %l = OpConstant %t " << len;
904 ss << " %a = OpTypeArray %t %l";
905 ss << " %void = OpTypeVoid \n"
906 " %voidfn = OpTypeFunction %void \n"
907 " %main = OpFunction %void None %voidfn \n"
908 " %entry = OpLabel\n"
909 " OpReturn\n"
910 " OpFunctionEnd\n";
911 return ss.str();
914 // Tests OpTypeArray. Parameter is the width (in bits) of the array-length's
915 // type.
916 class OpTypeArrayLengthTest
917 : public spvtest::TextToBinaryTestBase<::testing::TestWithParam<int>> {
918 protected:
919 OpTypeArrayLengthTest()
920 : env_(SPV_ENV_UNIVERSAL_1_0),
921 position_(spv_position_t{0, 0, 0}),
922 diagnostic_(spvDiagnosticCreate(&position_, "")) {}
924 ~OpTypeArrayLengthTest() override { spvDiagnosticDestroy(diagnostic_); }
926 // Runs spvValidate() on v, printing any errors via spvDiagnosticPrint().
927 spv_result_t Val(const SpirvVector& v, const std::string& expected_err = "") {
928 spv_const_binary_t cbinary{v.data(), v.size()};
929 spvDiagnosticDestroy(diagnostic_);
930 diagnostic_ = nullptr;
931 const auto status =
932 spvValidate(ScopedContext(env_).context, &cbinary, &diagnostic_);
933 if (status != SPV_SUCCESS) {
934 spvDiagnosticPrint(diagnostic_);
935 EXPECT_THAT(std::string(diagnostic_->error),
936 testing::ContainsRegex(expected_err));
938 return status;
941 protected:
942 spv_target_env env_;
944 private:
945 spv_position_t position_; // For creating diagnostic_.
946 spv_diagnostic diagnostic_;
949 TEST_P(OpTypeArrayLengthTest, LengthPositiveSmall) {
950 const int width = GetParam();
951 EXPECT_EQ(SPV_SUCCESS,
952 Val(CompileSuccessfully(MakeArrayLength("1", kSigned, width))));
953 EXPECT_EQ(SPV_SUCCESS,
954 Val(CompileSuccessfully(MakeArrayLength("1", kUnsigned, width))));
955 EXPECT_EQ(SPV_SUCCESS,
956 Val(CompileSuccessfully(MakeArrayLength("2", kSigned, width))));
957 EXPECT_EQ(SPV_SUCCESS,
958 Val(CompileSuccessfully(MakeArrayLength("2", kUnsigned, width))));
959 EXPECT_EQ(SPV_SUCCESS,
960 Val(CompileSuccessfully(MakeArrayLength("55", kSigned, width))));
961 EXPECT_EQ(SPV_SUCCESS,
962 Val(CompileSuccessfully(MakeArrayLength("55", kUnsigned, width))));
963 const std::string fpad(width / 4 - 1, 'F');
964 EXPECT_EQ(
965 SPV_SUCCESS,
966 Val(CompileSuccessfully(MakeArrayLength("0x7" + fpad, kSigned, width))))
967 << MakeArrayLength("0x7" + fpad, kSigned, width);
970 TEST_P(OpTypeArrayLengthTest, LengthZero) {
971 const int width = GetParam();
972 EXPECT_EQ(SPV_ERROR_INVALID_ID,
973 Val(CompileSuccessfully(MakeArrayLength("0", kSigned, width)),
974 "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
975 "least 1."));
976 EXPECT_EQ(SPV_ERROR_INVALID_ID,
977 Val(CompileSuccessfully(MakeArrayLength("0", kUnsigned, width)),
978 "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
979 "least 1."));
982 TEST_P(OpTypeArrayLengthTest, LengthNegative) {
983 const int width = GetParam();
984 EXPECT_EQ(SPV_ERROR_INVALID_ID,
985 Val(CompileSuccessfully(MakeArrayLength("-1", kSigned, width)),
986 "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
987 "least 1."));
988 EXPECT_EQ(SPV_ERROR_INVALID_ID,
989 Val(CompileSuccessfully(MakeArrayLength("-2", kSigned, width)),
990 "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
991 "least 1."));
992 EXPECT_EQ(SPV_ERROR_INVALID_ID,
993 Val(CompileSuccessfully(MakeArrayLength("-123", kSigned, width)),
994 "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
995 "least 1."));
996 const std::string neg_max = "0x8" + std::string(width / 4 - 1, '0');
997 EXPECT_EQ(SPV_ERROR_INVALID_ID,
998 Val(CompileSuccessfully(MakeArrayLength(neg_max, kSigned, width)),
999 "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
1000 "least 1."));
1003 // Returns the string form of an integer of the form 0x80....0 of the
1004 // given bit width.
1005 std::string big_num_ending_0(int bit_width) {
1006 return "0x8" + std::string(bit_width / 4 - 1, '0');
1009 // Returns the string form of an integer of the form 0x80..001 of the
1010 // given bit width.
1011 std::string big_num_ending_1(int bit_width) {
1012 return "0x8" + std::string(bit_width / 4 - 2, '0') + "1";
1015 TEST_P(OpTypeArrayLengthTest, LengthPositiveHugeEnding0InVulkan) {
1016 env_ = SPV_ENV_VULKAN_1_0;
1017 const int width = GetParam();
1018 for (int max_int_width : {32, 64}) {
1019 if (width > max_int_width) {
1020 // Not valid to even make the OpConstant in this case.
1021 continue;
1023 const auto module = CompileSuccessfully(MakeArrayLength(
1024 big_num_ending_0(width), kUnsigned, width, max_int_width));
1025 EXPECT_EQ(SPV_SUCCESS, Val(module));
1029 TEST_P(OpTypeArrayLengthTest, LengthPositiveHugeEnding1InVulkan) {
1030 env_ = SPV_ENV_VULKAN_1_0;
1031 const int width = GetParam();
1032 for (int max_int_width : {32, 64}) {
1033 if (width > max_int_width) {
1034 // Not valid to even make the OpConstant in this case.
1035 continue;
1037 const auto module = CompileSuccessfully(MakeArrayLength(
1038 big_num_ending_1(width), kUnsigned, width, max_int_width));
1039 EXPECT_EQ(SPV_SUCCESS, Val(module));
1043 // The only valid widths for integers are 8, 16, 32, and 64.
1044 // Since the Int8 capability requires the Kernel capability, and the Kernel
1045 // capability prohibits usage of signed integers, we can skip 8-bit integers
1046 // here since the purpose of these tests is to check the validity of
1047 // OpTypeArray, not OpTypeInt.
1048 INSTANTIATE_TEST_SUITE_P(Widths, OpTypeArrayLengthTest,
1049 ValuesIn(std::vector<int>{16, 32, 64}));
1051 TEST_P(ValidateIdWithMessage, OpTypeArrayLengthNull) {
1052 std::string spirv = kGLSL450MemoryModel + R"(
1053 %i32 = OpTypeInt 32 0
1054 %len = OpConstantNull %i32
1055 %ary = OpTypeArray %i32 %len)";
1056 CompileSuccessfully(spirv.c_str());
1057 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1058 EXPECT_THAT(getDiagnosticString(),
1059 HasSubstr(make_message("OpTypeArray Length <id> '2[%2]' default "
1060 "value must be at least 1: found 0")));
1063 TEST_P(ValidateIdWithMessage, OpTypeArrayLengthSpecConst) {
1064 std::string spirv = kGLSL450MemoryModel + R"(
1065 %i32 = OpTypeInt 32 0
1066 %len = OpSpecConstant %i32 2
1067 %ary = OpTypeArray %i32 %len)";
1068 CompileSuccessfully(spirv.c_str());
1069 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1072 TEST_P(ValidateIdWithMessage, OpTypeArrayLengthSpecConstOp) {
1073 std::string spirv = kGLSL450MemoryModel + R"(
1074 %i32 = OpTypeInt 32 0
1075 %c1 = OpConstant %i32 1
1076 %c2 = OpConstant %i32 2
1077 %len = OpSpecConstantOp %i32 IAdd %c1 %c2
1078 %ary = OpTypeArray %i32 %len)";
1079 CompileSuccessfully(spirv.c_str());
1080 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1083 TEST_P(ValidateIdWithMessage, OpTypeRuntimeArrayGood) {
1084 std::string spirv = kGLSL450MemoryModel + R"(
1085 %1 = OpTypeInt 32 0
1086 %2 = OpTypeRuntimeArray %1)";
1087 CompileSuccessfully(spirv.c_str());
1088 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1090 TEST_P(ValidateIdWithMessage, OpTypeRuntimeArrayBad) {
1091 std::string spirv = kGLSL450MemoryModel + R"(
1092 %1 = OpTypeInt 32 0
1093 %2 = OpConstant %1 0
1094 %3 = OpTypeRuntimeArray %2)";
1095 CompileSuccessfully(spirv.c_str());
1096 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1097 EXPECT_THAT(getDiagnosticString(),
1098 HasSubstr(make_message(
1099 "OpTypeRuntimeArray Element Type <id> '2[%uint_0]' is not a "
1100 "type.")));
1102 // TODO: Object of this type can only be created with OpVariable using the
1103 // Uniform Storage Class
1105 TEST_P(ValidateIdWithMessage, OpTypeStructGood) {
1106 std::string spirv = kGLSL450MemoryModel + R"(
1107 %1 = OpTypeInt 32 0
1108 %2 = OpTypeFloat 64
1109 %3 = OpTypePointer Input %1
1110 %4 = OpTypeStruct %1 %2 %3)";
1111 CompileSuccessfully(spirv.c_str());
1112 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1114 TEST_P(ValidateIdWithMessage, OpTypeStructMemberTypeBad) {
1115 std::string spirv = kGLSL450MemoryModel + R"(
1116 %1 = OpTypeInt 32 0
1117 %2 = OpTypeFloat 64
1118 %3 = OpConstant %2 0.0
1119 %4 = OpTypeStruct %1 %2 %3)";
1120 CompileSuccessfully(spirv.c_str());
1121 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1122 EXPECT_THAT(getDiagnosticString(),
1123 HasSubstr(make_message(
1124 "OpTypeStruct Member Type <id> '3[%double_0]' is not "
1125 "a type.")));
1128 TEST_P(ValidateIdWithMessage, OpTypeStructOpaqueTypeBad) {
1129 std::string spirv = R"(
1130 OpCapability Shader
1131 OpMemoryModel Logical GLSL450
1132 OpEntryPoint Vertex %main "main"
1133 %1 = OpTypeSampler
1134 %2 = OpTypeStruct %1
1135 %void = OpTypeVoid
1136 %3 = OpTypeFunction %void
1137 %main = OpFunction %void None %3
1138 %5 = OpLabel
1139 OpReturn
1140 OpFunctionEnd
1142 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
1143 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1144 EXPECT_THAT(getDiagnosticString(),
1145 AnyVUID("VUID-StandaloneSpirv-None-04667"));
1146 EXPECT_THAT(
1147 getDiagnosticString(),
1148 HasSubstr(make_message("OpTypeStruct must not contain an opaque type")));
1151 TEST_P(ValidateIdWithMessage, OpTypePointerGood) {
1152 std::string spirv = kGLSL450MemoryModel + R"(
1153 %1 = OpTypeInt 32 0
1154 %2 = OpTypePointer Input %1)";
1155 CompileSuccessfully(spirv.c_str());
1156 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1158 TEST_P(ValidateIdWithMessage, OpTypePointerBad) {
1159 std::string spirv = kGLSL450MemoryModel + R"(
1160 %1 = OpTypeInt 32 0
1161 %2 = OpConstant %1 0
1162 %3 = OpTypePointer Input %2)";
1163 CompileSuccessfully(spirv.c_str());
1164 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1165 EXPECT_THAT(
1166 getDiagnosticString(),
1167 HasSubstr(make_message("OpTypePointer Type <id> '2[%uint_0]' is not a "
1168 "type.")));
1171 TEST_P(ValidateIdWithMessage, OpTypePointerCanHaveUntypedPointer) {
1172 const std::string spirv = R"(
1173 OpCapability Kernel
1174 OpCapability Linkage
1175 OpCapability UntypedPointersKHR
1176 OpCapability WorkgroupMemoryExplicitLayoutKHR
1177 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
1178 OpExtension "SPV_KHR_untyped_pointers"
1179 OpMemoryModel Logical OpenCL
1180 %ptr = OpTypeUntypedPointerKHR Workgroup
1181 %ptr2 = OpTypePointer Private %ptr
1184 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1185 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1188 TEST_P(ValidateIdWithMessage, OpTypeUntypedPointerWorkgroupGood) {
1189 const std::string spirv = R"(
1190 OpCapability Shader
1191 OpCapability Linkage
1192 OpCapability UntypedPointersKHR
1193 OpCapability WorkgroupMemoryExplicitLayoutKHR
1194 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
1195 OpExtension "SPV_KHR_untyped_pointers"
1196 OpMemoryModel Logical GLSL450
1197 %ptr = OpTypeUntypedPointerKHR Workgroup
1200 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1201 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1204 TEST_P(ValidateIdWithMessage,
1205 OpTypeUntypedPointerWorkgroupMissingExplicitLayout) {
1206 const std::string spirv = R"(
1207 OpCapability Shader
1208 OpCapability UntypedPointersKHR
1209 OpExtension "SPV_KHR_untyped_pointers"
1210 OpMemoryModel Logical GLSL450
1211 OpEntryPoint GLCompute %main "main"
1212 OpExecutionMode %main LocalSize 1 1 1
1213 %ptr = OpTypeUntypedPointerKHR Workgroup
1214 %void = OpTypeVoid
1215 %void_fn = OpTypeFunction %void
1216 %main = OpFunction %void None %void_fn
1217 %entry = OpLabel
1218 OpReturn
1219 OpFunctionEnd
1222 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
1223 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
1224 EXPECT_THAT(
1225 getDiagnosticString(),
1226 HasSubstr("Workgroup storage class untyped pointers in Vulkan require "
1227 "WorkgroupMemoryExplicitLayoutKHR be declared"));
1230 TEST_P(ValidateIdWithMessage, OpTypeUntypedPointerWorkgroupGoodAll) {
1231 const std::string spirv = R"(
1232 OpCapability Shader
1233 OpCapability Linkage
1234 OpCapability UntypedPointersKHR
1235 OpExtension "SPV_KHR_untyped_pointers"
1236 OpMemoryModel Logical GLSL450
1237 %ptr = OpTypeUntypedPointerKHR Workgroup
1240 CompileSuccessfully(spirv);
1241 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1244 TEST_P(ValidateIdWithMessage, OpTypeUntypedPointerStorageBufferGood) {
1245 const std::string spirv = R"(
1246 OpCapability Shader
1247 OpCapability Linkage
1248 OpCapability UntypedPointersKHR
1249 OpExtension "SPV_KHR_storage_buffer_storage_class"
1250 OpExtension "SPV_KHR_untyped_pointers"
1251 OpMemoryModel Logical GLSL450
1252 %ptr = OpTypeUntypedPointerKHR StorageBuffer
1255 CompileSuccessfully(spirv);
1256 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1259 TEST_P(ValidateIdWithMessage, OpTypeUntypedPointerUniformGood) {
1260 const std::string spirv = R"(
1261 OpCapability Shader
1262 OpCapability Linkage
1263 OpCapability UntypedPointersKHR
1264 OpExtension "SPV_KHR_untyped_pointers"
1265 OpMemoryModel Logical GLSL450
1266 %ptr = OpTypeUntypedPointerKHR Uniform
1269 CompileSuccessfully(spirv);
1270 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1273 TEST_P(ValidateIdWithMessage, OpTypeUntypedPointerPushConstantGood) {
1274 const std::string spirv = R"(
1275 OpCapability Shader
1276 OpCapability Linkage
1277 OpCapability UntypedPointersKHR
1278 OpExtension "SPV_KHR_untyped_pointers"
1279 OpMemoryModel Logical GLSL450
1280 %ptr = OpTypeUntypedPointerKHR PushConstant
1283 CompileSuccessfully(spirv);
1284 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1287 TEST_P(ValidateIdWithMessage, OpTypeUntypedPointerCrossWorkgroupGood) {
1288 const std::string spirv = R"(
1289 OpCapability Kernel
1290 OpCapability Linkage
1291 OpCapability UntypedPointersKHR
1292 OpExtension "SPV_KHR_untyped_pointers"
1293 OpMemoryModel Logical OpenCL
1294 %ptr = OpTypeUntypedPointerKHR CrossWorkgroup
1297 CompileSuccessfully(spirv);
1298 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1301 TEST_P(ValidateIdWithMessage, OpTypeUntypedPointerVulkanInvalidStorageClass) {
1302 const std::string spirv = R"(
1303 OpCapability Shader
1304 OpCapability UntypedPointersKHR
1305 OpExtension "SPV_KHR_untyped_pointers"
1306 OpMemoryModel Logical GLSL450
1307 OpEntryPoint GLCompute %main "main"
1308 OpExecutionMode %main LocalSize 1 1 1
1309 %void = OpTypeVoid
1310 %void_fn = OpTypeFunction %void
1311 %ptr = OpTypeUntypedPointerKHR Private
1312 %main = OpFunction %void None %void_fn
1313 %entry = OpLabel
1314 OpReturn
1315 OpFunctionEnd
1318 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
1319 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1320 EXPECT_THAT(getDiagnosticString(),
1321 HasSubstr("In Vulkan, untyped pointers can only be used in an "
1322 "explicitly laid out storage class"));
1325 TEST_P(ValidateIdWithMessage, OpTypeFunctionGood) {
1326 std::string spirv = kGLSL450MemoryModel + R"(
1327 %1 = OpTypeVoid
1328 %2 = OpTypeFunction %1)";
1329 CompileSuccessfully(spirv.c_str());
1330 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1332 TEST_P(ValidateIdWithMessage, OpTypeFunctionReturnTypeBad) {
1333 std::string spirv = kGLSL450MemoryModel + R"(
1334 %1 = OpTypeInt 32 0
1335 %2 = OpConstant %1 0
1336 %3 = OpTypeFunction %2)";
1337 CompileSuccessfully(spirv.c_str());
1338 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1339 EXPECT_THAT(getDiagnosticString(),
1340 HasSubstr(make_message(
1341 "OpTypeFunction Return Type <id> '2[%uint_0]' is not "
1342 "a type.")));
1344 TEST_P(ValidateIdWithMessage, OpTypeFunctionParameterBad) {
1345 std::string spirv = kGLSL450MemoryModel + R"(
1346 %1 = OpTypeVoid
1347 %2 = OpTypeInt 32 0
1348 %3 = OpConstant %2 0
1349 %4 = OpTypeFunction %1 %2 %3)";
1350 CompileSuccessfully(spirv.c_str());
1351 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1352 EXPECT_THAT(getDiagnosticString(),
1353 HasSubstr(make_message(
1354 "OpTypeFunction Parameter Type <id> '3[%uint_0]' is not a "
1355 "type.")));
1358 TEST_P(ValidateIdWithMessage, OpTypeFunctionParameterTypeVoidBad) {
1359 std::string spirv = kGLSL450MemoryModel + R"(
1360 %1 = OpTypeVoid
1361 %2 = OpTypeInt 32 0
1362 %4 = OpTypeFunction %1 %2 %1)";
1363 CompileSuccessfully(spirv.c_str());
1364 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1365 EXPECT_THAT(getDiagnosticString(),
1366 HasSubstr(make_message(
1367 "OpTypeFunction Parameter Type <id> '1[%void]' cannot "
1368 "be OpTypeVoid.")));
1371 TEST_P(ValidateIdWithMessage, OpTypePipeGood) {
1372 std::string spirv = kGLSL450MemoryModel + R"(
1373 %1 = OpTypeFloat 32
1374 %2 = OpTypeVector %1 16
1375 %3 = OpTypePipe ReadOnly)";
1376 CompileSuccessfully(spirv.c_str());
1377 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1380 TEST_P(ValidateIdWithMessage, OpConstantTrueGood) {
1381 std::string spirv = kGLSL450MemoryModel + R"(
1382 %1 = OpTypeBool
1383 %2 = OpConstantTrue %1)";
1384 CompileSuccessfully(spirv.c_str());
1385 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1387 TEST_P(ValidateIdWithMessage, OpConstantTrueBad) {
1388 std::string spirv = kGLSL450MemoryModel + R"(
1389 %1 = OpTypeVoid
1390 %2 = OpConstantTrue %1)";
1391 CompileSuccessfully(spirv.c_str());
1392 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1393 EXPECT_THAT(getDiagnosticString(),
1394 HasSubstr(make_message(
1395 "OpConstantTrue Result Type <id> '1[%void]' is not a boolean "
1396 "type.")));
1399 TEST_P(ValidateIdWithMessage, OpConstantFalseGood) {
1400 std::string spirv = kGLSL450MemoryModel + R"(
1401 %1 = OpTypeBool
1402 %2 = OpConstantTrue %1)";
1403 CompileSuccessfully(spirv.c_str());
1404 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1406 TEST_P(ValidateIdWithMessage, OpConstantFalseBad) {
1407 std::string spirv = kGLSL450MemoryModel + R"(
1408 %1 = OpTypeVoid
1409 %2 = OpConstantFalse %1)";
1410 CompileSuccessfully(spirv.c_str());
1411 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1412 EXPECT_THAT(
1413 getDiagnosticString(),
1414 HasSubstr(make_message(
1415 "OpConstantFalse Result Type <id> '1[%void]' is not a boolean "
1416 "type.")));
1419 TEST_P(ValidateIdWithMessage, OpConstantGood) {
1420 std::string spirv = kGLSL450MemoryModel + R"(
1421 %1 = OpTypeInt 32 0
1422 %2 = OpConstant %1 1)";
1423 CompileSuccessfully(spirv.c_str());
1424 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1426 TEST_P(ValidateIdWithMessage, OpConstantBad) {
1427 std::string spirv = kGLSL450MemoryModel + R"(
1428 %1 = OpTypeVoid
1429 %2 = OpConstant !1 !0)";
1430 // The expected failure code is implementation dependent (currently
1431 // INVALID_BINARY because the binary parser catches these cases) and may
1432 // change over time, but this must always fail.
1433 CompileSuccessfully(spirv.c_str());
1434 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
1437 TEST_P(ValidateIdWithMessage, OpConstantCompositeVectorGood) {
1438 std::string spirv = kGLSL450MemoryModel + R"(
1439 %1 = OpTypeFloat 32
1440 %2 = OpTypeVector %1 4
1441 %3 = OpConstant %1 3.14
1442 %4 = OpConstantComposite %2 %3 %3 %3 %3)";
1443 CompileSuccessfully(spirv.c_str());
1444 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1446 TEST_P(ValidateIdWithMessage, OpConstantCompositeVectorWithUndefGood) {
1447 std::string spirv = kGLSL450MemoryModel + R"(
1448 %1 = OpTypeFloat 32
1449 %2 = OpTypeVector %1 4
1450 %3 = OpConstant %1 3.14
1451 %9 = OpUndef %1
1452 %4 = OpConstantComposite %2 %3 %3 %3 %9)";
1453 CompileSuccessfully(spirv.c_str());
1454 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1456 TEST_P(ValidateIdWithMessage, OpConstantCompositeVectorResultTypeBad) {
1457 std::string spirv = kGLSL450MemoryModel + R"(
1458 %1 = OpTypeFloat 32
1459 %2 = OpTypeVector %1 4
1460 %3 = OpConstant %1 3.14
1461 %4 = OpConstantComposite %1 %3 %3 %3 %3)";
1462 CompileSuccessfully(spirv.c_str());
1463 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1464 EXPECT_THAT(getDiagnosticString(),
1465 HasSubstr(make_message(
1466 "OpConstantComposite Result Type <id> '1[%float]' is not a "
1467 "composite type.")));
1469 TEST_P(ValidateIdWithMessage, OpConstantCompositeVectorConstituentTypeBad) {
1470 std::string spirv = kGLSL450MemoryModel + R"(
1471 %1 = OpTypeFloat 32
1472 %2 = OpTypeVector %1 4
1473 %4 = OpTypeInt 32 0
1474 %3 = OpConstant %1 3.14
1475 %5 = OpConstant %4 42 ; bad type for constant value
1476 %6 = OpConstantComposite %2 %3 %5 %3 %3)";
1477 CompileSuccessfully(spirv.c_str());
1478 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1479 EXPECT_THAT(getDiagnosticString(),
1480 HasSubstr(make_message(
1481 "OpConstantComposite Constituent <id> '5[%uint_42]'s type "
1482 "does not match Result Type <id> '2[%v4float]'s vector "
1483 "element type.")));
1485 TEST_P(ValidateIdWithMessage,
1486 OpConstantCompositeVectorConstituentUndefTypeBad) {
1487 std::string spirv = kGLSL450MemoryModel + R"(
1488 %1 = OpTypeFloat 32
1489 %2 = OpTypeVector %1 4
1490 %4 = OpTypeInt 32 0
1491 %3 = OpConstant %1 3.14
1492 %5 = OpUndef %4 ; bad type for undef value
1493 %6 = OpConstantComposite %2 %3 %5 %3 %3)";
1494 CompileSuccessfully(spirv.c_str());
1495 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1496 EXPECT_THAT(
1497 getDiagnosticString(),
1498 HasSubstr(make_message(
1499 "OpConstantComposite Constituent <id> '5[%5]'s type does not "
1500 "match Result Type <id> '2[%v4float]'s vector element type.")));
1502 TEST_P(ValidateIdWithMessage, OpConstantCompositeMatrixGood) {
1503 std::string spirv = kGLSL450MemoryModel + R"(
1504 %1 = OpTypeFloat 32
1505 %2 = OpTypeVector %1 4
1506 %3 = OpTypeMatrix %2 4
1507 %4 = OpConstant %1 1.0
1508 %5 = OpConstant %1 0.0
1509 %6 = OpConstantComposite %2 %4 %5 %5 %5
1510 %7 = OpConstantComposite %2 %5 %4 %5 %5
1511 %8 = OpConstantComposite %2 %5 %5 %4 %5
1512 %9 = OpConstantComposite %2 %5 %5 %5 %4
1513 %10 = OpConstantComposite %3 %6 %7 %8 %9)";
1514 CompileSuccessfully(spirv.c_str());
1515 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1517 TEST_P(ValidateIdWithMessage, OpConstantCompositeMatrixUndefGood) {
1518 std::string spirv = kGLSL450MemoryModel + R"(
1519 %1 = OpTypeFloat 32
1520 %2 = OpTypeVector %1 4
1521 %3 = OpTypeMatrix %2 4
1522 %4 = OpConstant %1 1.0
1523 %5 = OpConstant %1 0.0
1524 %6 = OpConstantComposite %2 %4 %5 %5 %5
1525 %7 = OpConstantComposite %2 %5 %4 %5 %5
1526 %8 = OpConstantComposite %2 %5 %5 %4 %5
1527 %9 = OpUndef %2
1528 %10 = OpConstantComposite %3 %6 %7 %8 %9)";
1529 CompileSuccessfully(spirv.c_str());
1530 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1532 TEST_P(ValidateIdWithMessage, OpConstantCompositeMatrixConstituentTypeBad) {
1533 std::string spirv = kGLSL450MemoryModel + R"(
1534 %1 = OpTypeFloat 32
1535 %2 = OpTypeVector %1 4
1536 %11 = OpTypeVector %1 3
1537 %3 = OpTypeMatrix %2 4
1538 %4 = OpConstant %1 1.0
1539 %5 = OpConstant %1 0.0
1540 %6 = OpConstantComposite %2 %4 %5 %5 %5
1541 %7 = OpConstantComposite %2 %5 %4 %5 %5
1542 %8 = OpConstantComposite %2 %5 %5 %4 %5
1543 %9 = OpConstantComposite %11 %5 %5 %5
1544 %10 = OpConstantComposite %3 %6 %7 %8 %9)";
1545 CompileSuccessfully(spirv.c_str());
1546 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1547 EXPECT_THAT(getDiagnosticString(),
1548 HasSubstr(make_message(
1549 "OpConstantComposite Constituent <id> '10[%10]' vector "
1550 "component count does not match Result Type <id> "
1551 "'4[%mat4v4float]'s vector component count.")));
1553 TEST_P(ValidateIdWithMessage,
1554 OpConstantCompositeMatrixConstituentUndefTypeBad) {
1555 std::string spirv = kGLSL450MemoryModel + R"(
1556 %1 = OpTypeFloat 32
1557 %2 = OpTypeVector %1 4
1558 %11 = OpTypeVector %1 3
1559 %3 = OpTypeMatrix %2 4
1560 %4 = OpConstant %1 1.0
1561 %5 = OpConstant %1 0.0
1562 %6 = OpConstantComposite %2 %4 %5 %5 %5
1563 %7 = OpConstantComposite %2 %5 %4 %5 %5
1564 %8 = OpConstantComposite %2 %5 %5 %4 %5
1565 %9 = OpUndef %11
1566 %10 = OpConstantComposite %3 %6 %7 %8 %9)";
1567 CompileSuccessfully(spirv.c_str());
1568 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1569 EXPECT_THAT(getDiagnosticString(),
1570 HasSubstr(make_message(
1571 "OpConstantComposite Constituent <id> '10[%10]' vector "
1572 "component count does not match Result Type <id> "
1573 "'4[%mat4v4float]'s vector component count.")));
1575 TEST_P(ValidateIdWithMessage, OpConstantCompositeArrayGood) {
1576 std::string spirv = kGLSL450MemoryModel + R"(
1577 %1 = OpTypeInt 32 0
1578 %2 = OpConstant %1 4
1579 %3 = OpTypeArray %1 %2
1580 %4 = OpConstantComposite %3 %2 %2 %2 %2)";
1581 CompileSuccessfully(spirv.c_str());
1582 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1584 TEST_P(ValidateIdWithMessage, OpConstantCompositeArrayWithUndefGood) {
1585 std::string spirv = kGLSL450MemoryModel + R"(
1586 %1 = OpTypeInt 32 0
1587 %2 = OpConstant %1 4
1588 %9 = OpUndef %1
1589 %3 = OpTypeArray %1 %2
1590 %4 = OpConstantComposite %3 %2 %2 %2 %9)";
1591 CompileSuccessfully(spirv.c_str());
1592 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1595 TEST_P(ValidateIdWithMessage, OpConstantCompositeArrayConstConstituentTypeBad) {
1596 std::string spirv = kGLSL450MemoryModel + R"(
1597 %1 = OpTypeInt 32 0
1598 %2 = OpConstant %1 4
1599 %3 = OpTypeArray %1 %2
1600 %4 = OpConstantComposite %3 %2 %2 %2 %1)"; // Uses a type as operand
1601 CompileSuccessfully(spirv.c_str());
1602 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1603 EXPECT_THAT(getDiagnosticString(),
1604 HasSubstr(make_message("Operand '1[%uint]' cannot be a "
1605 "type")));
1607 TEST_P(ValidateIdWithMessage, OpConstantCompositeArrayConstConstituentBad) {
1608 std::string spirv = kGLSL450MemoryModel + R"(
1609 %1 = OpTypeInt 32 0
1610 %2 = OpConstant %1 4
1611 %3 = OpTypeArray %1 %2
1612 %4 = OpTypePointer Uniform %1
1613 %5 = OpVariable %4 Uniform
1614 %6 = OpConstantComposite %3 %2 %2 %2 %5)";
1615 CompileSuccessfully(spirv.c_str());
1616 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1617 EXPECT_THAT(getDiagnosticString(),
1618 HasSubstr(make_message(
1619 "OpConstantComposite Constituent <id> '5[%5]' is not a "
1620 "constant or undef.")));
1622 TEST_P(ValidateIdWithMessage, OpConstantCompositeArrayConstituentTypeBad) {
1623 std::string spirv = kGLSL450MemoryModel + R"(
1624 %1 = OpTypeInt 32 0
1625 %2 = OpConstant %1 4
1626 %3 = OpTypeArray %1 %2
1627 %5 = OpTypeFloat 32
1628 %6 = OpConstant %5 3.14 ; bad type for const value
1629 %4 = OpConstantComposite %3 %2 %2 %2 %6)";
1630 CompileSuccessfully(spirv.c_str());
1631 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1632 EXPECT_THAT(getDiagnosticString(),
1633 HasSubstr(make_message(
1634 "OpConstantComposite Constituent <id> "
1635 "'5[%float_3_1400001]'s type does not match Result "
1636 "Type <id> '3[%_arr_uint_uint_4]'s array element "
1637 "type.")));
1639 TEST_P(ValidateIdWithMessage, OpConstantCompositeArrayConstituentUndefTypeBad) {
1640 std::string spirv = kGLSL450MemoryModel + R"(
1641 %1 = OpTypeInt 32 0
1642 %2 = OpConstant %1 4
1643 %3 = OpTypeArray %1 %2
1644 %5 = OpTypeFloat 32
1645 %6 = OpUndef %5 ; bad type for undef
1646 %4 = OpConstantComposite %3 %2 %2 %2 %6)";
1647 CompileSuccessfully(spirv.c_str());
1648 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1649 EXPECT_THAT(
1650 getDiagnosticString(),
1651 HasSubstr(make_message("OpConstantComposite Constituent <id> "
1652 "'5[%5]'s type does not match Result "
1653 "Type <id> '3[%_arr_uint_uint_4]'s array element "
1654 "type.")));
1656 TEST_P(ValidateIdWithMessage, OpConstantCompositeStructGood) {
1657 std::string spirv = kGLSL450MemoryModel + R"(
1658 %1 = OpTypeInt 32 0
1659 %2 = OpTypeInt 64 0
1660 %3 = OpTypeStruct %1 %1 %2
1661 %4 = OpConstant %1 42
1662 %5 = OpConstant %2 4300000000
1663 %6 = OpConstantComposite %3 %4 %4 %5)";
1664 CompileSuccessfully(spirv.c_str());
1665 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1667 TEST_P(ValidateIdWithMessage, OpConstantCompositeStructUndefGood) {
1668 std::string spirv = kGLSL450MemoryModel + R"(
1669 %1 = OpTypeInt 32 0
1670 %2 = OpTypeInt 64 0
1671 %3 = OpTypeStruct %1 %1 %2
1672 %4 = OpConstant %1 42
1673 %5 = OpUndef %2
1674 %6 = OpConstantComposite %3 %4 %4 %5)";
1675 CompileSuccessfully(spirv.c_str());
1676 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1678 TEST_P(ValidateIdWithMessage, OpConstantCompositeStructMemberTypeBad) {
1679 std::string spirv = kGLSL450MemoryModel + R"(
1680 %1 = OpTypeInt 32 0
1681 %2 = OpTypeInt 64 0
1682 %3 = OpTypeStruct %1 %1 %2
1683 %4 = OpConstant %1 42
1684 %5 = OpConstant %2 4300000000
1685 %6 = OpConstantComposite %3 %4 %5 %4)";
1686 CompileSuccessfully(spirv.c_str());
1687 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1688 EXPECT_THAT(getDiagnosticString(),
1689 HasSubstr(make_message(
1690 "OpConstantComposite Constituent <id> "
1691 "'5[%ulong_4300000000]' type does not match the "
1692 "Result Type <id> '3[%_struct_3]'s member type.")));
1695 TEST_P(ValidateIdWithMessage, OpConstantCompositeStructMemberUndefTypeBad) {
1696 std::string spirv = kGLSL450MemoryModel + R"(
1697 %1 = OpTypeInt 32 0
1698 %2 = OpTypeInt 64 0
1699 %3 = OpTypeStruct %1 %1 %2
1700 %4 = OpConstant %1 42
1701 %5 = OpUndef %2
1702 %6 = OpConstantComposite %3 %4 %5 %4)";
1703 CompileSuccessfully(spirv.c_str());
1704 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1705 EXPECT_THAT(getDiagnosticString(),
1706 HasSubstr(make_message(
1707 "OpConstantComposite Constituent <id> '5[%5]' type "
1708 "does not match the Result Type <id> '3[%_struct_3]'s "
1709 "member type.")));
1712 TEST_P(ValidateIdWithMessage, OpConstantSamplerGood) {
1713 std::string spirv = kGLSL450MemoryModel + R"(
1714 %float = OpTypeFloat 32
1715 %samplerType = OpTypeSampler
1716 %3 = OpConstantSampler %samplerType ClampToEdge 0 Nearest)";
1717 CompileSuccessfully(spirv.c_str());
1718 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1720 TEST_P(ValidateIdWithMessage, OpConstantSamplerResultTypeBad) {
1721 std::string spirv = kGLSL450MemoryModel + R"(
1722 %1 = OpTypeFloat 32
1723 %2 = OpConstantSampler %1 Clamp 0 Nearest)";
1724 CompileSuccessfully(spirv.c_str());
1725 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1726 EXPECT_THAT(
1727 getDiagnosticString(),
1728 HasSubstr(make_message(
1729 "OpConstantSampler Result Type <id> '1[%float]' is not a sampler "
1730 "type.")));
1733 TEST_P(ValidateIdWithMessage, OpConstantNullGood) {
1734 std::string spirv = kGLSL450MemoryModel + R"(
1735 %1 = OpTypeBool
1736 %2 = OpConstantNull %1
1737 %3 = OpTypeInt 32 0
1738 %4 = OpConstantNull %3
1739 %5 = OpTypeFloat 32
1740 %6 = OpConstantNull %5
1741 %7 = OpTypePointer UniformConstant %3
1742 %8 = OpConstantNull %7
1743 %9 = OpTypeEvent
1744 %10 = OpConstantNull %9
1745 %11 = OpTypeDeviceEvent
1746 %12 = OpConstantNull %11
1747 %13 = OpTypeReserveId
1748 %14 = OpConstantNull %13
1749 %15 = OpTypeQueue
1750 %16 = OpConstantNull %15
1751 %17 = OpTypeVector %5 2
1752 %18 = OpConstantNull %17
1753 %19 = OpTypeMatrix %17 2
1754 %20 = OpConstantNull %19
1755 %25 = OpConstant %3 8
1756 %21 = OpTypeArray %3 %25
1757 %22 = OpConstantNull %21
1758 %23 = OpTypeStruct %3 %5 %1
1759 %24 = OpConstantNull %23
1760 %26 = OpTypeArray %17 %25
1761 %27 = OpConstantNull %26
1762 %28 = OpTypeStruct %7 %26 %26 %1
1763 %29 = OpConstantNull %28
1765 CompileSuccessfully(spirv.c_str());
1766 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1769 TEST_P(ValidateIdWithMessage, OpConstantNullBasicBad) {
1770 std::string spirv = kGLSL450MemoryModel + R"(
1771 %1 = OpTypeVoid
1772 %2 = OpConstantNull %1)";
1773 CompileSuccessfully(spirv.c_str());
1774 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1775 EXPECT_THAT(
1776 getDiagnosticString(),
1777 HasSubstr(make_message(
1778 "OpConstantNull Result Type <id> '1[%void]' cannot have a null "
1779 "value.")));
1782 TEST_P(ValidateIdWithMessage, OpConstantNullArrayBad) {
1783 std::string spirv = kGLSL450MemoryModel + R"(
1784 %2 = OpTypeInt 32 0
1785 %3 = OpTypeSampler
1786 %4 = OpConstant %2 4
1787 %5 = OpTypeArray %3 %4
1788 %6 = OpConstantNull %5)";
1789 CompileSuccessfully(spirv.c_str());
1790 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1791 EXPECT_THAT(
1792 getDiagnosticString(),
1793 HasSubstr(make_message(
1794 "OpConstantNull Result Type <id> '4[%_arr_2_uint_4]' cannot have a "
1795 "null value.")));
1798 TEST_P(ValidateIdWithMessage, OpConstantNullStructBad) {
1799 std::string spirv = kGLSL450MemoryModel + R"(
1800 %2 = OpTypeSampler
1801 %3 = OpTypeStruct %2 %2
1802 %4 = OpConstantNull %3)";
1803 CompileSuccessfully(spirv.c_str());
1804 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1805 EXPECT_THAT(
1806 getDiagnosticString(),
1807 HasSubstr(make_message("OpConstantNull Result Type <id> '2[%_struct_2]' "
1808 "cannot have a null value.")));
1811 TEST_P(ValidateIdWithMessage, OpConstantNullRuntimeArrayBad) {
1812 std::string spirv = kGLSL450MemoryModel + R"(
1813 %bool = OpTypeBool
1814 %array = OpTypeRuntimeArray %bool
1815 %null = OpConstantNull %array)";
1816 CompileSuccessfully(spirv.c_str());
1817 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1818 EXPECT_THAT(
1819 getDiagnosticString(),
1820 HasSubstr(make_message(
1821 "OpConstantNull Result Type <id> '2[%_runtimearr_bool]' cannot have "
1822 "a null value.")));
1825 TEST_P(ValidateIdWithMessage, OpSpecConstantTrueGood) {
1826 std::string spirv = kGLSL450MemoryModel + R"(
1827 %1 = OpTypeBool
1828 %2 = OpSpecConstantTrue %1)";
1829 CompileSuccessfully(spirv.c_str());
1830 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1832 TEST_P(ValidateIdWithMessage, OpSpecConstantTrueBad) {
1833 std::string spirv = kGLSL450MemoryModel + R"(
1834 %1 = OpTypeVoid
1835 %2 = OpSpecConstantTrue %1)";
1836 CompileSuccessfully(spirv.c_str());
1837 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1838 EXPECT_THAT(getDiagnosticString(),
1839 HasSubstr(make_message(
1840 "OpSpecConstantTrue Result Type <id> '1[%void]' is not "
1841 "a boolean type")));
1844 TEST_P(ValidateIdWithMessage, OpSpecConstantFalseGood) {
1845 std::string spirv = kGLSL450MemoryModel + R"(
1846 %1 = OpTypeBool
1847 %2 = OpSpecConstantFalse %1)";
1848 CompileSuccessfully(spirv.c_str());
1849 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1851 TEST_P(ValidateIdWithMessage, OpSpecConstantFalseBad) {
1852 std::string spirv = kGLSL450MemoryModel + R"(
1853 %1 = OpTypeVoid
1854 %2 = OpSpecConstantFalse %1)";
1855 CompileSuccessfully(spirv.c_str());
1856 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1857 EXPECT_THAT(getDiagnosticString(),
1858 HasSubstr(make_message(
1859 "OpSpecConstantFalse Result Type <id> '1[%void]' is not "
1860 "a boolean type")));
1863 TEST_P(ValidateIdWithMessage, OpSpecConstantGood) {
1864 std::string spirv = kGLSL450MemoryModel + R"(
1865 %1 = OpTypeFloat 32
1866 %2 = OpSpecConstant %1 42)";
1867 CompileSuccessfully(spirv.c_str());
1868 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1870 TEST_P(ValidateIdWithMessage, OpSpecConstantBad) {
1871 std::string spirv = kGLSL450MemoryModel + R"(
1872 %1 = OpTypeVoid
1873 %2 = OpSpecConstant !1 !4)";
1874 // The expected failure code is implementation dependent (currently
1875 // INVALID_BINARY because the binary parser catches these cases) and may
1876 // change over time, but this must always fail.
1877 CompileSuccessfully(spirv.c_str());
1878 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
1879 EXPECT_THAT(
1880 getDiagnosticString(),
1881 HasSubstr(make_message("Type Id 1 is not a scalar numeric type")));
1884 // Valid: SpecConstantComposite specializes to a vector.
1885 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorGood) {
1886 std::string spirv = kGLSL450MemoryModel + R"(
1887 %1 = OpTypeFloat 32
1888 %2 = OpTypeVector %1 4
1889 %3 = OpSpecConstant %1 3.14
1890 %4 = OpConstant %1 3.14
1891 %5 = OpSpecConstantComposite %2 %3 %3 %4 %4)";
1892 CompileSuccessfully(spirv.c_str());
1893 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1896 // Valid: Vector of floats and Undefs.
1897 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorWithUndefGood) {
1898 std::string spirv = kGLSL450MemoryModel + R"(
1899 %1 = OpTypeFloat 32
1900 %2 = OpTypeVector %1 4
1901 %3 = OpSpecConstant %1 3.14
1902 %5 = OpConstant %1 3.14
1903 %9 = OpUndef %1
1904 %4 = OpSpecConstantComposite %2 %3 %5 %3 %9)";
1905 CompileSuccessfully(spirv.c_str());
1906 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1909 // Invalid: result type is float.
1910 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorResultTypeBad) {
1911 std::string spirv = kGLSL450MemoryModel + R"(
1912 %1 = OpTypeFloat 32
1913 %2 = OpTypeVector %1 4
1914 %3 = OpSpecConstant %1 3.14
1915 %4 = OpSpecConstantComposite %1 %3 %3 %3 %3)";
1916 CompileSuccessfully(spirv.c_str());
1917 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1918 EXPECT_THAT(getDiagnosticString(),
1919 HasSubstr(make_message("is not a composite type")));
1922 // Invalid: Vector contains a mix of Int and Float.
1923 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorConstituentTypeBad) {
1924 std::string spirv = kGLSL450MemoryModel + R"(
1925 %1 = OpTypeFloat 32
1926 %2 = OpTypeVector %1 4
1927 %4 = OpTypeInt 32 0
1928 %3 = OpSpecConstant %1 3.14
1929 %5 = OpConstant %4 42 ; bad type for constant value
1930 %6 = OpSpecConstantComposite %2 %3 %5 %3 %3)";
1931 CompileSuccessfully(spirv.c_str());
1932 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1933 EXPECT_THAT(getDiagnosticString(),
1934 HasSubstr(make_message(
1935 "OpSpecConstantComposite Constituent <id> "
1936 "'5[%uint_42]'s type does not match Result Type <id> "
1937 "'2[%v4float]'s vector element type.")));
1940 // Invalid: Constituent is not a constant
1941 TEST_P(ValidateIdWithMessage,
1942 OpSpecConstantCompositeVectorConstituentNotConstantBad) {
1943 std::string spirv = kGLSL450MemoryModel + R"(
1944 %1 = OpTypeFloat 32
1945 %2 = OpTypeVector %1 4
1946 %3 = OpTypeInt 32 0
1947 %4 = OpSpecConstant %1 3.14
1948 %5 = OpTypePointer Uniform %1
1949 %6 = OpVariable %5 Uniform
1950 %7 = OpSpecConstantComposite %2 %6 %4 %4 %4)";
1951 CompileSuccessfully(spirv.c_str());
1952 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1953 EXPECT_THAT(getDiagnosticString(),
1954 HasSubstr(make_message(
1955 "OpSpecConstantComposite Constituent <id> '6[%6]' is "
1956 "not a constant or undef.")));
1959 // Invalid: Vector contains a mix of Undef-int and Float.
1960 TEST_P(ValidateIdWithMessage,
1961 OpSpecConstantCompositeVectorConstituentUndefTypeBad) {
1962 std::string spirv = kGLSL450MemoryModel + R"(
1963 %1 = OpTypeFloat 32
1964 %2 = OpTypeVector %1 4
1965 %4 = OpTypeInt 32 0
1966 %3 = OpSpecConstant %1 3.14
1967 %5 = OpUndef %4 ; bad type for undef value
1968 %6 = OpSpecConstantComposite %2 %3 %5 %3 %3)";
1969 CompileSuccessfully(spirv.c_str());
1970 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1971 EXPECT_THAT(getDiagnosticString(),
1972 HasSubstr(make_message(
1973 "OpSpecConstantComposite Constituent <id> '5[%5]'s "
1974 "type does not match Result Type <id> '2[%v4float]'s "
1975 "vector element type.")));
1978 // Invalid: Vector expects 3 components, but 4 specified.
1979 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorNumComponentsBad) {
1980 std::string spirv = kGLSL450MemoryModel + R"(
1981 %1 = OpTypeFloat 32
1982 %2 = OpTypeVector %1 3
1983 %3 = OpConstant %1 3.14
1984 %5 = OpSpecConstant %1 4.0
1985 %6 = OpSpecConstantComposite %2 %3 %5 %3 %3)";
1986 CompileSuccessfully(spirv.c_str());
1987 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1988 EXPECT_THAT(getDiagnosticString(),
1989 HasSubstr(make_message(
1990 "OpSpecConstantComposite Constituent <id> count does "
1991 "not match Result Type <id> '2[%v3float]'s vector "
1992 "component count.")));
1995 // Valid: 4x4 matrix of floats
1996 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixGood) {
1997 std::string spirv = kGLSL450MemoryModel + R"(
1998 %1 = OpTypeFloat 32
1999 %2 = OpTypeVector %1 4
2000 %3 = OpTypeMatrix %2 4
2001 %4 = OpConstant %1 1.0
2002 %5 = OpSpecConstant %1 0.0
2003 %6 = OpSpecConstantComposite %2 %4 %5 %5 %5
2004 %7 = OpSpecConstantComposite %2 %5 %4 %5 %5
2005 %8 = OpSpecConstantComposite %2 %5 %5 %4 %5
2006 %9 = OpSpecConstantComposite %2 %5 %5 %5 %4
2007 %10 = OpSpecConstantComposite %3 %6 %7 %8 %9)";
2008 CompileSuccessfully(spirv.c_str());
2009 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2012 // Valid: Matrix in which one column is Undef
2013 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixUndefGood) {
2014 std::string spirv = kGLSL450MemoryModel + R"(
2015 %1 = OpTypeFloat 32
2016 %2 = OpTypeVector %1 4
2017 %3 = OpTypeMatrix %2 4
2018 %4 = OpConstant %1 1.0
2019 %5 = OpSpecConstant %1 0.0
2020 %6 = OpSpecConstantComposite %2 %4 %5 %5 %5
2021 %7 = OpSpecConstantComposite %2 %5 %4 %5 %5
2022 %8 = OpSpecConstantComposite %2 %5 %5 %4 %5
2023 %9 = OpUndef %2
2024 %10 = OpSpecConstantComposite %3 %6 %7 %8 %9)";
2025 CompileSuccessfully(spirv.c_str());
2026 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2029 // Invalid: Matrix in which the sizes of column vectors are not equal.
2030 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixConstituentTypeBad) {
2031 std::string spirv = kGLSL450MemoryModel + R"(
2032 %1 = OpTypeFloat 32
2033 %2 = OpTypeVector %1 4
2034 %3 = OpTypeVector %1 3
2035 %4 = OpTypeMatrix %2 4
2036 %5 = OpSpecConstant %1 1.0
2037 %6 = OpConstant %1 0.0
2038 %7 = OpSpecConstantComposite %2 %5 %6 %6 %6
2039 %8 = OpSpecConstantComposite %2 %6 %5 %6 %6
2040 %9 = OpSpecConstantComposite %2 %6 %6 %5 %6
2041 %10 = OpSpecConstantComposite %3 %6 %6 %6
2042 %11 = OpSpecConstantComposite %4 %7 %8 %9 %10)";
2043 CompileSuccessfully(spirv.c_str());
2044 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2045 EXPECT_THAT(getDiagnosticString(),
2046 HasSubstr(make_message(
2047 "OpSpecConstantComposite Constituent <id> '10[%10]' "
2048 "vector component count does not match Result Type "
2049 "<id> '4[%mat4v4float]'s vector component count.")));
2052 // Invalid: Matrix type expects 4 columns but only 3 specified.
2053 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixNumColsBad) {
2054 std::string spirv = kGLSL450MemoryModel + R"(
2055 %1 = OpTypeFloat 32
2056 %2 = OpTypeVector %1 4
2057 %3 = OpTypeMatrix %2 4
2058 %4 = OpSpecConstant %1 1.0
2059 %5 = OpConstant %1 0.0
2060 %6 = OpSpecConstantComposite %2 %4 %5 %5 %5
2061 %7 = OpSpecConstantComposite %2 %5 %4 %5 %5
2062 %8 = OpSpecConstantComposite %2 %5 %5 %4 %5
2063 %10 = OpSpecConstantComposite %3 %6 %7 %8)";
2064 CompileSuccessfully(spirv.c_str());
2065 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2066 EXPECT_THAT(getDiagnosticString(),
2067 HasSubstr(make_message(
2068 "OpSpecConstantComposite Constituent <id> count does "
2069 "not match Result Type <id> '3[%mat4v4float]'s matrix column "
2070 "count.")));
2073 // Invalid: Composite contains a non-const/undef component
2074 TEST_P(ValidateIdWithMessage,
2075 OpSpecConstantCompositeMatrixConstituentNotConstBad) {
2076 std::string spirv = kGLSL450MemoryModel + R"(
2077 %1 = OpTypeFloat 32
2078 %2 = OpConstant %1 0.0
2079 %3 = OpTypeVector %1 4
2080 %4 = OpTypeMatrix %3 4
2081 %5 = OpSpecConstantComposite %3 %2 %2 %2 %2
2082 %6 = OpTypePointer Uniform %1
2083 %7 = OpVariable %6 Uniform
2084 %8 = OpSpecConstantComposite %4 %5 %5 %5 %7)";
2085 CompileSuccessfully(spirv.c_str());
2086 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2087 EXPECT_THAT(getDiagnosticString(),
2088 HasSubstr(make_message(
2089 "OpSpecConstantComposite Constituent <id> '7[%7]' is "
2090 "not a constant or undef.")));
2093 // Invalid: Composite contains a column that is *not* a vector (it's an array)
2094 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixColTypeBad) {
2095 std::string spirv = kGLSL450MemoryModel + R"(
2096 %1 = OpTypeFloat 32
2097 %2 = OpTypeInt 32 0
2098 %3 = OpSpecConstant %2 4
2099 %4 = OpConstant %1 0.0
2100 %5 = OpTypeVector %1 4
2101 %6 = OpTypeArray %2 %3
2102 %7 = OpTypeMatrix %5 4
2103 %8 = OpSpecConstantComposite %6 %3 %3 %3 %3
2104 %9 = OpSpecConstantComposite %5 %4 %4 %4 %4
2105 %10 = OpSpecConstantComposite %7 %9 %9 %9 %8)";
2106 CompileSuccessfully(spirv.c_str());
2107 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2108 EXPECT_THAT(getDiagnosticString(),
2109 HasSubstr(make_message(
2110 "OpSpecConstantComposite Constituent <id> '8[%8]' type "
2111 "does not match Result Type <id> '7[%mat4v4float]'s "
2112 "matrix column type.")));
2115 // Invalid: Matrix with an Undef column of the wrong size.
2116 TEST_P(ValidateIdWithMessage,
2117 OpSpecConstantCompositeMatrixConstituentUndefTypeBad) {
2118 std::string spirv = kGLSL450MemoryModel + R"(
2119 %1 = OpTypeFloat 32
2120 %2 = OpTypeVector %1 4
2121 %3 = OpTypeVector %1 3
2122 %4 = OpTypeMatrix %2 4
2123 %5 = OpSpecConstant %1 1.0
2124 %6 = OpSpecConstant %1 0.0
2125 %7 = OpSpecConstantComposite %2 %5 %6 %6 %6
2126 %8 = OpSpecConstantComposite %2 %6 %5 %6 %6
2127 %9 = OpSpecConstantComposite %2 %6 %6 %5 %6
2128 %10 = OpUndef %3
2129 %11 = OpSpecConstantComposite %4 %7 %8 %9 %10)";
2130 CompileSuccessfully(spirv.c_str());
2131 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2132 EXPECT_THAT(getDiagnosticString(),
2133 HasSubstr(make_message(
2134 "OpSpecConstantComposite Constituent <id> '10[%10]' "
2135 "vector component count does not match Result Type "
2136 "<id> '4[%mat4v4float]'s vector component count.")));
2139 // Invalid: Matrix in which some columns are Int and some are Float.
2140 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixColumnTypeBad) {
2141 std::string spirv = kGLSL450MemoryModel + R"(
2142 %1 = OpTypeInt 32 0
2143 %2 = OpTypeFloat 32
2144 %3 = OpTypeVector %1 2
2145 %4 = OpTypeVector %2 2
2146 %5 = OpTypeMatrix %4 2
2147 %6 = OpSpecConstant %1 42
2148 %7 = OpConstant %2 3.14
2149 %8 = OpSpecConstantComposite %3 %6 %6
2150 %9 = OpSpecConstantComposite %4 %7 %7
2151 %10 = OpSpecConstantComposite %5 %8 %9)";
2152 CompileSuccessfully(spirv.c_str());
2153 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2154 EXPECT_THAT(getDiagnosticString(),
2155 HasSubstr(make_message(
2156 "OpSpecConstantComposite Constituent <id> '8[%8]' "
2157 "component type does not match Result Type <id> "
2158 "'5[%mat2v2float]'s matrix column component type.")));
2161 // Valid: Array of integers
2162 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayGood) {
2163 std::string spirv = kGLSL450MemoryModel + R"(
2164 %1 = OpTypeInt 32 0
2165 %2 = OpSpecConstant %1 4
2166 %5 = OpConstant %1 5
2167 %3 = OpTypeArray %1 %2
2168 %6 = OpTypeArray %1 %5
2169 %4 = OpSpecConstantComposite %3 %2 %2 %2 %2
2170 %7 = OpSpecConstantComposite %3 %5 %5 %5 %5)";
2171 CompileSuccessfully(spirv.c_str());
2172 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2175 // Invalid: Expecting an array of 4 components, but 3 specified.
2176 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayNumComponentsBad) {
2177 std::string spirv = kGLSL450MemoryModel + R"(
2178 %1 = OpTypeInt 32 0
2179 %2 = OpConstant %1 4
2180 %3 = OpTypeArray %1 %2
2181 %4 = OpSpecConstantComposite %3 %2 %2 %2)";
2182 CompileSuccessfully(spirv.c_str());
2183 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2184 EXPECT_THAT(getDiagnosticString(),
2185 HasSubstr(make_message(
2186 "OpSpecConstantComposite Constituent count does not "
2187 "match Result Type <id> '3[%_arr_uint_uint_4]'s array "
2188 "length.")));
2191 // Valid: Array of Integers and Undef-int
2192 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayWithUndefGood) {
2193 std::string spirv = kGLSL450MemoryModel + R"(
2194 %1 = OpTypeInt 32 0
2195 %2 = OpSpecConstant %1 4
2196 %9 = OpUndef %1
2197 %3 = OpTypeArray %1 %2
2198 %4 = OpSpecConstantComposite %3 %2 %2 %2 %9)";
2199 CompileSuccessfully(spirv.c_str());
2200 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2203 // Invalid: Array uses a type as operand.
2204 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayConstConstituentBad) {
2205 std::string spirv = kGLSL450MemoryModel + R"(
2206 %1 = OpTypeInt 32 0
2207 %2 = OpConstant %1 4
2208 %3 = OpTypeArray %1 %2
2209 %4 = OpTypePointer Uniform %1
2210 %5 = OpVariable %4 Uniform
2211 %6 = OpSpecConstantComposite %3 %2 %2 %2 %5)";
2212 CompileSuccessfully(spirv.c_str());
2213 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2214 EXPECT_THAT(getDiagnosticString(),
2215 HasSubstr(make_message(
2216 "OpSpecConstantComposite Constituent <id> '5[%5]' is "
2217 "not a constant or undef.")));
2220 // Invalid: Array has a mix of Int and Float components.
2221 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayConstituentTypeBad) {
2222 std::string spirv = kGLSL450MemoryModel + R"(
2223 %1 = OpTypeInt 32 0
2224 %2 = OpConstant %1 4
2225 %3 = OpTypeArray %1 %2
2226 %4 = OpTypeFloat 32
2227 %5 = OpSpecConstant %4 3.14 ; bad type for const value
2228 %6 = OpSpecConstantComposite %3 %2 %2 %2 %5)";
2229 CompileSuccessfully(spirv.c_str());
2230 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2231 EXPECT_THAT(getDiagnosticString(),
2232 HasSubstr(make_message(
2233 "OpSpecConstantComposite Constituent <id> '5[%5]'s "
2234 "type does not match Result Type <id> "
2235 "'3[%_arr_uint_uint_4]'s array element type.")));
2238 // Invalid: Array has a mix of Int and Undef-float.
2239 TEST_P(ValidateIdWithMessage,
2240 OpSpecConstantCompositeArrayConstituentUndefTypeBad) {
2241 std::string spirv = kGLSL450MemoryModel + R"(
2242 %1 = OpTypeInt 32 0
2243 %2 = OpSpecConstant %1 4
2244 %3 = OpTypeArray %1 %2
2245 %5 = OpTypeFloat 32
2246 %6 = OpUndef %5 ; bad type for undef
2247 %4 = OpSpecConstantComposite %3 %2 %2 %2 %6)";
2248 CompileSuccessfully(spirv.c_str());
2249 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2250 EXPECT_THAT(getDiagnosticString(),
2251 HasSubstr(make_message(
2252 "OpSpecConstantComposite Constituent <id> '5[%5]'s "
2253 "type does not match Result Type <id> "
2254 "'3[%_arr_uint_2]'s array element type.")));
2257 // Valid: Struct of {Int32,Int32,Int64}.
2258 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructGood) {
2259 std::string spirv = kGLSL450MemoryModel + R"(
2260 %1 = OpTypeInt 32 0
2261 %2 = OpTypeInt 64 0
2262 %3 = OpTypeStruct %1 %1 %2
2263 %4 = OpConstant %1 42
2264 %5 = OpSpecConstant %2 4300000000
2265 %6 = OpSpecConstantComposite %3 %4 %4 %5)";
2266 CompileSuccessfully(spirv.c_str());
2267 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2270 // Invalid: missing one int32 struct member.
2271 TEST_P(ValidateIdWithMessage,
2272 OpSpecConstantCompositeStructMissingComponentBad) {
2273 std::string spirv = kGLSL450MemoryModel + R"(
2274 %1 = OpTypeInt 32 0
2275 %3 = OpTypeStruct %1 %1 %1
2276 %4 = OpConstant %1 42
2277 %5 = OpSpecConstant %1 430
2278 %6 = OpSpecConstantComposite %3 %4 %5)";
2279 CompileSuccessfully(spirv.c_str());
2280 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2281 EXPECT_THAT(
2282 getDiagnosticString(),
2283 HasSubstr(make_message("OpSpecConstantComposite Constituent <id> "
2284 "'2[%_struct_2]' count does not match Result Type "
2285 "<id> '2[%_struct_2]'s struct member count.")));
2288 // Valid: Struct uses Undef-int64.
2289 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructUndefGood) {
2290 std::string spirv = kGLSL450MemoryModel + R"(
2291 %1 = OpTypeInt 32 0
2292 %2 = OpTypeInt 64 0
2293 %3 = OpTypeStruct %1 %1 %2
2294 %4 = OpSpecConstant %1 42
2295 %5 = OpUndef %2
2296 %6 = OpSpecConstantComposite %3 %4 %4 %5)";
2297 CompileSuccessfully(spirv.c_str());
2298 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2301 // Invalid: Composite contains non-const/undef component.
2302 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructNonConstBad) {
2303 std::string spirv = kGLSL450MemoryModel + R"(
2304 %1 = OpTypeInt 32 0
2305 %2 = OpTypeInt 64 0
2306 %3 = OpTypeStruct %1 %1 %2
2307 %4 = OpSpecConstant %1 42
2308 %5 = OpUndef %2
2309 %6 = OpTypePointer Uniform %1
2310 %7 = OpVariable %6 Uniform
2311 %8 = OpSpecConstantComposite %3 %4 %7 %5)";
2312 CompileSuccessfully(spirv.c_str());
2313 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2314 EXPECT_THAT(getDiagnosticString(),
2315 HasSubstr(make_message(
2316 "OpSpecConstantComposite Constituent <id> '7[%7]' is "
2317 "not a constant or undef.")));
2320 // Invalid: Struct component type does not match expected specialization type.
2321 // Second component was expected to be Int32, but got Int64.
2322 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructMemberTypeBad) {
2323 std::string spirv = kGLSL450MemoryModel + R"(
2324 %1 = OpTypeInt 32 0
2325 %2 = OpTypeInt 64 0
2326 %3 = OpTypeStruct %1 %1 %2
2327 %4 = OpConstant %1 42
2328 %5 = OpSpecConstant %2 4300000000
2329 %6 = OpSpecConstantComposite %3 %4 %5 %4)";
2330 CompileSuccessfully(spirv.c_str());
2331 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2332 EXPECT_THAT(getDiagnosticString(),
2333 HasSubstr(make_message(
2334 "OpSpecConstantComposite Constituent <id> '5[%5]' type "
2335 "does not match the Result Type <id> '3[%_struct_3]'s "
2336 "member type.")));
2339 // Invalid: Undef-int64 used when Int32 was expected.
2340 TEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructMemberUndefTypeBad) {
2341 std::string spirv = kGLSL450MemoryModel + R"(
2342 %1 = OpTypeInt 32 0
2343 %2 = OpTypeInt 64 0
2344 %3 = OpTypeStruct %1 %1 %2
2345 %4 = OpSpecConstant %1 42
2346 %5 = OpUndef %2
2347 %6 = OpSpecConstantComposite %3 %4 %5 %4)";
2348 CompileSuccessfully(spirv.c_str());
2349 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2350 EXPECT_THAT(getDiagnosticString(),
2351 HasSubstr(make_message(
2352 "OpSpecConstantComposite Constituent <id> '5[%5]' type "
2353 "does not match the Result Type <id> '3[%_struct_3]'s "
2354 "member type.")));
2357 // TODO: OpSpecConstantOp
2359 TEST_P(ValidateIdWithMessage, OpVariableGood) {
2360 std::string spirv = kGLSL450MemoryModel + R"(
2361 %1 = OpTypeInt 32 0
2362 %2 = OpTypePointer Input %1
2363 %3 = OpVariable %2 Input)";
2364 CompileSuccessfully(spirv.c_str());
2365 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2367 TEST_P(ValidateIdWithMessage, OpVariableInitializerConstantGood) {
2368 std::string spirv = kGLSL450MemoryModel + R"(
2369 %1 = OpTypeInt 32 0
2370 %2 = OpTypePointer Output %1
2371 %3 = OpConstant %1 42
2372 %4 = OpVariable %2 Output %3)";
2373 CompileSuccessfully(spirv.c_str());
2374 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2376 TEST_P(ValidateIdWithMessage, OpVariableInitializerGlobalVariableGood) {
2377 std::string spirv = kGLSL450MemoryModel + R"(
2378 %1 = OpTypeInt 32 0
2379 %2 = OpTypePointer Uniform %1
2380 %3 = OpVariable %2 Uniform
2381 %4 = OpTypePointer Private %2 ; pointer to pointer
2382 %5 = OpVariable %4 Private %3
2384 CompileSuccessfully(spirv.c_str());
2385 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2387 // TODO: Positive test OpVariable with OpConstantNull of OpTypePointer
2388 TEST_P(ValidateIdWithMessage, OpVariableResultTypeBad) {
2389 std::string spirv = kGLSL450MemoryModel + R"(
2390 %1 = OpTypeInt 32 0
2391 %2 = OpVariable %1 Input)";
2392 CompileSuccessfully(spirv.c_str());
2393 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2394 EXPECT_THAT(getDiagnosticString(),
2395 HasSubstr(make_message(
2396 "OpVariable Result Type <id> '1[%uint]' is not a pointer "
2397 "type.")));
2399 TEST_P(ValidateIdWithMessage, OpVariableInitializerIsTypeBad) {
2400 std::string spirv = kGLSL450MemoryModel + R"(
2401 %1 = OpTypeInt 32 0
2402 %2 = OpTypePointer Input %1
2403 %3 = OpVariable %2 Input %2)";
2404 CompileSuccessfully(spirv.c_str());
2405 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2406 EXPECT_THAT(getDiagnosticString(),
2407 HasSubstr(make_message("Operand '2[%_ptr_Input_uint]' "
2408 "cannot be a type")));
2411 TEST_P(ValidateIdWithMessage, OpVariableInitializerIsFunctionVarBad) {
2412 std::string spirv = kGLSL450MemoryModel + R"(
2413 %int = OpTypeInt 32 0
2414 %ptrint = OpTypePointer Function %int
2415 %ptrptrint = OpTypePointer Function %ptrint
2416 %void = OpTypeVoid
2417 %fnty = OpTypeFunction %void
2418 %main = OpFunction %void None %fnty
2419 %entry = OpLabel
2420 %var = OpVariable %ptrint Function
2421 %varinit = OpVariable %ptrptrint Function %var ; Can't initialize function variable.
2422 OpReturn
2423 OpFunctionEnd
2425 CompileSuccessfully(spirv.c_str());
2426 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2427 EXPECT_THAT(getDiagnosticString(),
2428 HasSubstr("Variable Initializer <id> '8[%8]' is not a constant "
2429 "or module-scope variable"));
2432 TEST_P(ValidateIdWithMessage, OpVariableInitializerIsModuleVarGood) {
2433 std::string spirv = kGLSL450MemoryModel + R"(
2434 %int = OpTypeInt 32 0
2435 %ptrint = OpTypePointer Uniform %int
2436 %mvar = OpVariable %ptrint Uniform
2437 %ptrptrint = OpTypePointer Function %ptrint
2438 %void = OpTypeVoid
2439 %fnty = OpTypeFunction %void
2440 %main = OpFunction %void None %fnty
2441 %entry = OpLabel
2442 %goodvar = OpVariable %ptrptrint Function %mvar ; This is ok
2443 OpReturn
2444 OpFunctionEnd
2446 CompileSuccessfully(spirv.c_str());
2447 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2450 TEST_P(ValidateIdWithMessage, OpVariableContainsBoolBad) {
2451 std::string spirv = kGLSL450MemoryModel + R"(
2452 %bool = OpTypeBool
2453 %int = OpTypeInt 32 0
2454 %block = OpTypeStruct %bool %int
2455 %_ptr_Uniform_block = OpTypePointer Uniform %block
2456 %var = OpVariable %_ptr_Uniform_block Uniform
2457 %void = OpTypeVoid
2458 %fnty = OpTypeFunction %void
2459 %main = OpFunction %void None %fnty
2460 %entry = OpLabel
2461 %load = OpLoad %block %var
2462 OpReturn
2463 OpFunctionEnd
2465 CompileSuccessfully(spirv.c_str());
2466 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2467 EXPECT_THAT(
2468 getDiagnosticString(),
2469 HasSubstr(make_message(
2470 "If OpTypeBool is stored in conjunction with OpVariable, it can only "
2471 "be used with non-externally visible shader Storage Classes: "
2472 "Workgroup, CrossWorkgroup, Private, Function, Input, Output, "
2473 "RayPayloadKHR, IncomingRayPayloadKHR, HitAttributeKHR, "
2474 "CallableDataKHR, IncomingCallableDataKHR, NodePayloadAMDX, or "
2475 "UniformConstant")));
2478 TEST_P(ValidateIdWithMessage, OpVariableContainsBoolPrivateGood) {
2479 std::string spirv = kGLSL450MemoryModel + R"(
2480 %bool = OpTypeBool
2481 %int = OpTypeInt 32 0
2482 %block = OpTypeStruct %bool %int
2483 %_ptr_Private_block = OpTypePointer Private %block
2484 %var = OpVariable %_ptr_Private_block Private
2485 %void = OpTypeVoid
2486 %fnty = OpTypeFunction %void
2487 %main = OpFunction %void None %fnty
2488 %entry = OpLabel
2489 %load = OpLoad %block %var
2490 OpReturn
2491 OpFunctionEnd
2493 CompileSuccessfully(spirv.c_str());
2494 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2497 TEST_P(ValidateIdWithMessage, OpVariableContainsBoolUniformConstantGood) {
2498 std::string spirv = kGLSL450MemoryModel + R"(
2499 %bool = OpTypeBool
2500 %int = OpTypeInt 32 0
2501 %block = OpTypeStruct %bool %int
2502 %_ptr_UniformConstant_block = OpTypePointer UniformConstant %block
2503 %var = OpVariable %_ptr_UniformConstant_block UniformConstant
2504 %void = OpTypeVoid
2505 %fnty = OpTypeFunction %void
2506 %main = OpFunction %void None %fnty
2507 %entry = OpLabel
2508 %load = OpLoad %block %var
2509 OpReturn
2510 OpFunctionEnd
2512 CompileSuccessfully(spirv.c_str());
2513 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2516 TEST_P(ValidateIdWithMessage, OpVariableContainsBoolPointerGood) {
2517 std::string spirv = kGLSL450MemoryModel + R"(
2518 %bool = OpTypeBool
2519 %boolptr = OpTypePointer Uniform %bool
2520 %int = OpTypeInt 32 0
2521 %block = OpTypeStruct %boolptr %int
2522 %_ptr_Uniform_block = OpTypePointer Uniform %block
2523 %var = OpVariable %_ptr_Uniform_block Uniform
2524 %void = OpTypeVoid
2525 %fnty = OpTypeFunction %void
2526 %main = OpFunction %void None %fnty
2527 %entry = OpLabel
2528 %load = OpLoad %block %var
2529 OpReturn
2530 OpFunctionEnd
2532 CompileSuccessfully(spirv.c_str());
2533 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2536 TEST_P(ValidateIdWithMessage, OpVariableContainsBuiltinBoolGood) {
2537 std::string spirv = kGLSL450MemoryModel + R"(
2538 OpMemberDecorate %input 0 BuiltIn FrontFacing
2539 %bool = OpTypeBool
2540 %input = OpTypeStruct %bool
2541 %_ptr_input = OpTypePointer Input %input
2542 %var = OpVariable %_ptr_input Input
2543 %void = OpTypeVoid
2544 %fnty = OpTypeFunction %void
2545 %main = OpFunction %void None %fnty
2546 %entry = OpLabel
2547 %load = OpLoad %input %var
2548 OpReturn
2549 OpFunctionEnd
2551 CompileSuccessfully(spirv.c_str());
2552 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2555 TEST_P(ValidateIdWithMessage, OpVariableContainsNoBuiltinBoolBad) {
2556 std::string spirv = kGLSL450MemoryModel + R"(
2557 %bool = OpTypeBool
2558 %input = OpTypeStruct %bool
2559 %_ptr_input = OpTypePointer Input %input
2560 %var = OpVariable %_ptr_input Input
2561 %void = OpTypeVoid
2562 %fnty = OpTypeFunction %void
2563 %main = OpFunction %void None %fnty
2564 %entry = OpLabel
2565 %load = OpLoad %input %var
2566 OpReturn
2567 OpFunctionEnd
2569 CompileSuccessfully(spirv.c_str());
2570 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2571 EXPECT_THAT(
2572 getDiagnosticString(),
2573 HasSubstr(make_message(
2574 "If OpTypeBool is stored in conjunction with OpVariable using Input "
2575 "or Output Storage Classes it requires a BuiltIn decoration")));
2578 TEST_P(ValidateIdWithMessage, OpVariableContainsNoBuiltinBoolBadVulkan) {
2579 std::string spirv = R"(
2580 OpCapability Shader
2581 OpMemoryModel Logical GLSL450
2582 OpEntryPoint Fragment %main "main" %var
2583 OpExecutionMode %main OriginUpperLeft
2584 %bool = OpTypeBool
2585 %input = OpTypeStruct %bool
2586 %_ptr_input = OpTypePointer Input %input
2587 %var = OpVariable %_ptr_input Input
2588 %void = OpTypeVoid
2589 %fnty = OpTypeFunction %void
2590 %main = OpFunction %void None %fnty
2591 %entry = OpLabel
2592 %load = OpLoad %input %var
2593 OpReturn
2594 OpFunctionEnd
2596 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
2597 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2598 EXPECT_THAT(getDiagnosticString(),
2599 AnyVUID("VUID-StandaloneSpirv-Input-07290"));
2600 EXPECT_THAT(
2601 getDiagnosticString(),
2602 HasSubstr(make_message(
2603 "If OpTypeBool is stored in conjunction with OpVariable using Input "
2604 "or Output Storage Classes it requires a BuiltIn decoration")));
2607 TEST_P(ValidateIdWithMessage, OpVariableContainsRayPayloadBoolGood) {
2608 std::string spirv = R"(
2609 OpCapability RayTracingNV
2610 OpCapability Shader
2611 OpCapability Linkage
2612 OpExtension "SPV_NV_ray_tracing"
2613 OpMemoryModel Logical GLSL450
2614 %bool = OpTypeBool
2615 %PerRayData = OpTypeStruct %bool
2616 %_ptr_PerRayData = OpTypePointer RayPayloadNV %PerRayData
2617 %var = OpVariable %_ptr_PerRayData RayPayloadNV
2618 %void = OpTypeVoid
2619 %fnty = OpTypeFunction %void
2620 %main = OpFunction %void None %fnty
2621 %entry = OpLabel
2622 %load = OpLoad %PerRayData %var
2623 OpReturn
2624 OpFunctionEnd
2626 CompileSuccessfully(spirv.c_str());
2627 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2630 TEST_P(ValidateIdWithMessage, OpVariablePointerNoVariablePointersBad) {
2631 const std::string spirv = R"(
2632 OpCapability Shader
2633 OpCapability Linkage
2634 OpMemoryModel Logical GLSL450
2635 %void = OpTypeVoid
2636 %int = OpTypeInt 32 0
2637 %_ptr_workgroup_int = OpTypePointer Workgroup %int
2638 %_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int
2639 %voidfn = OpTypeFunction %void
2640 %func = OpFunction %void None %voidfn
2641 %entry = OpLabel
2642 %var = OpVariable %_ptr_function_ptr Function
2643 OpReturn
2644 OpFunctionEnd
2647 CompileSuccessfully(spirv);
2648 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2649 EXPECT_THAT(
2650 getDiagnosticString(),
2651 HasSubstr(make_message(
2652 "In Logical addressing, variables may not allocate a pointer type")));
2655 TEST_P(ValidateIdWithMessage,
2656 OpVariablePointerNoVariablePointersRelaxedLogicalGood) {
2657 const std::string spirv = R"(
2658 OpCapability Shader
2659 OpCapability Linkage
2660 OpMemoryModel Logical GLSL450
2661 %void = OpTypeVoid
2662 %int = OpTypeInt 32 0
2663 %_ptr_workgroup_int = OpTypePointer Workgroup %int
2664 %_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int
2665 %voidfn = OpTypeFunction %void
2666 %func = OpFunction %void None %voidfn
2667 %entry = OpLabel
2668 %var = OpVariable %_ptr_function_ptr Function
2669 OpReturn
2670 OpFunctionEnd
2673 auto options = getValidatorOptions();
2674 options->relax_logical_pointer = true;
2675 CompileSuccessfully(spirv);
2676 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2679 TEST_P(ValidateIdWithMessage, OpFunctionWithNonMemoryObject) {
2680 // DXC generates code that looks like when given something like:
2681 // T t;
2682 // t.s.fn_1();
2683 // This needs to be accepted before legalization takes place, so we
2684 // will include it with the relaxed logical pointer.
2686 const std::string spirv = R"(
2687 OpCapability Shader
2688 OpMemoryModel Logical GLSL450
2689 OpEntryPoint Vertex %1 "main"
2690 OpSource HLSL 600
2691 %int = OpTypeInt 32 1
2692 %int_0 = OpConstant %int 0
2693 %void = OpTypeVoid
2694 %9 = OpTypeFunction %void
2695 %_struct_5 = OpTypeStruct
2696 %_struct_6 = OpTypeStruct %_struct_5
2697 %_ptr_Function__struct_6 = OpTypePointer Function %_struct_6
2698 %_ptr_Function__struct_5 = OpTypePointer Function %_struct_5
2699 %23 = OpTypeFunction %void %_ptr_Function__struct_5
2700 %1 = OpFunction %void None %9
2701 %10 = OpLabel
2702 %11 = OpVariable %_ptr_Function__struct_6 Function
2703 %20 = OpAccessChain %_ptr_Function__struct_5 %11 %int_0
2704 %21 = OpFunctionCall %void %12 %20
2705 OpReturn
2706 OpFunctionEnd
2707 %12 = OpFunction %void None %23
2708 %13 = OpFunctionParameter %_ptr_Function__struct_5
2709 %14 = OpLabel
2710 OpReturn
2711 OpFunctionEnd
2714 auto options = getValidatorOptions();
2715 options->relax_logical_pointer = true;
2716 CompileSuccessfully(spirv);
2717 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2720 TEST_P(ValidateIdWithMessage,
2721 OpVariablePointerVariablePointersStorageBufferGood) {
2722 const std::string spirv = R"(
2723 OpCapability Shader
2724 OpCapability Linkage
2725 OpCapability VariablePointersStorageBuffer
2726 OpExtension "SPV_KHR_variable_pointers"
2727 OpMemoryModel Logical GLSL450
2728 %void = OpTypeVoid
2729 %int = OpTypeInt 32 0
2730 %_ptr_workgroup_int = OpTypePointer Workgroup %int
2731 %_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int
2732 %voidfn = OpTypeFunction %void
2733 %func = OpFunction %void None %voidfn
2734 %entry = OpLabel
2735 %var = OpVariable %_ptr_function_ptr Function
2736 OpReturn
2737 OpFunctionEnd
2740 CompileSuccessfully(spirv);
2741 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2744 TEST_P(ValidateIdWithMessage, OpVariablePointerVariablePointersGood) {
2745 const std::string spirv = R"(
2746 OpCapability Shader
2747 OpCapability Linkage
2748 OpCapability VariablePointers
2749 OpExtension "SPV_KHR_variable_pointers"
2750 OpMemoryModel Logical GLSL450
2751 %void = OpTypeVoid
2752 %int = OpTypeInt 32 0
2753 %_ptr_workgroup_int = OpTypePointer Workgroup %int
2754 %_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int
2755 %voidfn = OpTypeFunction %void
2756 %func = OpFunction %void None %voidfn
2757 %entry = OpLabel
2758 %var = OpVariable %_ptr_function_ptr Function
2759 OpReturn
2760 OpFunctionEnd
2763 CompileSuccessfully(spirv);
2764 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2767 TEST_P(ValidateIdWithMessage, OpVariablePointerVariablePointersBad) {
2768 const std::string spirv = R"(
2769 OpCapability Shader
2770 OpCapability VariablePointers
2771 OpExtension "SPV_KHR_variable_pointers"
2772 OpMemoryModel Logical GLSL450
2773 %void = OpTypeVoid
2774 %int = OpTypeInt 32 0
2775 %_ptr_workgroup_int = OpTypePointer Workgroup %int
2776 %_ptr_uniform_ptr = OpTypePointer Uniform %_ptr_workgroup_int
2777 %var = OpVariable %_ptr_uniform_ptr Uniform
2780 CompileSuccessfully(spirv);
2781 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2782 EXPECT_THAT(getDiagnosticString(),
2783 HasSubstr(make_message(
2784 "In Logical addressing with variable pointers, "
2785 "variables that allocate pointers must be in Function "
2786 "or Private storage classes")));
2789 TEST_P(ValidateIdWithMessage, OpLoadGood) {
2790 std::string spirv = kGLSL450MemoryModel + R"(
2791 %1 = OpTypeVoid
2792 %2 = OpTypeInt 32 0
2793 %3 = OpTypePointer UniformConstant %2
2794 %4 = OpTypeFunction %1
2795 %5 = OpVariable %3 UniformConstant
2796 %6 = OpFunction %1 None %4
2797 %7 = OpLabel
2798 %8 = OpLoad %2 %5
2799 OpReturn
2800 OpFunctionEnd
2802 CompileSuccessfully(spirv.c_str());
2803 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2806 // TODO: Add tests that exercise VariablePointersStorageBuffer instead of
2807 // VariablePointers.
2808 void createVariablePointerSpirvProgram(std::ostringstream* spirv,
2809 std::string result_strategy,
2810 bool use_varptr_cap,
2811 bool add_helper_function) {
2812 *spirv << "OpCapability Shader ";
2813 if (use_varptr_cap) {
2814 *spirv << "OpCapability VariablePointers ";
2815 *spirv << "OpExtension \"SPV_KHR_variable_pointers\" ";
2817 *spirv << "OpExtension \"SPV_KHR_storage_buffer_storage_class\" ";
2818 *spirv << R"(
2819 OpMemoryModel Logical GLSL450
2820 OpEntryPoint GLCompute %main "main"
2821 %void = OpTypeVoid
2822 %voidf = OpTypeFunction %void
2823 %bool = OpTypeBool
2824 %i32 = OpTypeInt 32 1
2825 %f32 = OpTypeFloat 32
2826 %f32ptr = OpTypePointer StorageBuffer %f32
2827 %i = OpConstant %i32 1
2828 %zero = OpConstant %i32 0
2829 %float_1 = OpConstant %f32 1.0
2830 %ptr1 = OpVariable %f32ptr StorageBuffer
2831 %ptr2 = OpVariable %f32ptr StorageBuffer
2833 if (add_helper_function) {
2834 *spirv << R"(
2835 ; ////////////////////////////////////////////////////////////
2836 ;;;; Function that returns a pointer
2837 ; ////////////////////////////////////////////////////////////
2838 %selector_func_type = OpTypeFunction %f32ptr %bool %f32ptr %f32ptr
2839 %choose_input_func = OpFunction %f32ptr None %selector_func_type
2840 %is_neg_param = OpFunctionParameter %bool
2841 %first_ptr_param = OpFunctionParameter %f32ptr
2842 %second_ptr_param = OpFunctionParameter %f32ptr
2843 %selector_func_begin = OpLabel
2844 %result_ptr = OpSelect %f32ptr %is_neg_param %first_ptr_param %second_ptr_param
2845 OpReturnValue %result_ptr
2846 OpFunctionEnd
2849 *spirv << R"(
2850 %main = OpFunction %void None %voidf
2851 %label = OpLabel
2853 *spirv << result_strategy;
2854 *spirv << R"(
2855 OpReturn
2856 OpFunctionEnd
2860 // With the VariablePointer Capability, OpLoad should allow loading a
2861 // VaiablePointer. In this test the variable pointer is obtained by an OpSelect
2862 TEST_P(ValidateIdWithMessage, OpLoadVarPtrOpSelectGood) {
2863 std::string result_strategy = R"(
2864 %isneg = OpSLessThan %bool %i %zero
2865 %varptr = OpSelect %f32ptr %isneg %ptr1 %ptr2
2866 %result = OpLoad %f32 %varptr
2869 std::ostringstream spirv;
2870 createVariablePointerSpirvProgram(&spirv, result_strategy,
2871 true /* Add VariablePointers Capability? */,
2872 false /* Use Helper Function? */);
2873 CompileSuccessfully(spirv.str());
2874 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2877 // Without the VariablePointers Capability, OpLoad will not allow loading
2878 // through a variable pointer.
2879 // Disabled since using OpSelect with pointers without VariablePointers will
2880 // fail LogicalsPass.
2881 TEST_P(ValidateIdWithMessage, DISABLED_OpLoadVarPtrOpSelectBad) {
2882 std::string result_strategy = R"(
2883 %isneg = OpSLessThan %bool %i %zero
2884 %varptr = OpSelect %f32ptr %isneg %ptr1 %ptr2
2885 %result = OpLoad %f32 %varptr
2888 std::ostringstream spirv;
2889 createVariablePointerSpirvProgram(&spirv, result_strategy,
2890 false /* Add VariablePointers Capability?*/,
2891 false /* Use Helper Function? */);
2892 CompileSuccessfully(spirv.str());
2893 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2894 EXPECT_THAT(getDiagnosticString(),
2895 HasSubstr(make_message("is not a logical pointer.")));
2898 // With the VariablePointer Capability, OpLoad should allow loading a
2899 // VaiablePointer. In this test the variable pointer is obtained by an OpPhi
2900 TEST_P(ValidateIdWithMessage, OpLoadVarPtrOpPhiGood) {
2901 std::string result_strategy = R"(
2902 %is_neg = OpSLessThan %bool %i %zero
2903 OpSelectionMerge %end_label None
2904 OpBranchConditional %is_neg %take_ptr_1 %take_ptr_2
2905 %take_ptr_1 = OpLabel
2906 OpBranch %end_label
2907 %take_ptr_2 = OpLabel
2908 OpBranch %end_label
2909 %end_label = OpLabel
2910 %varptr = OpPhi %f32ptr %ptr1 %take_ptr_1 %ptr2 %take_ptr_2
2911 %result = OpLoad %f32 %varptr
2914 std::ostringstream spirv;
2915 createVariablePointerSpirvProgram(&spirv, result_strategy,
2916 true /* Add VariablePointers Capability?*/,
2917 false /* Use Helper Function? */);
2918 CompileSuccessfully(spirv.str());
2919 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2922 // Without the VariablePointers Capability, OpPhi can have a pointer result
2923 // type.
2924 TEST_P(ValidateIdWithMessage, OpPhiBad) {
2925 std::string result_strategy = R"(
2926 %is_neg = OpSLessThan %bool %i %zero
2927 OpSelectionMerge %end_label None
2928 OpBranchConditional %is_neg %take_ptr_1 %take_ptr_2
2929 %take_ptr_1 = OpLabel
2930 OpBranch %end_label
2931 %take_ptr_2 = OpLabel
2932 OpBranch %end_label
2933 %end_label = OpLabel
2934 %varptr = OpPhi %f32ptr %ptr1 %take_ptr_1 %ptr2 %take_ptr_2
2935 %result = OpLoad %f32 %varptr
2938 std::ostringstream spirv;
2939 createVariablePointerSpirvProgram(&spirv, result_strategy,
2940 false /* Add VariablePointers Capability?*/,
2941 false /* Use Helper Function? */);
2942 CompileSuccessfully(spirv.str());
2943 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2944 EXPECT_THAT(getDiagnosticString(),
2945 HasSubstr(make_message(
2946 "Using pointers with OpPhi requires capability "
2947 "VariablePointers or VariablePointersStorageBuffer")));
2950 // With the VariablePointer Capability, OpLoad should allow loading through a
2951 // VaiablePointer. In this test the variable pointer is obtained from an
2952 // OpFunctionCall (return value from a function)
2953 TEST_P(ValidateIdWithMessage, OpLoadVarPtrOpFunctionCallGood) {
2954 std::ostringstream spirv;
2955 std::string result_strategy = R"(
2956 %isneg = OpSLessThan %bool %i %zero
2957 %varptr = OpFunctionCall %f32ptr %choose_input_func %isneg %ptr1 %ptr2
2958 %result = OpLoad %f32 %varptr
2961 createVariablePointerSpirvProgram(&spirv, result_strategy,
2962 true /* Add VariablePointers Capability?*/,
2963 true /* Use Helper Function? */);
2964 CompileSuccessfully(spirv.str());
2965 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2968 TEST_P(ValidateIdWithMessage, OpLoadResultTypeBad) {
2969 std::string spirv = kGLSL450MemoryModel + R"(
2970 %1 = OpTypeVoid
2971 %2 = OpTypeInt 32 0
2972 %3 = OpTypePointer UniformConstant %2
2973 %4 = OpTypeFunction %1
2974 %5 = OpVariable %3 UniformConstant
2975 %6 = OpFunction %1 None %4
2976 %7 = OpLabel
2977 %8 = OpLoad %3 %5
2978 OpReturn
2979 OpFunctionEnd
2981 CompileSuccessfully(spirv.c_str());
2982 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2983 EXPECT_THAT(
2984 getDiagnosticString(),
2985 HasSubstr(make_message("OpLoad Result Type <id> "
2986 "'3[%_ptr_UniformConstant_uint]' does not match "
2987 "Pointer <id> '5[%5]'s type.")));
2990 TEST_P(ValidateIdWithMessage, OpLoadPointerBad) {
2991 std::string spirv = kGLSL450MemoryModel + R"(
2992 %1 = OpTypeVoid
2993 %2 = OpTypeInt 32 0
2994 %3 = OpTypePointer UniformConstant %2
2995 %4 = OpTypeFunction %1
2996 %5 = OpFunction %1 None %4
2997 %6 = OpLabel
2998 %7 = OpLoad %2 %8
2999 OpReturn
3000 OpFunctionEnd
3002 CompileSuccessfully(spirv.c_str());
3003 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3004 // Prove that SSA checks trigger for a bad Id value.
3005 // The next test case show the not-a-logical-pointer case.
3006 EXPECT_THAT(getDiagnosticString(),
3007 HasSubstr(make_message("ID '8[%8]' has not been "
3008 "defined")));
3011 // Disabled as bitcasting type to object is now not valid.
3012 TEST_P(ValidateIdWithMessage, DISABLED_OpLoadLogicalPointerBad) {
3013 std::string spirv = kGLSL450MemoryModel + R"(
3014 %1 = OpTypeVoid
3015 %2 = OpTypeInt 32 0
3016 %3 = OpTypeFloat 32
3017 %4 = OpTypePointer UniformConstant %2
3018 %5 = OpTypePointer UniformConstant %3
3019 %6 = OpTypeFunction %1
3020 %7 = OpFunction %1 None %6
3021 %8 = OpLabel
3022 %9 = OpBitcast %5 %4 ; Not valid in logical addressing
3023 %10 = OpLoad %3 %9 ; Should trigger message
3024 OpReturn
3025 OpFunctionEnd
3027 CompileSuccessfully(spirv.c_str());
3028 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3029 // Once we start checking bitcasts, we might catch that
3030 // as the error first, instead of catching it here.
3031 // I don't know if it's possible to generate a bad case
3032 // if/when the validator is complete.
3033 EXPECT_THAT(getDiagnosticString(),
3034 HasSubstr(make_message(
3035 "OpLoad Pointer <id> '9' is not a logical pointer.")));
3038 TEST_P(ValidateIdWithMessage, OpStoreGood) {
3039 std::string spirv = kGLSL450MemoryModel + R"(
3040 %1 = OpTypeVoid
3041 %2 = OpTypeInt 32 0
3042 %3 = OpTypePointer Uniform %2
3043 %4 = OpTypeFunction %1
3044 %5 = OpConstant %2 42
3045 %6 = OpVariable %3 Uniform
3046 %7 = OpFunction %1 None %4
3047 %8 = OpLabel
3048 OpStore %6 %5
3049 OpReturn
3050 OpFunctionEnd)";
3051 CompileSuccessfully(spirv.c_str());
3052 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3054 TEST_P(ValidateIdWithMessage, OpStorePointerBad) {
3055 std::string spirv = kGLSL450MemoryModel + R"(
3056 %1 = OpTypeVoid
3057 %2 = OpTypeInt 32 0
3058 %3 = OpTypePointer UniformConstant %2
3059 %4 = OpTypeFunction %1
3060 %5 = OpConstant %2 42
3061 %6 = OpVariable %3 UniformConstant
3062 %7 = OpConstant %2 0
3063 %8 = OpFunction %1 None %4
3064 %9 = OpLabel
3065 OpStore %7 %5
3066 OpReturn
3067 OpFunctionEnd)";
3068 CompileSuccessfully(spirv.c_str());
3069 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3070 EXPECT_THAT(getDiagnosticString(),
3071 HasSubstr(make_message(
3072 "OpStore Pointer <id> '7[%uint_0]' is not a logical "
3073 "pointer.")));
3076 // Disabled as bitcasting type to object is now not valid.
3077 TEST_P(ValidateIdWithMessage, DISABLED_OpStoreLogicalPointerBad) {
3078 std::string spirv = kGLSL450MemoryModel + R"(
3079 %1 = OpTypeVoid
3080 %2 = OpTypeInt 32 0
3081 %3 = OpTypeFloat 32
3082 %4 = OpTypePointer UniformConstant %2
3083 %5 = OpTypePointer UniformConstant %3
3084 %6 = OpTypeFunction %1
3085 %7 = OpConstantNull %5
3086 %8 = OpFunction %1 None %6
3087 %9 = OpLabel
3088 %10 = OpBitcast %5 %4 ; Not valid in logical addressing
3089 %11 = OpStore %10 %7 ; Should trigger message
3090 OpReturn
3091 OpFunctionEnd
3093 CompileSuccessfully(spirv.c_str());
3094 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3095 EXPECT_THAT(getDiagnosticString(),
3096 HasSubstr(make_message(
3097 "OpStore Pointer <id> '10' is not a logical pointer.")));
3100 // Without the VariablePointer Capability, OpStore should may not store
3101 // through a variable pointer.
3102 // Disabled since using OpSelect with pointers without VariablePointers will
3103 // fail LogicalsPass.
3104 TEST_P(ValidateIdWithMessage, DISABLED_OpStoreVarPtrBad) {
3105 std::string result_strategy = R"(
3106 %isneg = OpSLessThan %bool %i %zero
3107 %varptr = OpSelect %f32ptr %isneg %ptr1 %ptr2
3108 OpStore %varptr %float_1
3111 std::ostringstream spirv;
3112 createVariablePointerSpirvProgram(
3113 &spirv, result_strategy, false /* Add VariablePointers Capability? */,
3114 false /* Use Helper Function? */);
3115 CompileSuccessfully(spirv.str());
3116 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3117 EXPECT_THAT(getDiagnosticString(),
3118 HasSubstr(make_message("is not a logical pointer.")));
3121 // With the VariablePointer Capability, OpStore should allow storing through a
3122 // variable pointer.
3123 TEST_P(ValidateIdWithMessage, OpStoreVarPtrGood) {
3124 std::string result_strategy = R"(
3125 %isneg = OpSLessThan %bool %i %zero
3126 %varptr = OpSelect %f32ptr %isneg %ptr1 %ptr2
3127 OpStore %varptr %float_1
3130 std::ostringstream spirv;
3131 createVariablePointerSpirvProgram(&spirv, result_strategy,
3132 true /* Add VariablePointers Capability? */,
3133 false /* Use Helper Function? */);
3134 CompileSuccessfully(spirv.str());
3135 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3138 TEST_P(ValidateIdWithMessage, OpStoreObjectGood) {
3139 std::string spirv = kGLSL450MemoryModel + R"(
3140 %1 = OpTypeVoid
3141 %2 = OpTypeInt 32 0
3142 %3 = OpTypePointer Uniform %2
3143 %4 = OpTypeFunction %1
3144 %5 = OpConstant %2 42
3145 %6 = OpVariable %3 Uniform
3146 %7 = OpFunction %1 None %4
3147 %8 = OpLabel
3148 %9 = OpFunctionCall %1 %10
3149 OpStore %6 %9
3150 OpReturn
3151 OpFunctionEnd
3152 %10 = OpFunction %1 None %4
3153 %11 = OpLabel
3154 OpReturn
3155 OpFunctionEnd)";
3156 CompileSuccessfully(spirv.c_str());
3157 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3158 EXPECT_THAT(
3159 getDiagnosticString(),
3160 HasSubstr(make_message("OpStore Object <id> '9[%9]'s type is void.")));
3162 TEST_P(ValidateIdWithMessage, OpStoreTypeBad) {
3163 std::string spirv = kGLSL450MemoryModel + R"(
3164 %1 = OpTypeVoid
3165 %2 = OpTypeInt 32 0
3166 %9 = OpTypeFloat 32
3167 %3 = OpTypePointer Uniform %2
3168 %4 = OpTypeFunction %1
3169 %5 = OpConstant %9 3.14
3170 %6 = OpVariable %3 Uniform
3171 %7 = OpFunction %1 None %4
3172 %8 = OpLabel
3173 OpStore %6 %5
3174 OpReturn
3175 OpFunctionEnd)";
3176 CompileSuccessfully(spirv.c_str());
3177 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3178 EXPECT_THAT(getDiagnosticString(),
3179 HasSubstr(make_message(
3180 "OpStore Pointer <id> '7[%7]'s type does not match "
3181 "Object <id> '6[%float_3_1400001]'s type.")));
3184 // The next series of test check test a relaxation of the rules for stores to
3185 // structs. The first test checks that we get a failure when the option is not
3186 // set to relax the rule.
3187 // TODO: Add tests for layout compatible arrays and matricies when the validator
3188 // relaxes the rules for them as well. Also need test to check for layout
3189 // decorations specific to those types.
3190 TEST_P(ValidateIdWithMessage, OpStoreTypeBadStruct) {
3191 std::string spirv = kGLSL450MemoryModel + R"(
3192 OpMemberDecorate %1 0 Offset 0
3193 OpMemberDecorate %1 1 Offset 4
3194 OpMemberDecorate %2 0 Offset 0
3195 OpMemberDecorate %2 1 Offset 4
3196 %3 = OpTypeVoid
3197 %4 = OpTypeFloat 32
3198 %1 = OpTypeStruct %4 %4
3199 %5 = OpTypePointer Uniform %1
3200 %2 = OpTypeStruct %4 %4
3201 %6 = OpTypeFunction %3
3202 %7 = OpConstant %4 3.14
3203 %8 = OpVariable %5 Uniform
3204 %9 = OpFunction %3 None %6
3205 %10 = OpLabel
3206 %11 = OpCompositeConstruct %2 %7 %7
3207 OpStore %8 %11
3208 OpReturn
3209 OpFunctionEnd)";
3210 CompileSuccessfully(spirv.c_str());
3211 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3212 EXPECT_THAT(getDiagnosticString(),
3213 HasSubstr(make_message(
3214 "OpStore Pointer <id> '8[%8]'s type does not match "
3215 "Object <id> '11[%11]'s type.")));
3218 // Same code as the last test. The difference is that we relax the rule.
3219 // Because the structs %3 and %5 are defined the same way.
3220 TEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedStruct) {
3221 std::string spirv = kGLSL450MemoryModel + R"(
3222 OpMemberDecorate %1 0 Offset 0
3223 OpMemberDecorate %1 1 Offset 4
3224 OpMemberDecorate %2 0 Offset 0
3225 OpMemberDecorate %2 1 Offset 4
3226 %3 = OpTypeVoid
3227 %4 = OpTypeFloat 32
3228 %1 = OpTypeStruct %4 %4
3229 %5 = OpTypePointer Uniform %1
3230 %2 = OpTypeStruct %4 %4
3231 %6 = OpTypeFunction %3
3232 %7 = OpConstant %4 3.14
3233 %8 = OpVariable %5 Uniform
3234 %9 = OpFunction %3 None %6
3235 %10 = OpLabel
3236 %11 = OpCompositeConstruct %2 %7 %7
3237 OpStore %8 %11
3238 OpReturn
3239 OpFunctionEnd)";
3240 spvValidatorOptionsSetRelaxStoreStruct(options_, true);
3241 CompileSuccessfully(spirv.c_str());
3242 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3245 // Same code as the last test except for an extra decoration on one of the
3246 // members. With the relaxed rules, the code is still valid.
3247 TEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedStructWithExtraDecoration) {
3248 std::string spirv = kGLSL450MemoryModel + R"(
3249 OpMemberDecorate %1 0 Offset 0
3250 OpMemberDecorate %1 1 Offset 4
3251 OpMemberDecorate %1 0 RelaxedPrecision
3252 OpMemberDecorate %2 0 Offset 0
3253 OpMemberDecorate %2 1 Offset 4
3254 %3 = OpTypeVoid
3255 %4 = OpTypeFloat 32
3256 %1 = OpTypeStruct %4 %4
3257 %5 = OpTypePointer Uniform %1
3258 %2 = OpTypeStruct %4 %4
3259 %6 = OpTypeFunction %3
3260 %7 = OpConstant %4 3.14
3261 %8 = OpVariable %5 Uniform
3262 %9 = OpFunction %3 None %6
3263 %10 = OpLabel
3264 %11 = OpCompositeConstruct %2 %7 %7
3265 OpStore %8 %11
3266 OpReturn
3267 OpFunctionEnd)";
3268 spvValidatorOptionsSetRelaxStoreStruct(options_, true);
3269 CompileSuccessfully(spirv.c_str());
3270 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3273 // This test check that we recursively traverse the struct to check if they are
3274 // interchangable.
3275 TEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedNestedStruct) {
3276 std::string spirv = kGLSL450MemoryModel + R"(
3277 OpMemberDecorate %1 0 Offset 0
3278 OpMemberDecorate %1 1 Offset 4
3279 OpMemberDecorate %2 0 Offset 0
3280 OpMemberDecorate %2 1 Offset 8
3281 OpMemberDecorate %3 0 Offset 0
3282 OpMemberDecorate %3 1 Offset 4
3283 OpMemberDecorate %4 0 Offset 0
3284 OpMemberDecorate %4 1 Offset 8
3285 %5 = OpTypeVoid
3286 %6 = OpTypeInt 32 0
3287 %7 = OpTypeFloat 32
3288 %1 = OpTypeStruct %7 %6
3289 %2 = OpTypeStruct %1 %1
3290 %8 = OpTypePointer Uniform %2
3291 %3 = OpTypeStruct %7 %6
3292 %4 = OpTypeStruct %3 %3
3293 %9 = OpTypeFunction %5
3294 %10 = OpConstant %6 7
3295 %11 = OpConstant %7 3.14
3296 %12 = OpConstantComposite %3 %11 %10
3297 %13 = OpVariable %8 Uniform
3298 %14 = OpFunction %5 None %9
3299 %15 = OpLabel
3300 %16 = OpCompositeConstruct %4 %12 %12
3301 OpStore %13 %16
3302 OpReturn
3303 OpFunctionEnd)";
3304 spvValidatorOptionsSetRelaxStoreStruct(options_, true);
3305 CompileSuccessfully(spirv.c_str());
3306 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3309 // This test check that the even with the relaxed rules an error is identified
3310 // if the members of the struct are in a different order.
3311 TEST_P(ValidateIdWithMessage, OpStoreTypeBadRelaxedStruct1) {
3312 std::string spirv = kGLSL450MemoryModel + R"(
3313 OpMemberDecorate %1 0 Offset 0
3314 OpMemberDecorate %1 1 Offset 4
3315 OpMemberDecorate %2 0 Offset 0
3316 OpMemberDecorate %2 1 Offset 8
3317 OpMemberDecorate %3 0 Offset 0
3318 OpMemberDecorate %3 1 Offset 4
3319 OpMemberDecorate %4 0 Offset 0
3320 OpMemberDecorate %4 1 Offset 8
3321 %5 = OpTypeVoid
3322 %6 = OpTypeInt 32 0
3323 %7 = OpTypeFloat 32
3324 %1 = OpTypeStruct %6 %7
3325 %2 = OpTypeStruct %1 %1
3326 %8 = OpTypePointer Uniform %2
3327 %3 = OpTypeStruct %7 %6
3328 %4 = OpTypeStruct %3 %3
3329 %9 = OpTypeFunction %5
3330 %10 = OpConstant %6 7
3331 %11 = OpConstant %7 3.14
3332 %12 = OpConstantComposite %3 %11 %10
3333 %13 = OpVariable %8 Uniform
3334 %14 = OpFunction %5 None %9
3335 %15 = OpLabel
3336 %16 = OpCompositeConstruct %4 %12 %12
3337 OpStore %13 %16
3338 OpReturn
3339 OpFunctionEnd)";
3340 spvValidatorOptionsSetRelaxStoreStruct(options_, true);
3341 CompileSuccessfully(spirv.c_str());
3342 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3343 EXPECT_THAT(
3344 getDiagnosticString(),
3345 HasSubstr(make_message(
3346 "OpStore Pointer <id> '13[%13]'s layout does not match Object "
3347 "<id> '16[%16]'s layout.")));
3350 // This test check that the even with the relaxed rules an error is identified
3351 // if the members of the struct are at different offsets.
3352 TEST_P(ValidateIdWithMessage, OpStoreTypeBadRelaxedStruct2) {
3353 std::string spirv = kGLSL450MemoryModel + R"(
3354 OpMemberDecorate %1 0 Offset 4
3355 OpMemberDecorate %1 1 Offset 0
3356 OpMemberDecorate %2 0 Offset 0
3357 OpMemberDecorate %2 1 Offset 8
3358 OpMemberDecorate %3 0 Offset 0
3359 OpMemberDecorate %3 1 Offset 4
3360 OpMemberDecorate %4 0 Offset 0
3361 OpMemberDecorate %4 1 Offset 8
3362 %5 = OpTypeVoid
3363 %6 = OpTypeInt 32 0
3364 %7 = OpTypeFloat 32
3365 %1 = OpTypeStruct %7 %6
3366 %2 = OpTypeStruct %1 %1
3367 %8 = OpTypePointer Uniform %2
3368 %3 = OpTypeStruct %7 %6
3369 %4 = OpTypeStruct %3 %3
3370 %9 = OpTypeFunction %5
3371 %10 = OpConstant %6 7
3372 %11 = OpConstant %7 3.14
3373 %12 = OpConstantComposite %3 %11 %10
3374 %13 = OpVariable %8 Uniform
3375 %14 = OpFunction %5 None %9
3376 %15 = OpLabel
3377 %16 = OpCompositeConstruct %4 %12 %12
3378 OpStore %13 %16
3379 OpReturn
3380 OpFunctionEnd)";
3381 spvValidatorOptionsSetRelaxStoreStruct(options_, true);
3382 CompileSuccessfully(spirv.c_str());
3383 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3384 EXPECT_THAT(
3385 getDiagnosticString(),
3386 HasSubstr(make_message(
3387 "OpStore Pointer <id> '13[%13]'s layout does not match Object "
3388 "<id> '16[%16]'s layout.")));
3391 TEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedLogicalPointerReturnPointer) {
3392 const std::string spirv = R"(
3393 OpCapability Shader
3394 OpCapability Linkage
3395 OpMemoryModel Logical GLSL450
3396 %1 = OpTypeInt 32 1
3397 %2 = OpTypePointer Function %1
3398 %3 = OpTypeFunction %2 %2
3399 %4 = OpFunction %2 None %3
3400 %5 = OpFunctionParameter %2
3401 %6 = OpLabel
3402 OpReturnValue %5
3403 OpFunctionEnd)";
3405 spvValidatorOptionsSetRelaxLogicalPointer(options_, true);
3406 CompileSuccessfully(spirv.c_str());
3407 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3410 TEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedLogicalPointerAllocPointer) {
3411 const std::string spirv = R"(
3412 OpCapability Shader
3413 OpCapability Linkage
3414 OpMemoryModel Logical GLSL450
3415 %1 = OpTypeVoid
3416 %2 = OpTypeInt 32 1
3417 %3 = OpTypeFunction %1 ; void(void)
3418 %4 = OpTypePointer Uniform %2 ; int*
3419 %5 = OpTypePointer Private %4 ; int** (Private)
3420 %6 = OpTypePointer Function %4 ; int** (Function)
3421 %7 = OpVariable %5 Private
3422 %8 = OpFunction %1 None %3
3423 %9 = OpLabel
3424 %10 = OpVariable %6 Function
3425 OpReturn
3426 OpFunctionEnd)";
3428 spvValidatorOptionsSetRelaxLogicalPointer(options_, true);
3429 CompileSuccessfully(spirv.c_str());
3430 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3433 TEST_P(ValidateIdWithMessage, OpStoreVoid) {
3434 std::string spirv = kGLSL450MemoryModel + R"(
3435 %1 = OpTypeVoid
3436 %2 = OpTypeInt 32 0
3437 %3 = OpTypePointer Uniform %2
3438 %4 = OpTypeFunction %1
3439 %6 = OpVariable %3 Uniform
3440 %7 = OpFunction %1 None %4
3441 %8 = OpLabel
3442 %9 = OpFunctionCall %1 %7
3443 OpStore %6 %9
3444 OpReturn
3445 OpFunctionEnd)";
3446 CompileSuccessfully(spirv.c_str());
3447 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3448 EXPECT_THAT(
3449 getDiagnosticString(),
3450 HasSubstr(make_message("OpStore Object <id> '8[%8]'s type is void.")));
3453 TEST_P(ValidateIdWithMessage, OpStoreLabel) {
3454 std::string spirv = kGLSL450MemoryModel + R"(
3455 %1 = OpTypeVoid
3456 %2 = OpTypeInt 32 0
3457 %3 = OpTypePointer Uniform %2
3458 %4 = OpTypeFunction %1
3459 %6 = OpVariable %3 Uniform
3460 %7 = OpFunction %1 None %4
3461 %8 = OpLabel
3462 OpStore %6 %8
3463 OpReturn
3464 OpFunctionEnd)";
3465 CompileSuccessfully(spirv.c_str());
3466 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3467 EXPECT_THAT(getDiagnosticString(),
3468 HasSubstr(make_message("Operand '7[%7]' requires a type")));
3471 // TODO: enable when this bug is fixed:
3472 // https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404
3473 TEST_P(ValidateIdWithMessage, DISABLED_OpStoreFunction) {
3474 std::string spirv = kGLSL450MemoryModel + R"(
3475 %2 = OpTypeInt 32 0
3476 %3 = OpTypePointer UniformConstant %2
3477 %4 = OpTypeFunction %2
3478 %5 = OpConstant %2 123
3479 %6 = OpVariable %3 UniformConstant
3480 %7 = OpFunction %2 None %4
3481 %8 = OpLabel
3482 OpStore %6 %7
3483 OpReturnValue %5
3484 OpFunctionEnd)";
3485 CompileSuccessfully(spirv.c_str());
3486 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3489 TEST_P(ValidateIdWithMessage, OpStoreBuiltin) {
3490 std::string spirv = R"(
3491 OpCapability Shader
3492 %1 = OpExtInstImport "GLSL.std.450"
3493 OpMemoryModel Logical GLSL450
3494 OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
3495 OpExecutionMode %main LocalSize 1 1 1
3496 OpSource GLSL 450
3497 OpName %main "main"
3499 OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
3500 OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
3502 %int = OpTypeInt 32 1
3503 %uint = OpTypeInt 32 0
3504 %v3uint = OpTypeVector %uint 3
3505 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
3506 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
3508 %zero = OpConstant %uint 0
3509 %v3uint_000 = OpConstantComposite %v3uint %zero %zero %zero
3511 %void = OpTypeVoid
3512 %voidfunc = OpTypeFunction %void
3513 %main = OpFunction %void None %voidfunc
3514 %lmain = OpLabel
3516 OpStore %gl_GlobalInvocationID %v3uint_000
3518 OpReturn
3519 OpFunctionEnd
3522 CompileSuccessfully(spirv.c_str());
3523 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3524 EXPECT_THAT(getDiagnosticString(),
3525 HasSubstr(make_message("storage class is read-only")));
3528 TEST_P(ValidateIdWithMessage, OpCopyMemoryGood) {
3529 std::string spirv = kGLSL450MemoryModel + R"(
3530 %1 = OpTypeVoid
3531 %2 = OpTypeInt 32 0
3532 %3 = OpTypePointer UniformConstant %2
3533 %4 = OpConstant %2 42
3534 %5 = OpVariable %3 UniformConstant %4
3535 %6 = OpTypePointer Function %2
3536 %7 = OpTypeFunction %1
3537 %8 = OpFunction %1 None %7
3538 %9 = OpLabel
3539 %10 = OpVariable %6 Function
3540 OpCopyMemory %10 %5 None
3541 OpReturn
3542 OpFunctionEnd
3544 CompileSuccessfully(spirv.c_str());
3545 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3548 TEST_P(ValidateIdWithMessage, OpCopyMemoryNonPointerTarget) {
3549 const std::string spirv = kGLSL450MemoryModel + R"(
3550 %1 = OpTypeVoid
3551 %2 = OpTypeInt 32 0
3552 %3 = OpTypePointer Uniform %2
3553 %4 = OpTypeFunction %1 %2 %3
3554 %5 = OpFunction %1 None %4
3555 %6 = OpFunctionParameter %2
3556 %7 = OpFunctionParameter %3
3557 %8 = OpLabel
3558 OpCopyMemory %6 %7
3559 OpReturn
3560 OpFunctionEnd
3563 CompileSuccessfully(spirv);
3564 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3565 EXPECT_THAT(
3566 getDiagnosticString(),
3567 HasSubstr(make_message("Target operand <id> '6[%6]' is not a pointer.")));
3570 TEST_P(ValidateIdWithMessage, OpCopyMemoryNonPointerSource) {
3571 const std::string spirv = kGLSL450MemoryModel + R"(
3572 %1 = OpTypeVoid
3573 %2 = OpTypeInt 32 0
3574 %3 = OpTypePointer Uniform %2
3575 %4 = OpTypeFunction %1 %2 %3
3576 %5 = OpFunction %1 None %4
3577 %6 = OpFunctionParameter %2
3578 %7 = OpFunctionParameter %3
3579 %8 = OpLabel
3580 OpCopyMemory %7 %6
3581 OpReturn
3582 OpFunctionEnd
3585 CompileSuccessfully(spirv);
3586 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3587 EXPECT_THAT(
3588 getDiagnosticString(),
3589 HasSubstr(make_message("Source operand <id> '6[%6]' is not a pointer.")));
3592 TEST_P(ValidateIdWithMessage, OpCopyMemoryBad) {
3593 std::string spirv = kGLSL450MemoryModel + R"(
3594 %1 = OpTypeVoid
3595 %2 = OpTypeInt 32 0
3596 %3 = OpTypePointer UniformConstant %2
3597 %4 = OpConstant %2 42
3598 %5 = OpVariable %3 UniformConstant %4
3599 %11 = OpTypeFloat 32
3600 %6 = OpTypePointer Function %11
3601 %7 = OpTypeFunction %1
3602 %8 = OpFunction %1 None %7
3603 %9 = OpLabel
3604 %10 = OpVariable %6 Function
3605 OpCopyMemory %10 %5 None
3606 OpReturn
3607 OpFunctionEnd
3609 CompileSuccessfully(spirv.c_str());
3610 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3611 EXPECT_THAT(getDiagnosticString(),
3612 HasSubstr(make_message("Target <id> '5[%5]'s type does not match "
3613 "Source <id> '2[%uint]'s type.")));
3616 TEST_P(ValidateIdWithMessage, OpCopyMemoryVoidTarget) {
3617 const std::string spirv = kGLSL450MemoryModel + R"(
3618 %1 = OpTypeVoid
3619 %2 = OpTypeInt 32 0
3620 %3 = OpTypePointer Uniform %1
3621 %4 = OpTypePointer Uniform %2
3622 %5 = OpTypeFunction %1 %3 %4
3623 %6 = OpFunction %1 None %5
3624 %7 = OpFunctionParameter %3
3625 %8 = OpFunctionParameter %4
3626 %9 = OpLabel
3627 OpCopyMemory %7 %8
3628 OpReturn
3629 OpFunctionEnd
3632 CompileSuccessfully(spirv);
3633 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3634 EXPECT_THAT(
3635 getDiagnosticString(),
3636 HasSubstr(make_message("Target operand <id> '7[%7]' cannot be a void "
3637 "pointer.")));
3640 TEST_P(ValidateIdWithMessage, OpCopyMemoryVoidSource) {
3641 const std::string spirv = kGLSL450MemoryModel + R"(
3642 %1 = OpTypeVoid
3643 %2 = OpTypeInt 32 0
3644 %3 = OpTypePointer Uniform %1
3645 %4 = OpTypePointer Uniform %2
3646 %5 = OpTypeFunction %1 %3 %4
3647 %6 = OpFunction %1 None %5
3648 %7 = OpFunctionParameter %3
3649 %8 = OpFunctionParameter %4
3650 %9 = OpLabel
3651 OpCopyMemory %8 %7
3652 OpReturn
3653 OpFunctionEnd
3656 CompileSuccessfully(spirv);
3657 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3658 EXPECT_THAT(
3659 getDiagnosticString(),
3660 HasSubstr(make_message("Source operand <id> '7[%7]' cannot be a void "
3661 "pointer.")));
3664 TEST_P(ValidateIdWithMessage, OpCopyMemorySizedGood) {
3665 std::string spirv = kGLSL450MemoryModel + R"(
3666 %1 = OpTypeVoid
3667 %2 = OpTypeInt 32 0
3668 %3 = OpTypePointer UniformConstant %2
3669 %4 = OpTypePointer Function %2
3670 %5 = OpConstant %2 4
3671 %6 = OpVariable %3 UniformConstant %5
3672 %7 = OpTypeFunction %1
3673 %8 = OpFunction %1 None %7
3674 %9 = OpLabel
3675 %10 = OpVariable %4 Function
3676 OpCopyMemorySized %10 %6 %5 None
3677 OpReturn
3678 OpFunctionEnd)";
3679 CompileSuccessfully(spirv.c_str());
3680 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3682 TEST_P(ValidateIdWithMessage, OpCopyMemorySizedTargetBad) {
3683 std::string spirv = kGLSL450MemoryModel + R"(
3684 %1 = OpTypeVoid
3685 %2 = OpTypeInt 32 0
3686 %3 = OpTypePointer UniformConstant %2
3687 %4 = OpTypePointer Function %2
3688 %5 = OpConstant %2 4
3689 %6 = OpVariable %3 UniformConstant %5
3690 %7 = OpTypeFunction %1
3691 %8 = OpFunction %1 None %7
3692 %9 = OpLabel
3693 OpCopyMemorySized %5 %5 %5 None
3694 OpReturn
3695 OpFunctionEnd)";
3696 CompileSuccessfully(spirv.c_str());
3697 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3698 EXPECT_THAT(getDiagnosticString(),
3699 HasSubstr(make_message(
3700 "Target operand <id> '5[%uint_4]' is not a pointer.")));
3702 TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSourceBad) {
3703 std::string spirv = kGLSL450MemoryModel + R"(
3704 %1 = OpTypeVoid
3705 %2 = OpTypeInt 32 0
3706 %3 = OpTypePointer UniformConstant %2
3707 %4 = OpTypePointer Function %2
3708 %5 = OpConstant %2 4
3709 %6 = OpTypeFunction %1
3710 %7 = OpFunction %1 None %6
3711 %8 = OpLabel
3712 %9 = OpVariable %4 Function
3713 OpCopyMemorySized %9 %5 %5 None
3714 OpReturn
3715 OpFunctionEnd)";
3716 CompileSuccessfully(spirv.c_str());
3717 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3718 EXPECT_THAT(getDiagnosticString(),
3719 HasSubstr(make_message(
3720 "Source operand <id> '5[%uint_4]' is not a pointer.")));
3722 TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeBad) {
3723 std::string spirv = kGLSL450MemoryModel + R"(
3724 %1 = OpTypeVoid
3725 %2 = OpTypeInt 32 0
3726 %3 = OpTypePointer UniformConstant %2
3727 %4 = OpTypePointer Function %2
3728 %5 = OpConstant %2 4
3729 %6 = OpVariable %3 UniformConstant %5
3730 %7 = OpTypeFunction %1
3731 %8 = OpFunction %1 None %7
3732 %9 = OpLabel
3733 %10 = OpVariable %4 Function
3734 OpCopyMemorySized %10 %6 %6 None
3735 OpReturn
3736 OpFunctionEnd)";
3737 CompileSuccessfully(spirv.c_str());
3738 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3739 EXPECT_THAT(getDiagnosticString(),
3740 HasSubstr(make_message(
3741 "Size operand <id> '6[%6]' must be a scalar integer type.")));
3743 TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeTypeBad) {
3744 std::string spirv = kGLSL450MemoryModel + R"(
3745 %1 = OpTypeVoid
3746 %2 = OpTypeInt 32 0
3747 %3 = OpTypePointer UniformConstant %2
3748 %4 = OpTypePointer Function %2
3749 %5 = OpConstant %2 4
3750 %6 = OpVariable %3 UniformConstant %5
3751 %7 = OpTypeFunction %1
3752 %11 = OpTypeFloat 32
3753 %12 = OpConstant %11 1.0
3754 %8 = OpFunction %1 None %7
3755 %9 = OpLabel
3756 %10 = OpVariable %4 Function
3757 OpCopyMemorySized %10 %6 %12 None
3758 OpReturn
3759 OpFunctionEnd)";
3760 CompileSuccessfully(spirv.c_str());
3761 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3762 EXPECT_THAT(getDiagnosticString(),
3763 HasSubstr(make_message(
3764 "Size operand <id> '9[%float_1]' must be a scalar integer "
3765 "type.")));
3768 TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNull) {
3769 const std::string spirv = kGLSL450MemoryModel + R"(
3770 %1 = OpTypeVoid
3771 %2 = OpTypeInt 32 0
3772 %3 = OpConstantNull %2
3773 %4 = OpTypePointer Uniform %2
3774 %5 = OpTypeFloat 32
3775 %6 = OpTypePointer UniformConstant %5
3776 %7 = OpTypeFunction %1 %4 %6
3777 %8 = OpFunction %1 None %7
3778 %9 = OpFunctionParameter %4
3779 %10 = OpFunctionParameter %6
3780 %11 = OpLabel
3781 OpCopyMemorySized %9 %10 %3
3782 OpReturn
3783 OpFunctionEnd
3786 CompileSuccessfully(spirv);
3787 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3788 EXPECT_THAT(
3789 getDiagnosticString(),
3790 HasSubstr(make_message("Size operand <id> '3[%3]' cannot be a constant "
3791 "zero.")));
3794 TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantZero) {
3795 const std::string spirv = kGLSL450MemoryModel + R"(
3796 %1 = OpTypeVoid
3797 %2 = OpTypeInt 32 0
3798 %3 = OpConstant %2 0
3799 %4 = OpTypePointer Uniform %2
3800 %5 = OpTypeFloat 32
3801 %6 = OpTypePointer UniformConstant %5
3802 %7 = OpTypeFunction %1 %4 %6
3803 %8 = OpFunction %1 None %7
3804 %9 = OpFunctionParameter %4
3805 %10 = OpFunctionParameter %6
3806 %11 = OpLabel
3807 OpCopyMemorySized %9 %10 %3
3808 OpReturn
3809 OpFunctionEnd
3812 CompileSuccessfully(spirv);
3813 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3814 EXPECT_THAT(getDiagnosticString(),
3815 HasSubstr(make_message(
3816 "Size operand <id> '3[%uint_0]' cannot be a constant "
3817 "zero.")));
3820 TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantZero64) {
3821 const std::string spirv = kGLSL450MemoryModel + R"(
3822 %1 = OpTypeVoid
3823 %2 = OpTypeInt 64 0
3824 %3 = OpConstant %2 0
3825 %4 = OpTypePointer Uniform %2
3826 %5 = OpTypeFloat 32
3827 %6 = OpTypePointer UniformConstant %5
3828 %7 = OpTypeFunction %1 %4 %6
3829 %8 = OpFunction %1 None %7
3830 %9 = OpFunctionParameter %4
3831 %10 = OpFunctionParameter %6
3832 %11 = OpLabel
3833 OpCopyMemorySized %9 %10 %3
3834 OpReturn
3835 OpFunctionEnd
3838 CompileSuccessfully(spirv);
3839 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3840 EXPECT_THAT(getDiagnosticString(),
3841 HasSubstr(make_message(
3842 "Size operand <id> '3[%ulong_0]' cannot be a constant "
3843 "zero.")));
3846 TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNegative) {
3847 const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
3848 %1 = OpTypeVoid
3849 %2 = OpTypeInt 32 1
3850 %3 = OpConstant %2 -1
3851 %4 = OpTypePointer Uniform %2
3852 %5 = OpTypeFloat 32
3853 %6 = OpTypePointer UniformConstant %5
3854 %7 = OpTypeFunction %1 %4 %6
3855 %8 = OpFunction %1 None %7
3856 %9 = OpFunctionParameter %4
3857 %10 = OpFunctionParameter %6
3858 %11 = OpLabel
3859 OpCopyMemorySized %9 %10 %3
3860 OpReturn
3861 OpFunctionEnd
3864 CompileSuccessfully(spirv);
3865 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3866 EXPECT_THAT(getDiagnosticString(),
3867 HasSubstr(make_message(
3868 "Size operand <id> '3[%int_n1]' cannot have the sign bit set "
3869 "to 1.")));
3872 TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNegative64) {
3873 const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
3874 %1 = OpTypeVoid
3875 %2 = OpTypeInt 64 1
3876 %3 = OpConstant %2 -1
3877 %4 = OpTypePointer Uniform %2
3878 %5 = OpTypeFloat 32
3879 %6 = OpTypePointer UniformConstant %5
3880 %7 = OpTypeFunction %1 %4 %6
3881 %8 = OpFunction %1 None %7
3882 %9 = OpFunctionParameter %4
3883 %10 = OpFunctionParameter %6
3884 %11 = OpLabel
3885 OpCopyMemorySized %9 %10 %3
3886 OpReturn
3887 OpFunctionEnd
3890 CompileSuccessfully(spirv);
3891 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3892 EXPECT_THAT(
3893 getDiagnosticString(),
3894 HasSubstr(make_message(
3895 "Size operand <id> '3[%long_n1]' cannot have the sign bit set "
3896 "to 1.")));
3899 TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeUnsignedNegative) {
3900 const std::string spirv = kGLSL450MemoryModel + R"(
3901 %1 = OpTypeVoid
3902 %2 = OpTypeInt 32 0
3903 %3 = OpConstant %2 2147483648
3904 %4 = OpTypePointer Uniform %2
3905 %5 = OpTypeFloat 32
3906 %6 = OpTypePointer UniformConstant %5
3907 %7 = OpTypeFunction %1 %4 %6
3908 %8 = OpFunction %1 None %7
3909 %9 = OpFunctionParameter %4
3910 %10 = OpFunctionParameter %6
3911 %11 = OpLabel
3912 OpCopyMemorySized %9 %10 %3
3913 OpReturn
3914 OpFunctionEnd
3917 CompileSuccessfully(spirv);
3918 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3921 TEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeUnsignedNegative64) {
3922 const std::string spirv = kGLSL450MemoryModel + R"(
3923 %1 = OpTypeVoid
3924 %2 = OpTypeInt 64 0
3925 %3 = OpConstant %2 9223372036854775808
3926 %4 = OpTypePointer Uniform %2
3927 %5 = OpTypeFloat 32
3928 %6 = OpTypePointer UniformConstant %5
3929 %7 = OpTypeFunction %1 %4 %6
3930 %8 = OpFunction %1 None %7
3931 %9 = OpFunctionParameter %4
3932 %10 = OpFunctionParameter %6
3933 %11 = OpLabel
3934 OpCopyMemorySized %9 %10 %3
3935 OpReturn
3936 OpFunctionEnd
3939 CompileSuccessfully(spirv);
3940 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3943 const char kDeeplyNestedStructureSetup[] = R"(
3944 %void = OpTypeVoid
3945 %void_f = OpTypeFunction %void
3946 %int = OpTypeInt 32 0
3947 %float = OpTypeFloat 32
3948 %v3float = OpTypeVector %float 3
3949 %mat4x3 = OpTypeMatrix %v3float 4
3950 %_ptr_Private_mat4x3 = OpTypePointer Private %mat4x3
3951 %_ptr_Private_float = OpTypePointer Private %float
3952 %my_matrix = OpVariable %_ptr_Private_mat4x3 Private
3953 %my_float_var = OpVariable %_ptr_Private_float Private
3954 %_ptr_Function_float = OpTypePointer Function %float
3955 %int_0 = OpConstant %int 0
3956 %int_1 = OpConstant %int 1
3957 %int_2 = OpConstant %int 2
3958 %int_3 = OpConstant %int 3
3959 %int_5 = OpConstant %int 5
3961 ; Making the following nested structures.
3963 ; struct S {
3964 ; bool b;
3965 ; vec4 v[5];
3966 ; int i;
3967 ; mat4x3 m[5];
3969 ; uniform blockName {
3970 ; S s;
3971 ; bool cond;
3972 ; RunTimeArray arr;
3975 %f32arr = OpTypeRuntimeArray %float
3976 %v4float = OpTypeVector %float 4
3977 %array5_mat4x3 = OpTypeArray %mat4x3 %int_5
3978 %array5_vec4 = OpTypeArray %v4float %int_5
3979 %_ptr_Uniform_float = OpTypePointer Uniform %float
3980 %_ptr_Function_vec4 = OpTypePointer Function %v4float
3981 %_ptr_Uniform_vec4 = OpTypePointer Uniform %v4float
3982 %struct_s = OpTypeStruct %int %array5_vec4 %int %array5_mat4x3
3983 %struct_blockName = OpTypeStruct %struct_s %int %f32arr
3984 %_ptr_Uniform_blockName = OpTypePointer Uniform %struct_blockName
3985 %_ptr_Uniform_struct_s = OpTypePointer Uniform %struct_s
3986 %_ptr_Uniform_array5_mat4x3 = OpTypePointer Uniform %array5_mat4x3
3987 %_ptr_Uniform_mat4x3 = OpTypePointer Uniform %mat4x3
3988 %_ptr_Uniform_v3float = OpTypePointer Uniform %v3float
3989 %blockName_var = OpVariable %_ptr_Uniform_blockName Uniform
3990 %spec_int = OpSpecConstant %int 2
3991 %float_0 = OpConstant %float 0
3992 %func = OpFunction %void None %void_f
3993 %my_label = OpLabel
3996 // In what follows, Access Chain Instruction refers to one of the following:
3997 // OpAccessChain, OpInBoundsAccessChain, OpPtrAccessChain, and
3998 // OpInBoundsPtrAccessChain
3999 using AccessChainInstructionTest = spvtest::ValidateBase<std::string>;
4001 // Determines whether the access chain instruction requires the 'element id'
4002 // argument.
4003 bool AccessChainRequiresElemId(const std::string& instr) {
4004 return (instr == "OpPtrAccessChain" || instr == "OpInBoundsPtrAccessChain");
4007 // Valid: Access a float in a matrix using an access chain instruction.
4008 TEST_P(AccessChainInstructionTest, AccessChainGood) {
4009 const std::string instr = GetParam();
4010 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4011 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup +
4012 "%float_entry = " + instr +
4013 R"( %_ptr_Private_float %my_matrix )" + elem +
4014 R"(%int_0 %int_1
4015 OpReturn
4016 OpFunctionEnd
4018 CompileSuccessfully(spirv);
4019 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4022 // Invalid. The result type of an access chain instruction must be a pointer.
4023 TEST_P(AccessChainInstructionTest, AccessChainResultTypeBad) {
4024 const std::string instr = GetParam();
4025 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4026 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4027 %float_entry = )" +
4028 instr +
4029 R"( %float %my_matrix )" + elem +
4030 R"(%int_0 %int_1
4031 OpReturn
4032 OpFunctionEnd
4035 const std::string expected_err = "The Result Type of " + instr +
4036 " <id> '36[%36]' must be "
4037 "OpTypePointer. Found OpTypeFloat.";
4038 CompileSuccessfully(spirv);
4039 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4040 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4043 // Invalid. The base type of an access chain instruction must be a pointer.
4044 TEST_P(AccessChainInstructionTest, AccessChainBaseTypeVoidBad) {
4045 const std::string instr = GetParam();
4046 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4047 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4048 %float_entry = )" +
4049 instr + " %_ptr_Private_float %void " + elem +
4050 R"(%int_0 %int_1
4051 OpReturn
4052 OpFunctionEnd
4054 CompileSuccessfully(spirv);
4055 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4056 EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '1[%void]' cannot be a "
4057 "type"));
4060 // Invalid. The base type of an access chain instruction must be a pointer.
4061 TEST_P(AccessChainInstructionTest, AccessChainBaseTypeNonPtrVariableBad) {
4062 const std::string instr = GetParam();
4063 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4064 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4065 %entry = )" +
4066 instr + R"( %_ptr_Private_float %_ptr_Private_float )" +
4067 elem +
4068 R"(%int_0 %int_1
4069 OpReturn
4070 OpFunctionEnd
4072 CompileSuccessfully(spirv);
4073 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4074 EXPECT_THAT(getDiagnosticString(),
4075 HasSubstr("Operand '8[%_ptr_Private_float]' cannot be a type"));
4078 // Invalid: The storage class of Base and Result do not match.
4079 TEST_P(AccessChainInstructionTest,
4080 AccessChainResultAndBaseStorageClassDoesntMatchBad) {
4081 const std::string instr = GetParam();
4082 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4083 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4084 %entry = )" +
4085 instr + R"( %_ptr_Function_float %my_matrix )" + elem +
4086 R"(%int_0 %int_1
4087 OpReturn
4088 OpFunctionEnd
4090 const std::string expected_err =
4091 "The result pointer storage class and base pointer storage class in " +
4092 instr + " do not match.";
4093 CompileSuccessfully(spirv);
4094 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4095 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4098 // Invalid. The base type of an access chain instruction must point to a
4099 // composite object.
4100 TEST_P(AccessChainInstructionTest,
4101 AccessChainBasePtrNotPointingToCompositeBad) {
4102 const std::string instr = GetParam();
4103 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4104 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4105 %entry = )" +
4106 instr + R"( %_ptr_Private_float %my_float_var )" + elem +
4107 R"(%int_0
4108 OpReturn
4109 OpFunctionEnd
4111 const std::string expected_err = instr +
4112 " reached non-composite type while "
4113 "indexes still remain to be traversed.";
4114 CompileSuccessfully(spirv);
4115 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4116 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4119 // Valid. No Indexes were passed to the access chain instruction. The Result
4120 // Type is the same as the Base type.
4121 TEST_P(AccessChainInstructionTest, AccessChainNoIndexesGood) {
4122 const std::string instr = GetParam();
4123 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4124 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4125 %entry = )" +
4126 instr + R"( %_ptr_Private_float %my_float_var )" + elem +
4128 OpReturn
4129 OpFunctionEnd
4131 CompileSuccessfully(spirv);
4132 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4135 // Invalid. No Indexes were passed to the access chain instruction, but the
4136 // Result Type is different from the Base type.
4137 TEST_P(AccessChainInstructionTest, AccessChainNoIndexesBad) {
4138 const std::string instr = GetParam();
4139 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4140 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4141 %entry = )" +
4142 instr + R"( %_ptr_Private_mat4x3 %my_float_var )" + elem +
4144 OpReturn
4145 OpFunctionEnd
4147 CompileSuccessfully(spirv);
4148 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4149 EXPECT_THAT(
4150 getDiagnosticString(),
4151 HasSubstr("result type (OpTypeMatrix) does not match the type that "
4152 "results from indexing into the base <id> (OpTypeFloat)."));
4155 // Valid: 255 indexes passed to the access chain instruction. Limit is 255.
4156 TEST_P(AccessChainInstructionTest, AccessChainTooManyIndexesGood) {
4157 const std::string instr = GetParam();
4158 const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : "";
4159 const std::string arrayStride =
4160 " OpDecorate %_ptr_Uniform_deep_struct ArrayStride 8 ";
4161 int depth = 255;
4162 std::string header =
4163 kGLSL450MemoryModel + arrayStride + kDeeplyNestedStructureSetup;
4164 header.erase(header.find("%func"));
4165 std::ostringstream spirv;
4166 spirv << header << "\n";
4168 // Build nested structures. Struct 'i' contains struct 'i-1'
4169 spirv << "%s_depth_1 = OpTypeStruct %float\n";
4170 for (int i = 2; i <= depth; ++i) {
4171 spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n";
4174 // Define Pointer and Variable to use for the AccessChain instruction.
4175 spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_"
4176 << depth << "\n";
4177 spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n";
4179 // Function Start
4180 spirv << R"(
4181 %func = OpFunction %void None %void_f
4182 %my_label = OpLabel
4185 // AccessChain with 'n' indexes (n = depth)
4186 spirv << "%entry = " << instr << " %_ptr_Uniform_float %deep_var" << elem;
4187 for (int i = 0; i < depth; ++i) {
4188 spirv << " %int_0";
4191 // Function end
4192 spirv << R"(
4193 OpReturn
4194 OpFunctionEnd
4196 CompileSuccessfully(spirv.str());
4197 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4200 // Invalid: 256 indexes passed to the access chain instruction. Limit is 255.
4201 TEST_P(AccessChainInstructionTest, AccessChainTooManyIndexesBad) {
4202 const std::string instr = GetParam();
4203 const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : "";
4204 std::ostringstream spirv;
4205 spirv << kGLSL450MemoryModel << kDeeplyNestedStructureSetup;
4206 spirv << "%entry = " << instr << " %_ptr_Private_float %my_matrix" << elem;
4207 for (int i = 0; i < 256; ++i) {
4208 spirv << " %int_0";
4210 spirv << R"(
4211 OpReturn
4212 OpFunctionEnd
4214 const std::string expected_err = "The number of indexes in " + instr +
4215 " may not exceed 255. Found 256 indexes.";
4216 CompileSuccessfully(spirv.str());
4217 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4218 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4221 // Valid: 10 indexes passed to the access chain instruction. (Custom limit: 10)
4222 TEST_P(AccessChainInstructionTest, CustomizedAccessChainTooManyIndexesGood) {
4223 const std::string instr = GetParam();
4224 const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : "";
4225 const std::string arrayStride =
4226 " OpDecorate %_ptr_Uniform_deep_struct ArrayStride 8 ";
4227 int depth = 10;
4228 std::string header =
4229 kGLSL450MemoryModel + arrayStride + kDeeplyNestedStructureSetup;
4230 header.erase(header.find("%func"));
4231 std::ostringstream spirv;
4232 spirv << header << "\n";
4234 // Build nested structures. Struct 'i' contains struct 'i-1'
4235 spirv << "%s_depth_1 = OpTypeStruct %float\n";
4236 for (int i = 2; i <= depth; ++i) {
4237 spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n";
4240 // Define Pointer and Variable to use for the AccessChain instruction.
4241 spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_"
4242 << depth << "\n";
4243 spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n";
4245 // Function Start
4246 spirv << R"(
4247 %func = OpFunction %void None %void_f
4248 %my_label = OpLabel
4251 // AccessChain with 'n' indexes (n = depth)
4252 spirv << "%entry = " << instr << " %_ptr_Uniform_float %deep_var" << elem;
4253 for (int i = 0; i < depth; ++i) {
4254 spirv << " %int_0";
4257 // Function end
4258 spirv << R"(
4259 OpReturn
4260 OpFunctionEnd
4263 spvValidatorOptionsSetUniversalLimit(
4264 options_, spv_validator_limit_max_access_chain_indexes, 10u);
4265 CompileSuccessfully(spirv.str());
4266 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4269 // Invalid: 11 indexes passed to the access chain instruction. Custom Limit:10
4270 TEST_P(AccessChainInstructionTest, CustomizedAccessChainTooManyIndexesBad) {
4271 const std::string instr = GetParam();
4272 const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : "";
4273 std::ostringstream spirv;
4274 spirv << kGLSL450MemoryModel << kDeeplyNestedStructureSetup;
4275 spirv << "%entry = " << instr << " %_ptr_Private_float %my_matrix" << elem;
4276 for (int i = 0; i < 11; ++i) {
4277 spirv << " %int_0";
4279 spirv << R"(
4280 OpReturn
4281 OpFunctionEnd
4283 const std::string expected_err = "The number of indexes in " + instr +
4284 " may not exceed 10. Found 11 indexes.";
4285 spvValidatorOptionsSetUniversalLimit(
4286 options_, spv_validator_limit_max_access_chain_indexes, 10u);
4287 CompileSuccessfully(spirv.str());
4288 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4289 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4292 // Invalid: Index passed to the access chain instruction is float (must be
4293 // integer).
4294 TEST_P(AccessChainInstructionTest, AccessChainUndefinedIndexBad) {
4295 const std::string instr = GetParam();
4296 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4297 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4298 %entry = )" +
4299 instr + R"( %_ptr_Private_float %my_matrix )" + elem +
4300 R"(%float_0 %int_1
4301 OpReturn
4302 OpFunctionEnd
4304 const std::string expected_err =
4305 "Indexes passed to " + instr + " must be of type integer.";
4306 CompileSuccessfully(spirv);
4307 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4308 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4311 // Invalid: The index argument that indexes into a struct must be of type
4312 // OpConstant.
4313 TEST_P(AccessChainInstructionTest, AccessChainStructIndexNotConstantBad) {
4314 const std::string instr = GetParam();
4315 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4316 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4317 %f = )" +
4318 instr + R"( %_ptr_Uniform_float %blockName_var )" + elem +
4319 R"(%int_0 %spec_int %int_2
4320 OpReturn
4321 OpFunctionEnd
4323 CompileSuccessfully(spirv);
4324 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4325 EXPECT_THAT(getDiagnosticString(), HasSubstr("The <id> passed to " + instr));
4326 EXPECT_THAT(getDiagnosticString(),
4327 HasSubstr("into a structure must be an OpConstant"));
4330 // Invalid: Indexing up to a vec4 granularity, but result type expected float.
4331 TEST_P(AccessChainInstructionTest,
4332 AccessChainStructResultTypeDoesntMatchIndexedTypeBad) {
4333 const std::string instr = GetParam();
4334 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4335 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4336 %entry = )" +
4337 instr + R"( %_ptr_Uniform_float %blockName_var )" + elem +
4338 R"(%int_0 %int_1 %int_2
4339 OpReturn
4340 OpFunctionEnd
4342 const std::string expected_err = instr +
4343 " result type (OpTypeFloat) does not match "
4344 "the type that results from indexing into "
4345 "the base <id> (OpTypeVector).";
4346 CompileSuccessfully(spirv);
4347 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4348 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4351 // Invalid: Reach non-composite type (bool) when unused indexes remain.
4352 TEST_P(AccessChainInstructionTest, AccessChainStructTooManyIndexesBad) {
4353 const std::string instr = GetParam();
4354 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4355 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4356 %entry = )" +
4357 instr + R"( %_ptr_Uniform_float %blockName_var )" + elem +
4358 R"(%int_0 %int_2 %int_2
4359 OpReturn
4360 OpFunctionEnd
4362 const std::string expected_err = instr +
4363 " reached non-composite type while "
4364 "indexes still remain to be traversed.";
4365 CompileSuccessfully(spirv);
4366 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4367 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4370 // Invalid: Trying to find index 3 of the struct that has only 3 members.
4371 TEST_P(AccessChainInstructionTest, AccessChainStructIndexOutOfBoundBad) {
4372 const std::string instr = GetParam();
4373 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4374 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4375 %entry = )" +
4376 instr + R"( %_ptr_Uniform_float %blockName_var )" + elem +
4377 R"(%int_3 %int_2 %int_2
4378 OpReturn
4379 OpFunctionEnd
4381 const std::string expected_err = "is out of bounds: " + instr +
4382 " cannot find index 3 into the structure "
4383 "<id> '25[%_struct_25]'. This structure "
4384 "has 3 members. Largest valid index is 2.";
4385 CompileSuccessfully(spirv);
4386 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4387 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4390 // Valid: Tests that we can index into Struct, Array, Matrix, and Vector!
4391 TEST_P(AccessChainInstructionTest, AccessChainIndexIntoAllTypesGood) {
4392 // indexes that we are passing are: 0, 3, 1, 2, 0
4393 // 0 will select the struct_s within the base struct (blockName)
4394 // 3 will select the Array that contains 5 matrices
4395 // 1 will select the Matrix that is at index 1 of the array
4396 // 2 will select the column (which is a vector) within the matrix at index 2
4397 // 0 will select the element at the index 0 of the vector. (which is a float).
4398 const std::string instr = GetParam();
4399 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4400 const std::string arrayStride =
4401 " OpDecorate %_ptr_Uniform_blockName ArrayStride 8 ";
4402 std::ostringstream spirv;
4403 spirv << kGLSL450MemoryModel << arrayStride << kDeeplyNestedStructureSetup
4404 << std::endl;
4405 spirv << "%ss = " << instr << " %_ptr_Uniform_struct_s %blockName_var "
4406 << elem << "%int_0" << std::endl;
4407 spirv << "%sa = " << instr << " %_ptr_Uniform_array5_mat4x3 %blockName_var "
4408 << elem << "%int_0 %int_3" << std::endl;
4409 spirv << "%sm = " << instr << " %_ptr_Uniform_mat4x3 %blockName_var " << elem
4410 << "%int_0 %int_3 %int_1" << std::endl;
4411 spirv << "%sc = " << instr << " %_ptr_Uniform_v3float %blockName_var " << elem
4412 << "%int_0 %int_3 %int_1 %int_2" << std::endl;
4413 spirv << "%entry = " << instr << " %_ptr_Uniform_float %blockName_var "
4414 << elem << "%int_0 %int_3 %int_1 %int_2 %int_0" << std::endl;
4415 spirv << R"(
4416 OpReturn
4417 OpFunctionEnd
4419 CompileSuccessfully(spirv.str());
4420 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4423 // Valid: Access an element of OpTypeRuntimeArray.
4424 TEST_P(AccessChainInstructionTest, AccessChainIndexIntoRuntimeArrayGood) {
4425 const std::string instr = GetParam();
4426 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4427 const std::string arrayStride =
4428 " OpDecorate %_ptr_Uniform_blockName ArrayStride 8 ";
4429 std::string spirv = kGLSL450MemoryModel + arrayStride +
4430 kDeeplyNestedStructureSetup + R"(
4431 %runtime_arr_entry = )" + instr +
4432 R"( %_ptr_Uniform_float %blockName_var )" + elem +
4433 R"(%int_2 %int_0
4434 OpReturn
4435 OpFunctionEnd
4437 CompileSuccessfully(spirv);
4438 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4441 // Invalid: Unused index when accessing OpTypeRuntimeArray.
4442 TEST_P(AccessChainInstructionTest, AccessChainIndexIntoRuntimeArrayBad) {
4443 const std::string instr = GetParam();
4444 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4445 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4446 %runtime_arr_entry = )" +
4447 instr + R"( %_ptr_Uniform_float %blockName_var )" + elem +
4448 R"(%int_2 %int_0 %int_1
4449 OpReturn
4450 OpFunctionEnd
4452 const std::string expected_err =
4453 instr +
4454 " reached non-composite type while indexes still remain to be traversed.";
4455 CompileSuccessfully(spirv);
4456 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4457 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4460 // Invalid: Reached scalar type before arguments to the access chain instruction
4461 // finished.
4462 TEST_P(AccessChainInstructionTest, AccessChainMatrixMoreArgsThanNeededBad) {
4463 const std::string instr = GetParam();
4464 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4465 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4466 %entry = )" +
4467 instr + R"( %_ptr_Private_float %my_matrix )" + elem +
4468 R"(%int_0 %int_1 %int_0
4469 OpReturn
4470 OpFunctionEnd
4472 const std::string expected_err = instr +
4473 " reached non-composite type while "
4474 "indexes still remain to be traversed.";
4475 CompileSuccessfully(spirv);
4476 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4477 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4480 // Invalid: The result type and the type indexed into do not match.
4481 TEST_P(AccessChainInstructionTest,
4482 AccessChainResultTypeDoesntMatchIndexedTypeBad) {
4483 const std::string instr = GetParam();
4484 const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4485 std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4486 %entry = )" +
4487 instr + R"( %_ptr_Private_mat4x3 %my_matrix )" + elem +
4488 R"(%int_0 %int_1
4489 OpReturn
4490 OpFunctionEnd
4492 const std::string expected_err = instr +
4493 " result type (OpTypeMatrix) does not match "
4494 "the type that results from indexing into "
4495 "the base <id> (OpTypeFloat).";
4496 CompileSuccessfully(spirv);
4497 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4498 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4501 // Run tests for Access Chain Instructions.
4502 INSTANTIATE_TEST_SUITE_P(
4503 CheckAccessChainInstructions, AccessChainInstructionTest,
4504 ::testing::Values("OpAccessChain", "OpInBoundsAccessChain",
4505 "OpPtrAccessChain", "OpInBoundsPtrAccessChain"));
4507 // TODO: OpArrayLength
4508 // TODO: OpImagePointer
4509 // TODO: OpGenericPtrMemSemantics
4511 TEST_P(ValidateIdWithMessage, OpFunctionGood) {
4512 std::string spirv = kGLSL450MemoryModel + R"(
4513 %1 = OpTypeVoid
4514 %2 = OpTypeInt 32 0
4515 %3 = OpTypeFunction %1 %2 %2
4516 %4 = OpFunction %1 None %3
4517 %5 = OpLabel
4518 OpReturn
4519 OpFunctionEnd)";
4520 CompileSuccessfully(spirv.c_str());
4521 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4523 TEST_P(ValidateIdWithMessage, OpFunctionResultTypeBad) {
4524 std::string spirv = kGLSL450MemoryModel + R"(
4525 %1 = OpTypeVoid
4526 %2 = OpTypeInt 32 0
4527 %3 = OpConstant %2 42
4528 %4 = OpTypeFunction %1 %2 %2
4529 %5 = OpFunction %2 None %4
4530 %6 = OpLabel
4531 OpReturnValue %3
4532 OpFunctionEnd)";
4533 CompileSuccessfully(spirv.c_str());
4534 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4535 EXPECT_THAT(
4536 getDiagnosticString(),
4537 HasSubstr(make_message("OpFunction Result Type <id> '2[%uint]' does not "
4538 "match the Function Type's return type <id> "
4539 "'1[%void]'.")));
4541 TEST_P(ValidateIdWithMessage, OpReturnValueTypeBad) {
4542 std::string spirv = kGLSL450MemoryModel + R"(
4543 %1 = OpTypeInt 32 0
4544 %2 = OpTypeFloat 32
4545 %3 = OpConstant %2 0
4546 %4 = OpTypeFunction %1
4547 %5 = OpFunction %1 None %4
4548 %6 = OpLabel
4549 OpReturnValue %3
4550 OpFunctionEnd)";
4551 CompileSuccessfully(spirv.c_str());
4552 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4553 EXPECT_THAT(getDiagnosticString(),
4554 HasSubstr(make_message(
4555 "OpReturnValue Value <id> '3[%float_0]'s type does "
4556 "not match OpFunction's return type.")));
4558 TEST_P(ValidateIdWithMessage, OpFunctionFunctionTypeBad) {
4559 std::string spirv = kGLSL450MemoryModel + R"(
4560 %1 = OpTypeVoid
4561 %2 = OpTypeInt 32 0
4562 %4 = OpFunction %1 None %2
4563 %5 = OpLabel
4564 OpReturn
4565 OpFunctionEnd)";
4566 CompileSuccessfully(spirv.c_str());
4567 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4568 EXPECT_THAT(getDiagnosticString(),
4569 HasSubstr(make_message(
4570 "OpFunction Function Type <id> '2[%uint]' is not a function "
4571 "type.")));
4574 TEST_P(ValidateIdWithMessage, OpFunctionUseBad) {
4575 const std::string spirv = kGLSL450MemoryModel + R"(
4576 %1 = OpTypeFloat 32
4577 %2 = OpTypeFunction %1
4578 %3 = OpFunction %1 None %2
4579 %4 = OpLabel
4580 OpReturnValue %3
4581 OpFunctionEnd
4584 CompileSuccessfully(spirv);
4585 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4586 EXPECT_THAT(
4587 getDiagnosticString(),
4588 HasSubstr(make_message("Invalid use of function result id '3[%3]'.")));
4591 TEST_P(ValidateIdWithMessage, OpFunctionParameterGood) {
4592 std::string spirv = kGLSL450MemoryModel + R"(
4593 %1 = OpTypeVoid
4594 %2 = OpTypeInt 32 0
4595 %3 = OpTypeFunction %1 %2
4596 %4 = OpFunction %1 None %3
4597 %5 = OpFunctionParameter %2
4598 %6 = OpLabel
4599 OpReturn
4600 OpFunctionEnd)";
4601 CompileSuccessfully(spirv.c_str());
4602 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4604 TEST_P(ValidateIdWithMessage, OpFunctionParameterMultipleGood) {
4605 std::string spirv = kGLSL450MemoryModel + R"(
4606 %1 = OpTypeVoid
4607 %2 = OpTypeInt 32 0
4608 %3 = OpTypeFunction %1 %2 %2
4609 %4 = OpFunction %1 None %3
4610 %5 = OpFunctionParameter %2
4611 %6 = OpFunctionParameter %2
4612 %7 = OpLabel
4613 OpReturn
4614 OpFunctionEnd)";
4615 CompileSuccessfully(spirv.c_str());
4616 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4618 TEST_P(ValidateIdWithMessage, OpFunctionParameterResultTypeBad) {
4619 std::string spirv = kGLSL450MemoryModel + R"(
4620 %1 = OpTypeVoid
4621 %2 = OpTypeInt 32 0
4622 %3 = OpTypeFunction %1 %2
4623 %4 = OpFunction %1 None %3
4624 %5 = OpFunctionParameter %1
4625 %6 = OpLabel
4626 OpReturn
4627 OpFunctionEnd)";
4628 CompileSuccessfully(spirv.c_str());
4629 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4630 EXPECT_THAT(
4631 getDiagnosticString(),
4632 HasSubstr(make_message(
4633 "OpFunctionParameter Result Type <id> '1[%void]' does not "
4634 "match the OpTypeFunction parameter type of the same index.")));
4637 TEST_P(ValidateIdWithMessage, OpFunctionCallGood) {
4638 std::string spirv = kGLSL450MemoryModel + R"(
4639 %1 = OpTypeVoid
4640 %2 = OpTypeInt 32 0
4641 %3 = OpTypeFunction %2 %2
4642 %4 = OpTypeFunction %1
4643 %5 = OpConstant %2 42 ;21
4645 %6 = OpFunction %2 None %3
4646 %7 = OpFunctionParameter %2
4647 %8 = OpLabel
4648 OpReturnValue %7
4649 OpFunctionEnd
4651 %10 = OpFunction %1 None %4
4652 %11 = OpLabel
4653 %12 = OpFunctionCall %2 %6 %5
4654 OpReturn
4655 OpFunctionEnd)";
4656 CompileSuccessfully(spirv.c_str());
4657 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4659 TEST_P(ValidateIdWithMessage, OpFunctionCallResultTypeBad) {
4660 std::string spirv = kGLSL450MemoryModel + R"(
4661 %1 = OpTypeVoid
4662 %2 = OpTypeInt 32 0
4663 %3 = OpTypeFunction %2 %2
4664 %4 = OpTypeFunction %1
4665 %5 = OpConstant %2 42 ;21
4667 %6 = OpFunction %2 None %3
4668 %7 = OpFunctionParameter %2
4669 %8 = OpLabel
4670 %9 = OpIAdd %2 %7 %7
4671 OpReturnValue %9
4672 OpFunctionEnd
4674 %10 = OpFunction %1 None %4
4675 %11 = OpLabel
4676 %12 = OpFunctionCall %1 %6 %5
4677 OpReturn
4678 OpFunctionEnd)";
4679 CompileSuccessfully(spirv.c_str());
4680 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4681 EXPECT_THAT(
4682 getDiagnosticString(),
4683 HasSubstr(make_message("OpFunctionCall Result Type <id> '1[%void]'s type "
4684 "does not match Function <id> '2[%uint]'s return "
4685 "type.")));
4687 TEST_P(ValidateIdWithMessage, OpFunctionCallFunctionBad) {
4688 std::string spirv = kGLSL450MemoryModel + R"(
4689 %1 = OpTypeVoid
4690 %2 = OpTypeInt 32 0
4691 %3 = OpTypeFunction %2 %2
4692 %4 = OpTypeFunction %1
4693 %5 = OpConstant %2 42 ;21
4695 %10 = OpFunction %1 None %4
4696 %11 = OpLabel
4697 %12 = OpFunctionCall %2 %5 %5
4698 OpReturn
4699 OpFunctionEnd)";
4700 CompileSuccessfully(spirv.c_str());
4701 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4702 EXPECT_THAT(getDiagnosticString(),
4703 HasSubstr(make_message(
4704 "OpFunctionCall Function <id> '5[%uint_42]' is not a "
4705 "function.")));
4707 TEST_P(ValidateIdWithMessage, OpFunctionCallArgumentTypeBad) {
4708 std::string spirv = kGLSL450MemoryModel + R"(
4709 %1 = OpTypeVoid
4710 %2 = OpTypeInt 32 0
4711 %3 = OpTypeFunction %2 %2
4712 %4 = OpTypeFunction %1
4713 %5 = OpConstant %2 42
4715 %13 = OpTypeFloat 32
4716 %14 = OpConstant %13 3.14
4718 %6 = OpFunction %2 None %3
4719 %7 = OpFunctionParameter %2
4720 %8 = OpLabel
4721 %9 = OpIAdd %2 %7 %7
4722 OpReturnValue %9
4723 OpFunctionEnd
4725 %10 = OpFunction %1 None %4
4726 %11 = OpLabel
4727 %12 = OpFunctionCall %2 %6 %14
4728 OpReturn
4729 OpFunctionEnd)";
4730 CompileSuccessfully(spirv.c_str());
4731 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4732 EXPECT_THAT(getDiagnosticString(),
4733 HasSubstr(make_message(
4734 "OpFunctionCall Argument <id> '7[%float_3_1400001]'s "
4735 "type does not match Function <id> '2[%uint]'s "
4736 "parameter type.")));
4739 // Valid: OpSampledImage result <id> is used in the same block by
4740 // OpImageSampleImplictLod
4741 TEST_P(ValidateIdWithMessage, OpSampledImageGood) {
4742 std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
4743 %smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
4744 %si_lod = OpImageSampleImplicitLod %v4float %smpld_img %const_vec_1_1
4745 OpReturn
4746 OpFunctionEnd)";
4747 CompileSuccessfully(spirv.c_str());
4748 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4751 // Invalid: OpSampledImage result <id> is defined in one block and used in a
4752 // different block.
4753 TEST_P(ValidateIdWithMessage, OpSampledImageUsedInDifferentBlockBad) {
4754 std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
4755 %smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
4756 OpBranch %label_2
4757 %label_2 = OpLabel
4758 %si_lod = OpImageSampleImplicitLod %v4float %smpld_img %const_vec_1_1
4759 OpReturn
4760 OpFunctionEnd)";
4761 CompileSuccessfully(spirv.c_str());
4762 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4763 EXPECT_THAT(
4764 getDiagnosticString(),
4765 HasSubstr(make_message(
4766 "All OpSampledImage instructions must be in the same block in "
4767 "which their Result <id> are consumed. OpSampledImage Result "
4768 "Type <id> '23[%23]' has a consumer in a different basic "
4769 "block. The consumer instruction <id> is '25[%25]'.")));
4772 // Invalid: OpSampledImage result <id> is used by OpSelect
4773 // Note: According to the Spec, OpSelect parameters must be either a scalar or a
4774 // vector. Therefore, OpTypeSampledImage is an illegal parameter for OpSelect.
4775 // However, the OpSelect validation does not catch this today. Therefore, it is
4776 // caught by the OpSampledImage validation. If the OpSelect validation code is
4777 // updated, the error message for this test may change.
4779 // Disabled since OpSelect catches this now.
4780 TEST_P(ValidateIdWithMessage, DISABLED_OpSampledImageUsedInOpSelectBad) {
4781 std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
4782 %smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
4783 %select_img = OpSelect %sampled_image_type %spec_true %smpld_img %smpld_img
4784 OpReturn
4785 OpFunctionEnd)";
4786 CompileSuccessfully(spirv.c_str());
4787 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4788 EXPECT_THAT(getDiagnosticString(),
4789 HasSubstr(make_message(
4790 "Result <id> from OpSampledImage instruction must not "
4791 "appear as operands of OpSelect. Found result <id> "
4792 "'23' as an operand of <id> '24'.")));
4795 TEST_P(ValidateIdWithMessage, OpCopyObjectSampledImageGood) {
4796 std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
4797 %smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
4798 %smpld_img2 = OpCopyObject %sampled_image_type %smpld_img
4799 %image_inst2 = OpCopyObject %image_type %image_inst
4800 OpReturn
4801 OpFunctionEnd)";
4802 CompileSuccessfully(spirv.c_str());
4803 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4806 // Valid: Get a float in a matrix using CompositeExtract.
4807 // Valid: Insert float into a matrix using CompositeInsert.
4808 TEST_P(ValidateIdWithMessage, CompositeExtractInsertGood) {
4809 std::ostringstream spirv;
4810 spirv << kGLSL450MemoryModel << kDeeplyNestedStructureSetup << std::endl;
4811 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
4812 spirv << "%float_entry = OpCompositeExtract %float %matrix 0 1" << std::endl;
4814 // To test CompositeInsert, insert the object back in after extraction.
4815 spirv << "%new_composite = OpCompositeInsert %mat4x3 %float_entry %matrix 0 1"
4816 << std::endl;
4817 spirv << R"(OpReturn
4818 OpFunctionEnd)";
4819 CompileSuccessfully(spirv.str());
4820 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4823 #if 0
4824 TEST_P(ValidateIdWithMessage, OpFunctionCallArgumentCountBar) {
4825 const char *spirv = R"(
4826 %1 = OpTypeVoid
4827 %2 = OpTypeInt 32 0
4828 %3 = OpTypeFunction %2 %2
4829 %4 = OpTypeFunction %1
4830 %5 = OpConstant %2 42 ;21
4832 %6 = OpFunction %2 None %3
4833 %7 = OpFunctionParameter %2
4834 %8 = OpLabel
4835 %9 = OpLoad %2 %7
4836 OpReturnValue %9
4837 OpFunctionEnd
4839 %10 = OpFunction %1 None %4
4840 %11 = OpLabel
4841 OpReturn
4842 %12 = OpFunctionCall %2 %6 %5
4843 OpFunctionEnd)";
4844 CHECK(spirv, SPV_ERROR_INVALID_ID);
4846 #endif
4848 // TODO: The many things that changed with how images are used.
4849 // TODO: OpTextureSample
4850 // TODO: OpTextureSampleDref
4851 // TODO: OpTextureSampleLod
4852 // TODO: OpTextureSampleProj
4853 // TODO: OpTextureSampleGrad
4854 // TODO: OpTextureSampleOffset
4855 // TODO: OpTextureSampleProjLod
4856 // TODO: OpTextureSampleProjGrad
4857 // TODO: OpTextureSampleLodOffset
4858 // TODO: OpTextureSampleProjOffset
4859 // TODO: OpTextureSampleGradOffset
4860 // TODO: OpTextureSampleProjLodOffset
4861 // TODO: OpTextureSampleProjGradOffset
4862 // TODO: OpTextureFetchTexelLod
4863 // TODO: OpTextureFetchTexelOffset
4864 // TODO: OpTextureFetchSample
4865 // TODO: OpTextureFetchTexel
4866 // TODO: OpTextureGather
4867 // TODO: OpTextureGatherOffset
4868 // TODO: OpTextureGatherOffsets
4869 // TODO: OpTextureQuerySizeLod
4870 // TODO: OpTextureQuerySize
4871 // TODO: OpTextureQueryLevels
4872 // TODO: OpTextureQuerySamples
4873 // TODO: OpConvertUToF
4874 // TODO: OpConvertFToS
4875 // TODO: OpConvertSToF
4876 // TODO: OpConvertUToF
4877 // TODO: OpUConvert
4878 // TODO: OpSConvert
4879 // TODO: OpFConvert
4880 // TODO: OpConvertPtrToU
4881 // TODO: OpConvertUToPtr
4882 // TODO: OpPtrCastToGeneric
4883 // TODO: OpGenericCastToPtr
4884 // TODO: OpBitcast
4885 // TODO: OpGenericCastToPtrExplicit
4886 // TODO: OpSatConvertSToU
4887 // TODO: OpSatConvertUToS
4888 // TODO: OpVectorExtractDynamic
4889 // TODO: OpVectorInsertDynamic
4891 TEST_P(ValidateIdWithMessage, OpVectorShuffleIntGood) {
4892 std::string spirv = kGLSL450MemoryModel + R"(
4893 %int = OpTypeInt 32 0
4894 %ivec3 = OpTypeVector %int 3
4895 %ivec4 = OpTypeVector %int 4
4896 %ptr_ivec3 = OpTypePointer Function %ivec3
4897 %undef = OpUndef %ivec4
4898 %int_42 = OpConstant %int 42
4899 %int_0 = OpConstant %int 0
4900 %int_2 = OpConstant %int 2
4901 %1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2
4902 %2 = OpTypeFunction %ivec3
4903 %3 = OpFunction %ivec3 None %2
4904 %4 = OpLabel
4905 %var = OpVariable %ptr_ivec3 Function %1
4906 %5 = OpLoad %ivec3 %var
4907 %6 = OpVectorShuffle %ivec3 %5 %undef 2 1 0
4908 OpReturnValue %6
4909 OpFunctionEnd)";
4910 CompileSuccessfully(spirv.c_str());
4911 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4914 TEST_P(ValidateIdWithMessage, OpVectorShuffleFloatGood) {
4915 std::string spirv = kGLSL450MemoryModel + R"(
4916 %float = OpTypeFloat 32
4917 %vec2 = OpTypeVector %float 2
4918 %vec3 = OpTypeVector %float 3
4919 %vec4 = OpTypeVector %float 4
4920 %ptr_vec2 = OpTypePointer Function %vec2
4921 %ptr_vec3 = OpTypePointer Function %vec3
4922 %float_1 = OpConstant %float 1
4923 %float_2 = OpConstant %float 2
4924 %1 = OpConstantComposite %vec2 %float_2 %float_1
4925 %2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
4926 %3 = OpTypeFunction %vec4
4927 %4 = OpFunction %vec4 None %3
4928 %5 = OpLabel
4929 %var = OpVariable %ptr_vec2 Function %1
4930 %var2 = OpVariable %ptr_vec3 Function %2
4931 %6 = OpLoad %vec2 %var
4932 %7 = OpLoad %vec3 %var2
4933 %8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0xffffffff
4934 OpReturnValue %8
4935 OpFunctionEnd)";
4936 CompileSuccessfully(spirv.c_str());
4937 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4940 TEST_P(ValidateIdWithMessage, OpVectorShuffleScalarResultType) {
4941 std::string spirv = kGLSL450MemoryModel + R"(
4942 %float = OpTypeFloat 32
4943 %vec2 = OpTypeVector %float 2
4944 %ptr_vec2 = OpTypePointer Function %vec2
4945 %float_1 = OpConstant %float 1
4946 %float_2 = OpConstant %float 2
4947 %1 = OpConstantComposite %vec2 %float_2 %float_1
4948 %2 = OpTypeFunction %float
4949 %3 = OpFunction %float None %2
4950 %4 = OpLabel
4951 %var = OpVariable %ptr_vec2 Function %1
4952 %5 = OpLoad %vec2 %var
4953 %6 = OpVectorShuffle %float %5 %5 0
4954 OpReturnValue %6
4955 OpFunctionEnd)";
4956 CompileSuccessfully(spirv.c_str());
4957 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4958 EXPECT_THAT(getDiagnosticString(),
4959 HasSubstr(make_message(
4960 "Result Type of OpVectorShuffle must be OpTypeVector.")));
4963 TEST_P(ValidateIdWithMessage, OpVectorShuffleComponentCount) {
4964 std::string spirv = kGLSL450MemoryModel + R"(
4965 %int = OpTypeInt 32 0
4966 %ivec3 = OpTypeVector %int 3
4967 %ptr_ivec3 = OpTypePointer Function %ivec3
4968 %int_42 = OpConstant %int 42
4969 %int_0 = OpConstant %int 0
4970 %int_2 = OpConstant %int 2
4971 %1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2
4972 %2 = OpTypeFunction %ivec3
4973 %3 = OpFunction %ivec3 None %2
4974 %4 = OpLabel
4975 %var = OpVariable %ptr_ivec3 Function %1
4976 %5 = OpLoad %ivec3 %var
4977 %6 = OpVectorShuffle %ivec3 %5 %5 0 1
4978 OpReturnValue %6
4979 OpFunctionEnd)";
4980 CompileSuccessfully(spirv.c_str());
4981 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4982 EXPECT_THAT(getDiagnosticString(),
4983 HasSubstr(make_message(
4984 "OpVectorShuffle component literals count does not match "
4985 "Result Type <id> '2[%v3uint]'s vector component count.")));
4988 TEST_P(ValidateIdWithMessage, OpVectorShuffleVector1Type) {
4989 std::string spirv = kGLSL450MemoryModel + R"(
4990 %int = OpTypeInt 32 0
4991 %ivec2 = OpTypeVector %int 2
4992 %ptr_int = OpTypePointer Function %int
4993 %undef = OpUndef %ivec2
4994 %int_42 = OpConstant %int 42
4995 %2 = OpTypeFunction %ivec2
4996 %3 = OpFunction %ivec2 None %2
4997 %4 = OpLabel
4998 %var = OpVariable %ptr_int Function %int_42
4999 %5 = OpLoad %int %var
5000 %6 = OpVectorShuffle %ivec2 %5 %undef 0 0
5001 OpReturnValue %6
5002 OpFunctionEnd)";
5003 CompileSuccessfully(spirv.c_str());
5004 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5005 EXPECT_THAT(
5006 getDiagnosticString(),
5007 HasSubstr(make_message("The type of Vector 1 must be OpTypeVector.")));
5010 TEST_P(ValidateIdWithMessage, OpVectorShuffleVector2Type) {
5011 std::string spirv = kGLSL450MemoryModel + R"(
5012 %int = OpTypeInt 32 0
5013 %ivec2 = OpTypeVector %int 2
5014 %ptr_ivec2 = OpTypePointer Function %ivec2
5015 %undef = OpUndef %int
5016 %int_42 = OpConstant %int 42
5017 %1 = OpConstantComposite %ivec2 %int_42 %int_42
5018 %2 = OpTypeFunction %ivec2
5019 %3 = OpFunction %ivec2 None %2
5020 %4 = OpLabel
5021 %var = OpVariable %ptr_ivec2 Function %1
5022 %5 = OpLoad %ivec2 %var
5023 %6 = OpVectorShuffle %ivec2 %5 %undef 0 1
5024 OpReturnValue %6
5025 OpFunctionEnd)";
5026 CompileSuccessfully(spirv.c_str());
5027 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5028 EXPECT_THAT(
5029 getDiagnosticString(),
5030 HasSubstr(make_message("The type of Vector 2 must be OpTypeVector.")));
5033 TEST_P(ValidateIdWithMessage, OpVectorShuffleVector1ComponentType) {
5034 std::string spirv = kGLSL450MemoryModel + R"(
5035 %int = OpTypeInt 32 0
5036 %ivec3 = OpTypeVector %int 3
5037 %ptr_ivec3 = OpTypePointer Function %ivec3
5038 %int_42 = OpConstant %int 42
5039 %int_0 = OpConstant %int 0
5040 %int_2 = OpConstant %int 2
5041 %float = OpTypeFloat 32
5042 %vec3 = OpTypeVector %float 3
5043 %vec4 = OpTypeVector %float 4
5044 %ptr_vec3 = OpTypePointer Function %vec3
5045 %float_1 = OpConstant %float 1
5046 %float_2 = OpConstant %float 2
5047 %1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2
5048 %2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
5049 %3 = OpTypeFunction %vec4
5050 %4 = OpFunction %vec4 None %3
5051 %5 = OpLabel
5052 %var = OpVariable %ptr_ivec3 Function %1
5053 %var2 = OpVariable %ptr_vec3 Function %2
5054 %6 = OpLoad %ivec3 %var
5055 %7 = OpLoad %vec3 %var2
5056 %8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0
5057 OpReturnValue %8
5058 OpFunctionEnd)";
5059 CompileSuccessfully(spirv.c_str());
5060 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5061 EXPECT_THAT(getDiagnosticString(),
5062 HasSubstr(make_message(
5063 "The Component Type of Vector 1 must be the same as "
5064 "ResultType.")));
5067 TEST_P(ValidateIdWithMessage, OpVectorShuffleVector2ComponentType) {
5068 std::string spirv = kGLSL450MemoryModel + R"(
5069 %int = OpTypeInt 32 0
5070 %ivec3 = OpTypeVector %int 3
5071 %ptr_ivec3 = OpTypePointer Function %ivec3
5072 %int_42 = OpConstant %int 42
5073 %int_0 = OpConstant %int 0
5074 %int_2 = OpConstant %int 2
5075 %float = OpTypeFloat 32
5076 %vec3 = OpTypeVector %float 3
5077 %vec4 = OpTypeVector %float 4
5078 %ptr_vec3 = OpTypePointer Function %vec3
5079 %float_1 = OpConstant %float 1
5080 %float_2 = OpConstant %float 2
5081 %1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2
5082 %2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
5083 %3 = OpTypeFunction %vec4
5084 %4 = OpFunction %vec4 None %3
5085 %5 = OpLabel
5086 %var = OpVariable %ptr_ivec3 Function %1
5087 %var2 = OpVariable %ptr_vec3 Function %2
5088 %6 = OpLoad %vec3 %var2
5089 %7 = OpLoad %ivec3 %var
5090 %8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0
5091 OpReturnValue %8
5092 OpFunctionEnd)";
5093 CompileSuccessfully(spirv.c_str());
5094 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5095 EXPECT_THAT(getDiagnosticString(),
5096 HasSubstr(make_message(
5097 "The Component Type of Vector 2 must be the same as "
5098 "ResultType.")));
5101 TEST_P(ValidateIdWithMessage, OpVectorShuffleLiterals) {
5102 std::string spirv = kGLSL450MemoryModel + R"(
5103 %float = OpTypeFloat 32
5104 %vec2 = OpTypeVector %float 2
5105 %vec3 = OpTypeVector %float 3
5106 %vec4 = OpTypeVector %float 4
5107 %ptr_vec2 = OpTypePointer Function %vec2
5108 %ptr_vec3 = OpTypePointer Function %vec3
5109 %float_1 = OpConstant %float 1
5110 %float_2 = OpConstant %float 2
5111 %1 = OpConstantComposite %vec2 %float_2 %float_1
5112 %2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
5113 %3 = OpTypeFunction %vec4
5114 %4 = OpFunction %vec4 None %3
5115 %5 = OpLabel
5116 %var = OpVariable %ptr_vec2 Function %1
5117 %var2 = OpVariable %ptr_vec3 Function %2
5118 %6 = OpLoad %vec2 %var
5119 %7 = OpLoad %vec3 %var2
5120 %8 = OpVectorShuffle %vec4 %6 %7 0 8 2 6
5121 OpReturnValue %8
5122 OpFunctionEnd)";
5123 CompileSuccessfully(spirv.c_str());
5124 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5125 EXPECT_THAT(
5126 getDiagnosticString(),
5127 HasSubstr(make_message(
5128 "Component index 8 is out of bounds for combined (Vector1 + Vector2) "
5129 "size of 5.")));
5132 // TODO: OpCompositeConstruct
5133 // TODO: OpCompositeExtract
5134 // TODO: OpCompositeInsert
5135 // TODO: OpCopyObject
5136 // TODO: OpTranspose
5137 // TODO: OpSNegate
5138 // TODO: OpFNegate
5139 // TODO: OpNot
5140 // TODO: OpIAdd
5141 // TODO: OpFAdd
5142 // TODO: OpISub
5143 // TODO: OpFSub
5144 // TODO: OpIMul
5145 // TODO: OpFMul
5146 // TODO: OpUDiv
5147 // TODO: OpSDiv
5148 // TODO: OpFDiv
5149 // TODO: OpUMod
5150 // TODO: OpSRem
5151 // TODO: OpSMod
5152 // TODO: OpFRem
5153 // TODO: OpFMod
5154 // TODO: OpVectorTimesScalar
5155 // TODO: OpMatrixTimesScalar
5156 // TODO: OpVectorTimesMatrix
5157 // TODO: OpMatrixTimesVector
5158 // TODO: OpMatrixTimesMatrix
5159 // TODO: OpOuterProduct
5160 // TODO: OpDot
5161 // TODO: OpShiftRightLogical
5162 // TODO: OpShiftRightArithmetic
5163 // TODO: OpShiftLeftLogical
5164 // TODO: OpBitwiseOr
5165 // TODO: OpBitwiseXor
5166 // TODO: OpBitwiseAnd
5167 // TODO: OpAny
5168 // TODO: OpAll
5169 // TODO: OpIsNan
5170 // TODO: OpIsInf
5171 // TODO: OpIsFinite
5172 // TODO: OpIsNormal
5173 // TODO: OpSignBitSet
5174 // TODO: OpLessOrGreater
5175 // TODO: OpOrdered
5176 // TODO: OpUnordered
5177 // TODO: OpLogicalOr
5178 // TODO: OpLogicalXor
5179 // TODO: OpLogicalAnd
5180 // TODO: OpSelect
5181 // TODO: OpIEqual
5182 // TODO: OpFOrdEqual
5183 // TODO: OpFUnordEqual
5184 // TODO: OpINotEqual
5185 // TODO: OpFOrdNotEqual
5186 // TODO: OpFUnordNotEqual
5187 // TODO: OpULessThan
5188 // TODO: OpSLessThan
5189 // TODO: OpFOrdLessThan
5190 // TODO: OpFUnordLessThan
5191 // TODO: OpUGreaterThan
5192 // TODO: OpSGreaterThan
5193 // TODO: OpFOrdGreaterThan
5194 // TODO: OpFUnordGreaterThan
5195 // TODO: OpULessThanEqual
5196 // TODO: OpSLessThanEqual
5197 // TODO: OpFOrdLessThanEqual
5198 // TODO: OpFUnordLessThanEqual
5199 // TODO: OpUGreaterThanEqual
5200 // TODO: OpSGreaterThanEqual
5201 // TODO: OpFOrdGreaterThanEqual
5202 // TODO: OpFUnordGreaterThanEqual
5203 // TODO: OpDPdx
5204 // TODO: OpDPdy
5205 // TODO: OpFWidth
5206 // TODO: OpDPdxFine
5207 // TODO: OpDPdyFine
5208 // TODO: OpFwidthFine
5209 // TODO: OpDPdxCoarse
5210 // TODO: OpDPdyCoarse
5211 // TODO: OpFwidthCoarse
5212 // TODO: OpLoopMerge
5213 // TODO: OpSelectionMerge
5214 // TODO: OpBranch
5216 TEST_P(ValidateIdWithMessage, OpPhiNotAType) {
5217 std::string spirv = kOpenCLMemoryModel32 + R"(
5218 %2 = OpTypeBool
5219 %3 = OpConstantTrue %2
5220 %4 = OpTypeVoid
5221 %5 = OpTypeFunction %4
5222 %6 = OpFunction %4 None %5
5223 %7 = OpLabel
5224 OpBranch %8
5225 %8 = OpLabel
5226 %9 = OpPhi %3 %3 %7
5227 OpReturn
5228 OpFunctionEnd
5231 CompileSuccessfully(spirv.c_str());
5232 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5233 EXPECT_THAT(getDiagnosticString(),
5234 HasSubstr(make_message("ID '3[%true]' is not a type "
5235 "id")));
5238 TEST_P(ValidateIdWithMessage, OpPhiSamePredecessor) {
5239 std::string spirv = kOpenCLMemoryModel32 + R"(
5240 %2 = OpTypeBool
5241 %3 = OpConstantTrue %2
5242 %4 = OpTypeVoid
5243 %5 = OpTypeFunction %4
5244 %6 = OpFunction %4 None %5
5245 %7 = OpLabel
5246 OpBranchConditional %3 %8 %8
5247 %8 = OpLabel
5248 %9 = OpPhi %2 %3 %7
5249 OpReturn
5250 OpFunctionEnd
5253 CompileSuccessfully(spirv.c_str());
5254 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5257 TEST_P(ValidateIdWithMessage, OpPhiOddArgumentNumber) {
5258 std::string spirv = kOpenCLMemoryModel32 + R"(
5259 %2 = OpTypeBool
5260 %3 = OpConstantTrue %2
5261 %4 = OpTypeVoid
5262 %5 = OpTypeFunction %4
5263 %6 = OpFunction %4 None %5
5264 %7 = OpLabel
5265 OpBranch %8
5266 %8 = OpLabel
5267 %9 = OpPhi %2 %3
5268 OpReturn
5269 OpFunctionEnd
5272 CompileSuccessfully(spirv.c_str());
5273 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5274 EXPECT_THAT(
5275 getDiagnosticString(),
5276 HasSubstr(make_message("OpPhi does not have an equal number of incoming "
5277 "values and basic blocks.")));
5280 TEST_P(ValidateIdWithMessage, OpPhiTooFewPredecessors) {
5281 std::string spirv = kOpenCLMemoryModel32 + R"(
5282 %2 = OpTypeBool
5283 %3 = OpConstantTrue %2
5284 %4 = OpTypeVoid
5285 %5 = OpTypeFunction %4
5286 %6 = OpFunction %4 None %5
5287 %7 = OpLabel
5288 OpBranch %8
5289 %8 = OpLabel
5290 %9 = OpPhi %2
5291 OpReturn
5292 OpFunctionEnd
5295 CompileSuccessfully(spirv.c_str());
5296 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5297 EXPECT_THAT(getDiagnosticString(),
5298 HasSubstr(make_message(
5299 "OpPhi's number of incoming blocks (0) does not match "
5300 "block's predecessor count (1).")));
5303 TEST_P(ValidateIdWithMessage, OpPhiTooManyPredecessors) {
5304 std::string spirv = kOpenCLMemoryModel32 + R"(
5305 %2 = OpTypeBool
5306 %3 = OpConstantTrue %2
5307 %4 = OpTypeVoid
5308 %5 = OpTypeFunction %4
5309 %6 = OpFunction %4 None %5
5310 %7 = OpLabel
5311 OpBranch %8
5312 %9 = OpLabel
5313 OpReturn
5314 %8 = OpLabel
5315 %10 = OpPhi %2 %3 %7 %3 %9
5316 OpReturn
5317 OpFunctionEnd
5320 CompileSuccessfully(spirv.c_str());
5321 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5322 EXPECT_THAT(getDiagnosticString(),
5323 HasSubstr(make_message(
5324 "OpPhi's number of incoming blocks (2) does not match "
5325 "block's predecessor count (1).")));
5328 TEST_P(ValidateIdWithMessage, OpPhiMismatchedTypes) {
5329 std::string spirv = kOpenCLMemoryModel32 + R"(
5330 %2 = OpTypeBool
5331 %3 = OpConstantTrue %2
5332 %4 = OpTypeVoid
5333 %5 = OpTypeInt 32 0
5334 %6 = OpConstant %5 0
5335 %7 = OpTypeFunction %4
5336 %8 = OpFunction %4 None %7
5337 %9 = OpLabel
5338 OpBranchConditional %3 %10 %11
5339 %11 = OpLabel
5340 OpBranch %10
5341 %10 = OpLabel
5342 %12 = OpPhi %2 %3 %9 %6 %11
5343 OpReturn
5344 OpFunctionEnd
5347 CompileSuccessfully(spirv.c_str());
5348 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5349 EXPECT_THAT(getDiagnosticString(),
5350 HasSubstr(make_message(
5351 "OpPhi's result type <id> '2[%bool]' does not match "
5352 "incoming value <id> '6[%uint_0]' type <id> "
5353 "'5[%uint]'.")));
5356 TEST_P(ValidateIdWithMessage, OpPhiPredecessorNotABlock) {
5357 std::string spirv = kOpenCLMemoryModel32 + R"(
5358 %2 = OpTypeBool
5359 %3 = OpConstantTrue %2
5360 %4 = OpTypeVoid
5361 %5 = OpTypeFunction %4
5362 %6 = OpFunction %4 None %5
5363 %7 = OpLabel
5364 OpBranchConditional %3 %8 %9
5365 %9 = OpLabel
5366 OpBranch %11
5367 %11 = OpLabel
5368 OpBranch %8
5369 %8 = OpLabel
5370 %10 = OpPhi %2 %3 %7 %3 %3
5371 OpReturn
5372 OpFunctionEnd
5375 CompileSuccessfully(spirv.c_str());
5376 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5377 EXPECT_THAT(getDiagnosticString(),
5378 HasSubstr(make_message(
5379 "OpPhi's incoming basic block <id> '3[%true]' is not an "
5380 "OpLabel.")));
5383 TEST_P(ValidateIdWithMessage, OpPhiNotAPredecessor) {
5384 std::string spirv = kOpenCLMemoryModel32 + R"(
5385 %2 = OpTypeBool
5386 %3 = OpConstantTrue %2
5387 %4 = OpTypeVoid
5388 %5 = OpTypeFunction %4
5389 %6 = OpFunction %4 None %5
5390 %7 = OpLabel
5391 OpBranchConditional %3 %8 %9
5392 %9 = OpLabel
5393 OpBranch %11
5394 %11 = OpLabel
5395 OpBranch %8
5396 %8 = OpLabel
5397 %10 = OpPhi %2 %3 %7 %3 %9
5398 OpReturn
5399 OpFunctionEnd
5402 CompileSuccessfully(spirv.c_str());
5403 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5404 EXPECT_THAT(getDiagnosticString(),
5405 HasSubstr(make_message(
5406 "OpPhi's incoming basic block <id> '9[%9]' is not a "
5407 "predecessor of <id> '8[%8]'.")));
5410 TEST_P(ValidateIdWithMessage, OpBranchConditionalGood) {
5411 std::string spirv = BranchConditionalSetup + R"(
5412 %branch_cond = OpINotEqual %bool %i0 %i1
5413 OpSelectionMerge %end None
5414 OpBranchConditional %branch_cond %target_t %target_f
5415 )" + BranchConditionalTail;
5417 CompileSuccessfully(spirv.c_str());
5418 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
5421 TEST_P(ValidateIdWithMessage, OpBranchConditionalWithWeightsGood) {
5422 std::string spirv = BranchConditionalSetup + R"(
5423 %branch_cond = OpINotEqual %bool %i0 %i1
5424 OpSelectionMerge %end None
5425 OpBranchConditional %branch_cond %target_t %target_f 1 1
5426 )" + BranchConditionalTail;
5428 CompileSuccessfully(spirv.c_str());
5429 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
5432 TEST_P(ValidateIdWithMessage, OpBranchConditional_CondIsScalarInt) {
5433 std::string spirv = BranchConditionalSetup + R"(
5434 OpSelectionMerge %end None
5435 OpBranchConditional %i0 %target_t %target_f
5436 )" + BranchConditionalTail;
5438 CompileSuccessfully(spirv.c_str());
5439 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5440 EXPECT_THAT(
5441 getDiagnosticString(),
5442 HasSubstr(make_message("Condition operand for OpBranchConditional must "
5443 "be of boolean type")));
5446 TEST_P(ValidateIdWithMessage, OpBranchConditional_TrueTargetIsNotLabel) {
5447 std::string spirv = BranchConditionalSetup + R"(
5448 OpSelectionMerge %end None
5449 OpBranchConditional %true %i0 %target_f
5450 )" + BranchConditionalTail;
5452 CompileSuccessfully(spirv.c_str());
5453 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5454 EXPECT_THAT(getDiagnosticString(),
5455 HasSubstr(make_message(
5456 "The 'True Label' operand for OpBranchConditional must "
5457 "be the ID of an OpLabel instruction")));
5460 TEST_P(ValidateIdWithMessage, OpBranchConditional_FalseTargetIsNotLabel) {
5461 std::string spirv = BranchConditionalSetup + R"(
5462 OpSelectionMerge %end None
5463 OpBranchConditional %true %target_t %i0
5464 )" + BranchConditionalTail;
5466 CompileSuccessfully(spirv.c_str());
5467 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5468 EXPECT_THAT(getDiagnosticString(),
5469 HasSubstr(make_message(
5470 "The 'False Label' operand for OpBranchConditional "
5471 "must be the ID of an OpLabel instruction")));
5474 TEST_P(ValidateIdWithMessage, OpBranchConditional_NotEnoughWeights) {
5475 std::string spirv = BranchConditionalSetup + R"(
5476 %branch_cond = OpINotEqual %bool %i0 %i1
5477 OpSelectionMerge %end None
5478 OpBranchConditional %branch_cond %target_t %target_f 1
5479 )" + BranchConditionalTail;
5481 CompileSuccessfully(spirv.c_str());
5482 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5483 EXPECT_THAT(getDiagnosticString(),
5484 HasSubstr(make_message(
5485 "OpBranchConditional requires either 3 or 5 parameters")));
5488 TEST_P(ValidateIdWithMessage, OpBranchConditional_TooManyWeights) {
5489 std::string spirv = BranchConditionalSetup + R"(
5490 %branch_cond = OpINotEqual %bool %i0 %i1
5491 OpSelectionMerge %end None
5492 OpBranchConditional %branch_cond %target_t %target_f 1 2 3
5493 )" + BranchConditionalTail;
5495 CompileSuccessfully(spirv.c_str());
5496 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5497 EXPECT_THAT(getDiagnosticString(),
5498 HasSubstr(make_message(
5499 "OpBranchConditional requires either 3 or 5 parameters")));
5502 TEST_P(ValidateIdWithMessage, OpBranchConditional_ConditionIsAType) {
5503 std::string spirv = BranchConditionalSetup + R"(
5504 OpBranchConditional %bool %target_t %target_f
5505 )" + BranchConditionalTail;
5507 CompileSuccessfully(spirv.c_str());
5508 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5509 EXPECT_THAT(getDiagnosticString(),
5510 HasSubstr(make_message("Operand '3[%bool]' cannot be a "
5511 "type")));
5514 // TODO: OpSwitch
5516 TEST_P(ValidateIdWithMessage, OpReturnValueConstantGood) {
5517 std::string spirv = kGLSL450MemoryModel + R"(
5518 %1 = OpTypeVoid
5519 %2 = OpTypeInt 32 0
5520 %3 = OpTypeFunction %2
5521 %4 = OpConstant %2 42
5522 %5 = OpFunction %2 None %3
5523 %6 = OpLabel
5524 OpReturnValue %4
5525 OpFunctionEnd)";
5526 CompileSuccessfully(spirv.c_str());
5527 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5530 TEST_P(ValidateIdWithMessage, OpReturnValueVariableGood) {
5531 std::string spirv = kGLSL450MemoryModel + R"(
5532 %1 = OpTypeVoid
5533 %2 = OpTypeInt 32 0 ;10
5534 %3 = OpTypeFunction %2
5535 %8 = OpTypePointer Function %2 ;18
5536 %4 = OpConstant %2 42 ;22
5537 %5 = OpFunction %2 None %3 ;27
5538 %6 = OpLabel ;29
5539 %7 = OpVariable %8 Function %4 ;34
5540 %9 = OpLoad %2 %7
5541 OpReturnValue %9 ;36
5542 OpFunctionEnd)";
5543 CompileSuccessfully(spirv.c_str());
5544 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5547 TEST_P(ValidateIdWithMessage, OpReturnValueExpressionGood) {
5548 std::string spirv = kGLSL450MemoryModel + R"(
5549 %1 = OpTypeVoid
5550 %2 = OpTypeInt 32 0
5551 %3 = OpTypeFunction %2
5552 %4 = OpConstant %2 42
5553 %5 = OpFunction %2 None %3
5554 %6 = OpLabel
5555 %7 = OpIAdd %2 %4 %4
5556 OpReturnValue %7
5557 OpFunctionEnd)";
5558 CompileSuccessfully(spirv.c_str());
5559 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5562 TEST_P(ValidateIdWithMessage, OpReturnValueIsType) {
5563 std::string spirv = kGLSL450MemoryModel + R"(
5564 %1 = OpTypeVoid
5565 %2 = OpTypeInt 32 0
5566 %3 = OpTypeFunction %2
5567 %5 = OpFunction %2 None %3
5568 %6 = OpLabel
5569 OpReturnValue %1
5570 OpFunctionEnd)";
5571 CompileSuccessfully(spirv.c_str());
5572 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5573 EXPECT_THAT(getDiagnosticString(),
5574 HasSubstr(make_message("Operand '1[%void]' cannot be a "
5575 "type")));
5578 TEST_P(ValidateIdWithMessage, OpReturnValueIsLabel) {
5579 std::string spirv = kGLSL450MemoryModel + R"(
5580 %1 = OpTypeVoid
5581 %2 = OpTypeInt 32 0
5582 %3 = OpTypeFunction %2
5583 %5 = OpFunction %2 None %3
5584 %6 = OpLabel
5585 OpReturnValue %6
5586 OpFunctionEnd)";
5587 CompileSuccessfully(spirv.c_str());
5588 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5589 EXPECT_THAT(getDiagnosticString(),
5590 HasSubstr(make_message("Operand '5[%5]' requires a type")));
5593 TEST_P(ValidateIdWithMessage, OpReturnValueIsVoid) {
5594 std::string spirv = kGLSL450MemoryModel + R"(
5595 %1 = OpTypeVoid
5596 %2 = OpTypeInt 32 0
5597 %3 = OpTypeFunction %1
5598 %5 = OpFunction %1 None %3
5599 %6 = OpLabel
5600 %7 = OpFunctionCall %1 %5
5601 OpReturnValue %7
5602 OpFunctionEnd)";
5603 CompileSuccessfully(spirv.c_str());
5604 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5605 EXPECT_THAT(getDiagnosticString(),
5606 HasSubstr(make_message(
5607 "OpReturnValue value's type <id> '1[%void]' is missing or "
5608 "void.")));
5611 TEST_P(ValidateIdWithMessage, OpReturnValueIsVariableInPhysical) {
5612 // It's valid to return a pointer in a physical addressing model.
5613 std::string spirv = kOpCapabilitySetup + R"(
5614 OpMemoryModel Physical32 OpenCL
5615 %1 = OpTypeVoid
5616 %2 = OpTypeInt 32 0
5617 %3 = OpTypePointer Function %2
5618 %4 = OpTypeFunction %3
5619 %5 = OpFunction %3 None %4
5620 %6 = OpLabel
5621 %7 = OpVariable %3 Function
5622 OpReturnValue %7
5623 OpFunctionEnd)";
5624 CompileSuccessfully(spirv.c_str());
5625 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5628 TEST_P(ValidateIdWithMessage, OpReturnValueIsVariableInLogical) {
5629 // It's invalid to return a pointer in a physical addressing model.
5630 std::string spirv = kOpCapabilitySetup + R"(
5631 OpMemoryModel Logical GLSL450
5632 %1 = OpTypeVoid
5633 %2 = OpTypeInt 32 0
5634 %3 = OpTypePointer Function %2
5635 %4 = OpTypeFunction %3
5636 %5 = OpFunction %3 None %4
5637 %6 = OpLabel
5638 %7 = OpVariable %3 Function
5639 OpReturnValue %7
5640 OpFunctionEnd)";
5641 CompileSuccessfully(spirv.c_str());
5642 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5643 EXPECT_THAT(
5644 getDiagnosticString(),
5645 HasSubstr(make_message("OpReturnValue value's type <id> "
5646 "'3[%_ptr_Function_uint]' is a pointer, which is "
5647 "invalid in the Logical addressing model.")));
5650 // With the VariablePointer Capability, the return value of a function is
5651 // allowed to be a pointer.
5652 TEST_P(ValidateIdWithMessage, OpReturnValueVarPtrGood) {
5653 std::ostringstream spirv;
5654 createVariablePointerSpirvProgram(&spirv,
5655 "" /* Instructions to add to "main" */,
5656 true /* Add VariablePointers Capability?*/,
5657 true /* Use Helper Function? */);
5658 CompileSuccessfully(spirv.str());
5659 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5662 // Without the VariablePointer Capability, the return value of a function is
5663 // *not* allowed to be a pointer.
5664 // Disabled since using OpSelect with pointers without VariablePointers will
5665 // fail LogicalsPass.
5666 TEST_P(ValidateIdWithMessage, DISABLED_OpReturnValueVarPtrBad) {
5667 std::ostringstream spirv;
5668 createVariablePointerSpirvProgram(&spirv,
5669 "" /* Instructions to add to "main" */,
5670 false /* Add VariablePointers Capability?*/,
5671 true /* Use Helper Function? */);
5672 CompileSuccessfully(spirv.str());
5673 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5674 EXPECT_THAT(getDiagnosticString(),
5675 HasSubstr(make_message(
5676 "OpReturnValue value's type <id> '7' is a pointer, "
5677 "which is invalid in the Logical addressing model.")));
5680 // TODO: enable when this bug is fixed:
5681 // https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404
5682 TEST_P(ValidateIdWithMessage, DISABLED_OpReturnValueIsFunction) {
5683 std::string spirv = kGLSL450MemoryModel + R"(
5684 %1 = OpTypeVoid
5685 %2 = OpTypeInt 32 0
5686 %3 = OpTypeFunction %2
5687 %5 = OpFunction %2 None %3
5688 %6 = OpLabel
5689 OpReturnValue %5
5690 OpFunctionEnd)";
5691 CompileSuccessfully(spirv.c_str());
5692 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5695 TEST_P(ValidateIdWithMessage, UndefinedTypeId) {
5696 std::string spirv = kGLSL450MemoryModel + R"(
5697 %s = OpTypeStruct %i32
5699 CompileSuccessfully(spirv.c_str());
5700 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5701 EXPECT_THAT(getDiagnosticString(),
5702 HasSubstr(make_message(
5703 "Operand '2[%2]' requires a previous definition")));
5706 TEST_P(ValidateIdWithMessage, UndefinedIdScope) {
5707 std::string spirv = kGLSL450MemoryModel + R"(
5708 %u32 = OpTypeInt 32 0
5709 %memsem = OpConstant %u32 0
5710 %void = OpTypeVoid
5711 %void_f = OpTypeFunction %void
5712 %f = OpFunction %void None %void_f
5713 %l = OpLabel
5714 OpMemoryBarrier %undef %memsem
5715 OpReturn
5716 OpFunctionEnd
5718 CompileSuccessfully(spirv.c_str());
5719 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5720 EXPECT_THAT(getDiagnosticString(),
5721 HasSubstr(make_message("ID '7[%7]' has not been "
5722 "defined")));
5725 TEST_P(ValidateIdWithMessage, UndefinedIdMemSem) {
5726 std::string spirv = kGLSL450MemoryModel + R"(
5727 %u32 = OpTypeInt 32 0
5728 %scope = OpConstant %u32 0
5729 %void = OpTypeVoid
5730 %void_f = OpTypeFunction %void
5731 %f = OpFunction %void None %void_f
5732 %l = OpLabel
5733 OpMemoryBarrier %scope %undef
5734 OpReturn
5735 OpFunctionEnd
5737 CompileSuccessfully(spirv.c_str());
5738 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5739 EXPECT_THAT(getDiagnosticString(),
5740 HasSubstr(make_message("ID '7[%7]' has not been "
5741 "defined")));
5744 TEST_P(ValidateIdWithMessage,
5745 KernelOpEntryPointAndOpInBoundsPtrAccessChainGood) {
5746 std::string spirv = kOpenCLMemoryModel32 + R"(
5747 OpEntryPoint Kernel %2 "simple_kernel"
5748 OpSource OpenCL_C 200000
5749 OpDecorate %3 BuiltIn GlobalInvocationId
5750 OpDecorate %3 Constant
5751 OpDecorate %4 FuncParamAttr NoCapture
5752 OpDecorate %3 LinkageAttributes "__spirv_GlobalInvocationId" Import
5753 %5 = OpTypeInt 32 0
5754 %6 = OpTypeVector %5 3
5755 %7 = OpTypePointer UniformConstant %6
5756 %3 = OpVariable %7 UniformConstant
5757 %8 = OpTypeVoid
5758 %9 = OpTypeStruct %5
5759 %10 = OpTypePointer CrossWorkgroup %9
5760 %11 = OpTypeFunction %8 %10
5761 %12 = OpConstant %5 0
5762 %13 = OpTypePointer CrossWorkgroup %5
5763 %14 = OpConstant %5 42
5764 %2 = OpFunction %8 None %11
5765 %4 = OpFunctionParameter %10
5766 %15 = OpLabel
5767 %16 = OpLoad %6 %3 Aligned 0
5768 %17 = OpCompositeExtract %5 %16 0
5769 %18 = OpInBoundsPtrAccessChain %13 %4 %17 %12
5770 OpStore %18 %14 Aligned 4
5771 OpReturn
5772 OpFunctionEnd)";
5773 CompileSuccessfully(spirv.c_str());
5774 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5777 TEST_P(ValidateIdWithMessage, OpPtrAccessChainGood) {
5778 std::string spirv = kOpenCLMemoryModel64 + R"(
5779 OpEntryPoint Kernel %2 "another_kernel"
5780 OpSource OpenCL_C 200000
5781 OpDecorate %3 BuiltIn GlobalInvocationId
5782 OpDecorate %3 Constant
5783 OpDecorate %4 FuncParamAttr NoCapture
5784 OpDecorate %3 LinkageAttributes "__spirv_GlobalInvocationId" Import
5785 %5 = OpTypeInt 64 0
5786 %6 = OpTypeVector %5 3
5787 %7 = OpTypePointer UniformConstant %6
5788 %3 = OpVariable %7 UniformConstant
5789 %8 = OpTypeVoid
5790 %9 = OpTypeInt 32 0
5791 %10 = OpTypeStruct %9
5792 %11 = OpTypePointer CrossWorkgroup %10
5793 %12 = OpTypeFunction %8 %11
5794 %13 = OpConstant %5 4294967295
5795 %14 = OpConstant %9 0
5796 %15 = OpTypePointer CrossWorkgroup %9
5797 %16 = OpConstant %9 42
5798 %2 = OpFunction %8 None %12
5799 %4 = OpFunctionParameter %11
5800 %17 = OpLabel
5801 %18 = OpLoad %6 %3 Aligned 0
5802 %19 = OpCompositeExtract %5 %18 0
5803 %20 = OpBitwiseAnd %5 %19 %13
5804 %21 = OpPtrAccessChain %15 %4 %20 %14
5805 OpStore %21 %16 Aligned 4
5806 OpReturn
5807 OpFunctionEnd)";
5808 CompileSuccessfully(spirv.c_str());
5809 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5812 TEST_P(ValidateIdWithMessage, StgBufOpPtrAccessChainGood) {
5813 std::string spirv = R"(
5814 OpCapability Shader
5815 OpCapability Linkage
5816 OpCapability VariablePointersStorageBuffer
5817 OpExtension "SPV_KHR_variable_pointers"
5818 OpMemoryModel Logical GLSL450
5819 OpEntryPoint GLCompute %3 ""
5820 OpDecorate %ptr ArrayStride 8
5821 %int = OpTypeInt 32 0
5822 %int_2 = OpConstant %int 2
5823 %int_4 = OpConstant %int 4
5824 %struct = OpTypeStruct %int
5825 %array = OpTypeArray %struct %int_4
5826 %ptr = OpTypePointer StorageBuffer %array
5827 %var = OpVariable %ptr StorageBuffer
5828 %1 = OpTypeVoid
5829 %2 = OpTypeFunction %1
5830 %3 = OpFunction %1 None %2
5831 %4 = OpLabel
5832 %5 = OpPtrAccessChain %ptr %var %int_2
5833 OpReturn
5834 OpFunctionEnd
5836 CompileSuccessfully(spirv.c_str());
5837 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5840 TEST_P(ValidateIdWithMessage, OpLoadBitcastPointerGood) {
5841 std::string spirv = kOpenCLMemoryModel64 + R"(
5842 %2 = OpTypeVoid
5843 %3 = OpTypeInt 32 0
5844 %4 = OpTypeFloat 32
5845 %5 = OpTypePointer UniformConstant %3
5846 %6 = OpTypePointer UniformConstant %4
5847 %7 = OpVariable %5 UniformConstant
5848 %8 = OpTypeFunction %2
5849 %9 = OpFunction %2 None %8
5850 %10 = OpLabel
5851 %11 = OpBitcast %6 %7
5852 %12 = OpLoad %4 %11
5853 OpReturn
5854 OpFunctionEnd)";
5855 CompileSuccessfully(spirv.c_str());
5856 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5858 TEST_P(ValidateIdWithMessage, OpLoadBitcastNonPointerBad) {
5859 std::string spirv = kOpenCLMemoryModel64 + R"(
5860 %2 = OpTypeVoid
5861 %3 = OpTypeInt 32 0
5862 %4 = OpTypeFloat 32
5863 %5 = OpTypePointer UniformConstant %3
5864 %6 = OpTypeFunction %2
5865 %7 = OpVariable %5 UniformConstant
5866 %8 = OpFunction %2 None %6
5867 %9 = OpLabel
5868 %10 = OpLoad %3 %7
5869 %11 = OpBitcast %4 %10
5870 %12 = OpLoad %3 %11
5871 OpReturn
5872 OpFunctionEnd)";
5873 CompileSuccessfully(spirv.c_str());
5874 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5875 EXPECT_THAT(getDiagnosticString(),
5876 HasSubstr(make_message(
5877 "OpLoad type for pointer <id> '11[%11]' is not a pointer "
5878 "type.")));
5880 TEST_P(ValidateIdWithMessage, OpStoreBitcastPointerGood) {
5881 std::string spirv = kOpenCLMemoryModel64 + R"(
5882 %2 = OpTypeVoid
5883 %3 = OpTypeInt 32 0
5884 %4 = OpTypeFloat 32
5885 %5 = OpTypePointer Function %3
5886 %6 = OpTypePointer Function %4
5887 %7 = OpTypeFunction %2
5888 %8 = OpConstant %3 42
5889 %9 = OpFunction %2 None %7
5890 %10 = OpLabel
5891 %11 = OpVariable %6 Function
5892 %12 = OpBitcast %5 %11
5893 OpStore %12 %8
5894 OpReturn
5895 OpFunctionEnd)";
5896 CompileSuccessfully(spirv.c_str());
5897 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5899 TEST_P(ValidateIdWithMessage, OpStoreBitcastNonPointerBad) {
5900 std::string spirv = kOpenCLMemoryModel64 + R"(
5901 %2 = OpTypeVoid
5902 %3 = OpTypeInt 32 0
5903 %4 = OpTypeFloat 32
5904 %5 = OpTypePointer Function %4
5905 %6 = OpTypeFunction %2
5906 %7 = OpConstant %4 42
5907 %8 = OpFunction %2 None %6
5908 %9 = OpLabel
5909 %10 = OpVariable %5 Function
5910 %11 = OpBitcast %3 %7
5911 OpStore %11 %7
5912 OpReturn
5913 OpFunctionEnd)";
5914 CompileSuccessfully(spirv.c_str());
5915 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5916 EXPECT_THAT(getDiagnosticString(),
5917 HasSubstr(make_message(
5918 "OpStore type for pointer <id> '11[%11]' is not a pointer "
5919 "type.")));
5922 // Result <id> resulting from an instruction within a function may not be used
5923 // outside that function.
5924 TEST_P(ValidateIdWithMessage, ResultIdUsedOutsideOfFunctionBad) {
5925 std::string spirv = kGLSL450MemoryModel + R"(
5926 %1 = OpTypeVoid
5927 %2 = OpTypeFunction %1
5928 %3 = OpTypeInt 32 0
5929 %4 = OpTypePointer Function %3
5930 %5 = OpFunction %1 None %2
5931 %6 = OpLabel
5932 %7 = OpVariable %4 Function
5933 OpReturn
5934 OpFunctionEnd
5935 %8 = OpFunction %1 None %2
5936 %9 = OpLabel
5937 %10 = OpLoad %3 %7
5938 OpReturn
5939 OpFunctionEnd
5941 CompileSuccessfully(spirv.c_str());
5942 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5943 EXPECT_THAT(getDiagnosticString(),
5944 HasSubstr(make_message("ID '7[%7]' defined in block '6[%6]' does "
5945 "not dominate its use in block "
5946 "'9[%9]'")));
5949 TEST_P(ValidateIdWithMessage, SpecIdTargetNotSpecializationConstant) {
5950 std::string spirv = kGLSL450MemoryModel + R"(
5951 OpDecorate %1 SpecId 200
5952 %void = OpTypeVoid
5953 %2 = OpTypeFunction %void
5954 %int = OpTypeInt 32 0
5955 %1 = OpConstant %int 3
5956 %main = OpFunction %void None %2
5957 %4 = OpLabel
5958 OpReturnValue %1
5959 OpFunctionEnd
5961 CompileSuccessfully(spirv.c_str());
5962 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5963 EXPECT_THAT(
5964 getDiagnosticString(),
5965 HasSubstr(make_message("SpecId decoration on target <id> "
5966 "'1[%uint_3]' must be a scalar specialization "
5967 "constant")));
5970 TEST_P(ValidateIdWithMessage, SpecIdTargetOpSpecConstantOpBad) {
5971 std::string spirv = kGLSL450MemoryModel + R"(
5972 OpDecorate %1 SpecId 200
5973 %void = OpTypeVoid
5974 %2 = OpTypeFunction %void
5975 %int = OpTypeInt 32 0
5976 %3 = OpConstant %int 1
5977 %4 = OpConstant %int 2
5978 %1 = OpSpecConstantOp %int IAdd %3 %4
5979 %main = OpFunction %void None %2
5980 %6 = OpLabel
5981 OpReturnValue %3
5982 OpFunctionEnd
5984 CompileSuccessfully(spirv.c_str());
5985 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5986 EXPECT_THAT(
5987 getDiagnosticString(),
5988 HasSubstr(make_message("SpecId decoration on target <id> '1[%1]' "
5989 "must be a scalar specialization constant")));
5992 TEST_P(ValidateIdWithMessage, SpecIdTargetOpSpecConstantCompositeBad) {
5993 std::string spirv = kGLSL450MemoryModel + R"(
5994 OpDecorate %1 SpecId 200
5995 %void = OpTypeVoid
5996 %2 = OpTypeFunction %void
5997 %int = OpTypeInt 32 0
5998 %3 = OpConstant %int 1
5999 %1 = OpSpecConstantComposite %int
6000 %main = OpFunction %void None %2
6001 %4 = OpLabel
6002 OpReturnValue %3
6003 OpFunctionEnd
6005 CompileSuccessfully(spirv.c_str());
6006 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6007 EXPECT_THAT(
6008 getDiagnosticString(),
6009 HasSubstr(make_message("SpecId decoration on target <id> '1[%1]' "
6010 "must be a scalar specialization constant")));
6013 TEST_P(ValidateIdWithMessage, SpecIdTargetGood) {
6014 std::string spirv = kGLSL450MemoryModel + R"(
6015 OpDecorate %3 SpecId 200
6016 OpDecorate %4 SpecId 201
6017 OpDecorate %5 SpecId 202
6018 %1 = OpTypeVoid
6019 %2 = OpTypeFunction %1
6020 %int = OpTypeInt 32 0
6021 %bool = OpTypeBool
6022 %3 = OpSpecConstant %int 3
6023 %4 = OpSpecConstantTrue %bool
6024 %5 = OpSpecConstantFalse %bool
6025 %main = OpFunction %1 None %2
6026 %6 = OpLabel
6027 OpReturn
6028 OpFunctionEnd
6030 CompileSuccessfully(spirv.c_str());
6031 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
6034 TEST_P(ValidateIdWithMessage, CorrectErrorForShuffle) {
6035 std::string spirv = kGLSL450MemoryModel + R"(
6036 %uint = OpTypeInt 32 0
6037 %float = OpTypeFloat 32
6038 %v4float = OpTypeVector %float 4
6039 %v2float = OpTypeVector %float 2
6040 %void = OpTypeVoid
6041 %548 = OpTypeFunction %void
6042 %CS = OpFunction %void None %548
6043 %550 = OpLabel
6044 %6275 = OpUndef %v2float
6045 %6280 = OpUndef %v2float
6046 %6282 = OpVectorShuffle %v4float %6275 %6280 0 1 4 5
6047 OpReturn
6048 OpFunctionEnd
6051 CompileSuccessfully(spirv.c_str());
6052 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6053 EXPECT_THAT(
6054 getDiagnosticString(),
6055 HasSubstr(make_message(
6056 "Component index 4 is out of bounds for combined (Vector1 + Vector2) "
6057 "size of 4.")));
6058 EXPECT_EQ(25, getErrorPosition().index);
6061 TEST_P(ValidateIdWithMessage, VoidStructMember) {
6062 const std::string spirv = kGLSL450MemoryModel + R"(
6063 %void = OpTypeVoid
6064 %struct = OpTypeStruct %void
6067 CompileSuccessfully(spirv);
6068 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6069 EXPECT_THAT(
6070 getDiagnosticString(),
6071 HasSubstr(make_message("Structures cannot contain a void type.")));
6074 TEST_P(ValidateIdWithMessage, TypeFunctionBadUse) {
6075 std::string spirv = kGLSL450MemoryModel + R"(
6076 %1 = OpTypeVoid
6077 %2 = OpTypeFunction %1
6078 %3 = OpTypePointer Function %2
6079 %4 = OpFunction %1 None %2
6080 %5 = OpLabel
6081 OpReturn
6082 OpFunctionEnd)";
6084 CompileSuccessfully(spirv);
6085 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6086 EXPECT_THAT(getDiagnosticString(),
6087 HasSubstr(make_message(
6088 "Invalid use of function type result id '2[%2]'.")));
6091 TEST_P(ValidateIdWithMessage, BadTypeId) {
6092 std::string spirv = kGLSL450MemoryModel + R"(
6093 %1 = OpTypeVoid
6094 %2 = OpTypeFunction %1
6095 %3 = OpTypeFloat 32
6096 %4 = OpConstant %3 0
6097 %5 = OpFunction %1 None %2
6098 %6 = OpLabel
6099 %7 = OpUndef %4
6100 OpReturn
6101 OpFunctionEnd
6104 CompileSuccessfully(spirv);
6105 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6106 EXPECT_THAT(getDiagnosticString(),
6107 HasSubstr(make_message("ID '4[%float_0]' is not a type "
6108 "id")));
6111 TEST_P(ValidateIdWithMessage, VulkanMemoryModelLoadMakePointerVisibleGood) {
6112 std::string spirv = R"(
6113 OpCapability Shader
6114 OpCapability VulkanMemoryModelKHR
6115 OpCapability Linkage
6116 OpExtension "SPV_KHR_vulkan_memory_model"
6117 OpMemoryModel Logical VulkanKHR
6118 %1 = OpTypeVoid
6119 %2 = OpTypeInt 32 0
6120 %3 = OpTypePointer Workgroup %2
6121 %4 = OpVariable %3 Workgroup
6122 %5 = OpTypeFunction %1
6123 %6 = OpConstant %2 2
6124 %7 = OpFunction %1 None %5
6125 %8 = OpLabel
6126 %9 = OpLoad %2 %4 NonPrivatePointerKHR|MakePointerVisibleKHR %6
6127 OpReturn
6128 OpFunctionEnd
6131 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6132 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6135 TEST_P(ValidateIdWithMessage,
6136 VulkanMemoryModelLoadMakePointerVisibleMissingNonPrivatePointer) {
6137 std::string spirv = R"(
6138 OpCapability Shader
6139 OpCapability VulkanMemoryModelKHR
6140 OpCapability Linkage
6141 OpExtension "SPV_KHR_vulkan_memory_model"
6142 OpMemoryModel Logical VulkanKHR
6143 %1 = OpTypeVoid
6144 %2 = OpTypeInt 32 0
6145 %3 = OpTypePointer Workgroup %2
6146 %4 = OpVariable %3 Workgroup
6147 %5 = OpTypeFunction %1
6148 %6 = OpConstant %2 2
6149 %7 = OpFunction %1 None %5
6150 %8 = OpLabel
6151 %9 = OpLoad %2 %4 MakePointerVisibleKHR %6
6152 OpReturn
6153 OpFunctionEnd
6156 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6157 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6158 EXPECT_THAT(
6159 getDiagnosticString(),
6160 HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6161 "MakePointerVisibleKHR is specified.")));
6164 TEST_P(ValidateIdWithMessage,
6165 VulkanMemoryModelLoadNonPrivatePointerBadStorageClass) {
6166 std::string spirv = R"(
6167 OpCapability Shader
6168 OpCapability VulkanMemoryModelKHR
6169 OpCapability Linkage
6170 OpExtension "SPV_KHR_vulkan_memory_model"
6171 OpMemoryModel Logical VulkanKHR
6172 %1 = OpTypeVoid
6173 %2 = OpTypeInt 32 0
6174 %3 = OpTypePointer Private %2
6175 %4 = OpVariable %3 Private
6176 %5 = OpTypeFunction %1
6177 %6 = OpConstant %2 2
6178 %7 = OpFunction %1 None %5
6179 %8 = OpLabel
6180 %9 = OpLoad %2 %4 NonPrivatePointerKHR
6181 OpReturn
6182 OpFunctionEnd
6185 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6186 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6187 EXPECT_THAT(getDiagnosticString(),
6188 HasSubstr(make_message(
6189 "NonPrivatePointerKHR requires a pointer in Uniform, "
6190 "Workgroup, CrossWorkgroup, Generic, Image or "
6191 "StorageBuffer storage classes.")));
6194 TEST_P(ValidateIdWithMessage,
6195 VulkanMemoryModelLoadMakePointerAvailableCannotBeUsed) {
6196 std::string spirv = R"(
6197 OpCapability Shader
6198 OpCapability VulkanMemoryModelKHR
6199 OpCapability Linkage
6200 OpExtension "SPV_KHR_vulkan_memory_model"
6201 OpMemoryModel Logical VulkanKHR
6202 %1 = OpTypeVoid
6203 %2 = OpTypeInt 32 0
6204 %3 = OpTypePointer Workgroup %2
6205 %4 = OpVariable %3 Workgroup
6206 %5 = OpTypeFunction %1
6207 %6 = OpConstant %2 2
6208 %7 = OpFunction %1 None %5
6209 %8 = OpLabel
6210 %9 = OpLoad %2 %4 NonPrivatePointerKHR|MakePointerAvailableKHR %6
6211 OpReturn
6212 OpFunctionEnd
6215 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6216 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6217 EXPECT_THAT(getDiagnosticString(),
6218 HasSubstr(make_message(
6219 "MakePointerAvailableKHR cannot be used with OpLoad")));
6222 TEST_P(ValidateIdWithMessage, VulkanMemoryModelStoreMakePointerAvailableGood) {
6223 std::string spirv = R"(
6224 OpCapability Shader
6225 OpCapability VulkanMemoryModelKHR
6226 OpCapability Linkage
6227 OpExtension "SPV_KHR_vulkan_memory_model"
6228 OpMemoryModel Logical VulkanKHR
6229 %1 = OpTypeVoid
6230 %2 = OpTypeInt 32 0
6231 %3 = OpTypePointer Uniform %2
6232 %4 = OpVariable %3 Uniform
6233 %5 = OpTypeFunction %1
6234 %6 = OpConstant %2 5
6235 %7 = OpFunction %1 None %5
6236 %8 = OpLabel
6237 OpStore %4 %6 NonPrivatePointerKHR|MakePointerAvailableKHR %6
6238 OpReturn
6239 OpFunctionEnd
6242 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6243 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6246 TEST_P(ValidateIdWithMessage,
6247 VulkanMemoryModelStoreMakePointerAvailableMissingNonPrivatePointer) {
6248 std::string spirv = R"(
6249 OpCapability Shader
6250 OpCapability VulkanMemoryModelKHR
6251 OpCapability Linkage
6252 OpExtension "SPV_KHR_vulkan_memory_model"
6253 OpMemoryModel Logical VulkanKHR
6254 %1 = OpTypeVoid
6255 %2 = OpTypeInt 32 0
6256 %3 = OpTypePointer Uniform %2
6257 %4 = OpVariable %3 Uniform
6258 %5 = OpTypeFunction %1
6259 %6 = OpConstant %2 5
6260 %7 = OpFunction %1 None %5
6261 %8 = OpLabel
6262 OpStore %4 %6 MakePointerAvailableKHR %6
6263 OpReturn
6264 OpFunctionEnd
6267 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6268 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6269 EXPECT_THAT(
6270 getDiagnosticString(),
6271 HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6272 "MakePointerAvailableKHR is specified.")));
6275 TEST_P(ValidateIdWithMessage,
6276 VulkanMemoryModelStoreNonPrivatePointerBadStorageClass) {
6277 std::string spirv = R"(
6278 OpCapability Shader
6279 OpCapability VulkanMemoryModelKHR
6280 OpCapability Linkage
6281 OpExtension "SPV_KHR_vulkan_memory_model"
6282 OpMemoryModel Logical VulkanKHR
6283 %1 = OpTypeVoid
6284 %2 = OpTypeInt 32 0
6285 %3 = OpTypePointer Output %2
6286 %4 = OpVariable %3 Output
6287 %5 = OpTypeFunction %1
6288 %6 = OpConstant %2 5
6289 %7 = OpFunction %1 None %5
6290 %8 = OpLabel
6291 OpStore %4 %6 NonPrivatePointerKHR
6292 OpReturn
6293 OpFunctionEnd
6296 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6297 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6298 EXPECT_THAT(getDiagnosticString(),
6299 HasSubstr(make_message(
6300 "NonPrivatePointerKHR requires a pointer in Uniform, "
6301 "Workgroup, CrossWorkgroup, Generic, Image or "
6302 "StorageBuffer storage classes.")));
6305 TEST_P(ValidateIdWithMessage,
6306 VulkanMemoryModelStoreMakePointerVisibleCannotBeUsed) {
6307 std::string spirv = R"(
6308 OpCapability Shader
6309 OpCapability VulkanMemoryModelKHR
6310 OpCapability Linkage
6311 OpExtension "SPV_KHR_vulkan_memory_model"
6312 OpMemoryModel Logical VulkanKHR
6313 %1 = OpTypeVoid
6314 %2 = OpTypeInt 32 0
6315 %3 = OpTypePointer Uniform %2
6316 %4 = OpVariable %3 Uniform
6317 %5 = OpTypeFunction %1
6318 %6 = OpConstant %2 5
6319 %7 = OpFunction %1 None %5
6320 %8 = OpLabel
6321 OpStore %4 %6 NonPrivatePointerKHR|MakePointerVisibleKHR %6
6322 OpReturn
6323 OpFunctionEnd
6326 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6327 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6328 EXPECT_THAT(getDiagnosticString(),
6329 HasSubstr(make_message(
6330 "MakePointerVisibleKHR cannot be used with OpStore.")));
6333 TEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryAvailable) {
6334 std::string spirv = R"(
6335 OpCapability Shader
6336 OpCapability Linkage
6337 OpCapability VulkanMemoryModelKHR
6338 OpExtension "SPV_KHR_vulkan_memory_model"
6339 OpMemoryModel Logical VulkanKHR
6340 %1 = OpTypeVoid
6341 %2 = OpTypeInt 32 0
6342 %3 = OpTypePointer Workgroup %2
6343 %4 = OpVariable %3 Workgroup
6344 %5 = OpTypePointer Uniform %2
6345 %6 = OpVariable %5 Uniform
6346 %7 = OpConstant %2 2
6347 %8 = OpConstant %2 5
6348 %9 = OpTypeFunction %1
6349 %10 = OpFunction %1 None %9
6350 %11 = OpLabel
6351 OpCopyMemory %4 %6 NonPrivatePointerKHR|MakePointerAvailableKHR %7
6352 OpReturn
6353 OpFunctionEnd
6356 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6357 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6360 TEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryVisible) {
6361 std::string spirv = R"(
6362 OpCapability Shader
6363 OpCapability Linkage
6364 OpCapability VulkanMemoryModelKHR
6365 OpExtension "SPV_KHR_vulkan_memory_model"
6366 OpMemoryModel Logical VulkanKHR
6367 %1 = OpTypeVoid
6368 %2 = OpTypeInt 32 0
6369 %3 = OpTypePointer Workgroup %2
6370 %4 = OpVariable %3 Workgroup
6371 %5 = OpTypePointer Uniform %2
6372 %6 = OpVariable %5 Uniform
6373 %7 = OpConstant %2 2
6374 %8 = OpConstant %2 5
6375 %9 = OpTypeFunction %1
6376 %10 = OpFunction %1 None %9
6377 %11 = OpLabel
6378 OpCopyMemory %4 %6 NonPrivatePointerKHR|MakePointerVisibleKHR %8
6379 OpReturn
6380 OpFunctionEnd
6383 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6384 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6387 TEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryAvailableAndVisible) {
6388 std::string spirv = R"(
6389 OpCapability Shader
6390 OpCapability Linkage
6391 OpCapability VulkanMemoryModelKHR
6392 OpExtension "SPV_KHR_vulkan_memory_model"
6393 OpMemoryModel Logical VulkanKHR
6394 %1 = OpTypeVoid
6395 %2 = OpTypeInt 32 0
6396 %3 = OpTypePointer Workgroup %2
6397 %4 = OpVariable %3 Workgroup
6398 %5 = OpTypePointer Uniform %2
6399 %6 = OpVariable %5 Uniform
6400 %7 = OpConstant %2 2
6401 %8 = OpConstant %2 5
6402 %9 = OpTypeFunction %1
6403 %10 = OpFunction %1 None %9
6404 %11 = OpLabel
6405 OpCopyMemory %4 %6 NonPrivatePointerKHR|MakePointerAvailableKHR|MakePointerVisibleKHR %7 %8
6406 OpReturn
6407 OpFunctionEnd
6410 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6411 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6414 TEST_P(ValidateIdWithMessage,
6415 VulkanMemoryModelCopyMemoryAvailableMissingNonPrivatePointer) {
6416 std::string spirv = R"(
6417 OpCapability Shader
6418 OpCapability Linkage
6419 OpCapability VulkanMemoryModelKHR
6420 OpExtension "SPV_KHR_vulkan_memory_model"
6421 OpMemoryModel Logical VulkanKHR
6422 %1 = OpTypeVoid
6423 %2 = OpTypeInt 32 0
6424 %3 = OpTypePointer Workgroup %2
6425 %4 = OpVariable %3 Workgroup
6426 %5 = OpTypePointer Uniform %2
6427 %6 = OpVariable %5 Uniform
6428 %7 = OpConstant %2 2
6429 %8 = OpConstant %2 5
6430 %9 = OpTypeFunction %1
6431 %10 = OpFunction %1 None %9
6432 %11 = OpLabel
6433 OpCopyMemory %4 %6 MakePointerAvailableKHR %7
6434 OpReturn
6435 OpFunctionEnd
6438 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6439 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6440 EXPECT_THAT(
6441 getDiagnosticString(),
6442 HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6443 "MakePointerAvailableKHR is specified.")));
6446 TEST_P(ValidateIdWithMessage,
6447 VulkanMemoryModelCopyMemoryVisibleMissingNonPrivatePointer) {
6448 std::string spirv = R"(
6449 OpCapability Shader
6450 OpCapability Linkage
6451 OpCapability VulkanMemoryModelKHR
6452 OpExtension "SPV_KHR_vulkan_memory_model"
6453 OpMemoryModel Logical VulkanKHR
6454 %1 = OpTypeVoid
6455 %2 = OpTypeInt 32 0
6456 %3 = OpTypePointer Workgroup %2
6457 %4 = OpVariable %3 Workgroup
6458 %5 = OpTypePointer Uniform %2
6459 %6 = OpVariable %5 Uniform
6460 %7 = OpConstant %2 2
6461 %8 = OpConstant %2 5
6462 %9 = OpTypeFunction %1
6463 %10 = OpFunction %1 None %9
6464 %11 = OpLabel
6465 OpCopyMemory %4 %6 MakePointerVisibleKHR %8
6466 OpReturn
6467 OpFunctionEnd
6470 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6471 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6472 EXPECT_THAT(
6473 getDiagnosticString(),
6474 HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6475 "MakePointerVisibleKHR is specified.")));
6478 TEST_P(ValidateIdWithMessage,
6479 VulkanMemoryModelCopyMemoryAvailableBadStorageClass) {
6480 std::string spirv = R"(
6481 OpCapability Shader
6482 OpCapability Linkage
6483 OpCapability VulkanMemoryModelKHR
6484 OpExtension "SPV_KHR_vulkan_memory_model"
6485 OpMemoryModel Logical VulkanKHR
6486 %1 = OpTypeVoid
6487 %2 = OpTypeInt 32 0
6488 %3 = OpTypePointer Output %2
6489 %4 = OpVariable %3 Output
6490 %5 = OpTypePointer Uniform %2
6491 %6 = OpVariable %5 Uniform
6492 %7 = OpConstant %2 2
6493 %8 = OpConstant %2 5
6494 %9 = OpTypeFunction %1
6495 %10 = OpFunction %1 None %9
6496 %11 = OpLabel
6497 OpCopyMemory %4 %6 NonPrivatePointerKHR
6498 OpReturn
6499 OpFunctionEnd
6502 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6503 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6504 EXPECT_THAT(getDiagnosticString(),
6505 HasSubstr(make_message(
6506 "NonPrivatePointerKHR requires a pointer in Uniform, "
6507 "Workgroup, CrossWorkgroup, Generic, Image or "
6508 "StorageBuffer storage classes.")));
6511 TEST_P(ValidateIdWithMessage,
6512 VulkanMemoryModelCopyMemoryVisibleBadStorageClass) {
6513 std::string spirv = R"(
6514 OpCapability Shader
6515 OpCapability Linkage
6516 OpCapability VulkanMemoryModelKHR
6517 OpExtension "SPV_KHR_vulkan_memory_model"
6518 OpMemoryModel Logical VulkanKHR
6519 %1 = OpTypeVoid
6520 %2 = OpTypeInt 32 0
6521 %3 = OpTypePointer Workgroup %2
6522 %4 = OpVariable %3 Workgroup
6523 %5 = OpTypePointer Input %2
6524 %6 = OpVariable %5 Input
6525 %7 = OpConstant %2 2
6526 %8 = OpConstant %2 5
6527 %9 = OpTypeFunction %1
6528 %10 = OpFunction %1 None %9
6529 %11 = OpLabel
6530 OpCopyMemory %4 %6 NonPrivatePointerKHR
6531 OpReturn
6532 OpFunctionEnd
6535 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6536 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6537 EXPECT_THAT(getDiagnosticString(),
6538 HasSubstr(make_message(
6539 "NonPrivatePointerKHR requires a pointer in Uniform, "
6540 "Workgroup, CrossWorkgroup, Generic, Image or "
6541 "StorageBuffer storage classes.")));
6544 TEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemorySizedAvailable) {
6545 std::string spirv = R"(
6546 OpCapability Shader
6547 OpCapability Linkage
6548 OpCapability Addresses
6549 OpCapability VulkanMemoryModelKHR
6550 OpExtension "SPV_KHR_vulkan_memory_model"
6551 OpMemoryModel Logical VulkanKHR
6552 %1 = OpTypeVoid
6553 %2 = OpTypeInt 32 0
6554 %3 = OpTypePointer Workgroup %2
6555 %4 = OpVariable %3 Workgroup
6556 %5 = OpTypePointer Uniform %2
6557 %6 = OpVariable %5 Uniform
6558 %7 = OpConstant %2 2
6559 %8 = OpConstant %2 5
6560 %9 = OpTypeFunction %1
6561 %12 = OpConstant %2 4
6562 %10 = OpFunction %1 None %9
6563 %11 = OpLabel
6564 OpCopyMemorySized %4 %6 %12 NonPrivatePointerKHR|MakePointerAvailableKHR %7
6565 OpReturn
6566 OpFunctionEnd
6569 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6570 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6573 TEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemorySizedVisible) {
6574 std::string spirv = R"(
6575 OpCapability Shader
6576 OpCapability Linkage
6577 OpCapability Addresses
6578 OpCapability VulkanMemoryModelKHR
6579 OpExtension "SPV_KHR_vulkan_memory_model"
6580 OpMemoryModel Logical VulkanKHR
6581 %1 = OpTypeVoid
6582 %2 = OpTypeInt 32 0
6583 %3 = OpTypePointer Workgroup %2
6584 %4 = OpVariable %3 Workgroup
6585 %5 = OpTypePointer Uniform %2
6586 %6 = OpVariable %5 Uniform
6587 %7 = OpConstant %2 2
6588 %8 = OpConstant %2 5
6589 %12 = OpConstant %2 4
6590 %9 = OpTypeFunction %1
6591 %10 = OpFunction %1 None %9
6592 %11 = OpLabel
6593 OpCopyMemorySized %4 %6 %12 NonPrivatePointerKHR|MakePointerVisibleKHR %8
6594 OpReturn
6595 OpFunctionEnd
6598 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6599 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6602 TEST_P(ValidateIdWithMessage,
6603 VulkanMemoryModelCopyMemorySizedAvailableAndVisible) {
6604 std::string spirv = R"(
6605 OpCapability Shader
6606 OpCapability Linkage
6607 OpCapability Addresses
6608 OpCapability VulkanMemoryModelKHR
6609 OpExtension "SPV_KHR_vulkan_memory_model"
6610 OpMemoryModel Logical VulkanKHR
6611 %1 = OpTypeVoid
6612 %2 = OpTypeInt 32 0
6613 %3 = OpTypePointer Workgroup %2
6614 %4 = OpVariable %3 Workgroup
6615 %5 = OpTypePointer Uniform %2
6616 %6 = OpVariable %5 Uniform
6617 %7 = OpConstant %2 2
6618 %8 = OpConstant %2 5
6619 %12 = OpConstant %2 4
6620 %9 = OpTypeFunction %1
6621 %10 = OpFunction %1 None %9
6622 %11 = OpLabel
6623 OpCopyMemorySized %4 %6 %12 NonPrivatePointerKHR|MakePointerAvailableKHR|MakePointerVisibleKHR %7 %8
6624 OpReturn
6625 OpFunctionEnd
6628 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6629 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6632 TEST_P(ValidateIdWithMessage,
6633 VulkanMemoryModelCopyMemorySizedAvailableMissingNonPrivatePointer) {
6634 std::string spirv = R"(
6635 OpCapability Shader
6636 OpCapability Linkage
6637 OpCapability Addresses
6638 OpCapability VulkanMemoryModelKHR
6639 OpExtension "SPV_KHR_vulkan_memory_model"
6640 OpMemoryModel Logical VulkanKHR
6641 %1 = OpTypeVoid
6642 %2 = OpTypeInt 32 0
6643 %3 = OpTypePointer Workgroup %2
6644 %4 = OpVariable %3 Workgroup
6645 %5 = OpTypePointer Uniform %2
6646 %6 = OpVariable %5 Uniform
6647 %7 = OpConstant %2 2
6648 %8 = OpConstant %2 5
6649 %12 = OpConstant %2 4
6650 %9 = OpTypeFunction %1
6651 %10 = OpFunction %1 None %9
6652 %11 = OpLabel
6653 OpCopyMemorySized %4 %6 %12 MakePointerAvailableKHR %7
6654 OpReturn
6655 OpFunctionEnd
6658 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6659 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6660 EXPECT_THAT(
6661 getDiagnosticString(),
6662 HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6663 "MakePointerAvailableKHR is specified.")));
6666 TEST_P(ValidateIdWithMessage,
6667 VulkanMemoryModelCopyMemorySizedVisibleMissingNonPrivatePointer) {
6668 std::string spirv = R"(
6669 OpCapability Shader
6670 OpCapability Linkage
6671 OpCapability Addresses
6672 OpCapability VulkanMemoryModelKHR
6673 OpExtension "SPV_KHR_vulkan_memory_model"
6674 OpMemoryModel Logical VulkanKHR
6675 %1 = OpTypeVoid
6676 %2 = OpTypeInt 32 0
6677 %3 = OpTypePointer Workgroup %2
6678 %4 = OpVariable %3 Workgroup
6679 %5 = OpTypePointer Uniform %2
6680 %6 = OpVariable %5 Uniform
6681 %7 = OpConstant %2 2
6682 %8 = OpConstant %2 5
6683 %12 = OpConstant %2 4
6684 %9 = OpTypeFunction %1
6685 %10 = OpFunction %1 None %9
6686 %11 = OpLabel
6687 OpCopyMemorySized %4 %6 %12 MakePointerVisibleKHR %8
6688 OpReturn
6689 OpFunctionEnd
6692 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6693 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6694 EXPECT_THAT(
6695 getDiagnosticString(),
6696 HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6697 "MakePointerVisibleKHR is specified.")));
6700 TEST_P(ValidateIdWithMessage,
6701 VulkanMemoryModelCopyMemorySizedAvailableBadStorageClass) {
6702 std::string spirv = R"(
6703 OpCapability Shader
6704 OpCapability Linkage
6705 OpCapability Addresses
6706 OpCapability VulkanMemoryModelKHR
6707 OpExtension "SPV_KHR_vulkan_memory_model"
6708 OpMemoryModel Logical VulkanKHR
6709 %1 = OpTypeVoid
6710 %2 = OpTypeInt 32 0
6711 %3 = OpTypePointer Output %2
6712 %4 = OpVariable %3 Output
6713 %5 = OpTypePointer Uniform %2
6714 %6 = OpVariable %5 Uniform
6715 %7 = OpConstant %2 2
6716 %8 = OpConstant %2 5
6717 %12 = OpConstant %2 4
6718 %9 = OpTypeFunction %1
6719 %10 = OpFunction %1 None %9
6720 %11 = OpLabel
6721 OpCopyMemorySized %4 %6 %12 NonPrivatePointerKHR
6722 OpReturn
6723 OpFunctionEnd
6726 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6727 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6728 EXPECT_THAT(getDiagnosticString(),
6729 HasSubstr(make_message(
6730 "NonPrivatePointerKHR requires a pointer in Uniform, "
6731 "Workgroup, CrossWorkgroup, Generic, Image or "
6732 "StorageBuffer storage classes.")));
6735 TEST_P(ValidateIdWithMessage,
6736 VulkanMemoryModelCopyMemorySizedVisibleBadStorageClass) {
6737 std::string spirv = R"(
6738 OpCapability Shader
6739 OpCapability Linkage
6740 OpCapability Addresses
6741 OpCapability VulkanMemoryModelKHR
6742 OpExtension "SPV_KHR_vulkan_memory_model"
6743 OpMemoryModel Logical VulkanKHR
6744 %1 = OpTypeVoid
6745 %2 = OpTypeInt 32 0
6746 %3 = OpTypePointer Workgroup %2
6747 %4 = OpVariable %3 Workgroup
6748 %5 = OpTypePointer Input %2
6749 %6 = OpVariable %5 Input
6750 %7 = OpConstant %2 2
6751 %8 = OpConstant %2 5
6752 %12 = OpConstant %2 4
6753 %9 = OpTypeFunction %1
6754 %10 = OpFunction %1 None %9
6755 %11 = OpLabel
6756 OpCopyMemorySized %4 %6 %12 NonPrivatePointerKHR
6757 OpReturn
6758 OpFunctionEnd
6761 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6762 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6763 EXPECT_THAT(getDiagnosticString(),
6764 HasSubstr(make_message(
6765 "NonPrivatePointerKHR requires a pointer in Uniform, "
6766 "Workgroup, CrossWorkgroup, Generic, Image or "
6767 "StorageBuffer storage classes.")));
6770 TEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock1) {
6771 const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6772 %1 = OpTypeVoid
6773 %2 = OpTypeFunction %1
6774 %3 = OpTypeFloat 32
6775 %4 = OpTypeFunction %3
6776 %5 = OpFunction %1 None %2
6777 %6 = OpLabel
6778 OpReturn
6779 %7 = OpLabel
6780 %8 = OpFunctionCall %3 %9
6781 OpUnreachable
6782 OpFunctionEnd
6783 %9 = OpFunction %3 None %4
6784 %10 = OpLabel
6785 OpReturnValue %8
6786 OpFunctionEnd
6789 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6790 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6791 EXPECT_THAT(getDiagnosticString(),
6792 HasSubstr(make_message(
6793 "ID '8[%8]' defined in block '7[%7]' does not dominate its "
6794 "use in block '10[%10]'\n %10 = OpLabel")));
6797 TEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock2) {
6798 const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6799 %1 = OpTypeVoid
6800 %2 = OpTypeFunction %1
6801 %3 = OpTypeFloat 32
6802 %4 = OpTypeFunction %3
6803 %5 = OpFunction %1 None %2
6804 %6 = OpLabel
6805 OpReturn
6806 %7 = OpLabel
6807 %8 = OpFunctionCall %3 %9
6808 OpUnreachable
6809 OpFunctionEnd
6810 %9 = OpFunction %3 None %4
6811 %10 = OpLabel
6812 OpReturnValue %8
6813 OpFunctionEnd
6816 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6817 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6818 EXPECT_THAT(getDiagnosticString(),
6819 HasSubstr(make_message(
6820 "ID '8[%8]' defined in block '7[%7]' does not dominate its "
6821 "use in block '10[%10]'\n %10 = OpLabel")));
6824 TEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock3) {
6825 const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6826 %1 = OpTypeVoid
6827 %2 = OpTypeFunction %1
6828 %3 = OpTypeFloat 32
6829 %4 = OpTypeFunction %3
6830 %5 = OpFunction %1 None %2
6831 %6 = OpLabel
6832 OpReturn
6833 %7 = OpLabel
6834 %8 = OpFunctionCall %3 %9
6835 OpReturn
6836 OpFunctionEnd
6837 %9 = OpFunction %3 None %4
6838 %10 = OpLabel
6839 OpReturnValue %8
6840 OpFunctionEnd
6843 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6844 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6845 EXPECT_THAT(getDiagnosticString(),
6846 HasSubstr(make_message(
6847 "ID '8[%8]' defined in block '7[%7]' does not dominate its "
6848 "use in block '10[%10]'\n %10 = OpLabel")));
6851 TEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock4) {
6852 const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6853 %1 = OpTypeVoid
6854 %2 = OpTypeFunction %1
6855 %3 = OpTypeFloat 32
6856 %4 = OpTypeFunction %3
6857 %5 = OpFunction %1 None %2
6858 %6 = OpLabel
6859 OpReturn
6860 %7 = OpLabel
6861 %8 = OpUndef %3
6862 %9 = OpCopyObject %3 %8
6863 OpReturn
6864 OpFunctionEnd
6867 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6868 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6871 TEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock5) {
6872 const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6873 %1 = OpTypeVoid
6874 %2 = OpTypeFunction %1
6875 %3 = OpTypeFloat 32
6876 %4 = OpTypeFunction %3
6877 %5 = OpFunction %1 None %2
6878 %6 = OpLabel
6879 OpReturn
6880 %7 = OpLabel
6881 %8 = OpUndef %3
6882 OpBranch %9
6883 %9 = OpLabel
6884 %10 = OpCopyObject %3 %8
6885 OpReturn
6886 OpFunctionEnd
6889 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6890 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6893 TEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock6) {
6894 const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6895 %1 = OpTypeVoid
6896 %2 = OpTypeFunction %1
6897 %3 = OpTypeFloat 32
6898 %4 = OpTypeFunction %3
6899 %5 = OpFunction %1 None %2
6900 %6 = OpLabel
6901 OpBranch %7
6902 %8 = OpLabel
6903 %9 = OpUndef %3
6904 OpBranch %7
6905 %7 = OpLabel
6906 %10 = OpCopyObject %3 %9
6907 OpReturn
6908 OpFunctionEnd
6911 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6912 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6913 EXPECT_THAT(getDiagnosticString(),
6914 HasSubstr(make_message(
6915 "ID '9[%9]' defined in block '8[%8]' does not dominate its "
6916 "use in block '7[%7]'\n %7 = OpLabel")));
6919 TEST_P(ValidateIdWithMessage, ReachableDefUnreachableUse) {
6920 const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6921 %1 = OpTypeVoid
6922 %2 = OpTypeFunction %1
6923 %3 = OpTypeFloat 32
6924 %4 = OpTypeFunction %3
6925 %5 = OpFunction %1 None %2
6926 %6 = OpLabel
6927 %7 = OpUndef %3
6928 OpReturn
6929 %8 = OpLabel
6930 %9 = OpCopyObject %3 %7
6931 OpReturn
6932 OpFunctionEnd
6935 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6936 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6939 TEST_P(ValidateIdWithMessage, UnreachableDefUsedInPhi) {
6940 const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6941 %void = OpTypeVoid
6942 %3 = OpTypeFunction %void
6943 %float = OpTypeFloat 32
6944 %bool = OpTypeBool
6945 %6 = OpTypeFunction %float
6946 %1 = OpFunction %void None %3
6947 %7 = OpLabel
6948 %8 = OpUndef %bool
6949 OpSelectionMerge %9 None
6950 OpBranchConditional %8 %10 %9
6951 %10 = OpLabel
6952 %11 = OpUndef %float
6953 OpBranch %9
6954 %12 = OpLabel
6955 %13 = OpUndef %float
6956 OpUnreachable
6957 %9 = OpLabel
6958 %14 = OpPhi %float %11 %10 %13 %7
6959 OpReturn
6960 OpFunctionEnd
6963 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6964 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6965 EXPECT_THAT(
6966 getDiagnosticString(),
6967 HasSubstr(make_message(
6968 "In OpPhi instruction '14[%14]', ID '13[%13]' definition does not "
6969 "dominate its parent '7[%7]'\n %14 = OpPhi %float %11 %10 %13 "
6970 "%7")));
6973 TEST_P(ValidateIdWithMessage, OpTypeForwardPointerNotAPointerType) {
6974 std::string spirv = R"(
6975 OpCapability GenericPointer
6976 OpCapability VariablePointersStorageBuffer
6977 OpMemoryModel Logical GLSL450
6978 OpEntryPoint Fragment %1 "main"
6979 OpExecutionMode %1 OriginLowerLeft
6980 OpTypeForwardPointer %2 CrossWorkgroup
6981 %2 = OpTypeVoid
6982 %3 = OpTypeFunction %2
6983 %1 = OpFunction %2 DontInline %3
6984 %4 = OpLabel
6985 OpReturn
6986 OpFunctionEnd
6989 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6990 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6991 EXPECT_THAT(getDiagnosticString(),
6992 HasSubstr(make_message(
6993 "Pointer type in OpTypeForwardPointer is not a pointer "
6994 "type.\n OpTypeForwardPointer %void CrossWorkgroup")));
6997 TEST_P(ValidateIdWithMessage, OpTypeForwardPointerWrongStorageClass) {
6998 std::string spirv = R"(
6999 OpCapability GenericPointer
7000 OpCapability VariablePointersStorageBuffer
7001 OpMemoryModel Logical GLSL450
7002 OpEntryPoint Fragment %1 "main"
7003 OpExecutionMode %1 OriginLowerLeft
7004 OpTypeForwardPointer %2 CrossWorkgroup
7005 %int = OpTypeInt 32 1
7006 %2 = OpTypePointer Function %int
7007 %void = OpTypeVoid
7008 %3 = OpTypeFunction %void
7009 %1 = OpFunction %void None %3
7010 %4 = OpLabel
7011 OpReturn
7012 OpFunctionEnd
7015 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
7016 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
7017 EXPECT_THAT(getDiagnosticString(),
7018 HasSubstr(make_message(
7019 "Storage class in OpTypeForwardPointer does not match the "
7020 "pointer definition.\n OpTypeForwardPointer "
7021 "%_ptr_Function_int CrossWorkgroup")));
7024 TEST_P(ValidateIdWithMessage, MissingForwardPointer) {
7025 const std::string spirv = R"(
7026 OpCapability Linkage
7027 OpCapability Shader
7028 OpMemoryModel Logical Simple
7029 %float = OpTypeFloat 32
7030 %_struct_9 = OpTypeStruct %float %_ptr_Uniform__struct_9
7031 %_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9
7032 %1278 = OpVariable %_ptr_Uniform__struct_9 Uniform
7035 CompileSuccessfully(spirv);
7036 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
7037 EXPECT_THAT(getDiagnosticString(),
7038 HasSubstr(make_message("Operand '3[%_ptr_Uniform__struct_2]' "
7039 "requires a previous definition")));
7042 TEST_P(ValidateIdWithMessage, NVBindlessSamplerInStruct) {
7043 std::string spirv = R"(
7044 OpCapability Shader
7045 OpCapability BindlessTextureNV
7046 OpExtension "SPV_NV_bindless_texture"
7047 OpMemoryModel Logical GLSL450
7048 OpSamplerImageAddressingModeNV 64
7049 OpEntryPoint Fragment %main "main"
7050 OpExecutionMode %main OriginUpperLeft
7051 %void = OpTypeVoid
7052 %3 = OpTypeFunction %void
7053 %float = OpTypeFloat 32
7054 %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
7055 %8 = OpTypeSampledImage %7
7056 %9 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
7057 %10 = OpTypeSampler
7058 %UBO = OpTypeStruct %8 %9 %10
7059 %_ptr_Uniform_UBO = OpTypePointer Uniform %UBO
7060 %_ = OpVariable %_ptr_Uniform_UBO Uniform
7061 %main = OpFunction %void None %3
7062 %5 = OpLabel
7063 OpReturn
7064 OpFunctionEnd
7067 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
7068 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
7071 TEST_P(ValidateIdWithMessage,
7072 OpExtInstWithForwardRefsKHRDisallowedNoForwardRef) {
7073 std::string spirv = R"(
7074 OpCapability Shader
7075 OpExtension "SPV_KHR_non_semantic_info"
7076 OpExtension "SPV_KHR_relaxed_extended_instruction"
7077 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
7078 OpMemoryModel Logical GLSL450
7079 OpEntryPoint GLCompute %main "main"
7080 OpExecutionMode %main LocalSize 1 1 1
7081 %void = OpTypeVoid
7082 %main_type = OpTypeFunction %void
7083 %4 = OpExtInstWithForwardRefsKHR %void %1 DebugInfoNone
7084 %main = OpFunction %void None %main_type
7085 %5 = OpLabel
7086 OpReturn
7087 OpFunctionEnd
7090 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_6);
7091 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6));
7092 EXPECT_THAT(
7093 getDiagnosticString(),
7094 HasSubstr(make_message("Opcode OpExtInstWithForwardRefsKHR must have at "
7095 "least one forward declared ID.")));
7098 TEST_P(ValidateIdWithMessage, OpExtInstNoForwardRef) {
7099 std::string spirv = R"(
7100 OpCapability Shader
7101 OpExtension "SPV_KHR_non_semantic_info"
7102 OpExtension "SPV_KHR_relaxed_extended_instruction"
7103 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
7104 OpMemoryModel Logical GLSL450
7105 OpEntryPoint GLCompute %main "main"
7106 OpExecutionMode %main LocalSize 1 1 1
7107 %void = OpTypeVoid
7108 %main_type = OpTypeFunction %void
7109 %4 = OpExtInst %void %1 DebugInfoNone
7110 %main = OpFunction %void None %main_type
7111 %5 = OpLabel
7112 OpReturn
7113 OpFunctionEnd
7116 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_6);
7117 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6));
7120 TEST_P(ValidateIdWithMessage,
7121 OpExtInstWithForwardRefsKHRAllowedForwardReferenceInNonSemantic) {
7122 std::string spirv = R"(
7123 OpCapability Shader
7124 OpExtension "SPV_KHR_non_semantic_info"
7125 OpExtension "SPV_KHR_relaxed_extended_instruction"
7126 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
7127 OpMemoryModel Logical GLSL450
7128 OpEntryPoint GLCompute %2 "main"
7129 OpExecutionMode %2 LocalSize 1 1 1
7130 %3 = OpString "sample"
7131 %void = OpTypeVoid
7132 %uint = OpTypeInt 32 0
7133 %uint_0 = OpConstant %uint 0
7134 %7 = OpTypeFunction %void
7135 %8 = OpExtInst %void %1 DebugSource %3 %3
7136 %9 = OpExtInst %void %1 DebugCompilationUnit %uint_0 %uint_0 %8 %uint_0
7137 %10 = OpExtInstWithForwardRefsKHR %void %1 DebugTypeFunction %uint_0 %11
7138 %12 = OpExtInstWithForwardRefsKHR %void %1 DebugFunction %3 %10 %8 %uint_0 %uint_0 %11 %3 %uint_0 %uint_0
7139 %11 = OpExtInst %void %1 DebugTypeComposite %3 %uint_0 %8 %uint_0 %uint_0 %9 %3 %uint_0 %uint_0 %12
7140 %2 = OpFunction %void None %7
7141 %13 = OpLabel
7142 OpReturn
7143 OpFunctionEnd
7146 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_6);
7147 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6));
7150 TEST_P(ValidateIdWithMessage, OpExtInstNoForwardDeclAllowed) {
7151 std::string spirv = R"(
7152 OpCapability Shader
7153 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
7154 OpMemoryModel Logical GLSL450
7155 OpEntryPoint GLCompute %2 "main"
7156 OpExecutionMode %2 LocalSize 1 1 1
7157 %3 = OpString "sample"
7158 %void = OpTypeVoid
7159 %uint = OpTypeInt 32 0
7160 %uint_0 = OpConstant %uint 0
7161 %7 = OpTypeFunction %void
7162 %8 = OpExtInst %void %1 DebugSource %3 %3
7163 %9 = OpExtInst %void %1 DebugCompilationUnit %uint_0 %uint_0 %8 %uint_0
7164 %10 = OpExtInst %void %1 DebugTypeFunction %uint_0 %11
7165 %12 = OpExtInst %void %1 DebugFunction %3 %10 %8 %uint_0 %uint_0 %11 %3 %uint_0 %uint_0
7166 %11 = OpExtInst %void %1 DebugTypeComposite %3 %uint_0 %8 %uint_0 %uint_0 %9 %3 %uint_0 %uint_0 %12
7167 %2 = OpFunction %void None %7
7168 %13 = OpLabel
7169 OpReturn
7170 OpFunctionEnd
7173 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_6);
7174 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6));
7175 EXPECT_THAT(getDiagnosticString(),
7176 HasSubstr(make_message("ID '11[%11]' has not been defined")));
7179 INSTANTIATE_TEST_SUITE_P(, ValidateIdWithMessage, ::testing::Bool());
7181 } // namespace
7182 } // namespace val
7183 } // namespace spvtools