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