Home | History | Annotate | Download | only in val
      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