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