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 // Tests for unique type declaration rules validator.
16 
17 #include <string>
18 
19 #include "gmock/gmock.h"
20 #include "test/unit_spirv.h"
21 #include "test/val/val_fixtures.h"
22 
23 namespace spvtools {
24 namespace val {
25 namespace {
26 
27 using ::testing::Eq;
28 using ::testing::HasSubstr;
29 using ::testing::Not;
30 
31 using ValidateLogicals = spvtest::ValidateBase<bool>;
32 
GenerateShaderCode(const std::string & body,const std::string & capabilities_and_extensions="")33 std::string GenerateShaderCode(
34     const std::string& body,
35     const std::string& capabilities_and_extensions = "") {
36   const std::string capabilities =
37       R"(
38 OpCapability Shader
39 OpCapability Int64
40 OpCapability Float64)";
41 
42   const std::string after_extension_before_body =
43       R"(
44 %ext_inst = OpExtInstImport "GLSL.std.450"
45 OpMemoryModel Logical GLSL450
46 OpEntryPoint Fragment %main "main"
47 OpExecutionMode %main OriginUpperLeft
48 %void = OpTypeVoid
49 %func = OpTypeFunction %void
50 %bool = OpTypeBool
51 %f32 = OpTypeFloat 32
52 %u32 = OpTypeInt 32 0
53 %s32 = OpTypeInt 32 1
54 %f64 = OpTypeFloat 64
55 %u64 = OpTypeInt 64 0
56 %s64 = OpTypeInt 64 1
57 %boolvec2 = OpTypeVector %bool 2
58 %s32vec2 = OpTypeVector %s32 2
59 %u32vec2 = OpTypeVector %u32 2
60 %u64vec2 = OpTypeVector %u64 2
61 %f32vec2 = OpTypeVector %f32 2
62 %f64vec2 = OpTypeVector %f64 2
63 %boolvec3 = OpTypeVector %bool 3
64 %u32vec3 = OpTypeVector %u32 3
65 %u64vec3 = OpTypeVector %u64 3
66 %s32vec3 = OpTypeVector %s32 3
67 %f32vec3 = OpTypeVector %f32 3
68 %f64vec3 = OpTypeVector %f64 3
69 %boolvec4 = OpTypeVector %bool 4
70 %u32vec4 = OpTypeVector %u32 4
71 %u64vec4 = OpTypeVector %u64 4
72 %s32vec4 = OpTypeVector %s32 4
73 %f32vec4 = OpTypeVector %f32 4
74 %f64vec4 = OpTypeVector %f64 4
75 
76 %f32_0 = OpConstant %f32 0
77 %f32_1 = OpConstant %f32 1
78 %f32_2 = OpConstant %f32 2
79 %f32_3 = OpConstant %f32 3
80 %f32_4 = OpConstant %f32 4
81 
82 %s32_0 = OpConstant %s32 0
83 %s32_1 = OpConstant %s32 1
84 %s32_2 = OpConstant %s32 2
85 %s32_3 = OpConstant %s32 3
86 %s32_4 = OpConstant %s32 4
87 %s32_m1 = OpConstant %s32 -1
88 
89 %u32_0 = OpConstant %u32 0
90 %u32_1 = OpConstant %u32 1
91 %u32_2 = OpConstant %u32 2
92 %u32_3 = OpConstant %u32 3
93 %u32_4 = OpConstant %u32 4
94 
95 %f64_0 = OpConstant %f64 0
96 %f64_1 = OpConstant %f64 1
97 %f64_2 = OpConstant %f64 2
98 %f64_3 = OpConstant %f64 3
99 %f64_4 = OpConstant %f64 4
100 
101 %s64_0 = OpConstant %s64 0
102 %s64_1 = OpConstant %s64 1
103 %s64_2 = OpConstant %s64 2
104 %s64_3 = OpConstant %s64 3
105 %s64_4 = OpConstant %s64 4
106 %s64_m1 = OpConstant %s64 -1
107 
108 %u64_0 = OpConstant %u64 0
109 %u64_1 = OpConstant %u64 1
110 %u64_2 = OpConstant %u64 2
111 %u64_3 = OpConstant %u64 3
112 %u64_4 = OpConstant %u64 4
113 
114 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
115 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
116 %u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
117 %u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
118 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
119 %u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
120 
121 %s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1
122 %s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2
123 %s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2
124 %s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3
125 %s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3
126 %s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4
127 
128 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
129 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
130 %f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
131 %f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
132 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
133 %f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
134 
135 %f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1
136 %f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2
137 %f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2
138 %f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3
139 %f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3
140 %f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4
141 
142 %true = OpConstantTrue %bool
143 %false = OpConstantFalse %bool
144 %boolvec2_tf = OpConstantComposite %boolvec2 %true %false
145 %boolvec3_tft = OpConstantComposite %boolvec3 %true %false %true
146 %boolvec4_tftf = OpConstantComposite %boolvec4 %true %false %true %false
147 
148 %arr_u32_2 = OpTypeArray %u32 %u32_2
149 %st_u32_u32 = OpTypeStruct %u32 %u32
150 %mat_f32_2_2 = OpTypeMatrix %f32vec2 2
151 
152 %nul_arr_u32_2 = OpConstantNull %arr_u32_2
153 %nul_st_u32_u32 = OpConstantNull %st_u32_u32
154 %nul_mat_f32_2_2 = OpConstantNull %mat_f32_2_2
155 
156 %arr_u32_2_1_2 = OpConstantComposite %arr_u32_2 %u32_1 %u32_2
157 %st_u32_u32_1_2 = OpConstantComposite %st_u32_u32 %u32_1 %u32_2
158 %mat_f32_2_2_01_12 = OpConstantComposite %mat_f32_2_2 %f32vec2_01 %f32vec2_12
159 
160 %f32vec4ptr = OpTypePointer Function %f32vec4
161 
162 %main = OpFunction %void None %func
163 %main_entry = OpLabel)";
164 
165   const std::string after_body =
166       R"(
167 OpReturn
168 OpFunctionEnd)";
169 
170   return capabilities + capabilities_and_extensions +
171          after_extension_before_body + body + after_body;
172 }
173 
GenerateKernelCode(const std::string & body,const std::string & capabilities_and_extensions="")174 std::string GenerateKernelCode(
175     const std::string& body,
176     const std::string& capabilities_and_extensions = "") {
177   const std::string capabilities =
178       R"(
179 OpCapability Addresses
180 OpCapability Kernel
181 OpCapability Linkage
182 OpCapability Int64
183 OpCapability Float64)";
184 
185   const std::string after_extension_before_body =
186       R"(
187 OpMemoryModel Physical32 OpenCL
188 %void = OpTypeVoid
189 %func = OpTypeFunction %void
190 %bool = OpTypeBool
191 %f32 = OpTypeFloat 32
192 %u32 = OpTypeInt 32 0
193 %f64 = OpTypeFloat 64
194 %u64 = OpTypeInt 64 0
195 %boolvec2 = OpTypeVector %bool 2
196 %u32vec2 = OpTypeVector %u32 2
197 %u64vec2 = OpTypeVector %u64 2
198 %f32vec2 = OpTypeVector %f32 2
199 %f64vec2 = OpTypeVector %f64 2
200 %boolvec3 = OpTypeVector %bool 3
201 %u32vec3 = OpTypeVector %u32 3
202 %u64vec3 = OpTypeVector %u64 3
203 %f32vec3 = OpTypeVector %f32 3
204 %f64vec3 = OpTypeVector %f64 3
205 %boolvec4 = OpTypeVector %bool 4
206 %u32vec4 = OpTypeVector %u32 4
207 %u64vec4 = OpTypeVector %u64 4
208 %f32vec4 = OpTypeVector %f32 4
209 %f64vec4 = OpTypeVector %f64 4
210 
211 %f32_0 = OpConstant %f32 0
212 %f32_1 = OpConstant %f32 1
213 %f32_2 = OpConstant %f32 2
214 %f32_3 = OpConstant %f32 3
215 %f32_4 = OpConstant %f32 4
216 
217 %u32_0 = OpConstant %u32 0
218 %u32_1 = OpConstant %u32 1
219 %u32_2 = OpConstant %u32 2
220 %u32_3 = OpConstant %u32 3
221 %u32_4 = OpConstant %u32 4
222 
223 %f64_0 = OpConstant %f64 0
224 %f64_1 = OpConstant %f64 1
225 %f64_2 = OpConstant %f64 2
226 %f64_3 = OpConstant %f64 3
227 %f64_4 = OpConstant %f64 4
228 
229 %u64_0 = OpConstant %u64 0
230 %u64_1 = OpConstant %u64 1
231 %u64_2 = OpConstant %u64 2
232 %u64_3 = OpConstant %u64 3
233 %u64_4 = OpConstant %u64 4
234 
235 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
236 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
237 %u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
238 %u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
239 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
240 %u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
241 
242 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
243 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
244 %f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
245 %f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
246 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
247 %f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
248 
249 %f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1
250 %f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2
251 %f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2
252 %f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3
253 %f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3
254 %f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4
255 
256 %true = OpConstantTrue %bool
257 %false = OpConstantFalse %bool
258 %boolvec2_tf = OpConstantComposite %boolvec2 %true %false
259 %boolvec3_tft = OpConstantComposite %boolvec3 %true %false %true
260 %boolvec4_tftf = OpConstantComposite %boolvec4 %true %false %true %false
261 
262 %f32vec4ptr = OpTypePointer Function %f32vec4
263 
264 %main = OpFunction %void None %func
265 %main_entry = OpLabel)";
266 
267   const std::string after_body =
268       R"(
269 OpReturn
270 OpFunctionEnd)";
271 
272   return capabilities + capabilities_and_extensions +
273          after_extension_before_body + body + after_body;
274 }
275 
TEST_F(ValidateLogicals,OpAnySuccess)276 TEST_F(ValidateLogicals, OpAnySuccess) {
277   const std::string body = R"(
278 %val1 = OpAny %bool %boolvec2_tf
279 %val2 = OpAny %bool %boolvec3_tft
280 %val3 = OpAny %bool %boolvec4_tftf
281 )";
282 
283   CompileSuccessfully(GenerateShaderCode(body).c_str());
284   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
285 }
286 
TEST_F(ValidateLogicals,OpAnyWrongTypeId)287 TEST_F(ValidateLogicals, OpAnyWrongTypeId) {
288   const std::string body = R"(
289 %val = OpAny %u32 %boolvec2_tf
290 )";
291 
292   CompileSuccessfully(GenerateShaderCode(body).c_str());
293   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
294   EXPECT_THAT(getDiagnosticString(),
295               HasSubstr("Expected bool scalar type as Result Type: Any"));
296 }
297 
TEST_F(ValidateLogicals,OpAnyWrongOperand)298 TEST_F(ValidateLogicals, OpAnyWrongOperand) {
299   const std::string body = R"(
300 %val = OpAny %bool %u32vec3_123
301 )";
302 
303   CompileSuccessfully(GenerateShaderCode(body).c_str());
304   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
305   EXPECT_THAT(getDiagnosticString(),
306               HasSubstr("Expected operand to be vector bool: Any"));
307 }
308 
TEST_F(ValidateLogicals,OpIsNanSuccess)309 TEST_F(ValidateLogicals, OpIsNanSuccess) {
310   const std::string body = R"(
311 %val1 = OpIsNan %bool %f32_1
312 %val2 = OpIsNan %bool %f64_0
313 %val3 = OpIsNan %boolvec2 %f32vec2_12
314 %val4 = OpIsNan %boolvec3 %f32vec3_123
315 %val5 = OpIsNan %boolvec4 %f32vec4_1234
316 )";
317 
318   CompileSuccessfully(GenerateShaderCode(body).c_str());
319   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
320 }
321 
TEST_F(ValidateLogicals,OpIsNanWrongTypeId)322 TEST_F(ValidateLogicals, OpIsNanWrongTypeId) {
323   const std::string body = R"(
324 %val1 = OpIsNan %u32 %f32_1
325 )";
326 
327   CompileSuccessfully(GenerateShaderCode(body).c_str());
328   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
329   EXPECT_THAT(
330       getDiagnosticString(),
331       HasSubstr("Expected bool scalar or vector type as Result Type: IsNan"));
332 }
333 
TEST_F(ValidateLogicals,OpIsNanOperandNotFloat)334 TEST_F(ValidateLogicals, OpIsNanOperandNotFloat) {
335   const std::string body = R"(
336 %val1 = OpIsNan %bool %u32_1
337 )";
338 
339   CompileSuccessfully(GenerateShaderCode(body).c_str());
340   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
341   EXPECT_THAT(
342       getDiagnosticString(),
343       HasSubstr("Expected operand to be scalar or vector float: IsNan"));
344 }
345 
TEST_F(ValidateLogicals,OpIsNanOperandWrongSize)346 TEST_F(ValidateLogicals, OpIsNanOperandWrongSize) {
347   const std::string body = R"(
348 %val1 = OpIsNan %bool %f32vec2_12
349 )";
350 
351   CompileSuccessfully(GenerateShaderCode(body).c_str());
352   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
353   EXPECT_THAT(
354       getDiagnosticString(),
355       HasSubstr(
356           "Expected vector sizes of Result Type and the operand to be equal: "
357           "IsNan"));
358 }
359 
TEST_F(ValidateLogicals,OpLessOrGreaterSuccess)360 TEST_F(ValidateLogicals, OpLessOrGreaterSuccess) {
361   const std::string body = R"(
362 %val1 = OpLessOrGreater %bool %f32_0 %f32_1
363 %val2 = OpLessOrGreater %bool %f64_0 %f64_0
364 %val3 = OpLessOrGreater %boolvec2 %f32vec2_12 %f32vec2_12
365 %val4 = OpLessOrGreater %boolvec3 %f32vec3_123 %f32vec3_123
366 %val5 = OpLessOrGreater %boolvec4 %f32vec4_1234 %f32vec4_1234
367 )";
368 
369   CompileSuccessfully(GenerateKernelCode(body).c_str());
370   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
371 }
372 
TEST_F(ValidateLogicals,OpLessOrGreaterWrongTypeId)373 TEST_F(ValidateLogicals, OpLessOrGreaterWrongTypeId) {
374   const std::string body = R"(
375 %val1 = OpLessOrGreater %u32 %f32_1 %f32_1
376 )";
377 
378   CompileSuccessfully(GenerateKernelCode(body).c_str());
379   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
380   EXPECT_THAT(
381       getDiagnosticString(),
382       HasSubstr(
383           "Expected bool scalar or vector type as Result Type: LessOrGreater"));
384 }
385 
TEST_F(ValidateLogicals,OpLessOrGreaterLeftOperandNotFloat)386 TEST_F(ValidateLogicals, OpLessOrGreaterLeftOperandNotFloat) {
387   const std::string body = R"(
388 %val1 = OpLessOrGreater %bool %u32_1 %f32_1
389 )";
390 
391   CompileSuccessfully(GenerateKernelCode(body).c_str());
392   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
393   EXPECT_THAT(
394       getDiagnosticString(),
395       HasSubstr(
396           "Expected operands to be scalar or vector float: LessOrGreater"));
397 }
398 
TEST_F(ValidateLogicals,OpLessOrGreaterLeftOperandWrongSize)399 TEST_F(ValidateLogicals, OpLessOrGreaterLeftOperandWrongSize) {
400   const std::string body = R"(
401 %val1 = OpLessOrGreater %bool %f32vec2_12 %f32_1
402 )";
403 
404   CompileSuccessfully(GenerateKernelCode(body).c_str());
405   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
406   EXPECT_THAT(
407       getDiagnosticString(),
408       HasSubstr(
409           "Expected vector sizes of Result Type and the operands to be equal: "
410           "LessOrGreater"));
411 }
412 
TEST_F(ValidateLogicals,OpLessOrGreaterOperandsDifferentType)413 TEST_F(ValidateLogicals, OpLessOrGreaterOperandsDifferentType) {
414   const std::string body = R"(
415 %val1 = OpLessOrGreater %bool %f32_1 %f64_1
416 )";
417 
418   CompileSuccessfully(GenerateKernelCode(body).c_str());
419   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
420   EXPECT_THAT(
421       getDiagnosticString(),
422       HasSubstr("Expected left and right operands to have the same type: "
423                 "LessOrGreater"));
424 }
425 
TEST_F(ValidateLogicals,OpFOrdEqualSuccess)426 TEST_F(ValidateLogicals, OpFOrdEqualSuccess) {
427   const std::string body = R"(
428 %val1 = OpFOrdEqual %bool %f32_0 %f32_1
429 %val2 = OpFOrdEqual %bool %f64_0 %f64_0
430 %val3 = OpFOrdEqual %boolvec2 %f32vec2_12 %f32vec2_12
431 %val4 = OpFOrdEqual %boolvec3 %f32vec3_123 %f32vec3_123
432 %val5 = OpFOrdEqual %boolvec4 %f32vec4_1234 %f32vec4_1234
433 )";
434 
435   CompileSuccessfully(GenerateShaderCode(body).c_str());
436   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
437 }
438 
TEST_F(ValidateLogicals,OpFOrdEqualWrongTypeId)439 TEST_F(ValidateLogicals, OpFOrdEqualWrongTypeId) {
440   const std::string body = R"(
441 %val1 = OpFOrdEqual %u32 %f32_1 %f32_1
442 )";
443 
444   CompileSuccessfully(GenerateShaderCode(body).c_str());
445   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
446   EXPECT_THAT(
447       getDiagnosticString(),
448       HasSubstr(
449           "Expected bool scalar or vector type as Result Type: FOrdEqual"));
450 }
451 
TEST_F(ValidateLogicals,OpFOrdEqualLeftOperandNotFloat)452 TEST_F(ValidateLogicals, OpFOrdEqualLeftOperandNotFloat) {
453   const std::string body = R"(
454 %val1 = OpFOrdEqual %bool %u32_1 %f32_1
455 )";
456 
457   CompileSuccessfully(GenerateShaderCode(body).c_str());
458   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
459   EXPECT_THAT(
460       getDiagnosticString(),
461       HasSubstr("Expected operands to be scalar or vector float: FOrdEqual"));
462 }
463 
TEST_F(ValidateLogicals,OpFOrdEqualLeftOperandWrongSize)464 TEST_F(ValidateLogicals, OpFOrdEqualLeftOperandWrongSize) {
465   const std::string body = R"(
466 %val1 = OpFOrdEqual %bool %f32vec2_12 %f32_1
467 )";
468 
469   CompileSuccessfully(GenerateShaderCode(body).c_str());
470   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
471   EXPECT_THAT(
472       getDiagnosticString(),
473       HasSubstr(
474           "Expected vector sizes of Result Type and the operands to be equal: "
475           "FOrdEqual"));
476 }
477 
TEST_F(ValidateLogicals,OpFOrdEqualOperandsDifferentType)478 TEST_F(ValidateLogicals, OpFOrdEqualOperandsDifferentType) {
479   const std::string body = R"(
480 %val1 = OpFOrdEqual %bool %f32_1 %f64_1
481 )";
482 
483   CompileSuccessfully(GenerateShaderCode(body).c_str());
484   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
485   EXPECT_THAT(
486       getDiagnosticString(),
487       HasSubstr("Expected left and right operands to have the same type: "
488                 "FOrdEqual"));
489 }
490 
TEST_F(ValidateLogicals,OpLogicalEqualSuccess)491 TEST_F(ValidateLogicals, OpLogicalEqualSuccess) {
492   const std::string body = R"(
493 %val1 = OpLogicalEqual %bool %true %false
494 %val2 = OpLogicalEqual %boolvec2 %boolvec2_tf   %boolvec2_tf
495 %val3 = OpLogicalEqual %boolvec3 %boolvec3_tft  %boolvec3_tft
496 %val4 = OpLogicalEqual %boolvec4 %boolvec4_tftf %boolvec4_tftf
497 )";
498 
499   CompileSuccessfully(GenerateKernelCode(body).c_str());
500   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
501 }
502 
TEST_F(ValidateLogicals,OpLogicalEqualWrongTypeId)503 TEST_F(ValidateLogicals, OpLogicalEqualWrongTypeId) {
504   const std::string body = R"(
505 %val1 = OpLogicalEqual %u32 %true %false
506 )";
507 
508   CompileSuccessfully(GenerateKernelCode(body).c_str());
509   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
510   EXPECT_THAT(
511       getDiagnosticString(),
512       HasSubstr(
513           "Expected bool scalar or vector type as Result Type: LogicalEqual"));
514 }
515 
TEST_F(ValidateLogicals,OpLogicalEqualWrongLeftOperand)516 TEST_F(ValidateLogicals, OpLogicalEqualWrongLeftOperand) {
517   const std::string body = R"(
518 %val1 = OpLogicalEqual %bool %boolvec2_tf %false
519 )";
520 
521   CompileSuccessfully(GenerateKernelCode(body).c_str());
522   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
523   EXPECT_THAT(
524       getDiagnosticString(),
525       HasSubstr("Expected both operands to be of Result Type: LogicalEqual"));
526 }
527 
TEST_F(ValidateLogicals,OpLogicalEqualWrongRightOperand)528 TEST_F(ValidateLogicals, OpLogicalEqualWrongRightOperand) {
529   const std::string body = R"(
530 %val1 = OpLogicalEqual %boolvec2 %boolvec2_tf %false
531 )";
532 
533   CompileSuccessfully(GenerateKernelCode(body).c_str());
534   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
535   EXPECT_THAT(
536       getDiagnosticString(),
537       HasSubstr("Expected both operands to be of Result Type: LogicalEqual"));
538 }
539 
TEST_F(ValidateLogicals,OpLogicalNotSuccess)540 TEST_F(ValidateLogicals, OpLogicalNotSuccess) {
541   const std::string body = R"(
542 %val1 = OpLogicalNot %bool %true
543 %val2 = OpLogicalNot %boolvec2 %boolvec2_tf
544 %val3 = OpLogicalNot %boolvec3 %boolvec3_tft
545 %val4 = OpLogicalNot %boolvec4 %boolvec4_tftf
546 )";
547 
548   CompileSuccessfully(GenerateKernelCode(body).c_str());
549   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
550 }
551 
TEST_F(ValidateLogicals,OpLogicalNotWrongTypeId)552 TEST_F(ValidateLogicals, OpLogicalNotWrongTypeId) {
553   const std::string body = R"(
554 %val1 = OpLogicalNot %u32 %true
555 )";
556 
557   CompileSuccessfully(GenerateKernelCode(body).c_str());
558   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
559   EXPECT_THAT(
560       getDiagnosticString(),
561       HasSubstr(
562           "Expected bool scalar or vector type as Result Type: LogicalNot"));
563 }
564 
TEST_F(ValidateLogicals,OpLogicalNotWrongOperand)565 TEST_F(ValidateLogicals, OpLogicalNotWrongOperand) {
566   const std::string body = R"(
567 %val1 = OpLogicalNot %bool %boolvec2_tf
568 )";
569 
570   CompileSuccessfully(GenerateKernelCode(body).c_str());
571   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
572   EXPECT_THAT(getDiagnosticString(),
573               HasSubstr("Expected operand to be of Result Type: LogicalNot"));
574 }
575 
TEST_F(ValidateLogicals,OpSelectSuccess)576 TEST_F(ValidateLogicals, OpSelectSuccess) {
577   const std::string body = R"(
578 %val1 = OpSelect %u32 %true %u32_0 %u32_1
579 %val2 = OpSelect %f32 %true %f32_0 %f32_1
580 %val3 = OpSelect %f64 %true %f64_0 %f64_1
581 %val4 = OpSelect %f32vec2 %boolvec2_tf %f32vec2_01 %f32vec2_12
582 %val5 = OpSelect %f32vec4 %boolvec4_tftf %f32vec4_0123 %f32vec4_1234
583 )";
584 
585   CompileSuccessfully(GenerateShaderCode(body).c_str());
586   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
587 }
588 
TEST_F(ValidateLogicals,OpSelectWrongTypeId)589 TEST_F(ValidateLogicals, OpSelectWrongTypeId) {
590   const std::string body = R"(
591 %val1 = OpSelect %void %true %u32_0 %u32_1
592 )";
593 
594   CompileSuccessfully(GenerateShaderCode(body).c_str());
595   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
596   EXPECT_THAT(
597       getDiagnosticString(),
598       HasSubstr("Expected scalar or vector type as Result Type: Select"));
599 }
600 
TEST_F(ValidateLogicals,OpSelectWrongTypeIdV14)601 TEST_F(ValidateLogicals, OpSelectWrongTypeIdV14) {
602   // In 1.4, the message changes to allow composites.
603   const std::string body = R"(
604 %val1 = OpSelect %void %true %u32_0 %u32_1
605 )";
606 
607   CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_UNIVERSAL_1_4);
608   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
609             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
610   EXPECT_THAT(
611       getDiagnosticString(),
612       HasSubstr("Expected scalar or composite type as Result Type: Select"));
613 }
614 
TEST_F(ValidateLogicals,OpSelectPointerNoCapability)615 TEST_F(ValidateLogicals, OpSelectPointerNoCapability) {
616   const std::string body = R"(
617 %x = OpVariable %f32vec4ptr Function
618 %y = OpVariable %f32vec4ptr Function
619 OpStore %x %f32vec4_0123
620 OpStore %y %f32vec4_1234
621 %val1 = OpSelect %f32vec4ptr %true %x %y
622 )";
623 
624   CompileSuccessfully(GenerateShaderCode(body).c_str());
625   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
626   EXPECT_THAT(
627       getDiagnosticString(),
628       HasSubstr(
629           "Using pointers with OpSelect requires capability VariablePointers "
630           "or VariablePointersStorageBuffer"));
631 }
632 
TEST_F(ValidateLogicals,OpSelectPointerWithCapability1)633 TEST_F(ValidateLogicals, OpSelectPointerWithCapability1) {
634   const std::string body = R"(
635 %x = OpVariable %f32vec4ptr Function
636 %y = OpVariable %f32vec4ptr Function
637 OpStore %x %f32vec4_0123
638 OpStore %y %f32vec4_1234
639 %val1 = OpSelect %f32vec4ptr %true %x %y
640 )";
641 
642   const std::string extra_cap_ext = R"(
643 OpCapability VariablePointers
644 OpExtension "SPV_KHR_variable_pointers"
645 )";
646 
647   CompileSuccessfully(GenerateShaderCode(body, extra_cap_ext).c_str());
648   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
649 }
650 
TEST_F(ValidateLogicals,OpSelectPointerWithCapability2)651 TEST_F(ValidateLogicals, OpSelectPointerWithCapability2) {
652   const std::string body = R"(
653 %x = OpVariable %f32vec4ptr Function
654 %y = OpVariable %f32vec4ptr Function
655 OpStore %x %f32vec4_0123
656 OpStore %y %f32vec4_1234
657 %val1 = OpSelect %f32vec4ptr %true %x %y
658 )";
659 
660   const std::string extra_cap_ext = R"(
661 OpCapability VariablePointersStorageBuffer
662 OpExtension "SPV_KHR_variable_pointers"
663 )";
664 
665   CompileSuccessfully(GenerateShaderCode(body, extra_cap_ext).c_str());
666   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
667 }
668 
TEST_F(ValidateLogicals,OpSelectWrongCondition)669 TEST_F(ValidateLogicals, OpSelectWrongCondition) {
670   const std::string body = R"(
671 %val1 = OpSelect %u32 %u32_1 %u32_0 %u32_1
672 )";
673 
674   CompileSuccessfully(GenerateShaderCode(body).c_str());
675   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
676   EXPECT_THAT(
677       getDiagnosticString(),
678       HasSubstr("Expected bool scalar or vector type as condition: Select"));
679 }
680 
TEST_F(ValidateLogicals,OpSelectWrongConditionDimension)681 TEST_F(ValidateLogicals, OpSelectWrongConditionDimension) {
682   const std::string body = R"(
683 %val1 = OpSelect %u32vec2 %true %u32vec2_01 %u32vec2_12
684 )";
685 
686   CompileSuccessfully(GenerateShaderCode(body).c_str());
687   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
688   EXPECT_THAT(
689       getDiagnosticString(),
690       HasSubstr(
691           "Expected vector sizes of Result Type and the condition to be equal: "
692           "Select"));
693 }
694 
TEST_F(ValidateLogicals,OpSelectWrongLeftObject)695 TEST_F(ValidateLogicals, OpSelectWrongLeftObject) {
696   const std::string body = R"(
697 %val1 = OpSelect %bool %true %u32vec2_01 %u32_1
698 )";
699 
700   CompileSuccessfully(GenerateShaderCode(body).c_str());
701   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
702   EXPECT_THAT(getDiagnosticString(),
703               HasSubstr("Expected both objects to be of Result Type: Select"));
704 }
705 
TEST_F(ValidateLogicals,OpSelectWrongRightObject)706 TEST_F(ValidateLogicals, OpSelectWrongRightObject) {
707   const std::string body = R"(
708 %val1 = OpSelect %bool %true %u32_1 %u32vec2_01
709 )";
710 
711   CompileSuccessfully(GenerateShaderCode(body).c_str());
712   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
713   EXPECT_THAT(getDiagnosticString(),
714               HasSubstr("Expected both objects to be of Result Type: Select"));
715 }
716 
TEST_F(ValidateLogicals,OpSelectArrayV13Bad)717 TEST_F(ValidateLogicals, OpSelectArrayV13Bad) {
718   const std::string body = R"(
719 %val1 = OpSelect %arr_u32_2 %true %nul_arr_u32_2 %arr_u32_2_1_2
720 )";
721 
722   CompileSuccessfully(GenerateShaderCode(body).c_str());
723   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
724             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
725   EXPECT_THAT(
726       getDiagnosticString(),
727       HasSubstr("Expected scalar or vector type as Result Type: Select"));
728 }
729 
TEST_F(ValidateLogicals,OpSelectArrayV13TargetV14Bad)730 TEST_F(ValidateLogicals, OpSelectArrayV13TargetV14Bad) {
731   const std::string body = R"(
732 %val1 = OpSelect %arr_u32_2 %true %nul_arr_u32_2 %arr_u32_2_1_2
733 )";
734 
735   CompileSuccessfully(GenerateShaderCode(body).c_str());
736   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
737             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
738   EXPECT_THAT(getDiagnosticString(),
739               HasSubstr("Expected scalar or vector type as Result Type"));
740 }
741 
TEST_F(ValidateLogicals,OpSelectArrayV14Good)742 TEST_F(ValidateLogicals, OpSelectArrayV14Good) {
743   const std::string body = R"(
744 %val1 = OpSelect %arr_u32_2 %true %nul_arr_u32_2 %arr_u32_2_1_2
745 )";
746 
747   CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_UNIVERSAL_1_4);
748   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
749   EXPECT_THAT(getDiagnosticString(), Eq(""));
750 }
751 
TEST_F(ValidateLogicals,OpSelectStructV13Bad)752 TEST_F(ValidateLogicals, OpSelectStructV13Bad) {
753   const std::string body = R"(
754 %val1 = OpSelect %st_u32_u32 %true %nul_st_u32_u32 %st_u32_u32_1_2
755 )";
756 
757   CompileSuccessfully(GenerateShaderCode(body).c_str());
758   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
759             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
760   EXPECT_THAT(
761       getDiagnosticString(),
762       HasSubstr("Expected scalar or vector type as Result Type: Select"));
763 }
764 
TEST_F(ValidateLogicals,OpSelectStructV13TargetV14Bad)765 TEST_F(ValidateLogicals, OpSelectStructV13TargetV14Bad) {
766   const std::string body = R"(
767 %val1 = OpSelect %st_u32_u32 %true %nul_st_u32_u32 %st_u32_u32_1_2
768 )";
769 
770   CompileSuccessfully(GenerateShaderCode(body).c_str());
771   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
772             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
773   EXPECT_THAT(getDiagnosticString(),
774               HasSubstr("Expected scalar or vector type as Result Type"));
775 }
776 
TEST_F(ValidateLogicals,OpSelectStructV14Good)777 TEST_F(ValidateLogicals, OpSelectStructV14Good) {
778   const std::string body = R"(
779 %val1 = OpSelect %st_u32_u32 %true %nul_st_u32_u32 %st_u32_u32_1_2
780 )";
781 
782   CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_UNIVERSAL_1_4);
783   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
784   EXPECT_THAT(getDiagnosticString(), Eq(""));
785 }
786 
TEST_F(ValidateLogicals,OpSelectMatrixV13Bad)787 TEST_F(ValidateLogicals, OpSelectMatrixV13Bad) {
788   const std::string body = R"(
789 %val1 = OpSelect %mat_f32_2_2 %true %nul_mat_f32_2_2 %mat_f32_2_2_01_12
790 )";
791 
792   CompileSuccessfully(GenerateShaderCode(body).c_str());
793   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
794             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
795   EXPECT_THAT(
796       getDiagnosticString(),
797       HasSubstr("Expected scalar or vector type as Result Type: Select"));
798 }
799 
TEST_F(ValidateLogicals,OpSelectMatrixV13TargetV14Bad)800 TEST_F(ValidateLogicals, OpSelectMatrixV13TargetV14Bad) {
801   const std::string body = R"(
802 %val1 = OpSelect %mat_f32_2_2 %true %nul_mat_f32_2_2 %mat_f32_2_2_01_12
803 )";
804 
805   CompileSuccessfully(GenerateShaderCode(body).c_str());
806   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
807             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
808   EXPECT_THAT(getDiagnosticString(),
809               HasSubstr("Expected scalar or vector type as Result Type"));
810 }
811 
TEST_F(ValidateLogicals,OpSelectMatrixV14Good)812 TEST_F(ValidateLogicals, OpSelectMatrixV14Good) {
813   const std::string body = R"(
814 %val1 = OpSelect %mat_f32_2_2 %true %nul_mat_f32_2_2 %mat_f32_2_2_01_12
815 )";
816 
817   CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_UNIVERSAL_1_4);
818   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
819   EXPECT_THAT(getDiagnosticString(), Eq(""));
820 }
821 
TEST_F(ValidateLogicals,OpIEqualSuccess)822 TEST_F(ValidateLogicals, OpIEqualSuccess) {
823   const std::string body = R"(
824 %val1 = OpIEqual %bool %u32_0 %s32_1
825 %val2 = OpIEqual %bool %s64_0 %u64_0
826 %val3 = OpIEqual %boolvec2 %s32vec2_12 %u32vec2_12
827 %val4 = OpIEqual %boolvec3 %s32vec3_123 %u32vec3_123
828 %val5 = OpIEqual %boolvec4 %s32vec4_1234 %u32vec4_1234
829 )";
830 
831   CompileSuccessfully(GenerateShaderCode(body).c_str());
832   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
833 }
834 
TEST_F(ValidateLogicals,OpIEqualWrongTypeId)835 TEST_F(ValidateLogicals, OpIEqualWrongTypeId) {
836   const std::string body = R"(
837 %val1 = OpIEqual %u32 %s32_1 %s32_1
838 )";
839 
840   CompileSuccessfully(GenerateShaderCode(body).c_str());
841   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
842   EXPECT_THAT(
843       getDiagnosticString(),
844       HasSubstr("Expected bool scalar or vector type as Result Type: IEqual"));
845 }
846 
TEST_F(ValidateLogicals,OpIEqualLeftOperandNotInt)847 TEST_F(ValidateLogicals, OpIEqualLeftOperandNotInt) {
848   const std::string body = R"(
849 %val1 = OpIEqual %bool %f32_1 %s32_1
850 )";
851 
852   CompileSuccessfully(GenerateShaderCode(body).c_str());
853   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
854   EXPECT_THAT(
855       getDiagnosticString(),
856       HasSubstr("Expected operands to be scalar or vector int: IEqual"));
857 }
858 
TEST_F(ValidateLogicals,OpIEqualLeftOperandWrongSize)859 TEST_F(ValidateLogicals, OpIEqualLeftOperandWrongSize) {
860   const std::string body = R"(
861 %val1 = OpIEqual %bool %s32vec2_12 %s32_1
862 )";
863 
864   CompileSuccessfully(GenerateShaderCode(body).c_str());
865   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
866   EXPECT_THAT(
867       getDiagnosticString(),
868       HasSubstr(
869           "Expected vector sizes of Result Type and the operands to be equal: "
870           "IEqual"));
871 }
872 
TEST_F(ValidateLogicals,OpIEqualRightOperandNotInt)873 TEST_F(ValidateLogicals, OpIEqualRightOperandNotInt) {
874   const std::string body = R"(
875 %val1 = OpIEqual %bool %u32_1 %f32_1
876 )";
877 
878   CompileSuccessfully(GenerateShaderCode(body).c_str());
879   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
880   EXPECT_THAT(
881       getDiagnosticString(),
882       HasSubstr("Expected operands to be scalar or vector int: IEqual"));
883 }
884 
TEST_F(ValidateLogicals,OpIEqualDifferentBitWidth)885 TEST_F(ValidateLogicals, OpIEqualDifferentBitWidth) {
886   const std::string body = R"(
887 %val1 = OpIEqual %bool %u32_1 %u64_1
888 )";
889 
890   CompileSuccessfully(GenerateShaderCode(body).c_str());
891   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
892   EXPECT_THAT(getDiagnosticString(),
893               HasSubstr("Expected both operands to have the same component bit "
894                         "width: IEqual"));
895 }
896 
TEST_F(ValidateLogicals,OpUGreaterThanSuccess)897 TEST_F(ValidateLogicals, OpUGreaterThanSuccess) {
898   const std::string body = R"(
899 %val1 = OpUGreaterThan %bool %u32_0 %u32_1
900 %val2 = OpUGreaterThan %bool %s32_0 %u32_1
901 %val3 = OpUGreaterThan %bool %u64_0 %u64_0
902 %val4 = OpUGreaterThan %bool %u64_0 %s64_0
903 %val5 = OpUGreaterThan %boolvec2 %u32vec2_12 %u32vec2_12
904 %val6 = OpUGreaterThan %boolvec3 %s32vec3_123 %u32vec3_123
905 %val7 = OpUGreaterThan %boolvec4 %u32vec4_1234 %u32vec4_1234
906 )";
907 
908   CompileSuccessfully(GenerateShaderCode(body).c_str());
909   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
910 }
911 
TEST_F(ValidateLogicals,OpUGreaterThanWrongTypeId)912 TEST_F(ValidateLogicals, OpUGreaterThanWrongTypeId) {
913   const std::string body = R"(
914 %val1 = OpUGreaterThan %u32 %u32_1 %u32_1
915 )";
916 
917   CompileSuccessfully(GenerateShaderCode(body).c_str());
918   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
919   EXPECT_THAT(
920       getDiagnosticString(),
921       HasSubstr(
922           "Expected bool scalar or vector type as Result Type: UGreaterThan"));
923 }
924 
TEST_F(ValidateLogicals,OpUGreaterThanLeftOperandNotInt)925 TEST_F(ValidateLogicals, OpUGreaterThanLeftOperandNotInt) {
926   const std::string body = R"(
927 %val1 = OpUGreaterThan %bool %f32_1 %u32_1
928 )";
929 
930   CompileSuccessfully(GenerateShaderCode(body).c_str());
931   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
932   EXPECT_THAT(
933       getDiagnosticString(),
934       HasSubstr("Expected operands to be scalar or vector int: UGreaterThan"));
935 }
936 
TEST_F(ValidateLogicals,OpUGreaterThanLeftOperandWrongSize)937 TEST_F(ValidateLogicals, OpUGreaterThanLeftOperandWrongSize) {
938   const std::string body = R"(
939 %val1 = OpUGreaterThan %bool %u32vec2_12 %u32_1
940 )";
941 
942   CompileSuccessfully(GenerateShaderCode(body).c_str());
943   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
944   EXPECT_THAT(
945       getDiagnosticString(),
946       HasSubstr(
947           "Expected vector sizes of Result Type and the operands to be equal: "
948           "UGreaterThan"));
949 }
950 
TEST_F(ValidateLogicals,OpUGreaterThanRightOperandNotInt)951 TEST_F(ValidateLogicals, OpUGreaterThanRightOperandNotInt) {
952   const std::string body = R"(
953 %val1 = OpUGreaterThan %bool %u32_1 %f32_1
954 )";
955 
956   CompileSuccessfully(GenerateShaderCode(body).c_str());
957   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
958   EXPECT_THAT(
959       getDiagnosticString(),
960       HasSubstr("Expected operands to be scalar or vector int: UGreaterThan"));
961 }
962 
TEST_F(ValidateLogicals,OpUGreaterThanDifferentBitWidth)963 TEST_F(ValidateLogicals, OpUGreaterThanDifferentBitWidth) {
964   const std::string body = R"(
965 %val1 = OpUGreaterThan %bool %u32_1 %u64_1
966 )";
967 
968   CompileSuccessfully(GenerateShaderCode(body).c_str());
969   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
970   EXPECT_THAT(
971       getDiagnosticString(),
972       HasSubstr("Expected both operands to have the same component bit width: "
973                 "UGreaterThan"));
974 }
975 
TEST_F(ValidateLogicals,OpSGreaterThanSuccess)976 TEST_F(ValidateLogicals, OpSGreaterThanSuccess) {
977   const std::string body = R"(
978 %val1 = OpSGreaterThan %bool %s32_0 %s32_1
979 %val2 = OpSGreaterThan %bool %u32_0 %s32_1
980 %val3 = OpSGreaterThan %bool %s64_0 %s64_0
981 %val4 = OpSGreaterThan %bool %s64_0 %u64_0
982 %val5 = OpSGreaterThan %boolvec2 %s32vec2_12 %s32vec2_12
983 %val6 = OpSGreaterThan %boolvec3 %s32vec3_123 %u32vec3_123
984 %val7 = OpSGreaterThan %boolvec4 %s32vec4_1234 %s32vec4_1234
985 )";
986 
987   CompileSuccessfully(GenerateShaderCode(body).c_str());
988   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
989 }
990 
TEST_F(ValidateLogicals,OpSGreaterThanWrongTypeId)991 TEST_F(ValidateLogicals, OpSGreaterThanWrongTypeId) {
992   const std::string body = R"(
993 %val1 = OpSGreaterThan %s32 %s32_1 %s32_1
994 )";
995 
996   CompileSuccessfully(GenerateShaderCode(body).c_str());
997   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
998   EXPECT_THAT(
999       getDiagnosticString(),
1000       HasSubstr(
1001           "Expected bool scalar or vector type as Result Type: SGreaterThan"));
1002 }
1003 
TEST_F(ValidateLogicals,OpSGreaterThanLeftOperandNotInt)1004 TEST_F(ValidateLogicals, OpSGreaterThanLeftOperandNotInt) {
1005   const std::string body = R"(
1006 %val1 = OpSGreaterThan %bool %f32_1 %s32_1
1007 )";
1008 
1009   CompileSuccessfully(GenerateShaderCode(body).c_str());
1010   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1011   EXPECT_THAT(
1012       getDiagnosticString(),
1013       HasSubstr("Expected operands to be scalar or vector int: SGreaterThan"));
1014 }
1015 
TEST_F(ValidateLogicals,OpSGreaterThanLeftOperandWrongSize)1016 TEST_F(ValidateLogicals, OpSGreaterThanLeftOperandWrongSize) {
1017   const std::string body = R"(
1018 %val1 = OpSGreaterThan %bool %s32vec2_12 %s32_1
1019 )";
1020 
1021   CompileSuccessfully(GenerateShaderCode(body).c_str());
1022   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1023   EXPECT_THAT(
1024       getDiagnosticString(),
1025       HasSubstr(
1026           "Expected vector sizes of Result Type and the operands to be equal: "
1027           "SGreaterThan"));
1028 }
1029 
TEST_F(ValidateLogicals,OpSGreaterThanRightOperandNotInt)1030 TEST_F(ValidateLogicals, OpSGreaterThanRightOperandNotInt) {
1031   const std::string body = R"(
1032 %val1 = OpSGreaterThan %bool %s32_1 %f32_1
1033 )";
1034 
1035   CompileSuccessfully(GenerateShaderCode(body).c_str());
1036   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1037   EXPECT_THAT(
1038       getDiagnosticString(),
1039       HasSubstr("Expected operands to be scalar or vector int: SGreaterThan"));
1040 }
1041 
TEST_F(ValidateLogicals,OpSGreaterThanDifferentBitWidth)1042 TEST_F(ValidateLogicals, OpSGreaterThanDifferentBitWidth) {
1043   const std::string body = R"(
1044 %val1 = OpSGreaterThan %bool %s32_1 %s64_1
1045 )";
1046 
1047   CompileSuccessfully(GenerateShaderCode(body).c_str());
1048   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1049   EXPECT_THAT(getDiagnosticString(),
1050               HasSubstr("Expected both operands to have the same component bit "
1051                         "width: SGreaterThan"));
1052 }
1053 
TEST_F(ValidateLogicals,PSBSelectSuccess)1054 TEST_F(ValidateLogicals, PSBSelectSuccess) {
1055   const std::string body = R"(
1056 OpCapability PhysicalStorageBufferAddressesEXT
1057 OpCapability Int64
1058 OpCapability Shader
1059 OpExtension "SPV_EXT_physical_storage_buffer"
1060 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
1061 OpEntryPoint Fragment %main "main"
1062 OpExecutionMode %main OriginUpperLeft
1063 OpDecorate %val1 AliasedPointerEXT
1064 %uint64 = OpTypeInt 64 0
1065 %bool = OpTypeBool
1066 %true = OpConstantTrue %bool
1067 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
1068 %pptr_f = OpTypePointer Function %ptr
1069 %void = OpTypeVoid
1070 %voidfn = OpTypeFunction %void
1071 %main = OpFunction %void None %voidfn
1072 %entry = OpLabel
1073 %val1 = OpVariable %pptr_f Function
1074 %val2 = OpLoad %ptr %val1
1075 %val3 = OpSelect %ptr %true %val2 %val2
1076 OpReturn
1077 OpFunctionEnd
1078 )";
1079 
1080   CompileSuccessfully(body.c_str());
1081   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1082 }
1083 
TEST_F(ValidateLogicals,SelectVectorsScalarCondition)1084 TEST_F(ValidateLogicals, SelectVectorsScalarCondition) {
1085   const std::string spirv = R"(
1086 OpCapability Shader
1087 OpCapability Linkage
1088 OpMemoryModel Logical GLSL450
1089 %void = OpTypeVoid
1090 %bool = OpTypeBool
1091 %int = OpTypeInt 32 0
1092 %int4 = OpTypeVector %int 4
1093 %int4_0 = OpConstantNull %int4
1094 %true = OpConstantTrue %bool
1095 %void_fn = OpTypeFunction %void
1096 %func = OpFunction %void None %void_fn
1097 %1 = OpLabel
1098 %select = OpSelect %int4 %true %int4_0 %int4_0
1099 OpReturn
1100 OpFunctionEnd
1101 )";
1102 
1103   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1104   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1105             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1106   EXPECT_THAT(getDiagnosticString(),
1107               HasSubstr("Expected vector sizes of Result Type and the "
1108                         "condition to be equal: Select"));
1109 }
1110 
TEST_F(ValidateLogicals,SelectVectorsScalarCondition1p4)1111 TEST_F(ValidateLogicals, SelectVectorsScalarCondition1p4) {
1112   const std::string spirv = R"(
1113 OpCapability Shader
1114 OpCapability Linkage
1115 OpMemoryModel Logical GLSL450
1116 %void = OpTypeVoid
1117 %bool = OpTypeBool
1118 %int = OpTypeInt 32 0
1119 %int4 = OpTypeVector %int 4
1120 %int4_0 = OpConstantNull %int4
1121 %true = OpConstantTrue %bool
1122 %void_fn = OpTypeFunction %void
1123 %func = OpFunction %void None %void_fn
1124 %1 = OpLabel
1125 %select = OpSelect %int4 %true %int4_0 %int4_0
1126 OpReturn
1127 OpFunctionEnd
1128 )";
1129 
1130   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1131   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1132 }
1133 
TEST_F(ValidateLogicals,SelectVectorsVectorConditionMismatchedDimensions1p4)1134 TEST_F(ValidateLogicals, SelectVectorsVectorConditionMismatchedDimensions1p4) {
1135   const std::string spirv = R"(
1136 OpCapability Shader
1137 OpCapability Linkage
1138 OpMemoryModel Logical GLSL450
1139 %void = OpTypeVoid
1140 %bool = OpTypeBool
1141 %bool3 = OpTypeVector %bool 3
1142 %int = OpTypeInt 32 0
1143 %int4 = OpTypeVector %int 4
1144 %int4_0 = OpConstantNull %int4
1145 %bool3_null = OpConstantNull %bool3
1146 %void_fn = OpTypeFunction %void
1147 %func = OpFunction %void None %void_fn
1148 %1 = OpLabel
1149 %select = OpSelect %int4 %bool3_null %int4_0 %int4_0
1150 OpReturn
1151 OpFunctionEnd
1152 )";
1153 
1154   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1155   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1156             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1157   EXPECT_THAT(getDiagnosticString(),
1158               HasSubstr("Expected vector sizes of Result Type and the "
1159                         "condition to be equal: Select"));
1160 }
1161 
1162 }  // namespace
1163 }  // namespace val
1164 }  // namespace spvtools
1165