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