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