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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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} 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 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 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 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 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 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} 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 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 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("ID 3[%3] has not been defined")); 391 } 392 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 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 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 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 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 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 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 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 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 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 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 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 522 TEST_F(ValidateData, specialize_boolean_to_int) { 523 std::string str = header + R"( 524 %2 = OpTypeInt 32 1 525 %3 = OpSpecConstantTrue %2 526 %4 = OpSpecConstantFalse %2)"; 527 CompileSuccessfully(str.c_str()); 528 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 529 EXPECT_THAT(getDiagnosticString(), 530 HasSubstr("Specialization constant must be a boolean")); 531 } 532 533 TEST_F(ValidateData, missing_forward_pointer_decl) { 534 std::string str = header_with_addresses + R"( 535 %uintt = OpTypeInt 32 0 536 %3 = OpTypeStruct %fwd_ptrt %uintt 537 )"; 538 CompileSuccessfully(str.c_str()); 539 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 540 EXPECT_THAT(getDiagnosticString(), 541 HasSubstr("must first be declared using OpTypeForwardPointer")); 542 } 543 544 TEST_F(ValidateData, missing_forward_pointer_decl_self_reference) { 545 std::string str = header_with_addresses + R"( 546 %uintt = OpTypeInt 32 0 547 %3 = OpTypeStruct %3 %uintt 548 )"; 549 CompileSuccessfully(str.c_str()); 550 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 551 EXPECT_THAT(getDiagnosticString(), 552 HasSubstr("must first be declared using OpTypeForwardPointer")); 553 } 554 555 TEST_F(ValidateData, forward_pointer_missing_definition) { 556 std::string str = header_with_addresses + R"( 557 OpTypeForwardPointer %_ptr_Generic_struct_A Generic 558 %uintt = OpTypeInt 32 0 559 %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A 560 )"; 561 CompileSuccessfully(str.c_str()); 562 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 563 EXPECT_THAT(getDiagnosticString(), 564 HasSubstr("forward referenced IDs have not been defined")); 565 } 566 567 TEST_F(ValidateData, forward_ref_bad_type) { 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 %_ptr_Generic_struct_A = OpTypeFloat 32 573 )"; 574 CompileSuccessfully(str.c_str()); 575 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 576 EXPECT_THAT(getDiagnosticString(), 577 HasSubstr("Pointer type in OpTypeForwardPointer is not a pointer " 578 "type.\n OpTypeForwardPointer %float Generic\n")); 579 } 580 581 TEST_F(ValidateData, forward_ref_points_to_non_struct) { 582 std::string str = header_with_addresses + R"( 583 OpTypeForwardPointer %_ptr_Generic_struct_A Generic 584 %uintt = OpTypeInt 32 0 585 %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A 586 %_ptr_Generic_struct_A = OpTypePointer Generic %uintt 587 )"; 588 CompileSuccessfully(str.c_str()); 589 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 590 EXPECT_THAT(getDiagnosticString(), 591 HasSubstr("A forward reference operand in an OpTypeStruct must " 592 "be an OpTypePointer that points to an OpTypeStruct. " 593 "Found OpTypePointer that points to OpTypeInt.")); 594 } 595 596 TEST_F(ValidateData, struct_forward_pointer_good) { 597 std::string str = header_with_addresses + R"( 598 OpTypeForwardPointer %_ptr_Generic_struct_A Generic 599 %uintt = OpTypeInt 32 0 600 %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A 601 %struct_C = OpTypeStruct %uintt %struct_B 602 %struct_A = OpTypeStruct %uintt %struct_C 603 %_ptr_Generic_struct_A = OpTypePointer Generic %struct_C 604 )"; 605 CompileSuccessfully(str.c_str()); 606 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 607 } 608 609 TEST_F(ValidateData, ext_16bit_storage_caps_allow_free_fp_rounding_mode) { 610 for (const char* cap : {"StorageUniform16", "StorageUniformBufferBlock16", 611 "StoragePushConstant16", "StorageInputOutput16"}) { 612 for (const char* mode : {"RTE", "RTZ", "RTP", "RTN"}) { 613 std::string str = std::string(R"( 614 OpCapability Shader 615 OpCapability Linkage 616 OpCapability )") + 617 cap + R"( 618 OpExtension "SPV_KHR_storage_buffer_storage_class" 619 OpExtension "SPV_KHR_variable_pointers" 620 OpExtension "SPV_KHR_16bit_storage" 621 OpMemoryModel Logical GLSL450 622 OpDecorate %_ FPRoundingMode )" + mode + R"( 623 %half = OpTypeFloat 16 624 %float = OpTypeFloat 32 625 %float_1_25 = OpConstant %float 1.25 626 %half_ptr = OpTypePointer StorageBuffer %half 627 %half_ptr_var = OpVariable %half_ptr StorageBuffer 628 %void = OpTypeVoid 629 %func = OpTypeFunction %void 630 %main = OpFunction %void None %func 631 %main_entry = OpLabel 632 %_ = OpFConvert %half %float_1_25 633 OpStore %half_ptr_var %_ 634 OpReturn 635 OpFunctionEnd 636 )"; 637 CompileSuccessfully(str.c_str()); 638 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 639 } 640 } 641 } 642 643 TEST_F(ValidateData, vulkan_disallow_free_fp_rounding_mode) { 644 for (const char* mode : {"RTE", "RTZ"}) { 645 for (const auto env : {SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1}) { 646 std::string str = std::string(R"( 647 OpCapability Shader 648 OpExtension "SPV_KHR_storage_buffer_storage_class" 649 OpExtension "SPV_KHR_variable_pointers" 650 OpMemoryModel Logical GLSL450 651 OpDecorate %_ FPRoundingMode )") + 652 mode + R"( 653 %half = OpTypeFloat 16 654 %float = OpTypeFloat 32 655 %float_1_25 = OpConstant %float 1.25 656 %half_ptr = OpTypePointer StorageBuffer %half 657 %half_ptr_var = OpVariable %half_ptr StorageBuffer 658 %void = OpTypeVoid 659 %func = OpTypeFunction %void 660 %main = OpFunction %void None %func 661 %main_entry = OpLabel 662 %_ = OpFConvert %half %float_1_25 663 OpStore %half_ptr_var %_ 664 OpReturn 665 OpFunctionEnd 666 )"; 667 CompileSuccessfully(str.c_str()); 668 ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions(env)); 669 EXPECT_THAT( 670 getDiagnosticString(), 671 HasSubstr("Operand 2 of Decorate requires one of these capabilities: " 672 "StorageBuffer16BitAccess StorageUniform16 " 673 "StoragePushConstant16 StorageInputOutput16")); 674 } 675 } 676 } 677 678 TEST_F(ValidateData, void_array) { 679 std::string str = header + R"( 680 %void = OpTypeVoid 681 %int = OpTypeInt 32 0 682 %int_5 = OpConstant %int 5 683 %array = OpTypeArray %void %int_5 684 )"; 685 686 CompileSuccessfully(str.c_str()); 687 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 688 EXPECT_THAT( 689 getDiagnosticString(), 690 HasSubstr("OpTypeArray Element Type <id> '1[%void]' is a void type.")); 691 } 692 693 TEST_F(ValidateData, void_runtime_array) { 694 std::string str = header + R"( 695 %void = OpTypeVoid 696 %array = OpTypeRuntimeArray %void 697 )"; 698 699 CompileSuccessfully(str.c_str()); 700 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 701 EXPECT_THAT( 702 getDiagnosticString(), 703 HasSubstr( 704 "OpTypeRuntimeArray Element Type <id> '1[%void]' is a void type.")); 705 } 706 } // namespace 707 } // namespace val 708 } // namespace spvtools 709