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