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