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