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
23namespace spvtools {
24namespace val {
25namespace {
26
27using ::testing::HasSubstr;
28using ::testing::Not;
29
30using ValidateBitwise = spvtest::ValidateBase<bool>;
31
32std::string GenerateShaderCode(
33    const std::string& body,
34    const std::string& capabilities_and_extensions = "") {
35  const std::string capabilities =
36      R"(
37OpCapability Shader
38OpCapability Int64
39OpCapability Float64)";
40
41  const std::string after_extension_before_body =
42      R"(
43OpMemoryModel Logical GLSL450
44OpEntryPoint Fragment %main "main"
45OpExecutionMode %main OriginUpperLeft
46%void = OpTypeVoid
47%func = OpTypeFunction %void
48%bool = OpTypeBool
49%f32 = OpTypeFloat 32
50%u32 = OpTypeInt 32 0
51%s32 = OpTypeInt 32 1
52%f64 = OpTypeFloat 64
53%u64 = OpTypeInt 64 0
54%s64 = OpTypeInt 64 1
55%boolvec2 = OpTypeVector %bool 2
56%s32vec2 = OpTypeVector %s32 2
57%u32vec2 = OpTypeVector %u32 2
58%u64vec2 = OpTypeVector %u64 2
59%f32vec2 = OpTypeVector %f32 2
60%f64vec2 = OpTypeVector %f64 2
61%boolvec3 = OpTypeVector %bool 3
62%u32vec3 = OpTypeVector %u32 3
63%u64vec3 = OpTypeVector %u64 3
64%s32vec3 = OpTypeVector %s32 3
65%f32vec3 = OpTypeVector %f32 3
66%f64vec3 = OpTypeVector %f64 3
67%boolvec4 = OpTypeVector %bool 4
68%u32vec4 = OpTypeVector %u32 4
69%u64vec4 = OpTypeVector %u64 4
70%s32vec4 = OpTypeVector %s32 4
71%f32vec4 = OpTypeVector %f32 4
72%f64vec4 = OpTypeVector %f64 4
73
74%f32_0 = OpConstant %f32 0
75%f32_1 = OpConstant %f32 1
76%f32_2 = OpConstant %f32 2
77%f32_3 = OpConstant %f32 3
78%f32_4 = OpConstant %f32 4
79
80%s32_0 = OpConstant %s32 0
81%s32_1 = OpConstant %s32 1
82%s32_2 = OpConstant %s32 2
83%s32_3 = OpConstant %s32 3
84%s32_4 = OpConstant %s32 4
85%s32_m1 = OpConstant %s32 -1
86
87%u32_0 = OpConstant %u32 0
88%u32_1 = OpConstant %u32 1
89%u32_2 = OpConstant %u32 2
90%u32_3 = OpConstant %u32 3
91%u32_4 = OpConstant %u32 4
92
93%f64_0 = OpConstant %f64 0
94%f64_1 = OpConstant %f64 1
95%f64_2 = OpConstant %f64 2
96%f64_3 = OpConstant %f64 3
97%f64_4 = OpConstant %f64 4
98
99%s64_0 = OpConstant %s64 0
100%s64_1 = OpConstant %s64 1
101%s64_2 = OpConstant %s64 2
102%s64_3 = OpConstant %s64 3
103%s64_4 = OpConstant %s64 4
104%s64_m1 = OpConstant %s64 -1
105
106%u64_0 = OpConstant %u64 0
107%u64_1 = OpConstant %u64 1
108%u64_2 = OpConstant %u64 2
109%u64_3 = OpConstant %u64 3
110%u64_4 = OpConstant %u64 4
111
112%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
113%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
114%u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
115%u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
116%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
117%u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
118
119%s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1
120%s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2
121%s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2
122%s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3
123%s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3
124%s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4
125
126%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
127%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
128%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
129%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
130%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
131%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
132
133%main = OpFunction %void None %func
134%main_entry = OpLabel)";
135
136  const std::string after_body =
137      R"(
138OpReturn
139OpFunctionEnd)";
140
141  return capabilities + capabilities_and_extensions +
142         after_extension_before_body + body + after_body;
143}
144
145TEST_F(ValidateBitwise, ShiftAllSuccess) {
146  const std::string body = R"(
147%val1 = OpShiftRightLogical %u64 %u64_1 %s32_2
148%val2 = OpShiftRightArithmetic %s32vec2 %s32vec2_12 %s32vec2_12
149%val3 = OpShiftLeftLogical %u32vec2 %s32vec2_12 %u32vec2_12
150)";
151
152  CompileSuccessfully(GenerateShaderCode(body).c_str());
153  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
154}
155
156TEST_F(ValidateBitwise, OpShiftRightLogicalWrongResultType) {
157  const std::string body = R"(
158%val1 = OpShiftRightLogical %bool %u64_1 %s32_2
159)";
160
161  CompileSuccessfully(GenerateShaderCode(body).c_str());
162  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
163  EXPECT_THAT(getDiagnosticString(),
164              HasSubstr("Expected int scalar or vector type as Result Type: "
165                        "ShiftRightLogical"));
166}
167
168TEST_F(ValidateBitwise, OpShiftRightLogicalBaseNotInt) {
169  const std::string body = R"(
170%val1 = OpShiftRightLogical %u32 %f32_1 %s32_2
171)";
172
173  CompileSuccessfully(GenerateShaderCode(body).c_str());
174  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
175  EXPECT_THAT(
176      getDiagnosticString(),
177      HasSubstr("Expected Base to be int scalar or vector: ShiftRightLogical"));
178}
179
180TEST_F(ValidateBitwise, OpShiftRightLogicalBaseWrongDimension) {
181  const std::string body = R"(
182%val1 = OpShiftRightLogical %u32 %u32vec2_12 %s32_2
183)";
184
185  CompileSuccessfully(GenerateShaderCode(body).c_str());
186  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
187  EXPECT_THAT(
188      getDiagnosticString(),
189      HasSubstr("Expected Base to have the same dimension as Result Type: "
190                "ShiftRightLogical"));
191}
192
193TEST_F(ValidateBitwise, OpShiftRightLogicalBaseWrongBitWidth) {
194  const std::string body = R"(
195%val1 = OpShiftRightLogical %u64 %u32_1 %s32_2
196)";
197
198  CompileSuccessfully(GenerateShaderCode(body).c_str());
199  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
200  EXPECT_THAT(
201      getDiagnosticString(),
202      HasSubstr("Expected Base to have the same bit width as Result Type: "
203                "ShiftRightLogical"));
204}
205
206TEST_F(ValidateBitwise, OpShiftRightLogicalShiftNotInt) {
207  const std::string body = R"(
208%val1 = OpShiftRightLogical %u32 %u32_1 %f32_2
209)";
210
211  CompileSuccessfully(GenerateShaderCode(body).c_str());
212  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
213  EXPECT_THAT(
214      getDiagnosticString(),
215      HasSubstr(
216          "Expected Shift to be int scalar or vector: ShiftRightLogical"));
217}
218
219TEST_F(ValidateBitwise, OpShiftRightLogicalShiftWrongDimension) {
220  const std::string body = R"(
221%val1 = OpShiftRightLogical %u32 %u32_1 %s32vec2_12
222)";
223
224  CompileSuccessfully(GenerateShaderCode(body).c_str());
225  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
226  EXPECT_THAT(
227      getDiagnosticString(),
228      HasSubstr("Expected Shift to have the same dimension as Result Type: "
229                "ShiftRightLogical"));
230}
231
232TEST_F(ValidateBitwise, LogicAllSuccess) {
233  const std::string body = R"(
234%val1 = OpBitwiseOr %u64 %u64_1 %s64_0
235%val2 = OpBitwiseAnd %s64 %s64_1 %u64_0
236%val3 = OpBitwiseXor %s32vec2 %s32vec2_12 %u32vec2_01
237%val4 = OpNot %s32vec2 %u32vec2_01
238)";
239
240  CompileSuccessfully(GenerateShaderCode(body).c_str());
241  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
242}
243
244TEST_F(ValidateBitwise, OpBitwiseAndWrongResultType) {
245  const std::string body = R"(
246%val1 = OpBitwiseAnd %bool %u64_1 %s32_2
247)";
248
249  CompileSuccessfully(GenerateShaderCode(body).c_str());
250  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
251  EXPECT_THAT(
252      getDiagnosticString(),
253      HasSubstr(
254          "Expected int scalar or vector type as Result Type: BitwiseAnd"));
255}
256
257TEST_F(ValidateBitwise, OpBitwiseAndLeftNotInt) {
258  const std::string body = R"(
259%val1 = OpBitwiseAnd %u32 %f32_1 %s32_2
260)";
261
262  CompileSuccessfully(GenerateShaderCode(body).c_str());
263  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
264  EXPECT_THAT(getDiagnosticString(),
265              HasSubstr("Expected int scalar or vector as operand: BitwiseAnd "
266                        "operand index 2"));
267}
268
269TEST_F(ValidateBitwise, OpBitwiseAndRightNotInt) {
270  const std::string body = R"(
271%val1 = OpBitwiseAnd %u32 %u32_1 %f32_2
272)";
273
274  CompileSuccessfully(GenerateShaderCode(body).c_str());
275  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
276  EXPECT_THAT(getDiagnosticString(),
277              HasSubstr("Expected int scalar or vector as operand: BitwiseAnd "
278                        "operand index 3"));
279}
280
281TEST_F(ValidateBitwise, OpBitwiseAndLeftWrongDimension) {
282  const std::string body = R"(
283%val1 = OpBitwiseAnd %u32 %u32vec2_12 %s32_2
284)";
285
286  CompileSuccessfully(GenerateShaderCode(body).c_str());
287  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
288  EXPECT_THAT(
289      getDiagnosticString(),
290      HasSubstr("Expected operands to have the same dimension as Result Type: "
291                "BitwiseAnd operand index 2"));
292}
293
294TEST_F(ValidateBitwise, OpBitwiseAndRightWrongDimension) {
295  const std::string body = R"(
296%val1 = OpBitwiseAnd %u32 %s32_2 %u32vec2_12
297)";
298
299  CompileSuccessfully(GenerateShaderCode(body).c_str());
300  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
301  EXPECT_THAT(
302      getDiagnosticString(),
303      HasSubstr("Expected operands to have the same dimension as Result Type: "
304                "BitwiseAnd operand index 3"));
305}
306
307TEST_F(ValidateBitwise, OpBitwiseAndLeftWrongBitWidth) {
308  const std::string body = R"(
309%val1 = OpBitwiseAnd %u64 %u32_1 %s64_2
310)";
311
312  CompileSuccessfully(GenerateShaderCode(body).c_str());
313  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
314  EXPECT_THAT(
315      getDiagnosticString(),
316      HasSubstr("Expected operands to have the same bit width as Result Type: "
317                "BitwiseAnd operand index 2"));
318}
319
320TEST_F(ValidateBitwise, OpBitwiseAndRightWrongBitWidth) {
321  const std::string body = R"(
322%val1 = OpBitwiseAnd %u64 %u64_1 %s32_2
323)";
324
325  CompileSuccessfully(GenerateShaderCode(body).c_str());
326  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
327  EXPECT_THAT(
328      getDiagnosticString(),
329      HasSubstr("Expected operands to have the same bit width as Result Type: "
330                "BitwiseAnd operand index 3"));
331}
332
333TEST_F(ValidateBitwise, OpBitFieldInsertSuccess) {
334  const std::string body = R"(
335%val1 = OpBitFieldInsert %u64 %u64_1 %u64_2 %s32_1 %s32_2
336%val2 = OpBitFieldInsert %s32vec2 %s32vec2_12 %s32vec2_12 %s32_1 %u32_2
337)";
338
339  CompileSuccessfully(GenerateShaderCode(body).c_str());
340  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
341}
342
343TEST_F(ValidateBitwise, OpBitFieldInsertVulkanSuccess) {
344  const std::string body = R"(
345%val1 = OpBitFieldInsert %u32 %u32_1 %u32_2 %s32_1 %s32_2
346%val2 = OpBitFieldInsert %s32vec2 %s32vec2_12 %s32vec2_12 %s32_1 %u32_2
347)";
348
349  CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_VULKAN_1_0);
350  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
351}
352
353TEST_F(ValidateBitwise, OpBitFieldInsertWrongResultType) {
354  const std::string body = R"(
355%val1 = OpBitFieldInsert %bool %u64_1 %u64_2 %s32_1 %s32_2
356)";
357
358  CompileSuccessfully(GenerateShaderCode(body).c_str());
359  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
360  EXPECT_THAT(
361      getDiagnosticString(),
362      HasSubstr(
363          "Expected Base Type to be equal to Result Type: BitFieldInsert"));
364}
365
366TEST_F(ValidateBitwise, OpBitFieldInsertWrongBaseType) {
367  const std::string body = R"(
368%val1 = OpBitFieldInsert %u64 %s64_1 %u64_2 %s32_1 %s32_2
369)";
370
371  CompileSuccessfully(GenerateShaderCode(body).c_str());
372  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
373  EXPECT_THAT(
374      getDiagnosticString(),
375      HasSubstr(
376          "Expected Base Type to be equal to Result Type: BitFieldInsert"));
377}
378
379TEST_F(ValidateBitwise, OpBitFieldInsertWrongInsertType) {
380  const std::string body = R"(
381%val1 = OpBitFieldInsert %u64 %u64_1 %s64_2 %s32_1 %s32_2
382)";
383
384  CompileSuccessfully(GenerateShaderCode(body).c_str());
385  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
386  EXPECT_THAT(
387      getDiagnosticString(),
388      HasSubstr(
389          "Expected Insert Type to be equal to Result Type: BitFieldInsert"));
390}
391
392TEST_F(ValidateBitwise, OpBitFieldInsertOffsetNotInt) {
393  const std::string body = R"(
394%val1 = OpBitFieldInsert %u64 %u64_1 %u64_2 %f32_1 %s32_2
395)";
396
397  CompileSuccessfully(GenerateShaderCode(body).c_str());
398  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
399  EXPECT_THAT(
400      getDiagnosticString(),
401      HasSubstr("Expected Offset Type to be int scalar: BitFieldInsert"));
402}
403
404TEST_F(ValidateBitwise, OpBitFieldInsertCountNotInt) {
405  const std::string body = R"(
406%val1 = OpBitFieldInsert %u64 %u64_1 %u64_2 %u32_1 %f32_2
407)";
408
409  CompileSuccessfully(GenerateShaderCode(body).c_str());
410  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
411  EXPECT_THAT(
412      getDiagnosticString(),
413      HasSubstr("Expected Count Type to be int scalar: BitFieldInsert"));
414}
415
416TEST_F(ValidateBitwise, OpBitFieldInsertNot32Vulkan) {
417  const std::string body = R"(
418%val1 = OpBitFieldInsert %u64 %u64_1 %u64_2 %s32_1 %s32_2
419)";
420
421  CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_VULKAN_1_0);
422  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
423  EXPECT_THAT(getDiagnosticString(),
424              AnyVUID("VUID-StandaloneSpirv-Base-04781"));
425  EXPECT_THAT(
426      getDiagnosticString(),
427      HasSubstr("Expected 32-bit int type for Base operand: BitFieldInsert"));
428}
429
430TEST_F(ValidateBitwise, OpBitFieldSExtractSuccess) {
431  const std::string body = R"(
432%val1 = OpBitFieldSExtract %u64 %u64_1 %s32_1 %s32_2
433%val2 = OpBitFieldSExtract %s32vec2 %s32vec2_12 %s32_1 %u32_2
434)";
435
436  CompileSuccessfully(GenerateShaderCode(body).c_str());
437  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
438}
439
440TEST_F(ValidateBitwise, OpBitFieldSExtractVulkanSuccess) {
441  const std::string body = R"(
442%val1 = OpBitFieldSExtract %u32 %u32_1 %s32_1 %s32_2
443%val2 = OpBitFieldSExtract %s32vec2 %s32vec2_12 %s32_1 %u32_2
444)";
445
446  CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_VULKAN_1_0);
447  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
448}
449
450TEST_F(ValidateBitwise, OpBitFieldSExtractWrongResultType) {
451  const std::string body = R"(
452%val1 = OpBitFieldSExtract %bool %u64_1 %s32_1 %s32_2
453)";
454
455  CompileSuccessfully(GenerateShaderCode(body).c_str());
456  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
457  EXPECT_THAT(
458      getDiagnosticString(),
459      HasSubstr(
460          "Expected Base Type to be equal to Result Type: BitFieldSExtract"));
461}
462
463TEST_F(ValidateBitwise, OpBitFieldSExtractWrongBaseType) {
464  const std::string body = R"(
465%val1 = OpBitFieldSExtract %u64 %s64_1 %s32_1 %s32_2
466)";
467
468  CompileSuccessfully(GenerateShaderCode(body).c_str());
469  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
470  EXPECT_THAT(
471      getDiagnosticString(),
472      HasSubstr(
473          "Expected Base Type to be equal to Result Type: BitFieldSExtract"));
474}
475
476TEST_F(ValidateBitwise, OpBitFieldSExtractOffsetNotInt) {
477  const std::string body = R"(
478%val1 = OpBitFieldSExtract %u64 %u64_1 %f32_1 %s32_2
479)";
480
481  CompileSuccessfully(GenerateShaderCode(body).c_str());
482  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
483  EXPECT_THAT(
484      getDiagnosticString(),
485      HasSubstr("Expected Offset Type to be int scalar: BitFieldSExtract"));
486}
487
488TEST_F(ValidateBitwise, OpBitFieldSExtractCountNotInt) {
489  const std::string body = R"(
490%val1 = OpBitFieldSExtract %u64 %u64_1 %u32_1 %f32_2
491)";
492
493  CompileSuccessfully(GenerateShaderCode(body).c_str());
494  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
495  EXPECT_THAT(
496      getDiagnosticString(),
497      HasSubstr("Expected Count Type to be int scalar: BitFieldSExtract"));
498}
499
500TEST_F(ValidateBitwise, OpBitFieldSExtractNot32Vulkan) {
501  const std::string body = R"(
502%val1 = OpBitFieldSExtract %u64 %u64_1 %s32_1 %s32_2
503)";
504
505  CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_VULKAN_1_0);
506  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
507  EXPECT_THAT(getDiagnosticString(),
508              AnyVUID("VUID-StandaloneSpirv-Base-04781"));
509  EXPECT_THAT(
510      getDiagnosticString(),
511      HasSubstr("Expected 32-bit int type for Base operand: BitFieldSExtract"));
512}
513
514TEST_F(ValidateBitwise, OpBitReverseSuccess) {
515  const std::string body = R"(
516%val1 = OpBitReverse %u64 %u64_1
517%val2 = OpBitReverse %s32vec2 %s32vec2_12
518)";
519
520  CompileSuccessfully(GenerateShaderCode(body).c_str());
521  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
522}
523
524TEST_F(ValidateBitwise, OpBitReverseVulkanSuccess) {
525  const std::string body = R"(
526%val1 = OpBitReverse %u32 %u32_1
527%val2 = OpBitReverse %s32vec2 %s32vec2_12
528)";
529
530  CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_VULKAN_1_0);
531  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
532}
533
534TEST_F(ValidateBitwise, OpBitReverseWrongResultType) {
535  const std::string body = R"(
536%val1 = OpBitReverse %bool %u64_1
537)";
538
539  CompileSuccessfully(GenerateShaderCode(body).c_str());
540  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
541  EXPECT_THAT(
542      getDiagnosticString(),
543      HasSubstr("Expected Base Type to be equal to Result Type: BitReverse"));
544}
545
546TEST_F(ValidateBitwise, OpBitReverseWrongBaseType) {
547  const std::string body = R"(
548%val1 = OpBitReverse %u64 %s64_1
549)";
550
551  CompileSuccessfully(GenerateShaderCode(body).c_str());
552  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
553  EXPECT_THAT(
554      getDiagnosticString(),
555      HasSubstr("Expected Base Type to be equal to Result Type: BitReverse"));
556}
557
558TEST_F(ValidateBitwise, OpBitReverseNot32Vulkan) {
559  const std::string body = R"(
560%val1 = OpBitReverse %u64 %u64_1
561)";
562
563  CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_VULKAN_1_0);
564  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
565  EXPECT_THAT(getDiagnosticString(),
566              AnyVUID("VUID-StandaloneSpirv-Base-04781"));
567  EXPECT_THAT(
568      getDiagnosticString(),
569      HasSubstr("Expected 32-bit int type for Base operand: BitReverse"));
570}
571
572TEST_F(ValidateBitwise, OpBitCountSuccess) {
573  const std::string body = R"(
574%val1 = OpBitCount %s32 %u64_1
575%val2 = OpBitCount %u32vec2 %s32vec2_12
576%val3 = OpBitCount %s64 %s64_1
577)";
578
579  CompileSuccessfully(GenerateShaderCode(body).c_str());
580  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
581}
582
583TEST_F(ValidateBitwise, OpBitCountVulkanSuccess) {
584  const std::string body = R"(
585%val1 = OpBitCount %s32 %u32_1
586%val2 = OpBitCount %u32vec2 %s32vec2_12
587)";
588
589  CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_VULKAN_1_0);
590  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
591}
592
593TEST_F(ValidateBitwise, OpBitCountWrongResultType) {
594  const std::string body = R"(
595%val1 = OpBitCount %bool %u64_1
596)";
597
598  CompileSuccessfully(GenerateShaderCode(body).c_str());
599  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
600  EXPECT_THAT(
601      getDiagnosticString(),
602      HasSubstr("Expected int scalar or vector type as Result Type: BitCount"));
603}
604
605TEST_F(ValidateBitwise, OpBitCountBaseNotInt) {
606  const std::string body = R"(
607%val1 = OpBitCount %u32 %f64_1
608)";
609
610  CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_VULKAN_1_0);
611  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
612  EXPECT_THAT(getDiagnosticString(),
613              AnyVUID("VUID-StandaloneSpirv-Base-04781"));
614  EXPECT_THAT(
615      getDiagnosticString(),
616      HasSubstr(
617          "Expected int scalar or vector type for Base operand: BitCount"));
618}
619
620TEST_F(ValidateBitwise, OpBitCountBaseWrongDimension) {
621  const std::string body = R"(
622%val1 = OpBitCount %u32 %u32vec2_12
623)";
624
625  CompileSuccessfully(GenerateShaderCode(body).c_str());
626  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
627  EXPECT_THAT(
628      getDiagnosticString(),
629      HasSubstr("Expected Base dimension to be equal to Result Type dimension: "
630                "BitCount"));
631}
632
633TEST_F(ValidateBitwise, OpBitCountNot32Vulkan) {
634  const std::string body = R"(
635%val1 = OpBitCount %s64 %s64_1
636)";
637
638  CompileSuccessfully(GenerateShaderCode(body).c_str(), SPV_ENV_VULKAN_1_0);
639  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
640  EXPECT_THAT(getDiagnosticString(),
641              AnyVUID("VUID-StandaloneSpirv-Base-04781"));
642  EXPECT_THAT(getDiagnosticString(),
643              HasSubstr("Expected 32-bit int type for Base operand: BitCount"));
644}
645
646TEST_F(ValidateBitwise, OpBitCountPointer) {
647  const std::string body = R"(
648OpCapability Shader
649OpMemoryModel Logical GLSL450
650OpEntryPoint GLCompute %main "main"
651OpExecutionMode %main LocalSize 1 1 1
652%void = OpTypeVoid
653%int = OpTypeInt 32 0
654%ptr_int = OpTypePointer Function %int
655%void_fn = OpTypeFunction %void
656%main = OpFunction %void None %void_fn
657%entry = OpLabel
658%var = OpVariable %ptr_int Function
659%count = OpBitCount %int %var
660OpReturn
661OpFunctionEnd
662)";
663
664  CompileSuccessfully(body);
665  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
666  EXPECT_THAT(
667      getDiagnosticString(),
668      HasSubstr(
669          "Expected int scalar or vector type for Base operand: BitCount"));
670}
671
672}  // namespace
673}  // namespace val
674}  // namespace spvtools
675