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