| // Copyright (c) 2017 Google Inc. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| // Validation tests for illegal literals | |
| #include <string> | |
| #include <utility> | |
| #include "gmock/gmock.h" | |
| #include "test/val/val_fixtures.h" | |
| namespace spvtools { | |
| namespace val { | |
| namespace { | |
| using ::testing::HasSubstr; | |
| using ValidateLiterals = spvtest::ValidateBase<std::string>; | |
| using ValidateLiteralsShader = spvtest::ValidateBase<std::string>; | |
| using ValidateLiteralsKernel = spvtest::ValidateBase<std::string>; | |
| std::string GenerateShaderCode() { | |
| std::string str = R"( | |
| OpCapability Shader | |
| OpCapability Linkage | |
| OpCapability Int16 | |
| OpCapability Int64 | |
| OpCapability Float16 | |
| OpCapability Float64 | |
| OpMemoryModel Logical GLSL450 | |
| %int16 = OpTypeInt 16 1 | |
| %uint16 = OpTypeInt 16 0 | |
| %int32 = OpTypeInt 32 1 | |
| %uint32 = OpTypeInt 32 0 | |
| %int64 = OpTypeInt 64 1 | |
| %uint64 = OpTypeInt 64 0 | |
| %half = OpTypeFloat 16 | |
| %float = OpTypeFloat 32 | |
| %double = OpTypeFloat 64 | |
| %10 = OpTypeVoid | |
| )"; | |
| return str; | |
| } | |
| std::string GenerateKernelCode() { | |
| std::string str = R"( | |
| OpCapability Kernel | |
| OpCapability Addresses | |
| OpCapability Linkage | |
| OpCapability Int8 | |
| OpMemoryModel Physical64 OpenCL | |
| %uint8 = OpTypeInt 8 0 | |
| )"; | |
| return str; | |
| } | |
| TEST_F(ValidateLiterals, LiteralsShaderGood) { | |
| std::string str = GenerateShaderCode() + R"( | |
| %11 = OpConstant %int16 !0x00007FFF | |
| %12 = OpConstant %int16 !0xFFFF8000 | |
| %13 = OpConstant %int16 !0xFFFFABCD | |
| %14 = OpConstant %uint16 !0x0000ABCD | |
| %15 = OpConstant %int16 -32768 | |
| %16 = OpConstant %uint16 65535 | |
| %17 = OpConstant %int32 -2147483648 | |
| %18 = OpConstant %uint32 4294967295 | |
| %19 = OpConstant %int64 -9223372036854775808 | |
| %20 = OpConstant %uint64 18446744073709551615 | |
| %21 = OpConstant %half !0x0000FFFF | |
| %22 = OpConstant %float !0xFFFFFFFF | |
| %23 = OpConstant %double !0xFFFFFFFF !0xFFFFFFFF | |
| )"; | |
| CompileSuccessfully(str); | |
| ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); | |
| } | |
| TEST_F(ValidateLiterals, InvalidInt) { | |
| std::string str = GenerateShaderCode() + R"( | |
| %11 = OpTypeInt 32 90 | |
| )"; | |
| CompileSuccessfully(str); | |
| EXPECT_EQ(SPV_ERROR_INVALID_VALUE, ValidateInstructions()); | |
| EXPECT_THAT(getDiagnosticString(), | |
| HasSubstr("OpTypeInt has invalid signedness:")); | |
| } | |
| TEST_P(ValidateLiteralsShader, LiteralsShaderBad) { | |
| std::string str = GenerateShaderCode() + GetParam(); | |
| std::string inst_id = "11"; | |
| CompileSuccessfully(str); | |
| EXPECT_EQ(SPV_ERROR_INVALID_VALUE, ValidateInstructions()); | |
| EXPECT_THAT( | |
| getDiagnosticString(), | |
| HasSubstr("The high-order bits of a literal number in instruction <id> " + | |
| inst_id + | |
| " must be 0 for a floating-point type, " | |
| "or 0 for an integer type with Signedness of 0, " | |
| "or sign extended when Signedness is 1")); | |
| } | |
| INSTANTIATE_TEST_SUITE_P( | |
| LiteralsShaderCases, ValidateLiteralsShader, | |
| ::testing::Values("%11 = OpConstant %int16 !0xFFFF0000", // Sign bit is 0 | |
| "%11 = OpConstant %int16 !0x00008000", // Sign bit is 1 | |
| "%11 = OpConstant %int16 !0xABCD8000", // Sign bit is 1 | |
| "%11 = OpConstant %int16 !0xABCD0000", | |
| "%11 = OpConstant %uint16 !0xABCD0000", | |
| "%11 = OpConstant %half !0xABCD0000", | |
| "%11 = OpConstant %half !0x00010000")); | |
| TEST_F(ValidateLiterals, LiteralsKernelGood) { | |
| std::string str = GenerateKernelCode() + R"( | |
| %4 = OpConstant %uint8 !0x000000AB | |
| %6 = OpConstant %uint8 255 | |
| )"; | |
| CompileSuccessfully(str); | |
| ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); | |
| } | |
| TEST_P(ValidateLiteralsKernel, LiteralsKernelBad) { | |
| std::string str = GenerateKernelCode() + GetParam(); | |
| std::string inst_id = "2"; | |
| CompileSuccessfully(str); | |
| EXPECT_EQ(SPV_ERROR_INVALID_VALUE, ValidateInstructions()); | |
| EXPECT_THAT( | |
| getDiagnosticString(), | |
| HasSubstr("The high-order bits of a literal number in instruction <id> " + | |
| inst_id + | |
| " must be 0 for a floating-point type, " | |
| "or 0 for an integer type with Signedness of 0, " | |
| "or sign extended when Signedness is 1")); | |
| } | |
| INSTANTIATE_TEST_SUITE_P( | |
| LiteralsKernelCases, ValidateLiteralsKernel, | |
| ::testing::Values("%2 = OpConstant %uint8 !0xABCDEF00", | |
| "%2 = OpConstant %uint8 !0xABCDEFFF")); | |
| } // namespace | |
| } // namespace val | |
| } // namespace spvtools |