Home | History | Annotate | Download | only in val
      1 // Copyright (c) 2017 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 // Tests for unique type declaration rules validator.
     16 
     17 #include <string>
     18 
     19 #include "gmock/gmock.h"
     20 #include "test/unit_spirv.h"
     21 #include "test/val/val_fixtures.h"
     22 
     23 namespace spvtools {
     24 namespace val {
     25 namespace {
     26 
     27 using ::testing::HasSubstr;
     28 using ::testing::Not;
     29 
     30 using ValidateLogicals = spvtest::ValidateBase<bool>;
     31 
     32 std::string GenerateShaderCode(
     33     const std::string& body,
     34     const std::string& capabilities_and_extensions = "") {
     35   const std::string capabilities =
     36       R"(
     37 OpCapability Shader
     38 OpCapability Int64
     39 OpCapability Float64)";
     40 
     41   const std::string after_extension_before_body =
     42       R"(
     43 %ext_inst = OpExtInstImport "GLSL.std.450"
     44 OpMemoryModel Logical GLSL450
     45 OpEntryPoint Fragment %main "main"
     46 OpExecutionMode %main OriginUpperLeft
     47 %void = OpTypeVoid
     48 %func = OpTypeFunction %void
     49 %bool = OpTypeBool
     50 %f32 = OpTypeFloat 32
     51 %u32 = OpTypeInt 32 0
     52 %s32 = OpTypeInt 32 1
     53 %f64 = OpTypeFloat 64
     54 %u64 = OpTypeInt 64 0
     55 %s64 = OpTypeInt 64 1
     56 %boolvec2 = OpTypeVector %bool 2
     57 %s32vec2 = OpTypeVector %s32 2
     58 %u32vec2 = OpTypeVector %u32 2
     59 %u64vec2 = OpTypeVector %u64 2
     60 %f32vec2 = OpTypeVector %f32 2
     61 %f64vec2 = OpTypeVector %f64 2
     62 %boolvec3 = OpTypeVector %bool 3
     63 %u32vec3 = OpTypeVector %u32 3
     64 %u64vec3 = OpTypeVector %u64 3
     65 %s32vec3 = OpTypeVector %s32 3
     66 %f32vec3 = OpTypeVector %f32 3
     67 %f64vec3 = OpTypeVector %f64 3
     68 %boolvec4 = OpTypeVector %bool 4
     69 %u32vec4 = OpTypeVector %u32 4
     70 %u64vec4 = OpTypeVector %u64 4
     71 %s32vec4 = OpTypeVector %s32 4
     72 %f32vec4 = OpTypeVector %f32 4
     73 %f64vec4 = OpTypeVector %f64 4
     74 
     75 %f32_0 = OpConstant %f32 0
     76 %f32_1 = OpConstant %f32 1
     77 %f32_2 = OpConstant %f32 2
     78 %f32_3 = OpConstant %f32 3
     79 %f32_4 = OpConstant %f32 4
     80 
     81 %s32_0 = OpConstant %s32 0
     82 %s32_1 = OpConstant %s32 1
     83 %s32_2 = OpConstant %s32 2
     84 %s32_3 = OpConstant %s32 3
     85 %s32_4 = OpConstant %s32 4
     86 %s32_m1 = OpConstant %s32 -1
     87 
     88 %u32_0 = OpConstant %u32 0
     89 %u32_1 = OpConstant %u32 1
     90 %u32_2 = OpConstant %u32 2
     91 %u32_3 = OpConstant %u32 3
     92 %u32_4 = OpConstant %u32 4
     93 
     94 %f64_0 = OpConstant %f64 0
     95 %f64_1 = OpConstant %f64 1
     96 %f64_2 = OpConstant %f64 2
     97 %f64_3 = OpConstant %f64 3
     98 %f64_4 = OpConstant %f64 4
     99 
    100 %s64_0 = OpConstant %s64 0
    101 %s64_1 = OpConstant %s64 1
    102 %s64_2 = OpConstant %s64 2
    103 %s64_3 = OpConstant %s64 3
    104 %s64_4 = OpConstant %s64 4
    105 %s64_m1 = OpConstant %s64 -1
    106 
    107 %u64_0 = OpConstant %u64 0
    108 %u64_1 = OpConstant %u64 1
    109 %u64_2 = OpConstant %u64 2
    110 %u64_3 = OpConstant %u64 3
    111 %u64_4 = OpConstant %u64 4
    112 
    113 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
    114 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
    115 %u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
    116 %u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
    117 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
    118 %u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
    119 
    120 %s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1
    121 %s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2
    122 %s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2
    123 %s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3
    124 %s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3
    125 %s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4
    126 
    127 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
    128 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
    129 %f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
    130 %f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
    131 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
    132 %f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
    133 
    134 %f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1
    135 %f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2
    136 %f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2
    137 %f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3
    138 %f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3
    139 %f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4
    140 
    141 %true = OpConstantTrue %bool
    142 %false = OpConstantFalse %bool
    143 %boolvec2_tf = OpConstantComposite %boolvec2 %true %false
    144 %boolvec3_tft = OpConstantComposite %boolvec3 %true %false %true
    145 %boolvec4_tftf = OpConstantComposite %boolvec4 %true %false %true %false
    146 
    147 %f32vec4ptr = OpTypePointer Function %f32vec4
    148 
    149 %main = OpFunction %void None %func
    150 %main_entry = OpLabel)";
    151 
    152   const std::string after_body =
    153       R"(
    154 OpReturn
    155 OpFunctionEnd)";
    156 
    157   return capabilities + capabilities_and_extensions +
    158          after_extension_before_body + body + after_body;
    159 }
    160 
    161 std::string GenerateKernelCode(
    162     const std::string& body,
    163     const std::string& capabilities_and_extensions = "") {
    164   const std::string capabilities =
    165       R"(
    166 OpCapability Addresses
    167 OpCapability Kernel
    168 OpCapability Linkage
    169 OpCapability Int64
    170 OpCapability Float64)";
    171 
    172   const std::string after_extension_before_body =
    173       R"(
    174 OpMemoryModel Physical32 OpenCL
    175 %void = OpTypeVoid
    176 %func = OpTypeFunction %void
    177 %bool = OpTypeBool
    178 %f32 = OpTypeFloat 32
    179 %u32 = OpTypeInt 32 0
    180 %f64 = OpTypeFloat 64
    181 %u64 = OpTypeInt 64 0
    182 %boolvec2 = OpTypeVector %bool 2
    183 %u32vec2 = OpTypeVector %u32 2
    184 %u64vec2 = OpTypeVector %u64 2
    185 %f32vec2 = OpTypeVector %f32 2
    186 %f64vec2 = OpTypeVector %f64 2
    187 %boolvec3 = OpTypeVector %bool 3
    188 %u32vec3 = OpTypeVector %u32 3
    189 %u64vec3 = OpTypeVector %u64 3
    190 %f32vec3 = OpTypeVector %f32 3
    191 %f64vec3 = OpTypeVector %f64 3
    192 %boolvec4 = OpTypeVector %bool 4
    193 %u32vec4 = OpTypeVector %u32 4
    194 %u64vec4 = OpTypeVector %u64 4
    195 %f32vec4 = OpTypeVector %f32 4
    196 %f64vec4 = OpTypeVector %f64 4
    197 
    198 %f32_0 = OpConstant %f32 0
    199 %f32_1 = OpConstant %f32 1
    200 %f32_2 = OpConstant %f32 2
    201 %f32_3 = OpConstant %f32 3
    202 %f32_4 = OpConstant %f32 4
    203 
    204 %u32_0 = OpConstant %u32 0
    205 %u32_1 = OpConstant %u32 1
    206 %u32_2 = OpConstant %u32 2
    207 %u32_3 = OpConstant %u32 3
    208 %u32_4 = OpConstant %u32 4
    209 
    210 %f64_0 = OpConstant %f64 0
    211 %f64_1 = OpConstant %f64 1
    212 %f64_2 = OpConstant %f64 2
    213 %f64_3 = OpConstant %f64 3
    214 %f64_4 = OpConstant %f64 4
    215 
    216 %u64_0 = OpConstant %u64 0
    217 %u64_1 = OpConstant %u64 1
    218 %u64_2 = OpConstant %u64 2
    219 %u64_3 = OpConstant %u64 3
    220 %u64_4 = OpConstant %u64 4
    221 
    222 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
    223 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
    224 %u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
    225 %u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
    226 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
    227 %u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
    228 
    229 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
    230 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
    231 %f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
    232 %f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
    233 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
    234 %f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
    235 
    236 %f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1
    237 %f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2
    238 %f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2
    239 %f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3
    240 %f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3
    241 %f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4
    242 
    243 %true = OpConstantTrue %bool
    244 %false = OpConstantFalse %bool
    245 %boolvec2_tf = OpConstantComposite %boolvec2 %true %false
    246 %boolvec3_tft = OpConstantComposite %boolvec3 %true %false %true
    247 %boolvec4_tftf = OpConstantComposite %boolvec4 %true %false %true %false
    248 
    249 %f32vec4ptr = OpTypePointer Function %f32vec4
    250 
    251 %main = OpFunction %void None %func
    252 %main_entry = OpLabel)";
    253 
    254   const std::string after_body =
    255       R"(
    256 OpReturn
    257 OpFunctionEnd)";
    258 
    259   return capabilities + capabilities_and_extensions +
    260          after_extension_before_body + body + after_body;
    261 }
    262 
    263 TEST_F(ValidateLogicals, OpAnySuccess) {
    264   const std::string body = R"(
    265 %val1 = OpAny %bool %boolvec2_tf
    266 %val2 = OpAny %bool %boolvec3_tft
    267 %val3 = OpAny %bool %boolvec4_tftf
    268 )";
    269 
    270   CompileSuccessfully(GenerateShaderCode(body).c_str());
    271   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    272 }
    273 
    274 TEST_F(ValidateLogicals, OpAnyWrongTypeId) {
    275   const std::string body = R"(
    276 %val = OpAny %u32 %boolvec2_tf
    277 )";
    278 
    279   CompileSuccessfully(GenerateShaderCode(body).c_str());
    280   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    281   EXPECT_THAT(getDiagnosticString(),
    282               HasSubstr("Expected bool scalar type as Result Type: Any"));
    283 }
    284 
    285 TEST_F(ValidateLogicals, OpAnyWrongOperand) {
    286   const std::string body = R"(
    287 %val = OpAny %bool %u32vec3_123
    288 )";
    289 
    290   CompileSuccessfully(GenerateShaderCode(body).c_str());
    291   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    292   EXPECT_THAT(getDiagnosticString(),
    293               HasSubstr("Expected operand to be vector bool: Any"));
    294 }
    295 
    296 TEST_F(ValidateLogicals, OpIsNanSuccess) {
    297   const std::string body = R"(
    298 %val1 = OpIsNan %bool %f32_1
    299 %val2 = OpIsNan %bool %f64_0
    300 %val3 = OpIsNan %boolvec2 %f32vec2_12
    301 %val4 = OpIsNan %boolvec3 %f32vec3_123
    302 %val5 = OpIsNan %boolvec4 %f32vec4_1234
    303 )";
    304 
    305   CompileSuccessfully(GenerateShaderCode(body).c_str());
    306   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    307 }
    308 
    309 TEST_F(ValidateLogicals, OpIsNanWrongTypeId) {
    310   const std::string body = R"(
    311 %val1 = OpIsNan %u32 %f32_1
    312 )";
    313 
    314   CompileSuccessfully(GenerateShaderCode(body).c_str());
    315   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    316   EXPECT_THAT(
    317       getDiagnosticString(),
    318       HasSubstr("Expected bool scalar or vector type as Result Type: IsNan"));
    319 }
    320 
    321 TEST_F(ValidateLogicals, OpIsNanOperandNotFloat) {
    322   const std::string body = R"(
    323 %val1 = OpIsNan %bool %u32_1
    324 )";
    325 
    326   CompileSuccessfully(GenerateShaderCode(body).c_str());
    327   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    328   EXPECT_THAT(
    329       getDiagnosticString(),
    330       HasSubstr("Expected operand to be scalar or vector float: IsNan"));
    331 }
    332 
    333 TEST_F(ValidateLogicals, OpIsNanOperandWrongSize) {
    334   const std::string body = R"(
    335 %val1 = OpIsNan %bool %f32vec2_12
    336 )";
    337 
    338   CompileSuccessfully(GenerateShaderCode(body).c_str());
    339   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    340   EXPECT_THAT(
    341       getDiagnosticString(),
    342       HasSubstr(
    343           "Expected vector sizes of Result Type and the operand to be equal: "
    344           "IsNan"));
    345 }
    346 
    347 TEST_F(ValidateLogicals, OpLessOrGreaterSuccess) {
    348   const std::string body = R"(
    349 %val1 = OpLessOrGreater %bool %f32_0 %f32_1
    350 %val2 = OpLessOrGreater %bool %f64_0 %f64_0
    351 %val3 = OpLessOrGreater %boolvec2 %f32vec2_12 %f32vec2_12
    352 %val4 = OpLessOrGreater %boolvec3 %f32vec3_123 %f32vec3_123
    353 %val5 = OpLessOrGreater %boolvec4 %f32vec4_1234 %f32vec4_1234
    354 )";
    355 
    356   CompileSuccessfully(GenerateKernelCode(body).c_str());
    357   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    358 }
    359 
    360 TEST_F(ValidateLogicals, OpLessOrGreaterWrongTypeId) {
    361   const std::string body = R"(
    362 %val1 = OpLessOrGreater %u32 %f32_1 %f32_1
    363 )";
    364 
    365   CompileSuccessfully(GenerateKernelCode(body).c_str());
    366   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    367   EXPECT_THAT(
    368       getDiagnosticString(),
    369       HasSubstr(
    370           "Expected bool scalar or vector type as Result Type: LessOrGreater"));
    371 }
    372 
    373 TEST_F(ValidateLogicals, OpLessOrGreaterLeftOperandNotFloat) {
    374   const std::string body = R"(
    375 %val1 = OpLessOrGreater %bool %u32_1 %f32_1
    376 )";
    377 
    378   CompileSuccessfully(GenerateKernelCode(body).c_str());
    379   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    380   EXPECT_THAT(
    381       getDiagnosticString(),
    382       HasSubstr(
    383           "Expected operands to be scalar or vector float: LessOrGreater"));
    384 }
    385 
    386 TEST_F(ValidateLogicals, OpLessOrGreaterLeftOperandWrongSize) {
    387   const std::string body = R"(
    388 %val1 = OpLessOrGreater %bool %f32vec2_12 %f32_1
    389 )";
    390 
    391   CompileSuccessfully(GenerateKernelCode(body).c_str());
    392   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    393   EXPECT_THAT(
    394       getDiagnosticString(),
    395       HasSubstr(
    396           "Expected vector sizes of Result Type and the operands to be equal: "
    397           "LessOrGreater"));
    398 }
    399 
    400 TEST_F(ValidateLogicals, OpLessOrGreaterOperandsDifferentType) {
    401   const std::string body = R"(
    402 %val1 = OpLessOrGreater %bool %f32_1 %f64_1
    403 )";
    404 
    405   CompileSuccessfully(GenerateKernelCode(body).c_str());
    406   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    407   EXPECT_THAT(
    408       getDiagnosticString(),
    409       HasSubstr("Expected left and right operands to have the same type: "
    410                 "LessOrGreater"));
    411 }
    412 
    413 TEST_F(ValidateLogicals, OpFOrdEqualSuccess) {
    414   const std::string body = R"(
    415 %val1 = OpFOrdEqual %bool %f32_0 %f32_1
    416 %val2 = OpFOrdEqual %bool %f64_0 %f64_0
    417 %val3 = OpFOrdEqual %boolvec2 %f32vec2_12 %f32vec2_12
    418 %val4 = OpFOrdEqual %boolvec3 %f32vec3_123 %f32vec3_123
    419 %val5 = OpFOrdEqual %boolvec4 %f32vec4_1234 %f32vec4_1234
    420 )";
    421 
    422   CompileSuccessfully(GenerateShaderCode(body).c_str());
    423   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    424 }
    425 
    426 TEST_F(ValidateLogicals, OpFOrdEqualWrongTypeId) {
    427   const std::string body = R"(
    428 %val1 = OpFOrdEqual %u32 %f32_1 %f32_1
    429 )";
    430 
    431   CompileSuccessfully(GenerateShaderCode(body).c_str());
    432   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    433   EXPECT_THAT(
    434       getDiagnosticString(),
    435       HasSubstr(
    436           "Expected bool scalar or vector type as Result Type: FOrdEqual"));
    437 }
    438 
    439 TEST_F(ValidateLogicals, OpFOrdEqualLeftOperandNotFloat) {
    440   const std::string body = R"(
    441 %val1 = OpFOrdEqual %bool %u32_1 %f32_1
    442 )";
    443 
    444   CompileSuccessfully(GenerateShaderCode(body).c_str());
    445   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    446   EXPECT_THAT(
    447       getDiagnosticString(),
    448       HasSubstr("Expected operands to be scalar or vector float: FOrdEqual"));
    449 }
    450 
    451 TEST_F(ValidateLogicals, OpFOrdEqualLeftOperandWrongSize) {
    452   const std::string body = R"(
    453 %val1 = OpFOrdEqual %bool %f32vec2_12 %f32_1
    454 )";
    455 
    456   CompileSuccessfully(GenerateShaderCode(body).c_str());
    457   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    458   EXPECT_THAT(
    459       getDiagnosticString(),
    460       HasSubstr(
    461           "Expected vector sizes of Result Type and the operands to be equal: "
    462           "FOrdEqual"));
    463 }
    464 
    465 TEST_F(ValidateLogicals, OpFOrdEqualOperandsDifferentType) {
    466   const std::string body = R"(
    467 %val1 = OpFOrdEqual %bool %f32_1 %f64_1
    468 )";
    469 
    470   CompileSuccessfully(GenerateShaderCode(body).c_str());
    471   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    472   EXPECT_THAT(
    473       getDiagnosticString(),
    474       HasSubstr("Expected left and right operands to have the same type: "
    475                 "FOrdEqual"));
    476 }
    477 
    478 TEST_F(ValidateLogicals, OpLogicalEqualSuccess) {
    479   const std::string body = R"(
    480 %val1 = OpLogicalEqual %bool %true %false
    481 %val2 = OpLogicalEqual %boolvec2 %boolvec2_tf   %boolvec2_tf
    482 %val3 = OpLogicalEqual %boolvec3 %boolvec3_tft  %boolvec3_tft
    483 %val4 = OpLogicalEqual %boolvec4 %boolvec4_tftf %boolvec4_tftf
    484 )";
    485 
    486   CompileSuccessfully(GenerateKernelCode(body).c_str());
    487   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    488 }
    489 
    490 TEST_F(ValidateLogicals, OpLogicalEqualWrongTypeId) {
    491   const std::string body = R"(
    492 %val1 = OpLogicalEqual %u32 %true %false
    493 )";
    494 
    495   CompileSuccessfully(GenerateKernelCode(body).c_str());
    496   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    497   EXPECT_THAT(
    498       getDiagnosticString(),
    499       HasSubstr(
    500           "Expected bool scalar or vector type as Result Type: LogicalEqual"));
    501 }
    502 
    503 TEST_F(ValidateLogicals, OpLogicalEqualWrongLeftOperand) {
    504   const std::string body = R"(
    505 %val1 = OpLogicalEqual %bool %boolvec2_tf %false
    506 )";
    507 
    508   CompileSuccessfully(GenerateKernelCode(body).c_str());
    509   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    510   EXPECT_THAT(
    511       getDiagnosticString(),
    512       HasSubstr("Expected both operands to be of Result Type: LogicalEqual"));
    513 }
    514 
    515 TEST_F(ValidateLogicals, OpLogicalEqualWrongRightOperand) {
    516   const std::string body = R"(
    517 %val1 = OpLogicalEqual %boolvec2 %boolvec2_tf %false
    518 )";
    519 
    520   CompileSuccessfully(GenerateKernelCode(body).c_str());
    521   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    522   EXPECT_THAT(
    523       getDiagnosticString(),
    524       HasSubstr("Expected both operands to be of Result Type: LogicalEqual"));
    525 }
    526 
    527 TEST_F(ValidateLogicals, OpLogicalNotSuccess) {
    528   const std::string body = R"(
    529 %val1 = OpLogicalNot %bool %true
    530 %val2 = OpLogicalNot %boolvec2 %boolvec2_tf
    531 %val3 = OpLogicalNot %boolvec3 %boolvec3_tft
    532 %val4 = OpLogicalNot %boolvec4 %boolvec4_tftf
    533 )";
    534 
    535   CompileSuccessfully(GenerateKernelCode(body).c_str());
    536   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    537 }
    538 
    539 TEST_F(ValidateLogicals, OpLogicalNotWrongTypeId) {
    540   const std::string body = R"(
    541 %val1 = OpLogicalNot %u32 %true
    542 )";
    543 
    544   CompileSuccessfully(GenerateKernelCode(body).c_str());
    545   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    546   EXPECT_THAT(
    547       getDiagnosticString(),
    548       HasSubstr(
    549           "Expected bool scalar or vector type as Result Type: LogicalNot"));
    550 }
    551 
    552 TEST_F(ValidateLogicals, OpLogicalNotWrongOperand) {
    553   const std::string body = R"(
    554 %val1 = OpLogicalNot %bool %boolvec2_tf
    555 )";
    556 
    557   CompileSuccessfully(GenerateKernelCode(body).c_str());
    558   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    559   EXPECT_THAT(getDiagnosticString(),
    560               HasSubstr("Expected operand to be of Result Type: LogicalNot"));
    561 }
    562 
    563 TEST_F(ValidateLogicals, OpSelectSuccess) {
    564   const std::string body = R"(
    565 %val1 = OpSelect %u32 %true %u32_0 %u32_1
    566 %val2 = OpSelect %f32 %true %f32_0 %f32_1
    567 %val3 = OpSelect %f64 %true %f64_0 %f64_1
    568 %val4 = OpSelect %f32vec2 %boolvec2_tf %f32vec2_01 %f32vec2_12
    569 %val5 = OpSelect %f32vec4 %boolvec4_tftf %f32vec4_0123 %f32vec4_1234
    570 )";
    571 
    572   CompileSuccessfully(GenerateShaderCode(body).c_str());
    573   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    574 }
    575 
    576 TEST_F(ValidateLogicals, OpSelectWrongTypeId) {
    577   const std::string body = R"(
    578 %val1 = OpSelect %void %true %u32_0 %u32_1
    579 )";
    580 
    581   CompileSuccessfully(GenerateShaderCode(body).c_str());
    582   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    583   EXPECT_THAT(
    584       getDiagnosticString(),
    585       HasSubstr("Expected scalar or vector type as Result Type: Select"));
    586 }
    587 
    588 TEST_F(ValidateLogicals, OpSelectPointerNoCapability) {
    589   const std::string body = R"(
    590 %x = OpVariable %f32vec4ptr Function
    591 %y = OpVariable %f32vec4ptr Function
    592 OpStore %x %f32vec4_0123
    593 OpStore %y %f32vec4_1234
    594 %val1 = OpSelect %f32vec4ptr %true %x %y
    595 )";
    596 
    597   CompileSuccessfully(GenerateShaderCode(body).c_str());
    598   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    599   EXPECT_THAT(
    600       getDiagnosticString(),
    601       HasSubstr(
    602           "Using pointers with OpSelect requires capability VariablePointers "
    603           "or VariablePointersStorageBuffer"));
    604 }
    605 
    606 TEST_F(ValidateLogicals, OpSelectPointerWithCapability1) {
    607   const std::string body = R"(
    608 %x = OpVariable %f32vec4ptr Function
    609 %y = OpVariable %f32vec4ptr Function
    610 OpStore %x %f32vec4_0123
    611 OpStore %y %f32vec4_1234
    612 %val1 = OpSelect %f32vec4ptr %true %x %y
    613 )";
    614 
    615   const std::string extra_cap_ext = R"(
    616 OpCapability VariablePointers
    617 OpExtension "SPV_KHR_variable_pointers"
    618 )";
    619 
    620   CompileSuccessfully(GenerateShaderCode(body, extra_cap_ext).c_str());
    621   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    622 }
    623 
    624 TEST_F(ValidateLogicals, OpSelectPointerWithCapability2) {
    625   const std::string body = R"(
    626 %x = OpVariable %f32vec4ptr Function
    627 %y = OpVariable %f32vec4ptr Function
    628 OpStore %x %f32vec4_0123
    629 OpStore %y %f32vec4_1234
    630 %val1 = OpSelect %f32vec4ptr %true %x %y
    631 )";
    632 
    633   const std::string extra_cap_ext = R"(
    634 OpCapability VariablePointersStorageBuffer
    635 OpExtension "SPV_KHR_variable_pointers"
    636 )";
    637 
    638   CompileSuccessfully(GenerateShaderCode(body, extra_cap_ext).c_str());
    639   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    640 }
    641 
    642 TEST_F(ValidateLogicals, OpSelectWrongCondition) {
    643   const std::string body = R"(
    644 %val1 = OpSelect %u32 %u32_1 %u32_0 %u32_1
    645 )";
    646 
    647   CompileSuccessfully(GenerateShaderCode(body).c_str());
    648   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    649   EXPECT_THAT(
    650       getDiagnosticString(),
    651       HasSubstr("Expected bool scalar or vector type as condition: Select"));
    652 }
    653 
    654 TEST_F(ValidateLogicals, OpSelectWrongConditionDimension) {
    655   const std::string body = R"(
    656 %val1 = OpSelect %u32vec2 %true %u32vec2_01 %u32vec2_12
    657 )";
    658 
    659   CompileSuccessfully(GenerateShaderCode(body).c_str());
    660   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    661   EXPECT_THAT(
    662       getDiagnosticString(),
    663       HasSubstr(
    664           "Expected vector sizes of Result Type and the condition to be equal: "
    665           "Select"));
    666 }
    667 
    668 TEST_F(ValidateLogicals, OpSelectWrongLeftObject) {
    669   const std::string body = R"(
    670 %val1 = OpSelect %bool %true %u32vec2_01 %u32_1
    671 )";
    672 
    673   CompileSuccessfully(GenerateShaderCode(body).c_str());
    674   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    675   EXPECT_THAT(getDiagnosticString(),
    676               HasSubstr("Expected both objects to be of Result Type: Select"));
    677 }
    678 
    679 TEST_F(ValidateLogicals, OpSelectWrongRightObject) {
    680   const std::string body = R"(
    681 %val1 = OpSelect %bool %true %u32_1 %u32vec2_01
    682 )";
    683 
    684   CompileSuccessfully(GenerateShaderCode(body).c_str());
    685   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    686   EXPECT_THAT(getDiagnosticString(),
    687               HasSubstr("Expected both objects to be of Result Type: Select"));
    688 }
    689 
    690 TEST_F(ValidateLogicals, OpIEqualSuccess) {
    691   const std::string body = R"(
    692 %val1 = OpIEqual %bool %u32_0 %s32_1
    693 %val2 = OpIEqual %bool %s64_0 %u64_0
    694 %val3 = OpIEqual %boolvec2 %s32vec2_12 %u32vec2_12
    695 %val4 = OpIEqual %boolvec3 %s32vec3_123 %u32vec3_123
    696 %val5 = OpIEqual %boolvec4 %s32vec4_1234 %u32vec4_1234
    697 )";
    698 
    699   CompileSuccessfully(GenerateShaderCode(body).c_str());
    700   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    701 }
    702 
    703 TEST_F(ValidateLogicals, OpIEqualWrongTypeId) {
    704   const std::string body = R"(
    705 %val1 = OpIEqual %u32 %s32_1 %s32_1
    706 )";
    707 
    708   CompileSuccessfully(GenerateShaderCode(body).c_str());
    709   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    710   EXPECT_THAT(
    711       getDiagnosticString(),
    712       HasSubstr("Expected bool scalar or vector type as Result Type: IEqual"));
    713 }
    714 
    715 TEST_F(ValidateLogicals, OpIEqualLeftOperandNotInt) {
    716   const std::string body = R"(
    717 %val1 = OpIEqual %bool %f32_1 %s32_1
    718 )";
    719 
    720   CompileSuccessfully(GenerateShaderCode(body).c_str());
    721   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    722   EXPECT_THAT(
    723       getDiagnosticString(),
    724       HasSubstr("Expected operands to be scalar or vector int: IEqual"));
    725 }
    726 
    727 TEST_F(ValidateLogicals, OpIEqualLeftOperandWrongSize) {
    728   const std::string body = R"(
    729 %val1 = OpIEqual %bool %s32vec2_12 %s32_1
    730 )";
    731 
    732   CompileSuccessfully(GenerateShaderCode(body).c_str());
    733   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    734   EXPECT_THAT(
    735       getDiagnosticString(),
    736       HasSubstr(
    737           "Expected vector sizes of Result Type and the operands to be equal: "
    738           "IEqual"));
    739 }
    740 
    741 TEST_F(ValidateLogicals, OpIEqualRightOperandNotInt) {
    742   const std::string body = R"(
    743 %val1 = OpIEqual %bool %u32_1 %f32_1
    744 )";
    745 
    746   CompileSuccessfully(GenerateShaderCode(body).c_str());
    747   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    748   EXPECT_THAT(
    749       getDiagnosticString(),
    750       HasSubstr("Expected operands to be scalar or vector int: IEqual"));
    751 }
    752 
    753 TEST_F(ValidateLogicals, OpIEqualDifferentBitWidth) {
    754   const std::string body = R"(
    755 %val1 = OpIEqual %bool %u32_1 %u64_1
    756 )";
    757 
    758   CompileSuccessfully(GenerateShaderCode(body).c_str());
    759   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    760   EXPECT_THAT(getDiagnosticString(),
    761               HasSubstr("Expected both operands to have the same component bit "
    762                         "width: IEqual"));
    763 }
    764 
    765 TEST_F(ValidateLogicals, OpUGreaterThanSuccess) {
    766   const std::string body = R"(
    767 %val1 = OpUGreaterThan %bool %u32_0 %u32_1
    768 %val2 = OpUGreaterThan %bool %s32_0 %u32_1
    769 %val3 = OpUGreaterThan %bool %u64_0 %u64_0
    770 %val4 = OpUGreaterThan %bool %u64_0 %s64_0
    771 %val5 = OpUGreaterThan %boolvec2 %u32vec2_12 %u32vec2_12
    772 %val6 = OpUGreaterThan %boolvec3 %s32vec3_123 %u32vec3_123
    773 %val7 = OpUGreaterThan %boolvec4 %u32vec4_1234 %u32vec4_1234
    774 )";
    775 
    776   CompileSuccessfully(GenerateShaderCode(body).c_str());
    777   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    778 }
    779 
    780 TEST_F(ValidateLogicals, OpUGreaterThanWrongTypeId) {
    781   const std::string body = R"(
    782 %val1 = OpUGreaterThan %u32 %u32_1 %u32_1
    783 )";
    784 
    785   CompileSuccessfully(GenerateShaderCode(body).c_str());
    786   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    787   EXPECT_THAT(
    788       getDiagnosticString(),
    789       HasSubstr(
    790           "Expected bool scalar or vector type as Result Type: UGreaterThan"));
    791 }
    792 
    793 TEST_F(ValidateLogicals, OpUGreaterThanLeftOperandNotInt) {
    794   const std::string body = R"(
    795 %val1 = OpUGreaterThan %bool %f32_1 %u32_1
    796 )";
    797 
    798   CompileSuccessfully(GenerateShaderCode(body).c_str());
    799   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    800   EXPECT_THAT(
    801       getDiagnosticString(),
    802       HasSubstr("Expected operands to be scalar or vector int: UGreaterThan"));
    803 }
    804 
    805 TEST_F(ValidateLogicals, OpUGreaterThanLeftOperandWrongSize) {
    806   const std::string body = R"(
    807 %val1 = OpUGreaterThan %bool %u32vec2_12 %u32_1
    808 )";
    809 
    810   CompileSuccessfully(GenerateShaderCode(body).c_str());
    811   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    812   EXPECT_THAT(
    813       getDiagnosticString(),
    814       HasSubstr(
    815           "Expected vector sizes of Result Type and the operands to be equal: "
    816           "UGreaterThan"));
    817 }
    818 
    819 TEST_F(ValidateLogicals, OpUGreaterThanRightOperandNotInt) {
    820   const std::string body = R"(
    821 %val1 = OpUGreaterThan %bool %u32_1 %f32_1
    822 )";
    823 
    824   CompileSuccessfully(GenerateShaderCode(body).c_str());
    825   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    826   EXPECT_THAT(
    827       getDiagnosticString(),
    828       HasSubstr("Expected operands to be scalar or vector int: UGreaterThan"));
    829 }
    830 
    831 TEST_F(ValidateLogicals, OpUGreaterThanDifferentBitWidth) {
    832   const std::string body = R"(
    833 %val1 = OpUGreaterThan %bool %u32_1 %u64_1
    834 )";
    835 
    836   CompileSuccessfully(GenerateShaderCode(body).c_str());
    837   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    838   EXPECT_THAT(
    839       getDiagnosticString(),
    840       HasSubstr("Expected both operands to have the same component bit width: "
    841                 "UGreaterThan"));
    842 }
    843 
    844 TEST_F(ValidateLogicals, OpSGreaterThanSuccess) {
    845   const std::string body = R"(
    846 %val1 = OpSGreaterThan %bool %s32_0 %s32_1
    847 %val2 = OpSGreaterThan %bool %u32_0 %s32_1
    848 %val3 = OpSGreaterThan %bool %s64_0 %s64_0
    849 %val4 = OpSGreaterThan %bool %s64_0 %u64_0
    850 %val5 = OpSGreaterThan %boolvec2 %s32vec2_12 %s32vec2_12
    851 %val6 = OpSGreaterThan %boolvec3 %s32vec3_123 %u32vec3_123
    852 %val7 = OpSGreaterThan %boolvec4 %s32vec4_1234 %s32vec4_1234
    853 )";
    854 
    855   CompileSuccessfully(GenerateShaderCode(body).c_str());
    856   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
    857 }
    858 
    859 TEST_F(ValidateLogicals, OpSGreaterThanWrongTypeId) {
    860   const std::string body = R"(
    861 %val1 = OpSGreaterThan %s32 %s32_1 %s32_1
    862 )";
    863 
    864   CompileSuccessfully(GenerateShaderCode(body).c_str());
    865   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    866   EXPECT_THAT(
    867       getDiagnosticString(),
    868       HasSubstr(
    869           "Expected bool scalar or vector type as Result Type: SGreaterThan"));
    870 }
    871 
    872 TEST_F(ValidateLogicals, OpSGreaterThanLeftOperandNotInt) {
    873   const std::string body = R"(
    874 %val1 = OpSGreaterThan %bool %f32_1 %s32_1
    875 )";
    876 
    877   CompileSuccessfully(GenerateShaderCode(body).c_str());
    878   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    879   EXPECT_THAT(
    880       getDiagnosticString(),
    881       HasSubstr("Expected operands to be scalar or vector int: SGreaterThan"));
    882 }
    883 
    884 TEST_F(ValidateLogicals, OpSGreaterThanLeftOperandWrongSize) {
    885   const std::string body = R"(
    886 %val1 = OpSGreaterThan %bool %s32vec2_12 %s32_1
    887 )";
    888 
    889   CompileSuccessfully(GenerateShaderCode(body).c_str());
    890   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    891   EXPECT_THAT(
    892       getDiagnosticString(),
    893       HasSubstr(
    894           "Expected vector sizes of Result Type and the operands to be equal: "
    895           "SGreaterThan"));
    896 }
    897 
    898 TEST_F(ValidateLogicals, OpSGreaterThanRightOperandNotInt) {
    899   const std::string body = R"(
    900 %val1 = OpSGreaterThan %bool %s32_1 %f32_1
    901 )";
    902 
    903   CompileSuccessfully(GenerateShaderCode(body).c_str());
    904   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    905   EXPECT_THAT(
    906       getDiagnosticString(),
    907       HasSubstr("Expected operands to be scalar or vector int: SGreaterThan"));
    908 }
    909 
    910 TEST_F(ValidateLogicals, OpSGreaterThanDifferentBitWidth) {
    911   const std::string body = R"(
    912 %val1 = OpSGreaterThan %bool %s32_1 %s64_1
    913 )";
    914 
    915   CompileSuccessfully(GenerateShaderCode(body).c_str());
    916   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
    917   EXPECT_THAT(getDiagnosticString(),
    918               HasSubstr("Expected both operands to have the same component bit "
    919                         "width: SGreaterThan"));
    920 }
    921 
    922 }  // namespace
    923 }  // namespace val
    924 }  // namespace spvtools
    925