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 // Validation tests for ilegal literals
16 
17 #include <string>
18 #include <utility>
19 
20 #include "gmock/gmock.h"
21 #include "test/val/val_fixtures.h"
22 
23 namespace spvtools {
24 namespace val {
25 namespace {
26 
27 using ::testing::HasSubstr;
28 
29 using ValidateLiterals = spvtest::ValidateBase<std::string>;
30 using ValidateLiteralsShader = spvtest::ValidateBase<std::string>;
31 using ValidateLiteralsKernel = spvtest::ValidateBase<std::string>;
32 
GenerateShaderCode()33 std::string GenerateShaderCode() {
34   std::string str = R"(
35           OpCapability Shader
36           OpCapability Linkage
37           OpCapability Int16
38           OpCapability Int64
39           OpCapability Float16
40           OpCapability Float64
41           OpMemoryModel Logical GLSL450
42 %int16  = OpTypeInt 16 1
43 %uint16 = OpTypeInt 16 0
44 %int32  = OpTypeInt 32 1
45 %uint32 = OpTypeInt 32 0
46 %int64  = OpTypeInt 64 1
47 %uint64 = OpTypeInt 64 0
48 %half   = OpTypeFloat 16
49 %float  = OpTypeFloat 32
50 %double = OpTypeFloat 64
51 %10     = OpTypeVoid
52     )";
53   return str;
54 }
55 
GenerateKernelCode()56 std::string GenerateKernelCode() {
57   std::string str = R"(
58           OpCapability Kernel
59           OpCapability Addresses
60           OpCapability Linkage
61           OpCapability Int8
62           OpMemoryModel Physical64 OpenCL
63 %uint8  = OpTypeInt 8 0
64     )";
65   return str;
66 }
67 
TEST_F(ValidateLiterals,LiteralsShaderGood)68 TEST_F(ValidateLiterals, LiteralsShaderGood) {
69   std::string str = GenerateShaderCode() + R"(
70 %11 = OpConstant %int16   !0x00007FFF
71 %12 = OpConstant %int16   !0xFFFF8000
72 %13 = OpConstant %int16   !0xFFFFABCD
73 %14 = OpConstant %uint16  !0x0000ABCD
74 %15 = OpConstant %int16  -32768
75 %16 = OpConstant %uint16  65535
76 %17 = OpConstant %int32  -2147483648
77 %18 = OpConstant %uint32  4294967295
78 %19 = OpConstant %int64  -9223372036854775808
79 %20 = OpConstant %uint64  18446744073709551615
80 %21 = OpConstant %half    !0x0000FFFF
81 %22 = OpConstant %float   !0xFFFFFFFF
82 %23 = OpConstant %double  !0xFFFFFFFF !0xFFFFFFFF
83   )";
84   CompileSuccessfully(str);
85   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
86 }
87 
TEST_P(ValidateLiteralsShader,LiteralsShaderBad)88 TEST_P(ValidateLiteralsShader, LiteralsShaderBad) {
89   std::string str = GenerateShaderCode() + GetParam();
90   std::string inst_id = "11";
91   CompileSuccessfully(str);
92   EXPECT_EQ(SPV_ERROR_INVALID_VALUE, ValidateInstructions());
93   EXPECT_THAT(
94       getDiagnosticString(),
95       HasSubstr("The high-order bits of a literal number in instruction <id> " +
96                 inst_id +
97                 " must be 0 for a floating-point type, "
98                 "or 0 for an integer type with Signedness of 0, "
99                 "or sign extended when Signedness is 1"));
100 }
101 
102 INSTANTIATE_TEST_CASE_P(
103     LiteralsShaderCases, ValidateLiteralsShader,
104     ::testing::Values("%11 = OpConstant %int16  !0xFFFF0000",  // Sign bit is 0
105                       "%11 = OpConstant %int16  !0x00008000",  // Sign bit is 1
106                       "%11 = OpConstant %int16  !0xABCD8000",  // Sign bit is 1
107                       "%11 = OpConstant %int16  !0xABCD0000",
108                       "%11 = OpConstant %uint16 !0xABCD0000",
109                       "%11 = OpConstant %half   !0xABCD0000",
110                       "%11 = OpConstant %half   !0x00010000"));
111 
TEST_F(ValidateLiterals,LiteralsKernelGood)112 TEST_F(ValidateLiterals, LiteralsKernelGood) {
113   std::string str = GenerateKernelCode() + R"(
114 %4  = OpConstant %uint8  !0x000000AB
115 %6  = OpConstant %uint8  255
116   )";
117   CompileSuccessfully(str);
118   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
119 }
120 
TEST_P(ValidateLiteralsKernel,LiteralsKernelBad)121 TEST_P(ValidateLiteralsKernel, LiteralsKernelBad) {
122   std::string str = GenerateKernelCode() + GetParam();
123   std::string inst_id = "2";
124   CompileSuccessfully(str);
125   EXPECT_EQ(SPV_ERROR_INVALID_VALUE, ValidateInstructions());
126   EXPECT_THAT(
127       getDiagnosticString(),
128       HasSubstr("The high-order bits of a literal number in instruction <id> " +
129                 inst_id +
130                 " must be 0 for a floating-point type, "
131                 "or 0 for an integer type with Signedness of 0, "
132                 "or sign extended when Signedness is 1"));
133 }
134 
135 INSTANTIATE_TEST_CASE_P(
136     LiteralsKernelCases, ValidateLiteralsKernel,
137     ::testing::Values("%2 = OpConstant %uint8  !0xABCDEF00",
138                       "%2 = OpConstant %uint8  !0xABCDEFFF"));
139 
140 }  // namespace
141 }  // namespace val
142 }  // namespace spvtools
143