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