• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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