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