1 // Copyright (c) 2016 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 // Validation tests for Data Rules.
16
17 #include <sstream>
18 #include <string>
19 #include <utility>
20
21 #include "gmock/gmock.h"
22 #include "test/unit_spirv.h"
23 #include "test/val/val_fixtures.h"
24
25 namespace spvtools {
26 namespace val {
27 namespace {
28
29 using ::testing::HasSubstr;
30 using ::testing::MatchesRegex;
31
32 using ValidateData = spvtest::ValidateBase<std::pair<std::string, bool>>;
33
HeaderWith(std::string cap)34 std::string HeaderWith(std::string cap) {
35 return std::string("OpCapability Shader OpCapability Linkage OpCapability ") +
36 cap + " OpMemoryModel Logical GLSL450 ";
37 }
38
39 std::string header = R"(
40 OpCapability Shader
41 OpCapability Linkage
42 OpMemoryModel Logical GLSL450
43 )";
44 std::string header_with_addresses = R"(
45 OpCapability Addresses
46 OpCapability Kernel
47 OpCapability GenericPointer
48 OpCapability Linkage
49 OpMemoryModel Physical32 OpenCL
50 )";
51 std::string header_with_vec16_cap = R"(
52 OpCapability Shader
53 OpCapability Vector16
54 OpCapability Linkage
55 OpMemoryModel Logical GLSL450
56 )";
57 std::string header_with_int8 = R"(
58 OpCapability Shader
59 OpCapability Linkage
60 OpCapability Int8
61 OpMemoryModel Logical GLSL450
62 )";
63 std::string header_with_int16 = R"(
64 OpCapability Shader
65 OpCapability Linkage
66 OpCapability Int16
67 OpMemoryModel Logical GLSL450
68 )";
69 std::string header_with_int64 = R"(
70 OpCapability Shader
71 OpCapability Linkage
72 OpCapability Int64
73 OpMemoryModel Logical GLSL450
74 )";
75 std::string header_with_float16 = R"(
76 OpCapability Shader
77 OpCapability Linkage
78 OpCapability Float16
79 OpMemoryModel Logical GLSL450
80 )";
81 std::string header_with_float16_buffer = R"(
82 OpCapability Shader
83 OpCapability Linkage
84 OpCapability Float16Buffer
85 OpMemoryModel Logical GLSL450
86 )";
87 std::string header_with_float64 = R"(
88 OpCapability Shader
89 OpCapability Linkage
90 OpCapability Float64
91 OpMemoryModel Logical GLSL450
92 )";
93
94 std::string invalid_comp_error = "Illegal number of components";
95 std::string missing_cap_error = "requires the Vector16 capability";
96 std::string missing_int8_cap_error = "requires the Int8 capability";
97 std::string missing_int16_cap_error =
98 "requires the Int16 capability,"
99 " or an extension that explicitly enables 16-bit integers.";
100 std::string missing_int64_cap_error = "requires the Int64 capability";
101 std::string missing_float16_cap_error =
102 "requires the Float16 or Float16Buffer capability,"
103 " or an extension that explicitly enables 16-bit floating point.";
104 std::string missing_float64_cap_error = "requires the Float64 capability";
105 std::string invalid_num_bits_error = "Invalid number of bits";
106
TEST_F(ValidateData,vec0)107 TEST_F(ValidateData, vec0) {
108 std::string str = header + R"(
109 %1 = OpTypeFloat 32
110 %2 = OpTypeVector %1 0
111 )";
112 CompileSuccessfully(str.c_str());
113 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
114 EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
115 }
116
TEST_F(ValidateData,vec1)117 TEST_F(ValidateData, vec1) {
118 std::string str = header + R"(
119 %1 = OpTypeFloat 32
120 %2 = OpTypeVector %1 1
121 )";
122 CompileSuccessfully(str.c_str());
123 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
124 EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
125 }
126
TEST_F(ValidateData,vec2)127 TEST_F(ValidateData, vec2) {
128 std::string str = header + R"(
129 %1 = OpTypeFloat 32
130 %2 = OpTypeVector %1 2
131 )";
132 CompileSuccessfully(str.c_str());
133 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
134 }
135
TEST_F(ValidateData,vec3)136 TEST_F(ValidateData, vec3) {
137 std::string str = header + R"(
138 %1 = OpTypeFloat 32
139 %2 = OpTypeVector %1 3
140 )";
141 CompileSuccessfully(str.c_str());
142 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
143 }
144
TEST_F(ValidateData,vec4)145 TEST_F(ValidateData, vec4) {
146 std::string str = header + R"(
147 %1 = OpTypeFloat 32
148 %2 = OpTypeVector %1 4
149 )";
150 CompileSuccessfully(str.c_str());
151 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
152 }
153
TEST_F(ValidateData,vec5)154 TEST_F(ValidateData, vec5) {
155 std::string str = header + R"(
156 %1 = OpTypeFloat 32
157 %2 = OpTypeVector %1 5
158 )";
159 CompileSuccessfully(str.c_str());
160 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
161 EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
162 }
163
TEST_F(ValidateData,vec8)164 TEST_F(ValidateData, vec8) {
165 std::string str = header + R"(
166 %1 = OpTypeFloat 32
167 %2 = OpTypeVector %1 8
168 )";
169 CompileSuccessfully(str.c_str());
170 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
171 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_cap_error));
172 }
173
TEST_F(ValidateData,vec8_with_capability)174 TEST_F(ValidateData, vec8_with_capability) {
175 std::string str = header_with_vec16_cap + R"(
176 %1 = OpTypeFloat 32
177 %2 = OpTypeVector %1 8
178 )";
179 CompileSuccessfully(str.c_str());
180 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
181 }
182
TEST_F(ValidateData,vec16)183 TEST_F(ValidateData, vec16) {
184 std::string str = header + R"(
185 %1 = OpTypeFloat 32
186 %2 = OpTypeVector %1 8
187 )";
188 CompileSuccessfully(str.c_str());
189 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
190 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_cap_error));
191 }
192
TEST_F(ValidateData,vec16_with_capability)193 TEST_F(ValidateData, vec16_with_capability) {
194 std::string str = header_with_vec16_cap + R"(
195 %1 = OpTypeFloat 32
196 %2 = OpTypeVector %1 16
197 )";
198 CompileSuccessfully(str.c_str());
199 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
200 }
201
TEST_F(ValidateData,vec15)202 TEST_F(ValidateData, vec15) {
203 std::string str = header + R"(
204 %1 = OpTypeFloat 32
205 %2 = OpTypeVector %1 15
206 )";
207 CompileSuccessfully(str.c_str());
208 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
209 EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
210 }
211
TEST_F(ValidateData,int8_good)212 TEST_F(ValidateData, int8_good) {
213 std::string str = header_with_int8 + "%2 = OpTypeInt 8 0";
214 CompileSuccessfully(str.c_str());
215 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
216 }
217
TEST_F(ValidateData,int8_bad)218 TEST_F(ValidateData, int8_bad) {
219 std::string str = header + "%2 = OpTypeInt 8 1";
220 CompileSuccessfully(str.c_str());
221 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
222 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int8_cap_error));
223 }
224
TEST_F(ValidateData,int8_with_storage_buffer_8bit_access_good)225 TEST_F(ValidateData, int8_with_storage_buffer_8bit_access_good) {
226 std::string str = HeaderWith(
227 "StorageBuffer8BitAccess "
228 "OpExtension \"SPV_KHR_8bit_storage\"") +
229 " %2 = OpTypeInt 8 0";
230 CompileSuccessfully(str.c_str());
231 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
232 }
233
TEST_F(ValidateData,int8_with_uniform_and_storage_buffer_8bit_access_good)234 TEST_F(ValidateData, int8_with_uniform_and_storage_buffer_8bit_access_good) {
235 std::string str = HeaderWith(
236 "UniformAndStorageBuffer8BitAccess "
237 "OpExtension \"SPV_KHR_8bit_storage\"") +
238 " %2 = OpTypeInt 8 0";
239 CompileSuccessfully(str.c_str());
240 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
241 }
242
TEST_F(ValidateData,int8_with_storage_push_constant_8_good)243 TEST_F(ValidateData, int8_with_storage_push_constant_8_good) {
244 std::string str = HeaderWith(
245 "StoragePushConstant8 "
246 "OpExtension \"SPV_KHR_8bit_storage\"") +
247 " %2 = OpTypeInt 8 0";
248 CompileSuccessfully(str.c_str());
249 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
250 }
251
TEST_F(ValidateData,int16_good)252 TEST_F(ValidateData, int16_good) {
253 std::string str = header_with_int16 + "%2 = OpTypeInt 16 1";
254 CompileSuccessfully(str.c_str());
255 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
256 }
257
TEST_F(ValidateData,storage_uniform_buffer_block_16_good)258 TEST_F(ValidateData, storage_uniform_buffer_block_16_good) {
259 std::string str = HeaderWith(
260 "StorageUniformBufferBlock16 "
261 "OpExtension \"SPV_KHR_16bit_storage\"") +
262 "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
263 CompileSuccessfully(str.c_str());
264 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
265 }
266
TEST_F(ValidateData,storage_uniform_16_good)267 TEST_F(ValidateData, storage_uniform_16_good) {
268 std::string str =
269 HeaderWith("StorageUniform16 OpExtension \"SPV_KHR_16bit_storage\"") +
270 "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
271 CompileSuccessfully(str.c_str());
272 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
273 }
274
TEST_F(ValidateData,storage_push_constant_16_good)275 TEST_F(ValidateData, storage_push_constant_16_good) {
276 std::string str = HeaderWith(
277 "StoragePushConstant16 "
278 "OpExtension \"SPV_KHR_16bit_storage\"") +
279 "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
280 CompileSuccessfully(str.c_str());
281 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
282 }
283
TEST_F(ValidateData,storage_input_output_16_good)284 TEST_F(ValidateData, storage_input_output_16_good) {
285 std::string str = HeaderWith(
286 "StorageInputOutput16 "
287 "OpExtension \"SPV_KHR_16bit_storage\"") +
288 "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
289 CompileSuccessfully(str.c_str());
290 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
291 }
292
TEST_F(ValidateData,amd_gpu_shader_half_float_fetch_16_good)293 TEST_F(ValidateData, amd_gpu_shader_half_float_fetch_16_good) {
294 std::string str = R"(
295 OpCapability Shader
296 OpCapability Linkage
297 OpExtension "SPV_AMD_gpu_shader_half_float_fetch"
298 OpMemoryModel Logical GLSL450
299 %2 = OpTypeFloat 16)";
300 CompileSuccessfully(str.c_str());
301 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
302 }
303
TEST_F(ValidateData,int16_bad)304 TEST_F(ValidateData, int16_bad) {
305 std::string str = header + "%2 = OpTypeInt 16 1";
306 CompileSuccessfully(str.c_str());
307 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
308 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int16_cap_error));
309 }
310
TEST_F(ValidateData,int64_good)311 TEST_F(ValidateData, int64_good) {
312 std::string str = header_with_int64 + "%2 = OpTypeInt 64 1";
313 CompileSuccessfully(str.c_str());
314 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
315 }
316
TEST_F(ValidateData,int64_bad)317 TEST_F(ValidateData, int64_bad) {
318 std::string str = header + "%2 = OpTypeInt 64 1";
319 CompileSuccessfully(str.c_str());
320 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
321 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int64_cap_error));
322 }
323
324 // Number of bits in an integer may be only one of: {8,16,32,64}
TEST_F(ValidateData,int_invalid_num_bits)325 TEST_F(ValidateData, int_invalid_num_bits) {
326 std::string str = header + "%2 = OpTypeInt 48 1";
327 CompileSuccessfully(str.c_str());
328 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
329 EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_num_bits_error));
330 }
331
TEST_F(ValidateData,float16_good)332 TEST_F(ValidateData, float16_good) {
333 std::string str = header_with_float16 + "%2 = OpTypeFloat 16";
334 CompileSuccessfully(str.c_str());
335 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
336 }
337
TEST_F(ValidateData,float16_buffer_good)338 TEST_F(ValidateData, float16_buffer_good) {
339 std::string str = header_with_float16_buffer + "%2 = OpTypeFloat 16";
340 CompileSuccessfully(str.c_str());
341 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
342 }
343
TEST_F(ValidateData,float16_bad)344 TEST_F(ValidateData, float16_bad) {
345 std::string str = header + "%2 = OpTypeFloat 16";
346 CompileSuccessfully(str.c_str());
347 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
348 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float16_cap_error));
349 }
350
TEST_F(ValidateData,float64_good)351 TEST_F(ValidateData, float64_good) {
352 std::string str = header_with_float64 + "%2 = OpTypeFloat 64";
353 CompileSuccessfully(str.c_str());
354 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
355 }
356
TEST_F(ValidateData,float64_bad)357 TEST_F(ValidateData, float64_bad) {
358 std::string str = header + "%2 = OpTypeFloat 64";
359 CompileSuccessfully(str.c_str());
360 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
361 EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float64_cap_error));
362 }
363
364 // Number of bits in a float may be only one of: {16,32,64}
TEST_F(ValidateData,float_invalid_num_bits)365 TEST_F(ValidateData, float_invalid_num_bits) {
366 std::string str = header + "%2 = OpTypeFloat 48";
367 CompileSuccessfully(str.c_str());
368 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
369 EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_num_bits_error));
370 }
371
TEST_F(ValidateData,matrix_data_type_float)372 TEST_F(ValidateData, matrix_data_type_float) {
373 std::string str = header + R"(
374 %f32 = OpTypeFloat 32
375 %vec3 = OpTypeVector %f32 3
376 %mat33 = OpTypeMatrix %vec3 3
377 )";
378 CompileSuccessfully(str.c_str());
379 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
380 }
381
TEST_F(ValidateData,ids_should_be_validated_before_data)382 TEST_F(ValidateData, ids_should_be_validated_before_data) {
383 std::string str = header + R"(
384 %f32 = OpTypeFloat 32
385 %mat33 = OpTypeMatrix %vec3 3
386 )";
387 CompileSuccessfully(str.c_str());
388 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
389 EXPECT_THAT(getDiagnosticString(),
390 HasSubstr("Operand 3[%3] requires a previous definition"));
391 }
392
TEST_F(ValidateData,matrix_bad_column_type)393 TEST_F(ValidateData, matrix_bad_column_type) {
394 std::string str = header + R"(
395 %f32 = OpTypeFloat 32
396 %mat33 = OpTypeMatrix %f32 3
397 )";
398 CompileSuccessfully(str.c_str());
399 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
400 EXPECT_THAT(getDiagnosticString(),
401 HasSubstr("Columns in a matrix must be of type vector"));
402 }
403
TEST_F(ValidateData,matrix_data_type_int)404 TEST_F(ValidateData, matrix_data_type_int) {
405 std::string str = header + R"(
406 %int32 = OpTypeInt 32 1
407 %vec3 = OpTypeVector %int32 3
408 %mat33 = OpTypeMatrix %vec3 3
409 )";
410 CompileSuccessfully(str.c_str());
411 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
412 EXPECT_THAT(getDiagnosticString(),
413 HasSubstr("can only be parameterized with floating-point types"));
414 }
415
TEST_F(ValidateData,matrix_data_type_bool)416 TEST_F(ValidateData, matrix_data_type_bool) {
417 std::string str = header + R"(
418 %boolt = OpTypeBool
419 %vec3 = OpTypeVector %boolt 3
420 %mat33 = OpTypeMatrix %vec3 3
421 )";
422 CompileSuccessfully(str.c_str());
423 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
424 EXPECT_THAT(getDiagnosticString(),
425 HasSubstr("can only be parameterized with floating-point types"));
426 }
427
TEST_F(ValidateData,matrix_with_0_columns)428 TEST_F(ValidateData, matrix_with_0_columns) {
429 std::string str = header + R"(
430 %f32 = OpTypeFloat 32
431 %vec3 = OpTypeVector %f32 3
432 %mat33 = OpTypeMatrix %vec3 0
433 )";
434 CompileSuccessfully(str.c_str());
435 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
436 EXPECT_THAT(
437 getDiagnosticString(),
438 HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
439 }
440
TEST_F(ValidateData,matrix_with_1_column)441 TEST_F(ValidateData, matrix_with_1_column) {
442 std::string str = header + R"(
443 %f32 = OpTypeFloat 32
444 %vec3 = OpTypeVector %f32 3
445 %mat33 = OpTypeMatrix %vec3 1
446 )";
447 CompileSuccessfully(str.c_str());
448 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
449 EXPECT_THAT(
450 getDiagnosticString(),
451 HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
452 }
453
TEST_F(ValidateData,matrix_with_2_columns)454 TEST_F(ValidateData, matrix_with_2_columns) {
455 std::string str = header + R"(
456 %f32 = OpTypeFloat 32
457 %vec3 = OpTypeVector %f32 3
458 %mat33 = OpTypeMatrix %vec3 2
459 )";
460 CompileSuccessfully(str.c_str());
461 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
462 }
463
TEST_F(ValidateData,matrix_with_3_columns)464 TEST_F(ValidateData, matrix_with_3_columns) {
465 std::string str = header + R"(
466 %f32 = OpTypeFloat 32
467 %vec3 = OpTypeVector %f32 3
468 %mat33 = OpTypeMatrix %vec3 3
469 )";
470 CompileSuccessfully(str.c_str());
471 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
472 }
473
TEST_F(ValidateData,matrix_with_4_columns)474 TEST_F(ValidateData, matrix_with_4_columns) {
475 std::string str = header + R"(
476 %f32 = OpTypeFloat 32
477 %vec3 = OpTypeVector %f32 3
478 %mat33 = OpTypeMatrix %vec3 4
479 )";
480 CompileSuccessfully(str.c_str());
481 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
482 }
483
TEST_F(ValidateData,matrix_with_5_column)484 TEST_F(ValidateData, matrix_with_5_column) {
485 std::string str = header + R"(
486 %f32 = OpTypeFloat 32
487 %vec3 = OpTypeVector %f32 3
488 %mat33 = OpTypeMatrix %vec3 5
489 )";
490 CompileSuccessfully(str.c_str());
491 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
492 EXPECT_THAT(
493 getDiagnosticString(),
494 HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
495 }
496
TEST_F(ValidateData,specialize_int)497 TEST_F(ValidateData, specialize_int) {
498 std::string str = header + R"(
499 %i32 = OpTypeInt 32 1
500 %len = OpSpecConstant %i32 2)";
501 CompileSuccessfully(str.c_str());
502 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
503 }
504
TEST_F(ValidateData,specialize_float)505 TEST_F(ValidateData, specialize_float) {
506 std::string str = header + R"(
507 %f32 = OpTypeFloat 32
508 %len = OpSpecConstant %f32 2)";
509 CompileSuccessfully(str.c_str());
510 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
511 }
512
TEST_F(ValidateData,specialize_boolean)513 TEST_F(ValidateData, specialize_boolean) {
514 std::string str = header + R"(
515 %2 = OpTypeBool
516 %3 = OpSpecConstantTrue %2
517 %4 = OpSpecConstantFalse %2)";
518 CompileSuccessfully(str.c_str());
519 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
520 }
521
TEST_F(ValidateData,specialize_boolean_true_to_int)522 TEST_F(ValidateData, specialize_boolean_true_to_int) {
523 std::string str = header + R"(
524 %2 = OpTypeInt 32 1
525 %3 = OpSpecConstantTrue %2)";
526 CompileSuccessfully(str.c_str());
527 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
528 EXPECT_THAT(getDiagnosticString(),
529 HasSubstr("OpSpecConstantTrue Result Type <id> '1[%int]' is not "
530 "a boolean type"));
531 }
532
TEST_F(ValidateData,specialize_boolean_false_to_int)533 TEST_F(ValidateData, specialize_boolean_false_to_int) {
534 std::string str = header + R"(
535 %2 = OpTypeInt 32 1
536 %4 = OpSpecConstantFalse %2)";
537 CompileSuccessfully(str.c_str());
538 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
539 EXPECT_THAT(getDiagnosticString(),
540 HasSubstr("OpSpecConstantFalse Result Type <id> '1[%int]' is not "
541 "a boolean type"));
542 }
543
TEST_F(ValidateData,missing_forward_pointer_decl)544 TEST_F(ValidateData, missing_forward_pointer_decl) {
545 std::string str = header_with_addresses + R"(
546 %uintt = OpTypeInt 32 0
547 %3 = OpTypeStruct %fwd_ptrt %uintt
548 )";
549 CompileSuccessfully(str.c_str());
550 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
551 EXPECT_THAT(getDiagnosticString(),
552 HasSubstr("Operand 3[%3] requires a previous definition"));
553 }
554
TEST_F(ValidateData,missing_forward_pointer_decl_self_reference)555 TEST_F(ValidateData, missing_forward_pointer_decl_self_reference) {
556 std::string str = header_with_addresses + R"(
557 %uintt = OpTypeInt 32 0
558 %3 = OpTypeStruct %3 %uintt
559 )";
560 CompileSuccessfully(str.c_str());
561 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
562 EXPECT_THAT(
563 getDiagnosticString(),
564 HasSubstr("Operand 2[%_struct_2] requires a previous definition"));
565 }
566
TEST_F(ValidateData,forward_pointer_missing_definition)567 TEST_F(ValidateData, forward_pointer_missing_definition) {
568 std::string str = header_with_addresses + R"(
569 OpTypeForwardPointer %_ptr_Generic_struct_A Generic
570 %uintt = OpTypeInt 32 0
571 %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
572 )";
573 CompileSuccessfully(str.c_str());
574 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
575 EXPECT_THAT(getDiagnosticString(),
576 HasSubstr("forward referenced IDs have not been defined"));
577 }
578
TEST_F(ValidateData,forward_ref_bad_type)579 TEST_F(ValidateData, forward_ref_bad_type) {
580 std::string str = header_with_addresses + R"(
581 OpTypeForwardPointer %_ptr_Generic_struct_A Generic
582 %uintt = OpTypeInt 32 0
583 %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
584 %_ptr_Generic_struct_A = OpTypeFloat 32
585 )";
586 CompileSuccessfully(str.c_str());
587 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
588 EXPECT_THAT(getDiagnosticString(),
589 HasSubstr("Pointer type in OpTypeForwardPointer is not a pointer "
590 "type.\n OpTypeForwardPointer %float Generic\n"));
591 }
592
TEST_F(ValidateData,forward_ref_points_to_non_struct)593 TEST_F(ValidateData, forward_ref_points_to_non_struct) {
594 std::string str = header_with_addresses + R"(
595 OpTypeForwardPointer %_ptr_Generic_struct_A Generic
596 %uintt = OpTypeInt 32 0
597 %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
598 %_ptr_Generic_struct_A = OpTypePointer Generic %uintt
599 )";
600 CompileSuccessfully(str.c_str());
601 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
602 EXPECT_THAT(getDiagnosticString(),
603 HasSubstr("Forward pointers must point to a structure"));
604 }
605
TEST_F(ValidateData,struct_forward_pointer_good)606 TEST_F(ValidateData, struct_forward_pointer_good) {
607 std::string str = header_with_addresses + R"(
608 OpTypeForwardPointer %_ptr_Generic_struct_A Generic
609 %uintt = OpTypeInt 32 0
610 %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
611 %struct_C = OpTypeStruct %uintt %struct_B
612 %struct_A = OpTypeStruct %uintt %struct_C
613 %_ptr_Generic_struct_A = OpTypePointer Generic %struct_C
614 )";
615 CompileSuccessfully(str.c_str());
616 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
617 }
618
TEST_F(ValidateData,ext_16bit_storage_caps_allow_free_fp_rounding_mode)619 TEST_F(ValidateData, ext_16bit_storage_caps_allow_free_fp_rounding_mode) {
620 for (const char* cap : {"StorageUniform16", "StorageUniformBufferBlock16"}) {
621 for (const char* mode : {"RTE", "RTZ", "RTP", "RTN"}) {
622 std::string str = std::string(R"(
623 OpCapability Shader
624 OpCapability Linkage
625 OpCapability )") +
626 cap + R"(
627 OpExtension "SPV_KHR_storage_buffer_storage_class"
628 OpExtension "SPV_KHR_variable_pointers"
629 OpExtension "SPV_KHR_16bit_storage"
630 OpMemoryModel Logical GLSL450
631 OpDecorate %_ FPRoundingMode )" + mode + R"(
632 %half = OpTypeFloat 16
633 %float = OpTypeFloat 32
634 %float_1_25 = OpConstant %float 1.25
635 %half_ptr = OpTypePointer StorageBuffer %half
636 %half_ptr_var = OpVariable %half_ptr StorageBuffer
637 %void = OpTypeVoid
638 %func = OpTypeFunction %void
639 %main = OpFunction %void None %func
640 %main_entry = OpLabel
641 %_ = OpFConvert %half %float_1_25
642 OpStore %half_ptr_var %_
643 OpReturn
644 OpFunctionEnd
645 )";
646 CompileSuccessfully(str.c_str());
647 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
648 }
649 }
650 }
651
TEST_F(ValidateData,vulkan_disallow_free_fp_rounding_mode)652 TEST_F(ValidateData, vulkan_disallow_free_fp_rounding_mode) {
653 for (const char* mode : {"RTE", "RTZ"}) {
654 for (const auto env : {SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1}) {
655 std::string str = std::string(R"(
656 OpCapability Shader
657 OpExtension "SPV_KHR_storage_buffer_storage_class"
658 OpExtension "SPV_KHR_variable_pointers"
659 OpMemoryModel Logical GLSL450
660 OpDecorate %_ FPRoundingMode )") +
661 mode + R"(
662 %half = OpTypeFloat 16
663 %float = OpTypeFloat 32
664 %float_1_25 = OpConstant %float 1.25
665 %half_ptr = OpTypePointer StorageBuffer %half
666 %half_ptr_var = OpVariable %half_ptr StorageBuffer
667 %void = OpTypeVoid
668 %func = OpTypeFunction %void
669 %main = OpFunction %void None %func
670 %main_entry = OpLabel
671 %_ = OpFConvert %half %float_1_25
672 OpStore %half_ptr_var %_
673 OpReturn
674 OpFunctionEnd
675 )";
676 CompileSuccessfully(str.c_str());
677 ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions(env));
678 EXPECT_THAT(
679 getDiagnosticString(),
680 HasSubstr(
681 "Operand 2 of Decorate requires one of these capabilities: "
682 "StorageBuffer16BitAccess UniformAndStorageBuffer16BitAccess "
683 "StoragePushConstant16 StorageInputOutput16"));
684 }
685 }
686 }
687
TEST_F(ValidateData,void_array)688 TEST_F(ValidateData, void_array) {
689 std::string str = header + R"(
690 %void = OpTypeVoid
691 %int = OpTypeInt 32 0
692 %int_5 = OpConstant %int 5
693 %array = OpTypeArray %void %int_5
694 )";
695
696 CompileSuccessfully(str.c_str());
697 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
698 EXPECT_THAT(
699 getDiagnosticString(),
700 HasSubstr("OpTypeArray Element Type <id> '1[%void]' is a void type."));
701 }
702
TEST_F(ValidateData,void_runtime_array)703 TEST_F(ValidateData, void_runtime_array) {
704 std::string str = header + R"(
705 %void = OpTypeVoid
706 %array = OpTypeRuntimeArray %void
707 )";
708
709 CompileSuccessfully(str.c_str());
710 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
711 EXPECT_THAT(
712 getDiagnosticString(),
713 HasSubstr(
714 "OpTypeRuntimeArray Element Type <id> '1[%void]' is a void type."));
715 }
716
TEST_F(ValidateData,vulkan_RTA_array_at_end_of_struct)717 TEST_F(ValidateData, vulkan_RTA_array_at_end_of_struct) {
718 std::string str = R"(
719 OpCapability Shader
720 OpMemoryModel Logical GLSL450
721 OpEntryPoint Fragment %func "func"
722 OpExecutionMode %func OriginUpperLeft
723 OpDecorate %array_t ArrayStride 4
724 OpMemberDecorate %struct_t 0 Offset 0
725 OpMemberDecorate %struct_t 1 Offset 4
726 OpDecorate %struct_t Block
727 %uint_t = OpTypeInt 32 0
728 %array_t = OpTypeRuntimeArray %uint_t
729 %struct_t = OpTypeStruct %uint_t %array_t
730 %struct_ptr = OpTypePointer StorageBuffer %struct_t
731 %2 = OpVariable %struct_ptr StorageBuffer
732 %void = OpTypeVoid
733 %func_t = OpTypeFunction %void
734 %func = OpFunction %void None %func_t
735 %1 = OpLabel
736 OpReturn
737 OpFunctionEnd
738 )";
739
740 CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1);
741 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
742 }
743
TEST_F(ValidateData,vulkan_RTA_not_at_end_of_struct)744 TEST_F(ValidateData, vulkan_RTA_not_at_end_of_struct) {
745 std::string str = R"(
746 OpCapability Shader
747 OpMemoryModel Logical GLSL450
748 OpEntryPoint Fragment %func "func"
749 OpExecutionMode %func OriginUpperLeft
750 OpDecorate %array_t ArrayStride 4
751 OpMemberDecorate %struct_t 0 Offset 0
752 OpMemberDecorate %struct_t 1 Offset 4
753 OpDecorate %struct_t Block
754 %uint_t = OpTypeInt 32 0
755 %array_t = OpTypeRuntimeArray %uint_t
756 %struct_t = OpTypeStruct %array_t %uint_t
757 %struct_ptr = OpTypePointer StorageBuffer %struct_t
758 %2 = OpVariable %struct_ptr StorageBuffer
759 %void = OpTypeVoid
760 %func_t = OpTypeFunction %void
761 %func = OpFunction %void None %func_t
762 %1 = OpLabel
763 OpReturn
764 OpFunctionEnd
765 )";
766
767 CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1);
768 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
769 EXPECT_THAT(getDiagnosticString(),
770 HasSubstr("In Vulkan, OpTypeRuntimeArray must only be used for "
771 "the last member of an OpTypeStruct\n %_struct_3 = "
772 "OpTypeStruct %_runtimearr_uint %uint\n"));
773 }
774
TEST_F(ValidateData,TypeForwardReference)775 TEST_F(ValidateData, TypeForwardReference) {
776 std::string test = R"(
777 OpCapability Shader
778 OpCapability PhysicalStorageBufferAddresses
779 OpCapability Linkage
780 OpMemoryModel Logical GLSL450
781 OpTypeForwardPointer %1 PhysicalStorageBuffer
782 %2 = OpTypeStruct
783 %3 = OpTypeRuntimeArray %1
784 %1 = OpTypePointer PhysicalStorageBuffer %2
785 )";
786
787 CompileSuccessfully(test, SPV_ENV_UNIVERSAL_1_5);
788 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
789 }
790
TEST_F(ValidateData,VulkanTypeForwardStorageClass)791 TEST_F(ValidateData, VulkanTypeForwardStorageClass) {
792 std::string test = R"(
793 OpCapability Shader
794 OpCapability PhysicalStorageBufferAddresses
795 OpMemoryModel Logical GLSL450
796 OpTypeForwardPointer %1 Uniform
797 %2 = OpTypeStruct
798 %3 = OpTypeRuntimeArray %1
799 %1 = OpTypePointer Uniform %2
800 )";
801
802 CompileSuccessfully(test, SPV_ENV_VULKAN_1_2);
803 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
804 EXPECT_THAT(getDiagnosticString(),
805 AnyVUID("VUID-StandaloneSpirv-OpTypeForwardPointer-04711"));
806 EXPECT_THAT(getDiagnosticString(),
807 HasSubstr("In Vulkan, OpTypeForwardPointer must have "
808 "a storage class of PhysicalStorageBuffer."));
809 }
810
TEST_F(ValidateData,TypeForwardReferenceMustBeForwardPointer)811 TEST_F(ValidateData, TypeForwardReferenceMustBeForwardPointer) {
812 std::string test = R"(
813 OpCapability Shader
814 OpCapability PhysicalStorageBufferAddresses
815 OpCapability Linkage
816 OpMemoryModel Logical GLSL450
817 %1 = OpTypeStruct
818 %2 = OpTypeRuntimeArray %3
819 %3 = OpTypePointer PhysicalStorageBuffer %1
820 )";
821
822 CompileSuccessfully(test, SPV_ENV_UNIVERSAL_1_5);
823 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
824 EXPECT_THAT(getDiagnosticString(),
825 HasSubstr("Operand 3[%_ptr_PhysicalStorageBuffer__struct_1] "
826 "requires a previous definition"));
827 }
828
829 } // namespace
830 } // namespace val
831 } // namespace spvtools
832