• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2020 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 OpExtension validator rules.
16 
17 #include <string>
18 #include <vector>
19 
20 #include "gmock/gmock.h"
21 #include "source/enum_string_mapping.h"
22 #include "source/extensions.h"
23 #include "source/spirv_target_env.h"
24 #include "test/test_fixture.h"
25 #include "test/unit_spirv.h"
26 #include "test/val/val_fixtures.h"
27 
28 namespace spvtools {
29 namespace val {
30 namespace {
31 
32 using ::testing::HasSubstr;
33 using ::testing::Values;
34 using ::testing::ValuesIn;
35 
36 using ValidateSpvExpectAssumeKHR = spvtest::ValidateBase<bool>;
37 
TEST_F(ValidateSpvExpectAssumeKHR,Valid)38 TEST_F(ValidateSpvExpectAssumeKHR, Valid) {
39   const std::string str = R"(
40     OpCapability Kernel
41     OpCapability Addresses
42     OpCapability Linkage
43     OpCapability ExpectAssumeKHR
44     OpExtension "SPV_KHR_expect_assume"
45     OpMemoryModel Physical32 OpenCL
46 
47     %void = OpTypeVoid
48     %voidfn = OpTypeFunction %void
49 
50     %bool = OpTypeBool
51     %true = OpConstantTrue %bool
52     %undef = OpUndef %bool
53 
54     %uint = OpTypeInt 32 0
55     %uint_1 = OpConstant %uint 1
56     %uint_2 = OpConstant %uint 2
57 
58     %v2bool = OpTypeVector %bool 2
59     %v2uint = OpTypeVector %uint 2
60 
61     %null_v2bool = OpConstantNull %v2bool
62     %null_v2uint = OpConstantNull %v2uint
63 
64     %main = OpFunction %void None %voidfn
65     %entry = OpLabel
66     OpAssumeTrueKHR %true
67     OpAssumeTrueKHR %undef       ; probably undefined behaviour
68     %bool_val = OpExpectKHR %bool %true %true
69     %uint_val = OpExpectKHR %uint %uint_1 %uint_2 ; a bad expectation
70     %v2bool_val = OpExpectKHR %v2bool %null_v2bool %null_v2bool
71     %v2uint_val = OpExpectKHR %v2uint %null_v2uint %null_v2uint
72     OpReturn
73     OpFunctionEnd
74 
75 )";
76   CompileSuccessfully(str.c_str());
77   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
78 }
79 
TEST_F(ValidateSpvExpectAssumeKHR,RequiresExtension)80 TEST_F(ValidateSpvExpectAssumeKHR, RequiresExtension) {
81   const std::string str = R"(
82     OpCapability Kernel
83     OpCapability Addresses
84     OpCapability Linkage
85     OpCapability ExpectAssumeKHR
86     OpMemoryModel Physical32 OpenCL
87 
88     %void = OpTypeVoid
89     %voidfn = OpTypeFunction %void
90 
91     %bool = OpTypeBool
92     %true = OpConstantTrue %bool
93     %undef = OpUndef %bool
94 
95     %uint = OpTypeInt 32 0
96     %uint_1 = OpConstant %uint 1
97     %uint_2 = OpConstant %uint 2
98 
99     %main = OpFunction %void None %voidfn
100     %entry = OpLabel
101     OpAssumeTrueKHR %true
102     OpAssumeTrueKHR %undef       ; probably undefined behaviour
103     %val = OpExpectKHR %uint %uint_1 %uint_2 ; a bad expectation
104     OpReturn
105     OpFunctionEnd
106 
107 )";
108   CompileSuccessfully(str.c_str());
109   EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
110   EXPECT_THAT(getDiagnosticString(),
111               HasSubstr("Capability: operand ExpectAssumeKHR(5629) requires "
112                         "one of these extensions: SPV_KHR_expect_assume"));
113 }
114 
TEST_F(ValidateSpvExpectAssumeKHR,AssumeTrueKHR_RequiresExpectAssumeCapability)115 TEST_F(ValidateSpvExpectAssumeKHR,
116        AssumeTrueKHR_RequiresExpectAssumeCapability) {
117   const std::string str = R"(
118     OpCapability Kernel
119     OpCapability Addresses
120     OpCapability Linkage
121     OpExtension "SPV_KHR_expect_assume"
122     OpMemoryModel Physical32 OpenCL
123 
124     %void = OpTypeVoid
125     %voidfn = OpTypeFunction %void
126 
127     %bool = OpTypeBool
128     %true = OpConstantTrue %bool
129     %undef = OpUndef %bool
130 
131     %uint = OpTypeInt 32 0
132     %uint_1 = OpConstant %uint 1
133     %uint_2 = OpConstant %uint 2
134 
135     %main = OpFunction %void None %voidfn
136     %entry = OpLabel
137     OpAssumeTrueKHR %true
138     OpAssumeTrueKHR %undef       ; probably undefined behaviour
139     OpReturn
140     OpFunctionEnd
141 )";
142   CompileSuccessfully(str.c_str());
143   EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
144   EXPECT_THAT(getDiagnosticString(),
145               HasSubstr("Opcode AssumeTrueKHR requires one of these "
146                         "capabilities: ExpectAssumeKHR \n"
147                         "  OpAssumeTrueKHR %true\n"));
148 }
149 
TEST_F(ValidateSpvExpectAssumeKHR,AssumeTrueKHR_OperandMustBeBool)150 TEST_F(ValidateSpvExpectAssumeKHR, AssumeTrueKHR_OperandMustBeBool) {
151   const std::string str = R"(
152     OpCapability Kernel
153     OpCapability Addresses
154     OpCapability Linkage
155     OpCapability ExpectAssumeKHR
156     OpExtension "SPV_KHR_expect_assume"
157     OpMemoryModel Physical32 OpenCL
158 
159     %void = OpTypeVoid
160     %voidfn = OpTypeFunction %void
161 
162     %bool = OpTypeBool
163     %true = OpConstantTrue %bool
164     %undef = OpUndef %bool
165 
166     %uint = OpTypeInt 32 0
167     %uint_1 = OpConstant %uint 1
168     %uint_2 = OpConstant %uint 2
169 
170     %main = OpFunction %void None %voidfn
171     %entry = OpLabel
172     OpAssumeTrueKHR %uint_1 ; bad type
173     OpReturn
174     OpFunctionEnd
175 )";
176   CompileSuccessfully(str.c_str());
177   EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
178   EXPECT_THAT(
179       getDiagnosticString(),
180       HasSubstr("Value operand of OpAssumeTrueKHR must be a boolean scalar\n"
181                 "  OpAssumeTrueKHR %uint_1\n"));
182 }
183 
TEST_F(ValidateSpvExpectAssumeKHR,ExpectKHR_RequiresExpectAssumeCapability)184 TEST_F(ValidateSpvExpectAssumeKHR, ExpectKHR_RequiresExpectAssumeCapability) {
185   const std::string str = R"(
186     OpCapability Kernel
187     OpCapability Addresses
188     OpCapability Linkage
189     OpExtension "SPV_KHR_expect_assume"
190     OpMemoryModel Physical32 OpenCL
191 
192     %void = OpTypeVoid
193     %voidfn = OpTypeFunction %void
194 
195     %bool = OpTypeBool
196     %true = OpConstantTrue %bool
197     %undef = OpUndef %bool
198 
199     %uint = OpTypeInt 32 0
200     %uint_1 = OpConstant %uint 1
201     %uint_2 = OpConstant %uint 2
202 
203     %main = OpFunction %void None %voidfn
204     %entry = OpLabel
205     %val = OpExpectKHR %uint %uint_1 %uint_2 ; a bad expectation
206     OpReturn
207     OpFunctionEnd
208 )";
209   CompileSuccessfully(str.c_str());
210   EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
211   EXPECT_THAT(getDiagnosticString(),
212               HasSubstr("Opcode ExpectKHR requires one of these capabilities: "
213                         "ExpectAssumeKHR \n"
214                         "  %11 = OpExpectKHR %uint %uint_1 %uint_2\n"));
215 }
216 
TEST_F(ValidateSpvExpectAssumeKHR,ExpectKHR_ResultMustBeBoolOrIntScalar)217 TEST_F(ValidateSpvExpectAssumeKHR, ExpectKHR_ResultMustBeBoolOrIntScalar) {
218   const std::string str = R"(
219     OpCapability Kernel
220     OpCapability Addresses
221     OpCapability Linkage
222     OpCapability ExpectAssumeKHR
223     OpExtension "SPV_KHR_expect_assume"
224     OpMemoryModel Physical32 OpenCL
225 
226     %void = OpTypeVoid
227     %voidfn = OpTypeFunction %void
228 
229     %float = OpTypeFloat 32
230 
231     %float_0 = OpConstant %float 0
232 
233     %main = OpFunction %void None %voidfn
234     %entry = OpLabel
235     %val = OpExpectKHR %float %float_0 %float_0
236     OpReturn
237     OpFunctionEnd
238 )";
239   CompileSuccessfully(str.c_str());
240   EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
241   EXPECT_THAT(getDiagnosticString(),
242               HasSubstr("Result of OpExpectKHR must be a scalar or vector of "
243                         "integer type or boolean type\n"
244                         "  %7 = OpExpectKHR %float %float_0 %float_0\n"));
245 }
246 
TEST_F(ValidateSpvExpectAssumeKHR,ExpectKHR_Value0MustMatchResultType)247 TEST_F(ValidateSpvExpectAssumeKHR, ExpectKHR_Value0MustMatchResultType) {
248   const std::string str = R"(
249     OpCapability Kernel
250     OpCapability Addresses
251     OpCapability Linkage
252     OpCapability ExpectAssumeKHR
253     OpExtension "SPV_KHR_expect_assume"
254     OpMemoryModel Physical32 OpenCL
255 
256     %void = OpTypeVoid
257     %voidfn = OpTypeFunction %void
258 
259     %uint = OpTypeInt 32 0
260     %float = OpTypeFloat 32
261     %float_0 = OpConstant %float 0
262 
263     %main = OpFunction %void None %voidfn
264     %entry = OpLabel
265     %val = OpExpectKHR %uint %float_0 %float_0
266     OpReturn
267     OpFunctionEnd
268 )";
269   CompileSuccessfully(str.c_str());
270   EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
271   EXPECT_THAT(getDiagnosticString(),
272               HasSubstr("Type of Value operand of OpExpectKHR does not match "
273                         "the result type \n"
274                         "  %8 = OpExpectKHR %uint %float_0 %float_0\n"));
275 }
276 
TEST_F(ValidateSpvExpectAssumeKHR,ExpectKHR_Value1MustMatchResultType)277 TEST_F(ValidateSpvExpectAssumeKHR, ExpectKHR_Value1MustMatchResultType) {
278   const std::string str = R"(
279     OpCapability Kernel
280     OpCapability Addresses
281     OpCapability Linkage
282     OpCapability ExpectAssumeKHR
283     OpExtension "SPV_KHR_expect_assume"
284     OpMemoryModel Physical32 OpenCL
285 
286     %void = OpTypeVoid
287     %voidfn = OpTypeFunction %void
288 
289     %uint = OpTypeInt 32 0
290     %uint_0 = OpConstant %uint 0
291     %float = OpTypeFloat 32
292     %float_0 = OpConstant %float 0
293 
294     %main = OpFunction %void None %voidfn
295     %entry = OpLabel
296     %val = OpExpectKHR %uint %uint_0 %float_0
297     OpReturn
298     OpFunctionEnd
299 )";
300   CompileSuccessfully(str.c_str());
301   EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
302   EXPECT_THAT(getDiagnosticString(),
303               HasSubstr("Type of ExpectedValue operand of OpExpectKHR does not "
304                         "match the result type \n"
305                         "  %9 = OpExpectKHR %uint %uint_0 %float_0\n"));
306 }
307 
308 }  // namespace
309 }  // namespace val
310 }  // namespace spvtools
311