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