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