• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2017 Google 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 
18 #include "gmock/gmock.h"
19 #include "test/unit_spirv.h"
20 #include "test/val/val_fixtures.h"
21 
22 namespace spvtools {
23 namespace val {
24 namespace {
25 
26 using ::testing::HasSubstr;
27 using ::testing::Not;
28 
29 using ValidateComposites = spvtest::ValidateBase<bool>;
30 
GenerateShaderCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & execution_model="Fragment")31 std::string GenerateShaderCode(
32     const std::string& body,
33     const std::string& capabilities_and_extensions = "",
34     const std::string& execution_model = "Fragment") {
35   std::ostringstream ss;
36   ss << R"(
37 OpCapability Shader
38 OpCapability Float64
39 )";
40 
41   ss << capabilities_and_extensions;
42   ss << "OpMemoryModel Logical GLSL450\n";
43   ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
44   if (execution_model == "Fragment") {
45     ss << "OpExecutionMode %main OriginUpperLeft\n";
46   }
47 
48   ss << R"(
49 %void = OpTypeVoid
50 %func = OpTypeFunction %void
51 %bool = OpTypeBool
52 %f32 = OpTypeFloat 32
53 %f64 = OpTypeFloat 64
54 %u32 = OpTypeInt 32 0
55 %s32 = OpTypeInt 32 1
56 %f32vec2 = OpTypeVector %f32 2
57 %f32vec3 = OpTypeVector %f32 3
58 %f32vec4 = OpTypeVector %f32 4
59 %f64vec2 = OpTypeVector %f64 2
60 %u32vec2 = OpTypeVector %u32 2
61 %u32vec4 = OpTypeVector %u32 4
62 %f64mat22 = OpTypeMatrix %f64vec2 2
63 %f32mat22 = OpTypeMatrix %f32vec2 2
64 %f32mat23 = OpTypeMatrix %f32vec2 3
65 %f32mat32 = OpTypeMatrix %f32vec3 2
66 
67 %f32_0 = OpConstant %f32 0
68 %f32_1 = OpConstant %f32 1
69 %f32_2 = OpConstant %f32 2
70 %f32_3 = OpConstant %f32 3
71 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
72 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
73 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
74 
75 %u32_0 = OpConstant %u32 0
76 %u32_1 = OpConstant %u32 1
77 %u32_2 = OpConstant %u32 2
78 %u32_3 = OpConstant %u32 3
79 
80 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
81 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
82 
83 %f32mat22_1212 = OpConstantComposite %f32mat22 %f32vec2_12 %f32vec2_12
84 %f32mat23_121212 = OpConstantComposite %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12
85 
86 %f32vec2arr3 = OpTypeArray %f32vec2 %u32_3
87 %f32vec2rarr = OpTypeRuntimeArray %f32vec2
88 
89 %f32u32struct = OpTypeStruct %f32 %u32
90 %big_struct = OpTypeStruct %f32 %f32vec4 %f32mat23 %f32vec2arr3 %f32vec2rarr %f32u32struct
91 
92 %ptr_big_struct = OpTypePointer Uniform %big_struct
93 %var_big_struct = OpVariable %ptr_big_struct Uniform
94 
95 %main = OpFunction %void None %func
96 %main_entry = OpLabel
97 )";
98 
99   ss << body;
100 
101   ss << R"(
102 OpReturn
103 OpFunctionEnd)";
104 
105   return ss.str();
106 }
107 
108 // Returns header for legacy tests taken from val_id_test.cpp.
GetHeaderForTestsFromValId()109 std::string GetHeaderForTestsFromValId() {
110   return R"(
111 OpCapability Shader
112 OpCapability Linkage
113 OpCapability Addresses
114 OpCapability Pipes
115 OpCapability LiteralSampler
116 OpCapability DeviceEnqueue
117 OpCapability Vector16
118 OpCapability Int8
119 OpCapability Int16
120 OpCapability Int64
121 OpCapability Float64
122 OpMemoryModel Logical GLSL450
123 %void = OpTypeVoid
124 %void_f  = OpTypeFunction %void
125 %int = OpTypeInt 32 0
126 %float = OpTypeFloat 32
127 %v3float = OpTypeVector %float 3
128 %mat4x3 = OpTypeMatrix %v3float 4
129 %_ptr_Private_mat4x3 = OpTypePointer Private %mat4x3
130 %_ptr_Private_float = OpTypePointer Private %float
131 %my_matrix = OpVariable %_ptr_Private_mat4x3 Private
132 %my_float_var = OpVariable %_ptr_Private_float Private
133 %_ptr_Function_float = OpTypePointer Function %float
134 %int_0 = OpConstant %int 0
135 %int_1 = OpConstant %int 1
136 %int_2 = OpConstant %int 2
137 %int_3 = OpConstant %int 3
138 %int_5 = OpConstant %int 5
139 
140 ; Making the following nested structures.
141 ;
142 ; struct S {
143 ;   bool b;
144 ;   vec4 v[5];
145 ;   int i;
146 ;   mat4x3 m[5];
147 ; }
148 ; uniform blockName {
149 ;   S s;
150 ;   bool cond;
151 ;   RunTimeArray arr;
152 ; }
153 
154 %f32arr = OpTypeRuntimeArray %float
155 %v4float = OpTypeVector %float 4
156 %array5_mat4x3 = OpTypeArray %mat4x3 %int_5
157 %array5_vec4 = OpTypeArray %v4float %int_5
158 %_ptr_Uniform_float = OpTypePointer Uniform %float
159 %_ptr_Function_vec4 = OpTypePointer Function %v4float
160 %_ptr_Uniform_vec4 = OpTypePointer Uniform %v4float
161 %struct_s = OpTypeStruct %int %array5_vec4 %int %array5_mat4x3
162 %struct_blockName = OpTypeStruct %struct_s %int %f32arr
163 %_ptr_Uniform_blockName = OpTypePointer Uniform %struct_blockName
164 %_ptr_Uniform_struct_s = OpTypePointer Uniform %struct_s
165 %_ptr_Uniform_array5_mat4x3 = OpTypePointer Uniform %array5_mat4x3
166 %_ptr_Uniform_mat4x3 = OpTypePointer Uniform %mat4x3
167 %_ptr_Uniform_v3float = OpTypePointer Uniform %v3float
168 %blockName_var = OpVariable %_ptr_Uniform_blockName Uniform
169 %spec_int = OpSpecConstant %int 2
170 %func = OpFunction %void None %void_f
171 %my_label = OpLabel
172 )";
173 }
174 
TEST_F(ValidateComposites,VectorExtractDynamicSuccess)175 TEST_F(ValidateComposites, VectorExtractDynamicSuccess) {
176   const std::string body = R"(
177 %val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %u32_0
178 )";
179 
180   CompileSuccessfully(GenerateShaderCode(body).c_str());
181   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
182 }
183 
TEST_F(ValidateComposites,VectorExtractDynamicWrongResultType)184 TEST_F(ValidateComposites, VectorExtractDynamicWrongResultType) {
185   const std::string body = R"(
186 %val1 = OpVectorExtractDynamic %f32vec4 %f32vec4_0123 %u32_0
187 )";
188 
189   CompileSuccessfully(GenerateShaderCode(body).c_str());
190   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
191   EXPECT_THAT(getDiagnosticString(),
192               HasSubstr("Expected Result Type to be a scalar type"));
193 }
194 
TEST_F(ValidateComposites,VectorExtractDynamicNotVector)195 TEST_F(ValidateComposites, VectorExtractDynamicNotVector) {
196   const std::string body = R"(
197 %val1 = OpVectorExtractDynamic %f32 %f32mat22_1212 %u32_0
198 )";
199 
200   CompileSuccessfully(GenerateShaderCode(body).c_str());
201   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
202   EXPECT_THAT(getDiagnosticString(),
203               HasSubstr("Expected Vector type to be OpTypeVector"));
204 }
205 
TEST_F(ValidateComposites,VectorExtractDynamicWrongVectorComponent)206 TEST_F(ValidateComposites, VectorExtractDynamicWrongVectorComponent) {
207   const std::string body = R"(
208 %val1 = OpVectorExtractDynamic %f32 %u32vec4_0123 %u32_0
209 )";
210 
211   CompileSuccessfully(GenerateShaderCode(body).c_str());
212   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
213   EXPECT_THAT(
214       getDiagnosticString(),
215       HasSubstr("Expected Vector component type to be equal to Result Type"));
216 }
217 
TEST_F(ValidateComposites,VectorExtractDynamicWrongIndexType)218 TEST_F(ValidateComposites, VectorExtractDynamicWrongIndexType) {
219   const std::string body = R"(
220 %val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %f32_0
221 )";
222 
223   CompileSuccessfully(GenerateShaderCode(body).c_str());
224   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
225   EXPECT_THAT(getDiagnosticString(),
226               HasSubstr("Expected Index to be int scalar"));
227 }
228 
TEST_F(ValidateComposites,VectorInsertDynamicSuccess)229 TEST_F(ValidateComposites, VectorInsertDynamicSuccess) {
230   const std::string body = R"(
231 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %u32_0
232 )";
233 
234   CompileSuccessfully(GenerateShaderCode(body).c_str());
235   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
236 }
237 
TEST_F(ValidateComposites,VectorInsertDynamicWrongResultType)238 TEST_F(ValidateComposites, VectorInsertDynamicWrongResultType) {
239   const std::string body = R"(
240 %val1 = OpVectorInsertDynamic %f32 %f32vec4_0123 %f32_1 %u32_0
241 )";
242 
243   CompileSuccessfully(GenerateShaderCode(body).c_str());
244   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
245   EXPECT_THAT(getDiagnosticString(),
246               HasSubstr("Expected Result Type to be OpTypeVector"));
247 }
248 
TEST_F(ValidateComposites,VectorInsertDynamicNotVector)249 TEST_F(ValidateComposites, VectorInsertDynamicNotVector) {
250   const std::string body = R"(
251 %val1 = OpVectorInsertDynamic %f32vec4 %f32mat22_1212 %f32_1 %u32_0
252 )";
253 
254   CompileSuccessfully(GenerateShaderCode(body).c_str());
255   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
256   EXPECT_THAT(getDiagnosticString(),
257               HasSubstr("Expected Vector type to be equal to Result Type"));
258 }
259 
TEST_F(ValidateComposites,VectorInsertDynamicWrongComponentType)260 TEST_F(ValidateComposites, VectorInsertDynamicWrongComponentType) {
261   const std::string body = R"(
262 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %u32_1 %u32_0
263 )";
264 
265   CompileSuccessfully(GenerateShaderCode(body).c_str());
266   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
267   EXPECT_THAT(getDiagnosticString(),
268               HasSubstr("Expected Component type to be equal to Result Type "
269                         "component type"));
270 }
271 
TEST_F(ValidateComposites,VectorInsertDynamicWrongIndexType)272 TEST_F(ValidateComposites, VectorInsertDynamicWrongIndexType) {
273   const std::string body = R"(
274 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %f32_0
275 )";
276 
277   CompileSuccessfully(GenerateShaderCode(body).c_str());
278   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
279   EXPECT_THAT(getDiagnosticString(),
280               HasSubstr("Expected Index to be int scalar"));
281 }
282 
TEST_F(ValidateComposites,CompositeConstructNotComposite)283 TEST_F(ValidateComposites, CompositeConstructNotComposite) {
284   const std::string body = R"(
285 %val1 = OpCompositeConstruct %f32 %f32_1
286 )";
287 
288   CompileSuccessfully(GenerateShaderCode(body).c_str());
289   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
290   EXPECT_THAT(getDiagnosticString(),
291               HasSubstr("Expected Result Type to be a composite type"));
292 }
293 
TEST_F(ValidateComposites,CompositeConstructVectorSuccess)294 TEST_F(ValidateComposites, CompositeConstructVectorSuccess) {
295   const std::string body = R"(
296 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12
297 %val2 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0 %f32_0
298 %val3 = OpCompositeConstruct %f32vec4 %f32_0 %f32_0 %f32vec2_12
299 %val4 = OpCompositeConstruct %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
300 )";
301 
302   CompileSuccessfully(GenerateShaderCode(body).c_str());
303   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
304 }
305 
TEST_F(ValidateComposites,CompositeConstructVectorOnlyOneConstituent)306 TEST_F(ValidateComposites, CompositeConstructVectorOnlyOneConstituent) {
307   const std::string body = R"(
308 %val1 = OpCompositeConstruct %f32vec4 %f32vec4_0123
309 )";
310 
311   CompileSuccessfully(GenerateShaderCode(body).c_str());
312   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
313   EXPECT_THAT(getDiagnosticString(),
314               HasSubstr("Expected number of constituents to be at least 2"));
315 }
316 
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituent1)317 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent1) {
318   const std::string body = R"(
319 %val1 = OpCompositeConstruct %f32vec4 %f32 %f32vec2_12
320 )";
321 
322   CompileSuccessfully(GenerateShaderCode(body).c_str());
323   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
324   EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 5[%float] cannot be a "
325                                                "type"));
326 }
327 
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituent2)328 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent2) {
329   const std::string body = R"(
330 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32vec2_01
331 )";
332 
333   CompileSuccessfully(GenerateShaderCode(body).c_str());
334   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
335   EXPECT_THAT(
336       getDiagnosticString(),
337       HasSubstr("Expected Constituents to be scalars or vectors of the same "
338                 "type as Result Type components"));
339 }
340 
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituent3)341 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent3) {
342   const std::string body = R"(
343 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32_0 %f32_0
344 )";
345 
346   CompileSuccessfully(GenerateShaderCode(body).c_str());
347   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
348   EXPECT_THAT(
349       getDiagnosticString(),
350       HasSubstr("Expected Constituents to be scalars or vectors of the same "
351                 "type as Result Type components"));
352 }
353 
TEST_F(ValidateComposites,CompositeConstructVectorWrongComponentNumber1)354 TEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber1) {
355   const std::string body = R"(
356 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0
357 )";
358 
359   CompileSuccessfully(GenerateShaderCode(body).c_str());
360   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
361   EXPECT_THAT(
362       getDiagnosticString(),
363       HasSubstr("Expected total number of given components to be equal to the "
364                 "size of Result Type vector"));
365 }
366 
TEST_F(ValidateComposites,CompositeConstructVectorWrongComponentNumber2)367 TEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber2) {
368   const std::string body = R"(
369 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12 %f32_0
370 )";
371 
372   CompileSuccessfully(GenerateShaderCode(body).c_str());
373   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
374   EXPECT_THAT(
375       getDiagnosticString(),
376       HasSubstr("Expected total number of given components to be equal to the "
377                 "size of Result Type vector"));
378 }
379 
TEST_F(ValidateComposites,CompositeConstructMatrixSuccess)380 TEST_F(ValidateComposites, CompositeConstructMatrixSuccess) {
381   const std::string body = R"(
382 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12
383 %val2 = OpCompositeConstruct %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12
384 )";
385 
386   CompileSuccessfully(GenerateShaderCode(body).c_str());
387   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
388 }
389 
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituentNumber1)390 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber1) {
391   const std::string body = R"(
392 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12
393 )";
394 
395   CompileSuccessfully(GenerateShaderCode(body).c_str());
396   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
397   EXPECT_THAT(
398       getDiagnosticString(),
399       HasSubstr("Expected total number of Constituents to be equal to the "
400                 "number of columns of Result Type matrix"));
401 }
402 
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituentNumber2)403 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber2) {
404   const std::string body = R"(
405 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12 %f32vec2_12
406 )";
407 
408   CompileSuccessfully(GenerateShaderCode(body).c_str());
409   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
410   EXPECT_THAT(
411       getDiagnosticString(),
412       HasSubstr("Expected total number of Constituents to be equal to the "
413                 "number of columns of Result Type matrix"));
414 }
415 
TEST_F(ValidateComposites,CompositeConstructVectorWrongConsituent)416 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent) {
417   const std::string body = R"(
418 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %u32vec2_01
419 )";
420 
421   CompileSuccessfully(GenerateShaderCode(body).c_str());
422   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
423   EXPECT_THAT(
424       getDiagnosticString(),
425       HasSubstr("Expected Constituent type to be equal to the column type "
426                 "Result Type matrix"));
427 }
428 
TEST_F(ValidateComposites,CompositeConstructArraySuccess)429 TEST_F(ValidateComposites, CompositeConstructArraySuccess) {
430   const std::string body = R"(
431 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
432 )";
433 
434   CompileSuccessfully(GenerateShaderCode(body).c_str());
435   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
436 }
437 
TEST_F(ValidateComposites,CompositeConstructArrayWrongConsituentNumber1)438 TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber1) {
439   const std::string body = R"(
440 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12
441 )";
442 
443   CompileSuccessfully(GenerateShaderCode(body).c_str());
444   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
445   EXPECT_THAT(
446       getDiagnosticString(),
447       HasSubstr("Expected total number of Constituents to be equal to the "
448                 "number of elements of Result Type array"));
449 }
450 
TEST_F(ValidateComposites,CompositeConstructArrayWrongConsituentNumber2)451 TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber2) {
452   const std::string body = R"(
453 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 %f32vec2_12
454 )";
455 
456   CompileSuccessfully(GenerateShaderCode(body).c_str());
457   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
458   EXPECT_THAT(
459       getDiagnosticString(),
460       HasSubstr("Expected total number of Constituents to be equal to the "
461                 "number of elements of Result Type array"));
462 }
463 
TEST_F(ValidateComposites,CompositeConstructArrayWrongConsituent)464 TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituent) {
465   const std::string body = R"(
466 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %u32vec2_01 %f32vec2_12
467 )";
468 
469   CompileSuccessfully(GenerateShaderCode(body).c_str());
470   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
471   EXPECT_THAT(
472       getDiagnosticString(),
473       HasSubstr("Expected Constituent type to be equal to the column type "
474                 "Result Type array"));
475 }
476 
TEST_F(ValidateComposites,CompositeConstructStructSuccess)477 TEST_F(ValidateComposites, CompositeConstructStructSuccess) {
478   const std::string body = R"(
479 %val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1
480 )";
481 
482   CompileSuccessfully(GenerateShaderCode(body).c_str());
483   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
484 }
485 
TEST_F(ValidateComposites,CompositeConstructStructWrongConstituentNumber1)486 TEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber1) {
487   const std::string body = R"(
488 %val1 = OpCompositeConstruct %f32u32struct %f32_0
489 )";
490 
491   CompileSuccessfully(GenerateShaderCode(body).c_str());
492   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
493   EXPECT_THAT(
494       getDiagnosticString(),
495       HasSubstr("Expected total number of Constituents to be equal to the "
496                 "number of members of Result Type struct"));
497 }
498 
TEST_F(ValidateComposites,CompositeConstructStructWrongConstituentNumber2)499 TEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber2) {
500   const std::string body = R"(
501 %val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1 %u32_1
502 )";
503 
504   CompileSuccessfully(GenerateShaderCode(body).c_str());
505   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
506   EXPECT_THAT(
507       getDiagnosticString(),
508       HasSubstr("Expected total number of Constituents to be equal to the "
509                 "number of members of Result Type struct"));
510 }
511 
TEST_F(ValidateComposites,CompositeConstructStructWrongConstituent)512 TEST_F(ValidateComposites, CompositeConstructStructWrongConstituent) {
513   const std::string body = R"(
514 %val1 = OpCompositeConstruct %f32u32struct %f32_0 %f32_1
515 )";
516 
517   CompileSuccessfully(GenerateShaderCode(body).c_str());
518   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
519   EXPECT_THAT(getDiagnosticString(),
520               HasSubstr("Expected Constituent type to be equal to the "
521                         "corresponding member type of Result Type struct"));
522 }
523 
TEST_F(ValidateComposites,CopyObjectSuccess)524 TEST_F(ValidateComposites, CopyObjectSuccess) {
525   const std::string body = R"(
526 %val1 = OpCopyObject %f32 %f32_0
527 %val2 = OpCopyObject %f32vec4 %f32vec4_0123
528 )";
529 
530   CompileSuccessfully(GenerateShaderCode(body).c_str());
531   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
532 }
533 
TEST_F(ValidateComposites,CopyObjectResultTypeNotType)534 TEST_F(ValidateComposites, CopyObjectResultTypeNotType) {
535   const std::string body = R"(
536 %val1 = OpCopyObject %f32_0 %f32_0
537 )";
538 
539   CompileSuccessfully(GenerateShaderCode(body).c_str());
540   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
541   EXPECT_THAT(getDiagnosticString(),
542               HasSubstr("ID 19[%float_0] is not a type id"));
543 }
544 
TEST_F(ValidateComposites,CopyObjectWrongOperandType)545 TEST_F(ValidateComposites, CopyObjectWrongOperandType) {
546   const std::string body = R"(
547 %val1 = OpCopyObject %f32 %u32_0
548 )";
549 
550   CompileSuccessfully(GenerateShaderCode(body).c_str());
551   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
552   EXPECT_THAT(
553       getDiagnosticString(),
554       HasSubstr("Expected Result Type and Operand type to be the same"));
555 }
556 
TEST_F(ValidateComposites,TransposeSuccess)557 TEST_F(ValidateComposites, TransposeSuccess) {
558   const std::string body = R"(
559 %val1 = OpTranspose %f32mat32 %f32mat23_121212
560 %val2 = OpTranspose %f32mat22 %f32mat22_1212
561 )";
562 
563   CompileSuccessfully(GenerateShaderCode(body).c_str());
564   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
565 }
566 
TEST_F(ValidateComposites,TransposeResultTypeNotMatrix)567 TEST_F(ValidateComposites, TransposeResultTypeNotMatrix) {
568   const std::string body = R"(
569 %val1 = OpTranspose %f32vec4 %f32mat22_1212
570 )";
571 
572   CompileSuccessfully(GenerateShaderCode(body).c_str());
573   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
574   EXPECT_THAT(getDiagnosticString(),
575               HasSubstr("Expected Result Type to be a matrix type"));
576 }
577 
TEST_F(ValidateComposites,TransposeDifferentComponentTypes)578 TEST_F(ValidateComposites, TransposeDifferentComponentTypes) {
579   const std::string body = R"(
580 %val1 = OpTranspose %f64mat22 %f32mat22_1212
581 )";
582 
583   CompileSuccessfully(GenerateShaderCode(body).c_str());
584   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
585   EXPECT_THAT(
586       getDiagnosticString(),
587       HasSubstr("Expected component types of Matrix and Result Type to be "
588                 "identical"));
589 }
590 
TEST_F(ValidateComposites,TransposeIncompatibleDimensions1)591 TEST_F(ValidateComposites, TransposeIncompatibleDimensions1) {
592   const std::string body = R"(
593 %val1 = OpTranspose %f32mat23 %f32mat22_1212
594 )";
595 
596   CompileSuccessfully(GenerateShaderCode(body).c_str());
597   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
598   EXPECT_THAT(getDiagnosticString(),
599               HasSubstr("Expected number of columns and the column size "
600                         "of Matrix to be the reverse of those of Result Type"));
601 }
602 
TEST_F(ValidateComposites,TransposeIncompatibleDimensions2)603 TEST_F(ValidateComposites, TransposeIncompatibleDimensions2) {
604   const std::string body = R"(
605 %val1 = OpTranspose %f32mat32 %f32mat22_1212
606 )";
607 
608   CompileSuccessfully(GenerateShaderCode(body).c_str());
609   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
610   EXPECT_THAT(getDiagnosticString(),
611               HasSubstr("Expected number of columns and the column size "
612                         "of Matrix to be the reverse of those of Result Type"));
613 }
614 
TEST_F(ValidateComposites,TransposeIncompatibleDimensions3)615 TEST_F(ValidateComposites, TransposeIncompatibleDimensions3) {
616   const std::string body = R"(
617 %val1 = OpTranspose %f32mat23 %f32mat23_121212
618 )";
619 
620   CompileSuccessfully(GenerateShaderCode(body).c_str());
621   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
622   EXPECT_THAT(getDiagnosticString(),
623               HasSubstr("Expected number of columns and the column size "
624                         "of Matrix to be the reverse of those of Result Type"));
625 }
626 
TEST_F(ValidateComposites,CompositeExtractSuccess)627 TEST_F(ValidateComposites, CompositeExtractSuccess) {
628   const std::string body = R"(
629 %val1 = OpCompositeExtract %f32 %f32vec4_0123 1
630 %val2 = OpCompositeExtract %u32 %u32vec4_0123 0
631 %val3 = OpCompositeExtract %f32 %f32mat22_1212 0 1
632 %val4 = OpCompositeExtract %f32vec2 %f32mat22_1212 0
633 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
634 %val5 = OpCompositeExtract %f32vec2 %array 2
635 %val6 = OpCompositeExtract %f32 %array 2 1
636 %struct = OpLoad %big_struct %var_big_struct
637 %val7 = OpCompositeExtract %f32 %struct 0
638 %val8 = OpCompositeExtract %f32vec4 %struct 1
639 %val9 = OpCompositeExtract %f32 %struct 1 2
640 %val10 = OpCompositeExtract %f32mat23 %struct 2
641 %val11 = OpCompositeExtract %f32vec2 %struct 2 2
642 %val12 = OpCompositeExtract %f32 %struct 2 2 1
643 %val13 = OpCompositeExtract %f32vec2 %struct 3 2
644 %val14 = OpCompositeExtract %f32 %struct 3 2 1
645 %val15 = OpCompositeExtract %f32vec2 %struct 4 100
646 %val16 = OpCompositeExtract %f32 %struct 4 1000 1
647 %val17 = OpCompositeExtract %f32 %struct 5 0
648 %val18 = OpCompositeExtract %u32 %struct 5 1
649 %val19 = OpCompositeExtract %big_struct %struct
650 )";
651 
652   CompileSuccessfully(GenerateShaderCode(body));
653   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
654 }
655 
TEST_F(ValidateComposites,CompositeExtractNotObject)656 TEST_F(ValidateComposites, CompositeExtractNotObject) {
657   const std::string body = R"(
658 %val1 = OpCompositeExtract %f32 %f32vec4 1
659 )";
660 
661   CompileSuccessfully(GenerateShaderCode(body));
662   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
663   EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 11[%v4float] cannot "
664                                                "be a type"));
665 }
666 
TEST_F(ValidateComposites,CompositeExtractNotComposite)667 TEST_F(ValidateComposites, CompositeExtractNotComposite) {
668   const std::string body = R"(
669 %val1 = OpCompositeExtract %f32 %f32_1 0
670 )";
671 
672   CompileSuccessfully(GenerateShaderCode(body));
673   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
674   EXPECT_THAT(getDiagnosticString(),
675               HasSubstr("Reached non-composite type while indexes still remain "
676                         "to be traversed."));
677 }
678 
TEST_F(ValidateComposites,CompositeExtractVectorOutOfBounds)679 TEST_F(ValidateComposites, CompositeExtractVectorOutOfBounds) {
680   const std::string body = R"(
681 %val1 = OpCompositeExtract %f32 %f32vec4_0123 4
682 )";
683 
684   CompileSuccessfully(GenerateShaderCode(body));
685   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
686   EXPECT_THAT(getDiagnosticString(),
687               HasSubstr("Vector access is out of bounds, "
688                         "vector size is 4, but access index is 4"));
689 }
690 
TEST_F(ValidateComposites,CompositeExtractMatrixOutOfCols)691 TEST_F(ValidateComposites, CompositeExtractMatrixOutOfCols) {
692   const std::string body = R"(
693 %val1 = OpCompositeExtract %f32 %f32mat23_121212 3 1
694 )";
695 
696   CompileSuccessfully(GenerateShaderCode(body));
697   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
698   EXPECT_THAT(getDiagnosticString(),
699               HasSubstr("Matrix access is out of bounds, "
700                         "matrix has 3 columns, but access index is 3"));
701 }
702 
TEST_F(ValidateComposites,CompositeExtractMatrixOutOfRows)703 TEST_F(ValidateComposites, CompositeExtractMatrixOutOfRows) {
704   const std::string body = R"(
705 %val1 = OpCompositeExtract %f32 %f32mat23_121212 2 5
706 )";
707 
708   CompileSuccessfully(GenerateShaderCode(body));
709   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
710   EXPECT_THAT(getDiagnosticString(),
711               HasSubstr("Vector access is out of bounds, "
712                         "vector size is 2, but access index is 5"));
713 }
714 
TEST_F(ValidateComposites,CompositeExtractArrayOutOfBounds)715 TEST_F(ValidateComposites, CompositeExtractArrayOutOfBounds) {
716   const std::string body = R"(
717 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
718 %val1 = OpCompositeExtract %f32vec2 %array 3
719 )";
720 
721   CompileSuccessfully(GenerateShaderCode(body));
722   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
723   EXPECT_THAT(getDiagnosticString(),
724               HasSubstr("Array access is out of bounds, "
725                         "array size is 3, but access index is 3"));
726 }
727 
TEST_F(ValidateComposites,CompositeExtractStructOutOfBounds)728 TEST_F(ValidateComposites, CompositeExtractStructOutOfBounds) {
729   const std::string body = R"(
730 %struct = OpLoad %big_struct %var_big_struct
731 %val1 = OpCompositeExtract %f32 %struct 6
732 )";
733 
734   CompileSuccessfully(GenerateShaderCode(body));
735   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
736   EXPECT_THAT(getDiagnosticString(),
737               HasSubstr("Index is out of bounds, can not find index 6 in the "
738                         "structure <id> '37'. This structure has 6 members. "
739                         "Largest valid index is 5."));
740 }
741 
TEST_F(ValidateComposites,CompositeExtractNestedVectorOutOfBounds)742 TEST_F(ValidateComposites, CompositeExtractNestedVectorOutOfBounds) {
743   const std::string body = R"(
744 %struct = OpLoad %big_struct %var_big_struct
745 %val1 = OpCompositeExtract %f32 %struct 3 1 5
746 )";
747 
748   CompileSuccessfully(GenerateShaderCode(body));
749   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
750   EXPECT_THAT(getDiagnosticString(),
751               HasSubstr("Vector access is out of bounds, "
752                         "vector size is 2, but access index is 5"));
753 }
754 
TEST_F(ValidateComposites,CompositeExtractTooManyIndices)755 TEST_F(ValidateComposites, CompositeExtractTooManyIndices) {
756   const std::string body = R"(
757 %struct = OpLoad %big_struct %var_big_struct
758 %val1 = OpCompositeExtract %f32 %struct 3 1 1 2
759 )";
760 
761   CompileSuccessfully(GenerateShaderCode(body));
762   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
763   EXPECT_THAT(getDiagnosticString(),
764               HasSubstr("Reached non-composite type while "
765                         "indexes still remain to be traversed."));
766 }
767 
TEST_F(ValidateComposites,CompositeExtractWrongType1)768 TEST_F(ValidateComposites, CompositeExtractWrongType1) {
769   const std::string body = R"(
770 %struct = OpLoad %big_struct %var_big_struct
771 %val1 = OpCompositeExtract %f32vec2 %struct 3 1 1
772 )";
773 
774   CompileSuccessfully(GenerateShaderCode(body));
775   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
776   EXPECT_THAT(
777       getDiagnosticString(),
778       HasSubstr(
779           "Result type (OpTypeVector) does not match the type that results "
780           "from indexing into the composite (OpTypeFloat)."));
781 }
782 
TEST_F(ValidateComposites,CompositeExtractWrongType2)783 TEST_F(ValidateComposites, CompositeExtractWrongType2) {
784   const std::string body = R"(
785 %struct = OpLoad %big_struct %var_big_struct
786 %val1 = OpCompositeExtract %f32 %struct 3 1
787 )";
788 
789   CompileSuccessfully(GenerateShaderCode(body));
790   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
791   EXPECT_THAT(getDiagnosticString(),
792               HasSubstr("Result type (OpTypeFloat) does not match the type "
793                         "that results from indexing into the composite "
794                         "(OpTypeVector)."));
795 }
796 
TEST_F(ValidateComposites,CompositeExtractWrongType3)797 TEST_F(ValidateComposites, CompositeExtractWrongType3) {
798   const std::string body = R"(
799 %struct = OpLoad %big_struct %var_big_struct
800 %val1 = OpCompositeExtract %f32 %struct 2 1
801 )";
802 
803   CompileSuccessfully(GenerateShaderCode(body));
804   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
805   EXPECT_THAT(getDiagnosticString(),
806               HasSubstr("Result type (OpTypeFloat) does not match the type "
807                         "that results from indexing into the composite "
808                         "(OpTypeVector)."));
809 }
810 
TEST_F(ValidateComposites,CompositeExtractWrongType4)811 TEST_F(ValidateComposites, CompositeExtractWrongType4) {
812   const std::string body = R"(
813 %struct = OpLoad %big_struct %var_big_struct
814 %val1 = OpCompositeExtract %f32 %struct 4 1
815 )";
816 
817   CompileSuccessfully(GenerateShaderCode(body));
818   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
819   EXPECT_THAT(getDiagnosticString(),
820               HasSubstr("Result type (OpTypeFloat) does not match the type "
821                         "that results from indexing into the composite "
822                         "(OpTypeVector)."));
823 }
824 
TEST_F(ValidateComposites,CompositeExtractWrongType5)825 TEST_F(ValidateComposites, CompositeExtractWrongType5) {
826   const std::string body = R"(
827 %struct = OpLoad %big_struct %var_big_struct
828 %val1 = OpCompositeExtract %f32 %struct 5 1
829 )";
830 
831   CompileSuccessfully(GenerateShaderCode(body));
832   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
833   EXPECT_THAT(
834       getDiagnosticString(),
835       HasSubstr(
836           "Result type (OpTypeFloat) does not match the "
837           "type that results from indexing into the composite (OpTypeInt)."));
838 }
839 
TEST_F(ValidateComposites,CompositeInsertSuccess)840 TEST_F(ValidateComposites, CompositeInsertSuccess) {
841   const std::string body = R"(
842 %val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 0
843 %val2 = OpCompositeInsert %u32vec4 %u32_1 %u32vec4_0123 0
844 %val3 = OpCompositeInsert %f32mat22 %f32_2 %f32mat22_1212 0 1
845 %val4 = OpCompositeInsert %f32mat22 %f32vec2_01 %f32mat22_1212 0
846 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
847 %val5 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 2
848 %val6 = OpCompositeInsert %f32vec2arr3 %f32_3 %array 2 1
849 %struct = OpLoad %big_struct %var_big_struct
850 %val7 = OpCompositeInsert %big_struct %f32_3 %struct 0
851 %val8 = OpCompositeInsert %big_struct %f32vec4_0123 %struct 1
852 %val9 = OpCompositeInsert %big_struct %f32_3 %struct 1 2
853 %val10 = OpCompositeInsert %big_struct %f32mat23_121212 %struct 2
854 %val11 = OpCompositeInsert %big_struct %f32vec2_01 %struct 2 2
855 %val12 = OpCompositeInsert %big_struct %f32_3 %struct 2 2 1
856 %val13 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 2
857 %val14 = OpCompositeInsert %big_struct %f32_3 %struct 3 2 1
858 %val15 = OpCompositeInsert %big_struct %f32vec2_01 %struct 4 100
859 %val16 = OpCompositeInsert %big_struct %f32_3 %struct 4 1000 1
860 %val17 = OpCompositeInsert %big_struct %f32_3 %struct 5 0
861 %val18 = OpCompositeInsert %big_struct %u32_3 %struct 5 1
862 %val19 = OpCompositeInsert %big_struct %struct %struct
863 )";
864 
865   CompileSuccessfully(GenerateShaderCode(body));
866   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
867 }
868 
TEST_F(ValidateComposites,CompositeInsertResultTypeDifferentFromComposite)869 TEST_F(ValidateComposites, CompositeInsertResultTypeDifferentFromComposite) {
870   const std::string body = R"(
871 %val1 = OpCompositeInsert %f32 %f32_1 %f32vec4_0123 0
872 )";
873 
874   CompileSuccessfully(GenerateShaderCode(body));
875   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
876   EXPECT_THAT(getDiagnosticString(),
877               HasSubstr("The Result Type must be the same as Composite type in "
878                         "OpCompositeInsert yielding Result Id 5."));
879 }
880 
TEST_F(ValidateComposites,CompositeInsertNotComposite)881 TEST_F(ValidateComposites, CompositeInsertNotComposite) {
882   const std::string body = R"(
883 %val1 = OpCompositeInsert %f32 %f32_1 %f32_0 0
884 )";
885 
886   CompileSuccessfully(GenerateShaderCode(body));
887   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
888   EXPECT_THAT(getDiagnosticString(),
889               HasSubstr("Reached non-composite type while indexes still remain "
890                         "to be traversed."));
891 }
892 
TEST_F(ValidateComposites,CompositeInsertVectorOutOfBounds)893 TEST_F(ValidateComposites, CompositeInsertVectorOutOfBounds) {
894   const std::string body = R"(
895 %val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 4
896 )";
897 
898   CompileSuccessfully(GenerateShaderCode(body));
899   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
900   EXPECT_THAT(getDiagnosticString(),
901               HasSubstr("Vector access is out of bounds, "
902                         "vector size is 4, but access index is 4"));
903 }
904 
TEST_F(ValidateComposites,CompositeInsertMatrixOutOfCols)905 TEST_F(ValidateComposites, CompositeInsertMatrixOutOfCols) {
906   const std::string body = R"(
907 %val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 3 1
908 )";
909 
910   CompileSuccessfully(GenerateShaderCode(body));
911   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
912   EXPECT_THAT(getDiagnosticString(),
913               HasSubstr("Matrix access is out of bounds, "
914                         "matrix has 3 columns, but access index is 3"));
915 }
916 
TEST_F(ValidateComposites,CompositeInsertMatrixOutOfRows)917 TEST_F(ValidateComposites, CompositeInsertMatrixOutOfRows) {
918   const std::string body = R"(
919 %val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 2 5
920 )";
921 
922   CompileSuccessfully(GenerateShaderCode(body));
923   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
924   EXPECT_THAT(getDiagnosticString(),
925               HasSubstr("Vector access is out of bounds, "
926                         "vector size is 2, but access index is 5"));
927 }
928 
TEST_F(ValidateComposites,CompositeInsertArrayOutOfBounds)929 TEST_F(ValidateComposites, CompositeInsertArrayOutOfBounds) {
930   const std::string body = R"(
931 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
932 %val1 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 3
933 )";
934 
935   CompileSuccessfully(GenerateShaderCode(body));
936   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
937   EXPECT_THAT(getDiagnosticString(),
938               HasSubstr("Array access is out of bounds, array "
939                         "size is 3, but access index is 3"));
940 }
941 
TEST_F(ValidateComposites,CompositeInsertStructOutOfBounds)942 TEST_F(ValidateComposites, CompositeInsertStructOutOfBounds) {
943   const std::string body = R"(
944 %struct = OpLoad %big_struct %var_big_struct
945 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 6
946 )";
947 
948   CompileSuccessfully(GenerateShaderCode(body));
949   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
950   EXPECT_THAT(getDiagnosticString(),
951               HasSubstr("Index is out of bounds, can not find index 6 in the "
952                         "structure <id> '37'. This structure has 6 members. "
953                         "Largest valid index is 5."));
954 }
955 
TEST_F(ValidateComposites,CompositeInsertNestedVectorOutOfBounds)956 TEST_F(ValidateComposites, CompositeInsertNestedVectorOutOfBounds) {
957   const std::string body = R"(
958 %struct = OpLoad %big_struct %var_big_struct
959 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 5
960 )";
961 
962   CompileSuccessfully(GenerateShaderCode(body));
963   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
964   EXPECT_THAT(getDiagnosticString(),
965               HasSubstr("Vector access is out of bounds, "
966                         "vector size is 2, but access index is 5"));
967 }
968 
TEST_F(ValidateComposites,CompositeInsertTooManyIndices)969 TEST_F(ValidateComposites, CompositeInsertTooManyIndices) {
970   const std::string body = R"(
971 %struct = OpLoad %big_struct %var_big_struct
972 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 1 2
973 )";
974 
975   CompileSuccessfully(GenerateShaderCode(body));
976   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
977   EXPECT_THAT(getDiagnosticString(),
978               HasSubstr("Reached non-composite type while indexes still remain "
979                         "to be traversed."));
980 }
981 
TEST_F(ValidateComposites,CompositeInsertWrongType1)982 TEST_F(ValidateComposites, CompositeInsertWrongType1) {
983   const std::string body = R"(
984 %struct = OpLoad %big_struct %var_big_struct
985 %val1 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 1 1
986 )";
987 
988   CompileSuccessfully(GenerateShaderCode(body));
989   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
990   EXPECT_THAT(getDiagnosticString(),
991               HasSubstr("The Object type (OpTypeVector) does not match the "
992                         "type that results from indexing into the Composite "
993                         "(OpTypeFloat)."));
994 }
995 
TEST_F(ValidateComposites,CompositeInsertWrongType2)996 TEST_F(ValidateComposites, CompositeInsertWrongType2) {
997   const std::string body = R"(
998 %struct = OpLoad %big_struct %var_big_struct
999 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1
1000 )";
1001 
1002   CompileSuccessfully(GenerateShaderCode(body));
1003   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1004   EXPECT_THAT(getDiagnosticString(),
1005               HasSubstr("The Object type (OpTypeFloat) does not match the type "
1006                         "that results from indexing into the Composite "
1007                         "(OpTypeVector)."));
1008 }
1009 
TEST_F(ValidateComposites,CompositeInsertWrongType3)1010 TEST_F(ValidateComposites, CompositeInsertWrongType3) {
1011   const std::string body = R"(
1012 %struct = OpLoad %big_struct %var_big_struct
1013 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 2 1
1014 )";
1015 
1016   CompileSuccessfully(GenerateShaderCode(body));
1017   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1018   EXPECT_THAT(getDiagnosticString(),
1019               HasSubstr("The Object type (OpTypeFloat) does not match the type "
1020                         "that results from indexing into the Composite "
1021                         "(OpTypeVector)."));
1022 }
1023 
TEST_F(ValidateComposites,CompositeInsertWrongType4)1024 TEST_F(ValidateComposites, CompositeInsertWrongType4) {
1025   const std::string body = R"(
1026 %struct = OpLoad %big_struct %var_big_struct
1027 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 4 1
1028 )";
1029 
1030   CompileSuccessfully(GenerateShaderCode(body));
1031   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1032   EXPECT_THAT(getDiagnosticString(),
1033               HasSubstr("The Object type (OpTypeFloat) does not match the type "
1034                         "that results from indexing into the Composite "
1035                         "(OpTypeVector)."));
1036 }
1037 
TEST_F(ValidateComposites,CompositeInsertWrongType5)1038 TEST_F(ValidateComposites, CompositeInsertWrongType5) {
1039   const std::string body = R"(
1040 %struct = OpLoad %big_struct %var_big_struct
1041 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 5 1
1042 )";
1043 
1044   CompileSuccessfully(GenerateShaderCode(body));
1045   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1046   EXPECT_THAT(getDiagnosticString(),
1047               HasSubstr("The Object type (OpTypeFloat) does not match the type "
1048                         "that results from indexing into the Composite "
1049                         "(OpTypeInt)."));
1050 }
1051 
1052 // Tests ported from val_id_test.cpp.
1053 
1054 // Valid. Tests both CompositeExtract and CompositeInsert with 255 indexes.
TEST_F(ValidateComposites,CompositeExtractInsertLimitsGood)1055 TEST_F(ValidateComposites, CompositeExtractInsertLimitsGood) {
1056   int depth = 255;
1057   std::string header = GetHeaderForTestsFromValId();
1058   header.erase(header.find("%func"));
1059   std::ostringstream spirv;
1060   spirv << header << std::endl;
1061 
1062   // Build nested structures. Struct 'i' contains struct 'i-1'
1063   spirv << "%s_depth_1 = OpTypeStruct %float\n";
1064   for (int i = 2; i <= depth; ++i) {
1065     spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n";
1066   }
1067 
1068   // Define Pointer and Variable to use for CompositeExtract/Insert.
1069   spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_"
1070         << depth << "\n";
1071   spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n";
1072 
1073   // Function Start
1074   spirv << R"(
1075   %func = OpFunction %void None %void_f
1076   %my_label = OpLabel
1077   )";
1078 
1079   // OpCompositeExtract/Insert with 'n' indexes (n = depth)
1080   spirv << "%deep = OpLoad %s_depth_" << depth << " %deep_var" << std::endl;
1081   spirv << "%entry = OpCompositeExtract  %float %deep";
1082   for (int i = 0; i < depth; ++i) {
1083     spirv << " 0";
1084   }
1085   spirv << std::endl;
1086   spirv << "%new_composite = OpCompositeInsert %s_depth_" << depth
1087         << " %entry %deep";
1088   for (int i = 0; i < depth; ++i) {
1089     spirv << " 0";
1090   }
1091   spirv << std::endl;
1092 
1093   // Function end
1094   spirv << R"(
1095     OpReturn
1096     OpFunctionEnd
1097   )";
1098   CompileSuccessfully(spirv.str());
1099   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1100 }
1101 
1102 // Invalid: 256 indexes passed to OpCompositeExtract. Limit is 255.
TEST_F(ValidateComposites,CompositeExtractArgCountExceededLimitBad)1103 TEST_F(ValidateComposites, CompositeExtractArgCountExceededLimitBad) {
1104   std::ostringstream spirv;
1105   spirv << GetHeaderForTestsFromValId() << std::endl;
1106   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1107   spirv << "%entry = OpCompositeExtract %float %matrix";
1108   for (int i = 0; i < 256; ++i) {
1109     spirv << " 0";
1110   }
1111   spirv << R"(
1112     OpReturn
1113     OpFunctionEnd
1114   )";
1115   CompileSuccessfully(spirv.str());
1116   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1117   EXPECT_THAT(getDiagnosticString(),
1118               HasSubstr("The number of indexes in OpCompositeExtract may not "
1119                         "exceed 255. Found 256 indexes."));
1120 }
1121 
1122 // Invalid: 256 indexes passed to OpCompositeInsert. Limit is 255.
TEST_F(ValidateComposites,CompositeInsertArgCountExceededLimitBad)1123 TEST_F(ValidateComposites, CompositeInsertArgCountExceededLimitBad) {
1124   std::ostringstream spirv;
1125   spirv << GetHeaderForTestsFromValId() << std::endl;
1126   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1127   spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix";
1128   for (int i = 0; i < 256; ++i) {
1129     spirv << " 0";
1130   }
1131   spirv << R"(
1132     OpReturn
1133     OpFunctionEnd
1134   )";
1135   CompileSuccessfully(spirv.str());
1136   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1137   EXPECT_THAT(getDiagnosticString(),
1138               HasSubstr("The number of indexes in OpCompositeInsert may not "
1139                         "exceed 255. Found 256 indexes."));
1140 }
1141 
1142 // Invalid: In OpCompositeInsert, result type must be the same as composite type
TEST_F(ValidateComposites,CompositeInsertWrongResultTypeBad)1143 TEST_F(ValidateComposites, CompositeInsertWrongResultTypeBad) {
1144   std::ostringstream spirv;
1145   spirv << GetHeaderForTestsFromValId() << std::endl;
1146   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1147   spirv << "%float_entry = OpCompositeExtract  %float %matrix 0 1" << std::endl;
1148   spirv << "%new_composite = OpCompositeInsert %float %float_entry %matrix 0 1"
1149         << std::endl;
1150   spirv << R"(OpReturn
1151               OpFunctionEnd)";
1152   CompileSuccessfully(spirv.str());
1153   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1154   EXPECT_THAT(getDiagnosticString(),
1155               HasSubstr("The Result Type must be the same as Composite type"));
1156 }
1157 
1158 // Valid: No Indexes were passed to OpCompositeExtract, and the Result Type is
1159 // the same as the Base Composite type.
TEST_F(ValidateComposites,CompositeExtractNoIndexesGood)1160 TEST_F(ValidateComposites, CompositeExtractNoIndexesGood) {
1161   std::ostringstream spirv;
1162   spirv << GetHeaderForTestsFromValId() << std::endl;
1163   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1164   spirv << "%float_entry = OpCompositeExtract  %mat4x3 %matrix" << std::endl;
1165   spirv << R"(OpReturn
1166               OpFunctionEnd)";
1167   CompileSuccessfully(spirv.str());
1168   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1169 }
1170 
1171 // Invalid: No Indexes were passed to OpCompositeExtract, but the Result Type is
1172 // different from the Base Composite type.
TEST_F(ValidateComposites,CompositeExtractNoIndexesBad)1173 TEST_F(ValidateComposites, CompositeExtractNoIndexesBad) {
1174   std::ostringstream spirv;
1175   spirv << GetHeaderForTestsFromValId() << std::endl;
1176   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1177   spirv << "%float_entry = OpCompositeExtract  %float %matrix" << std::endl;
1178   spirv << R"(OpReturn
1179               OpFunctionEnd)";
1180   CompileSuccessfully(spirv.str());
1181   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1182   EXPECT_THAT(getDiagnosticString(),
1183               HasSubstr("Result type (OpTypeFloat) does not match the type "
1184                         "that results from indexing into the composite "
1185                         "(OpTypeMatrix)."));
1186 }
1187 
1188 // Valid: No Indexes were passed to OpCompositeInsert, and the type of the
1189 // Object<id> argument matches the Composite type.
TEST_F(ValidateComposites,CompositeInsertMissingIndexesGood)1190 TEST_F(ValidateComposites, CompositeInsertMissingIndexesGood) {
1191   std::ostringstream spirv;
1192   spirv << GetHeaderForTestsFromValId() << std::endl;
1193   spirv << "%matrix   = OpLoad %mat4x3 %my_matrix" << std::endl;
1194   spirv << "%matrix_2 = OpLoad %mat4x3 %my_matrix" << std::endl;
1195   spirv << "%new_composite = OpCompositeInsert %mat4x3 %matrix_2 %matrix";
1196   spirv << R"(
1197               OpReturn
1198               OpFunctionEnd)";
1199   CompileSuccessfully(spirv.str());
1200   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1201 }
1202 
1203 // Invalid: No Indexes were passed to OpCompositeInsert, but the type of the
1204 // Object<id> argument does not match the Composite type.
TEST_F(ValidateComposites,CompositeInsertMissingIndexesBad)1205 TEST_F(ValidateComposites, CompositeInsertMissingIndexesBad) {
1206   std::ostringstream spirv;
1207   spirv << GetHeaderForTestsFromValId() << std::endl;
1208   spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1209   spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix";
1210   spirv << R"(
1211               OpReturn
1212               OpFunctionEnd)";
1213   CompileSuccessfully(spirv.str());
1214   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1215   EXPECT_THAT(getDiagnosticString(),
1216               HasSubstr("The Object type (OpTypeInt) does not match the type "
1217                         "that results from indexing into the Composite "
1218                         "(OpTypeMatrix)."));
1219 }
1220 
1221 // Valid: Tests that we can index into Struct, Array, Matrix, and Vector!
TEST_F(ValidateComposites,CompositeExtractInsertIndexIntoAllTypesGood)1222 TEST_F(ValidateComposites, CompositeExtractInsertIndexIntoAllTypesGood) {
1223   // indexes that we are passing are: 0, 3, 1, 2, 0
1224   // 0 will select the struct_s within the base struct (blockName)
1225   // 3 will select the Array that contains 5 matrices
1226   // 1 will select the Matrix that is at index 1 of the array
1227   // 2 will select the column (which is a vector) within the matrix at index 2
1228   // 0 will select the element at the index 0 of the vector. (which is a float).
1229   std::ostringstream spirv;
1230   spirv << GetHeaderForTestsFromValId() << R"(
1231     %myblock = OpLoad %struct_blockName %blockName_var
1232     %ss = OpCompositeExtract %struct_s %myblock 0
1233     %sa = OpCompositeExtract %array5_mat4x3 %myblock 0 3
1234     %sm = OpCompositeExtract %mat4x3 %myblock 0 3 1
1235     %sc = OpCompositeExtract %v3float %myblock 0 3 1 2
1236     %fl = OpCompositeExtract %float %myblock 0 3 1 2 0
1237     ;
1238     ; Now let's insert back at different levels...
1239     ;
1240     %b1 = OpCompositeInsert %struct_blockName %ss %myblock 0
1241     %b2 = OpCompositeInsert %struct_blockName %sa %myblock 0 3
1242     %b3 = OpCompositeInsert %struct_blockName %sm %myblock 0 3 1
1243     %b4 = OpCompositeInsert %struct_blockName %sc %myblock 0 3 1 2
1244     %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0
1245     OpReturn
1246     OpFunctionEnd
1247   )";
1248 
1249   CompileSuccessfully(spirv.str());
1250   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1251 }
1252 
1253 // Invalid. More indexes are provided than needed for OpCompositeExtract.
TEST_F(ValidateComposites,CompositeExtractReachedScalarBad)1254 TEST_F(ValidateComposites, CompositeExtractReachedScalarBad) {
1255   // indexes that we are passing are: 0, 3, 1, 2, 0
1256   // 0 will select the struct_s within the base struct (blockName)
1257   // 3 will select the Array that contains 5 matrices
1258   // 1 will select the Matrix that is at index 1 of the array
1259   // 2 will select the column (which is a vector) within the matrix at index 2
1260   // 0 will select the element at the index 0 of the vector. (which is a float).
1261   std::ostringstream spirv;
1262   spirv << GetHeaderForTestsFromValId() << R"(
1263     %myblock = OpLoad %struct_blockName %blockName_var
1264     %fl = OpCompositeExtract %float %myblock 0 3 1 2 0 1
1265     OpReturn
1266     OpFunctionEnd
1267   )";
1268 
1269   CompileSuccessfully(spirv.str());
1270   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1271   EXPECT_THAT(getDiagnosticString(),
1272               HasSubstr("Reached non-composite type while indexes still remain "
1273                         "to be traversed."));
1274 }
1275 
1276 // Invalid. More indexes are provided than needed for OpCompositeInsert.
TEST_F(ValidateComposites,CompositeInsertReachedScalarBad)1277 TEST_F(ValidateComposites, CompositeInsertReachedScalarBad) {
1278   // indexes that we are passing are: 0, 3, 1, 2, 0
1279   // 0 will select the struct_s within the base struct (blockName)
1280   // 3 will select the Array that contains 5 matrices
1281   // 1 will select the Matrix that is at index 1 of the array
1282   // 2 will select the column (which is a vector) within the matrix at index 2
1283   // 0 will select the element at the index 0 of the vector. (which is a float).
1284   std::ostringstream spirv;
1285   spirv << GetHeaderForTestsFromValId() << R"(
1286     %myblock = OpLoad %struct_blockName %blockName_var
1287     %fl = OpCompositeExtract %float %myblock 0 3 1 2 0
1288     %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0 1
1289     OpReturn
1290     OpFunctionEnd
1291   )";
1292 
1293   CompileSuccessfully(spirv.str());
1294   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1295   EXPECT_THAT(getDiagnosticString(),
1296               HasSubstr("Reached non-composite type while indexes still remain "
1297                         "to be traversed."));
1298 }
1299 
1300 // Invalid. Result type doesn't match the type we get from indexing into
1301 // the composite.
TEST_F(ValidateComposites,CompositeExtractResultTypeDoesntMatchIndexedTypeBad)1302 TEST_F(ValidateComposites,
1303        CompositeExtractResultTypeDoesntMatchIndexedTypeBad) {
1304   // indexes that we are passing are: 0, 3, 1, 2, 0
1305   // 0 will select the struct_s within the base struct (blockName)
1306   // 3 will select the Array that contains 5 matrices
1307   // 1 will select the Matrix that is at index 1 of the array
1308   // 2 will select the column (which is a vector) within the matrix at index 2
1309   // 0 will select the element at the index 0 of the vector. (which is a float).
1310   std::ostringstream spirv;
1311   spirv << GetHeaderForTestsFromValId() << R"(
1312     %myblock = OpLoad %struct_blockName %blockName_var
1313     %fl = OpCompositeExtract %int %myblock 0 3 1 2 0
1314     OpReturn
1315     OpFunctionEnd
1316   )";
1317 
1318   CompileSuccessfully(spirv.str());
1319   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1320   EXPECT_THAT(getDiagnosticString(),
1321               HasSubstr("Result type (OpTypeInt) does not match the type that "
1322                         "results from indexing into the composite "
1323                         "(OpTypeFloat)."));
1324 }
1325 
1326 // Invalid. Given object type doesn't match the type we get from indexing into
1327 // the composite.
TEST_F(ValidateComposites,CompositeInsertObjectTypeDoesntMatchIndexedTypeBad)1328 TEST_F(ValidateComposites, CompositeInsertObjectTypeDoesntMatchIndexedTypeBad) {
1329   // indexes that we are passing are: 0, 3, 1, 2, 0
1330   // 0 will select the struct_s within the base struct (blockName)
1331   // 3 will select the Array that contains 5 matrices
1332   // 1 will select the Matrix that is at index 1 of the array
1333   // 2 will select the column (which is a vector) within the matrix at index 2
1334   // 0 will select the element at the index 0 of the vector. (which is a float).
1335   // We are trying to insert an integer where we should be inserting a float.
1336   std::ostringstream spirv;
1337   spirv << GetHeaderForTestsFromValId() << R"(
1338     %myblock = OpLoad %struct_blockName %blockName_var
1339     %b5 = OpCompositeInsert %struct_blockName %int_0 %myblock 0 3 1 2 0
1340     OpReturn
1341     OpFunctionEnd
1342   )";
1343 
1344   CompileSuccessfully(spirv.str());
1345   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1346   EXPECT_THAT(getDiagnosticString(),
1347               HasSubstr("The Object type (OpTypeInt) does not match the type "
1348                         "that results from indexing into the Composite "
1349                         "(OpTypeFloat)."));
1350 }
1351 
1352 // Invalid. Index into a struct is larger than the number of struct members.
TEST_F(ValidateComposites,CompositeExtractStructIndexOutOfBoundBad)1353 TEST_F(ValidateComposites, CompositeExtractStructIndexOutOfBoundBad) {
1354   // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3.
1355   std::ostringstream spirv;
1356   spirv << GetHeaderForTestsFromValId() << R"(
1357     %myblock = OpLoad %struct_blockName %blockName_var
1358     %ss = OpCompositeExtract %struct_s %myblock 3
1359     OpReturn
1360     OpFunctionEnd
1361   )";
1362 
1363   CompileSuccessfully(spirv.str());
1364   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1365   EXPECT_THAT(getDiagnosticString(),
1366               HasSubstr("Index is out of bounds, can not find index 3 in the "
1367                         "structure <id> '25'. This structure has 3 members. "
1368                         "Largest valid index is 2."));
1369 }
1370 
1371 // Invalid. Index into a struct is larger than the number of struct members.
TEST_F(ValidateComposites,CompositeInsertStructIndexOutOfBoundBad)1372 TEST_F(ValidateComposites, CompositeInsertStructIndexOutOfBoundBad) {
1373   // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3.
1374   std::ostringstream spirv;
1375   spirv << GetHeaderForTestsFromValId() << R"(
1376     %myblock = OpLoad %struct_blockName %blockName_var
1377     %ss = OpCompositeExtract %struct_s %myblock 0
1378     %new_composite = OpCompositeInsert %struct_blockName %ss %myblock 3
1379     OpReturn
1380     OpFunctionEnd
1381   )";
1382 
1383   CompileSuccessfully(spirv.str());
1384   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1385   EXPECT_THAT(
1386       getDiagnosticString(),
1387       HasSubstr("Index is out of bounds, can not find index 3 in the structure "
1388                 "<id> '25'. This structure has 3 members. Largest valid index "
1389                 "is 2."));
1390 }
1391 
1392 // #1403: Ensure that the default spec constant value is not used to check the
1393 // extract index.
TEST_F(ValidateComposites,ExtractFromSpecConstantSizedArray)1394 TEST_F(ValidateComposites, ExtractFromSpecConstantSizedArray) {
1395   std::string spirv = R"(
1396 OpCapability Kernel
1397 OpCapability Linkage
1398 OpMemoryModel Logical OpenCL
1399 OpDecorate %spec_const SpecId 1
1400 %void = OpTypeVoid
1401 %uint = OpTypeInt 32 0
1402 %spec_const = OpSpecConstant %uint 3
1403 %uint_array = OpTypeArray %uint %spec_const
1404 %undef = OpUndef %uint_array
1405 %voidf = OpTypeFunction %void
1406 %func = OpFunction %void None %voidf
1407 %1 = OpLabel
1408 %2 = OpCompositeExtract %uint %undef 4
1409 OpReturn
1410 OpFunctionEnd
1411 )";
1412 
1413   CompileSuccessfully(spirv);
1414   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1415 }
1416 
1417 // #1403: Ensure that spec constant ops do not produce false positives.
TEST_F(ValidateComposites,ExtractFromSpecConstantOpSizedArray)1418 TEST_F(ValidateComposites, ExtractFromSpecConstantOpSizedArray) {
1419   std::string spirv = R"(
1420 OpCapability Kernel
1421 OpCapability Linkage
1422 OpMemoryModel Logical OpenCL
1423 OpDecorate %spec_const SpecId 1
1424 %void = OpTypeVoid
1425 %uint = OpTypeInt 32 0
1426 %const = OpConstant %uint 1
1427 %spec_const = OpSpecConstant %uint 3
1428 %spec_const_op = OpSpecConstantOp %uint IAdd %spec_const %const
1429 %uint_array = OpTypeArray %uint %spec_const_op
1430 %undef = OpUndef %uint_array
1431 %voidf = OpTypeFunction %void
1432 %func = OpFunction %void None %voidf
1433 %1 = OpLabel
1434 %2 = OpCompositeExtract %uint %undef 4
1435 OpReturn
1436 OpFunctionEnd
1437 )";
1438 
1439   CompileSuccessfully(spirv);
1440   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1441 }
1442 
1443 // #1403: Ensure that the default spec constant value is not used to check the
1444 // size of the array for a composite construct. This code has limited actual
1445 // value as it is incorrect unless the specialization constant is assigned the
1446 // value of 2, but it is still a valid module.
TEST_F(ValidateComposites,CompositeConstructSpecConstantSizedArray)1447 TEST_F(ValidateComposites, CompositeConstructSpecConstantSizedArray) {
1448   std::string spirv = R"(
1449 OpCapability Kernel
1450 OpCapability Linkage
1451 OpMemoryModel Logical OpenCL
1452 OpDecorate %spec_const SpecId 1
1453 %void = OpTypeVoid
1454 %uint = OpTypeInt 32 0
1455 %uint_0 = OpConstant %uint 0
1456 %spec_const = OpSpecConstant %uint 3
1457 %uint_array = OpTypeArray %uint %spec_const
1458 %voidf = OpTypeFunction %void
1459 %func = OpFunction %void None %voidf
1460 %1 = OpLabel
1461 %2 = OpCompositeConstruct %uint_array %uint_0 %uint_0
1462 OpReturn
1463 OpFunctionEnd
1464 )";
1465 
1466   CompileSuccessfully(spirv);
1467   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1468 }
1469 
TEST_F(ValidateComposites,ExtractDynamicLabelIndex)1470 TEST_F(ValidateComposites, ExtractDynamicLabelIndex) {
1471   const std::string spirv = R"(
1472 OpCapability Shader
1473 OpCapability Linkage
1474 OpMemoryModel Logical GLSL450
1475 %void = OpTypeVoid
1476 %float = OpTypeFloat 32
1477 %v4float = OpTypeVector %float 4
1478 %void_fn = OpTypeFunction %void
1479 %float_0 = OpConstant %float 0
1480 %v4float_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1481 %func = OpFunction %void None %void_fn
1482 %1 = OpLabel
1483 %ex = OpVectorExtractDynamic %float %v4float_0 %1
1484 OpReturn
1485 OpFunctionEnd
1486 )";
1487 
1488   CompileSuccessfully(spirv);
1489   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1490   EXPECT_THAT(getDiagnosticString(),
1491               HasSubstr("Expected Index to be int scalar"));
1492 }
1493 
1494 }  // namespace
1495 }  // namespace val
1496 }  // namespace spvtools
1497