| // 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 ilegal 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_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_CASE_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_CASE_P( |
| LiteralsKernelCases, ValidateLiteralsKernel, |
| ::testing::Values("%2 = OpConstant %uint8 !0xABCDEF00", |
| "%2 = OpConstant %uint8 !0xABCDEFFF")); |
| |
| } // namespace |
| } // namespace val |
| } // namespace spvtools |