• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Tint Authors.  //
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #include "gmock/gmock.h"
15 #include "src/reader/spirv/function.h"
16 #include "src/reader/spirv/parser_impl_test_helper.h"
17 #include "src/reader/spirv/spirv_tools_helpers_test.h"
18 
19 namespace tint {
20 namespace reader {
21 namespace spirv {
22 namespace {
23 
24 using ::testing::HasSubstr;
25 
CommonTypes()26 std::string CommonTypes() {
27   return R"(
28   %void = OpTypeVoid
29   %voidfn = OpTypeFunction %void
30 
31   %uint = OpTypeInt 32 0
32   %int = OpTypeInt 32 1
33   %float = OpTypeFloat 32
34 
35   %uint_10 = OpConstant %uint 10
36   %uint_20 = OpConstant %uint 20
37   %int_30 = OpConstant %int 30
38   %int_40 = OpConstant %int 40
39   %float_50 = OpConstant %float 50
40   %float_60 = OpConstant %float 60
41 
42   %ptr_uint = OpTypePointer Function %uint
43   %ptr_int = OpTypePointer Function %int
44   %ptr_float = OpTypePointer Function %float
45 
46   %v2uint = OpTypeVector %uint 2
47   %v2int = OpTypeVector %int 2
48   %v2float = OpTypeVector %float 2
49 
50   %v2uint_10_20 = OpConstantComposite %v2uint %uint_10 %uint_20
51   %v2uint_20_10 = OpConstantComposite %v2uint %uint_20 %uint_10
52   %v2int_30_40 = OpConstantComposite %v2int %int_30 %int_40
53   %v2int_40_30 = OpConstantComposite %v2int %int_40 %int_30
54   %v2float_50_60 = OpConstantComposite %v2float %float_50 %float_60
55   %v2float_60_50 = OpConstantComposite %v2float %float_60 %float_50
56 )";
57 }
58 
SimplePreamble()59 std::string SimplePreamble() {
60   return R"(
61   OpCapability Shader
62   OpMemoryModel Logical Simple
63   OpEntryPoint Fragment %100 "main"
64   OpExecutionMode %100 OriginUpperLeft
65 )" + CommonTypes();
66 }
67 
68 // Returns the AST dump for a given SPIR-V assembly constant.
AstFor(std::string assembly)69 std::string AstFor(std::string assembly) {
70   if (assembly == "v2uint_10_20") {
71     return "vec2<u32>(10u, 20u)";
72   }
73   if (assembly == "v2uint_20_10") {
74     return "vec2<u32>(20u, 10u)";
75   }
76   if (assembly == "v2int_30_40") {
77     return "vec2<i32>(30, 40)";
78   }
79   if (assembly == "v2int_40_30") {
80     return "vec2<i32>(40, 30)";
81   }
82   if (assembly == "cast_int_v2uint_10_20") {
83     return "bitcast<vec2<i32>(vec2<u32>(10u, 20u))";
84   }
85   if (assembly == "v2float_50_60") {
86     return "vec2<f32>(50.0, 60.0))";
87   }
88   if (assembly == "v2float_60_50") {
89     return "vec2<f32>(60.0, 50.0))";
90   }
91   return "bad case";
92 }
93 
94 using SpvUnaryBitTest = SpvParserTestBase<::testing::Test>;
95 
96 struct BinaryData {
97   const std::string res_type;
98   const std::string lhs;
99   const std::string op;
100   const std::string rhs;
101   const std::string ast_type;
102   const std::string ast_lhs;
103   const std::string ast_op;
104   const std::string ast_rhs;
105 };
operator <<(std::ostream & out,BinaryData data)106 inline std::ostream& operator<<(std::ostream& out, BinaryData data) {
107   out << "BinaryData{" << data.res_type << "," << data.lhs << "," << data.op
108       << "," << data.rhs << "," << data.ast_type << "," << data.ast_lhs << ","
109       << data.ast_op << "," << data.ast_rhs << "}";
110   return out;
111 }
112 
113 using SpvBinaryBitTest =
114     SpvParserTestBase<::testing::TestWithParam<BinaryData>>;
115 using SpvBinaryBitTestBasic = SpvParserTestBase<::testing::Test>;
116 
TEST_P(SpvBinaryBitTest,EmitExpression)117 TEST_P(SpvBinaryBitTest, EmitExpression) {
118   const auto assembly = SimplePreamble() + R"(
119      %100 = OpFunction %void None %voidfn
120      %entry = OpLabel
121      %1 = )" + GetParam().op +
122                         " %" + GetParam().res_type + " %" + GetParam().lhs +
123                         " %" + GetParam().rhs + R"(
124      OpReturn
125      OpFunctionEnd
126   )";
127   auto p = parser(test::Assemble(assembly));
128   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions())
129       << p->error() << "\n"
130       << assembly;
131   auto fe = p->function_emitter(100);
132   EXPECT_TRUE(fe.EmitBody()) << p->error();
133   std::ostringstream ss;
134   ss << "let x_1 : " << GetParam().ast_type << " = (" << GetParam().ast_lhs
135      << " " << GetParam().ast_op << " " << GetParam().ast_rhs << ");";
136   auto ast_body = fe.ast_body();
137   EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr(ss.str()))
138       << assembly;
139 }
140 
141 // Use this when the result might have extra bitcasts on the outside.
142 struct BinaryDataGeneral {
143   const std::string res_type;
144   const std::string lhs;
145   const std::string op;
146   const std::string rhs;
147   const std::string wgsl_type;
148   const std::string expected;
149 };
operator <<(std::ostream & out,BinaryDataGeneral data)150 inline std::ostream& operator<<(std::ostream& out, BinaryDataGeneral data) {
151   out << "BinaryDataGeneral{" << data.res_type << "," << data.lhs << ","
152       << data.op << "," << data.rhs << "," << data.wgsl_type << ","
153       << data.expected << "}";
154   return out;
155 }
156 
157 using SpvBinaryBitGeneralTest =
158     SpvParserTestBase<::testing::TestWithParam<BinaryDataGeneral>>;
159 
TEST_P(SpvBinaryBitGeneralTest,EmitExpression)160 TEST_P(SpvBinaryBitGeneralTest, EmitExpression) {
161   const auto assembly = SimplePreamble() + R"(
162      %100 = OpFunction %void None %voidfn
163      %entry = OpLabel
164      %1 = )" + GetParam().op +
165                         " %" + GetParam().res_type + " %" + GetParam().lhs +
166                         " %" + GetParam().rhs + R"(
167      OpReturn
168      OpFunctionEnd
169   )";
170   auto p = parser(test::Assemble(assembly));
171   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions())
172       << p->error() << "\n"
173       << assembly;
174   auto fe = p->function_emitter(100);
175   EXPECT_TRUE(fe.EmitBody()) << p->error() << assembly;
176   std::ostringstream ss;
177   ss << "let x_1 : " << GetParam().wgsl_type << " = " << GetParam().expected
178      << ";\nreturn;\n";
179   auto ast_body = fe.ast_body();
180   auto got = test::ToString(p->program(), ast_body);
181   EXPECT_THAT(got, HasSubstr(ss.str())) << "got:\n" << got << assembly;
182 }
183 
184 INSTANTIATE_TEST_SUITE_P(
185     SpvParserTest_ShiftLeftLogical_Arg2Unsigned,
186     SpvBinaryBitTest,
187     ::testing::Values(
188         // uint uint -> uint
189         BinaryData{"uint", "uint_10", "OpShiftLeftLogical", "uint_20", "u32",
190                    "10u", "<<", "20u"},
191         // int, uint -> int
192         BinaryData{"int", "int_30", "OpShiftLeftLogical", "uint_20", "i32",
193                    "30", "<<", "20u"},
194         // v2uint v2uint -> v2uint
195         BinaryData{"v2uint", "v2uint_10_20", "OpShiftLeftLogical",
196                    "v2uint_20_10", "vec2<u32>", AstFor("v2uint_10_20"), "<<",
197                    AstFor("v2uint_20_10")},
198         // v2int, v2uint -> v2int
199         BinaryData{"v2int", "v2int_30_40", "OpShiftLeftLogical", "v2uint_20_10",
200                    "vec2<i32>", AstFor("v2int_30_40"), "<<",
201                    AstFor("v2uint_20_10")}));
202 
203 INSTANTIATE_TEST_SUITE_P(
204     // WGSL requires second operand to be unsigned, so insert bitcasts
205     SpvParserTest_ShiftLeftLogical_Arg2Signed,
206     SpvBinaryBitGeneralTest,
207     ::testing::Values(
208         // int, int -> int
209         BinaryDataGeneral{"int", "int_30", "OpShiftLeftLogical", "int_40",
210                           "i32", "(30 << bitcast<u32>(40))"},
211         // uint, int -> uint
212         BinaryDataGeneral{"uint", "uint_10", "OpShiftLeftLogical", "int_40",
213                           "u32", "(10u << bitcast<u32>(40))"},
214         // v2uint, v2int -> v2uint
215         BinaryDataGeneral{"v2uint", "v2uint_10_20", "OpShiftLeftLogical",
216                           "v2uint_20_10", "vec2<u32>",
217                           "(vec2<u32>(10u, 20u) << vec2<u32>(20u, 10u))"},
218         // v2int, v2int -> v2int
219         BinaryDataGeneral{
220             "v2int", "v2int_30_40", "OpShiftLeftLogical", "v2int_40_30",
221             "vec2<i32>",
222             "(vec2<i32>(30, 40) << bitcast<vec2<u32>>(vec2<i32>(40, 30)))"}));
223 
224 INSTANTIATE_TEST_SUITE_P(
225     SpvParserTest_ShiftLeftLogical_BitcastResult,
226     SpvBinaryBitGeneralTest,
227     ::testing::Values(
228         // int, int -> uint
229         BinaryDataGeneral{"uint", "int_30", "OpShiftLeftLogical", "uint_10",
230                           "u32", "bitcast<u32>((30 << 10u))"},
231         // v2uint, v2int -> v2uint
232         BinaryDataGeneral{
233             "v2uint", "v2int_30_40", "OpShiftLeftLogical", "v2uint_20_10",
234             "vec2<u32>",
235             "bitcast<vec2<u32>>((vec2<i32>(30, 40) << vec2<u32>(20u, 10u)))"}));
236 
237 INSTANTIATE_TEST_SUITE_P(
238     SpvParserTest_ShiftRightLogical_Arg2Unsigned,
239     SpvBinaryBitGeneralTest,
240     ::testing::Values(
241         // uint, uint -> uint
242         BinaryDataGeneral{"uint", "uint_10", "OpShiftRightLogical", "uint_20",
243                           "u32", "(10u >> 20u)"},
244         // int, uint -> int
245         BinaryDataGeneral{"int", "int_30", "OpShiftRightLogical", "uint_20",
246                           "i32", "bitcast<i32>((bitcast<u32>(30) >> 20u))"},
247         // v2uint, v2uint -> v2uint
248         BinaryDataGeneral{"v2uint", "v2uint_10_20", "OpShiftRightLogical",
249                           "v2uint_20_10", "vec2<u32>",
250                           "(vec2<u32>(10u, 20u) >> vec2<u32>(20u, 10u))"},
251         // v2int, v2uint -> v2int
252         BinaryDataGeneral{
253             "v2int", "v2int_30_40", "OpShiftRightLogical", "v2uint_10_20",
254             "vec2<i32>",
255             R"(bitcast<vec2<i32>>((bitcast<vec2<u32>>(vec2<i32>(30, 40)) >> vec2<u32>(10u, 20u))))"}));
256 
257 INSTANTIATE_TEST_SUITE_P(
258     SpvParserTest_ShiftRightLogical_Arg2Signed,
259     SpvBinaryBitGeneralTest,
260     ::testing::Values(
261         // uint, int -> uint
262         BinaryDataGeneral{"uint", "uint_10", "OpShiftRightLogical", "int_30",
263                           "u32", "(10u >> bitcast<u32>(30))"},
264         // int, int -> int
265         BinaryDataGeneral{
266             "int", "int_30", "OpShiftRightLogical", "int_40", "i32",
267             "bitcast<i32>((bitcast<u32>(30) >> bitcast<u32>(40)))"},
268         // v2uint, v2int -> v2uint
269         BinaryDataGeneral{
270             "v2uint", "v2uint_10_20", "OpShiftRightLogical", "v2int_30_40",
271             "vec2<u32>",
272             "(vec2<u32>(10u, 20u) >> bitcast<vec2<u32>>(vec2<i32>(30, 40)))"},
273         // v2int, v2int -> v2int
274         BinaryDataGeneral{
275             "v2int", "v2int_40_30", "OpShiftRightLogical", "v2int_30_40",
276             "vec2<i32>",
277             R"(bitcast<vec2<i32>>((bitcast<vec2<u32>>(vec2<i32>(40, 30)) >> bitcast<vec2<u32>>(vec2<i32>(30, 40)))))"}));
278 
279 INSTANTIATE_TEST_SUITE_P(
280     SpvParserTest_ShiftRightLogical_BitcastResult,
281     SpvBinaryBitGeneralTest,
282     ::testing::Values(
283         // uint, uint -> int
284         BinaryDataGeneral{"int", "uint_20", "OpShiftRightLogical", "uint_10",
285                           "i32", "bitcast<i32>((20u >> 10u))"},
286         // v2uint, v2uint -> v2int
287         BinaryDataGeneral{
288             "v2int", "v2uint_10_20", "OpShiftRightLogical", "v2uint_20_10",
289             "vec2<i32>",
290             R"(bitcast<vec2<i32>>((vec2<u32>(10u, 20u) >> vec2<u32>(20u, 10u))))"}));
291 
292 INSTANTIATE_TEST_SUITE_P(
293     SpvParserTest_ShiftRightArithmetic_Arg2Unsigned,
294     SpvBinaryBitGeneralTest,
295     ::testing::Values(
296         // uint, uint -> uint
297         BinaryDataGeneral{"uint", "uint_10", "OpShiftRightArithmetic",
298                           "uint_20", "u32",
299                           "bitcast<u32>((bitcast<i32>(10u) >> 20u))"},
300         // int, uint -> int
301         BinaryDataGeneral{"int", "int_30", "OpShiftRightArithmetic", "uint_10",
302                           "i32", "(30 >> 10u)"},
303         // v2uint, v2uint -> v2uint
304         BinaryDataGeneral{
305             "v2uint", "v2uint_10_20", "OpShiftRightArithmetic", "v2uint_20_10",
306             "vec2<u32>",
307             R"(bitcast<vec2<u32>>((bitcast<vec2<i32>>(vec2<u32>(10u, 20u)) >> vec2<u32>(20u, 10u))))"},
308         // v2int, v2uint -> v2int
309         BinaryDataGeneral{"v2int", "v2int_40_30", "OpShiftRightArithmetic",
310                           "v2uint_20_10", "vec2<i32>",
311                           "(vec2<i32>(40, 30) >> vec2<u32>(20u, 10u))"}));
312 
313 INSTANTIATE_TEST_SUITE_P(
314     SpvParserTest_ShiftRightArithmetic_Arg2Signed,
315     SpvBinaryBitGeneralTest,
316     ::testing::Values(
317         // uint, int -> uint
318         BinaryDataGeneral{
319             "uint", "uint_10", "OpShiftRightArithmetic", "int_30", "u32",
320             "bitcast<u32>((bitcast<i32>(10u) >> bitcast<u32>(30)))"},
321         // int, int -> int
322         BinaryDataGeneral{"int", "int_30", "OpShiftRightArithmetic", "int_40",
323                           "i32", "(30 >> bitcast<u32>(40))"},
324         // v2uint, v2int -> v2uint
325         BinaryDataGeneral{
326             "v2uint", "v2uint_10_20", "OpShiftRightArithmetic", "v2int_30_40",
327             "vec2<u32>",
328             R"(bitcast<vec2<u32>>((bitcast<vec2<i32>>(vec2<u32>(10u, 20u)) >> bitcast<vec2<u32>>(vec2<i32>(30, 40)))))"},
329         // v2int, v2int -> v2int
330         BinaryDataGeneral{
331             "v2int", "v2int_40_30", "OpShiftRightArithmetic", "v2int_30_40",
332             "vec2<i32>",
333             "(vec2<i32>(40, 30) >> bitcast<vec2<u32>>(vec2<i32>(30, 40)))"}));
334 
335 INSTANTIATE_TEST_SUITE_P(
336     SpvParserTest_ShiftRightArithmetic_BitcastResult,
337     SpvBinaryBitGeneralTest,
338     ::testing::Values(
339         // int, uint -> uint
340         BinaryDataGeneral{"uint", "int_30", "OpShiftRightArithmetic", "uint_10",
341                           "u32", "bitcast<u32>((30 >> 10u))"},
342         // v2int, v2uint -> v2uint
343         BinaryDataGeneral{
344             "v2uint", "v2int_30_40", "OpShiftRightArithmetic", "v2uint_20_10",
345             "vec2<u32>",
346             "bitcast<vec2<u32>>((vec2<i32>(30, 40) >> vec2<u32>(20u, 10u)))"}));
347 
348 INSTANTIATE_TEST_SUITE_P(
349     SpvParserTest_BitwiseAnd,
350     SpvBinaryBitTest,
351     ::testing::Values(
352         // Both uint
353         BinaryData{"uint", "uint_10", "OpBitwiseAnd", "uint_20", "u32", "10u",
354                    "&", "20u"},
355         // Both int
356         BinaryData{"int", "int_30", "OpBitwiseAnd", "int_40", "i32", "30", "&",
357                    "40"},
358         // TODO(crbug.com/tint/678): Resolver fails on vector bitwise operations
359         // Both v2uint
360         BinaryData{"v2uint", "v2uint_10_20", "OpBitwiseAnd", "v2uint_20_10",
361                    "vec2<u32>", AstFor("v2uint_10_20"), "&",
362                    AstFor("v2uint_20_10")},
363         // Both v2int
364         BinaryData{"v2int", "v2int_30_40", "OpBitwiseAnd", "v2int_40_30",
365                    "vec2<i32>", AstFor("v2int_30_40"), "&",
366                    AstFor("v2int_40_30")}));
367 
368 INSTANTIATE_TEST_SUITE_P(
369     SpvParserTest_BitwiseAnd_MixedSignedness,
370     SpvBinaryBitGeneralTest,
371     ::testing::Values(
372         // Mixed, uint <- int uint
373         BinaryDataGeneral{"uint", "int_30", "OpBitwiseAnd", "uint_10", "u32",
374                           "bitcast<u32>((30 & bitcast<i32>(10u)))"},
375         // Mixed, int <- int uint
376         BinaryDataGeneral{"int", "int_30", "OpBitwiseAnd", "uint_10", "i32",
377                           "(30 & bitcast<i32>(10u))"},
378         // Mixed, uint <- uint int
379         BinaryDataGeneral{"uint", "uint_10", "OpBitwiseAnd", "int_30", "u32",
380                           "(10u & bitcast<u32>(30))"},
381         // Mixed, int <- uint uint
382         BinaryDataGeneral{"int", "uint_20", "OpBitwiseAnd", "uint_10", "i32",
383                           "bitcast<i32>((20u & 10u))"},
384         // Mixed, returning v2uint
385         BinaryDataGeneral{
386             "v2uint", "v2int_30_40", "OpBitwiseAnd", "v2uint_10_20",
387             "vec2<u32>",
388             R"(bitcast<vec2<u32>>((vec2<i32>(30, 40) & bitcast<vec2<i32>>(vec2<u32>(10u, 20u)))))"},
389         // Mixed, returning v2int
390         BinaryDataGeneral{
391             "v2int", "v2uint_10_20", "OpBitwiseAnd", "v2int_40_30", "vec2<i32>",
392             R"(bitcast<vec2<i32>>((vec2<u32>(10u, 20u) & bitcast<vec2<u32>>(vec2<i32>(40, 30)))))"}));
393 
394 INSTANTIATE_TEST_SUITE_P(
395     SpvParserTest_BitwiseOr,
396     SpvBinaryBitTest,
397     ::testing::Values(
398         // Both uint
399         BinaryData{"uint", "uint_10", "OpBitwiseOr", "uint_20", "u32", "10u",
400                    "|", "20u"},
401         // Both int
402         BinaryData{"int", "int_30", "OpBitwiseOr", "int_40", "i32", "30", "|",
403                    "40"},
404         // TODO(crbug.com/tint/678): Resolver fails on vector bitwise operations
405         // Both v2uint
406         BinaryData{"v2uint", "v2uint_10_20", "OpBitwiseOr", "v2uint_20_10",
407                    "vec2<u32>", AstFor("v2uint_10_20"), "|",
408                    AstFor("v2uint_20_10")},
409         // Both v2int
410         BinaryData{"v2int", "v2int_30_40", "OpBitwiseOr", "v2int_40_30",
411                    "vec2<i32>", AstFor("v2int_30_40"), "|",
412                    AstFor("v2int_40_30")}));
413 
414 INSTANTIATE_TEST_SUITE_P(
415     SpvParserTest_BitwiseOr_MixedSignedness,
416     SpvBinaryBitGeneralTest,
417     ::testing::Values(
418         // Mixed, uint <- int uint
419         BinaryDataGeneral{"uint", "int_30", "OpBitwiseOr", "uint_10", "u32",
420                           "bitcast<u32>((30 | bitcast<i32>(10u)))"},
421         // Mixed, int <- int uint
422         BinaryDataGeneral{"int", "int_30", "OpBitwiseOr", "uint_10", "i32",
423                           "(30 | bitcast<i32>(10u))"},
424         // Mixed, uint <- uint int
425         BinaryDataGeneral{"uint", "uint_10", "OpBitwiseOr", "int_30", "u32",
426                           "(10u | bitcast<u32>(30))"},
427         // Mixed, int <- uint uint
428         BinaryDataGeneral{"int", "uint_20", "OpBitwiseOr", "uint_10", "i32",
429                           "bitcast<i32>((20u | 10u))"},
430         // Mixed, returning v2uint
431         BinaryDataGeneral{
432             "v2uint", "v2int_30_40", "OpBitwiseOr", "v2uint_10_20", "vec2<u32>",
433             R"(bitcast<vec2<u32>>((vec2<i32>(30, 40) | bitcast<vec2<i32>>(vec2<u32>(10u, 20u)))))"},
434         // Mixed, returning v2int
435         BinaryDataGeneral{
436             "v2int", "v2uint_10_20", "OpBitwiseOr", "v2int_40_30", "vec2<i32>",
437             R"(bitcast<vec2<i32>>((vec2<u32>(10u, 20u) | bitcast<vec2<u32>>(vec2<i32>(40, 30)))))"}));
438 
439 INSTANTIATE_TEST_SUITE_P(
440     SpvParserTest_BitwiseXor,
441     SpvBinaryBitTest,
442     ::testing::Values(
443         // Both uint
444         BinaryData{"uint", "uint_10", "OpBitwiseXor", "uint_20", "u32", "10u",
445                    "^", "20u"},
446         // Both int
447         BinaryData{"int", "int_30", "OpBitwiseXor", "int_40", "i32", "30", "^",
448                    "40"},
449         // TODO(crbug.com/tint/678): Resolver fails on vector bitwise operations
450         // Both v2uint
451         BinaryData{"v2uint", "v2uint_10_20", "OpBitwiseXor", "v2uint_20_10",
452                    "vec2<u32>", AstFor("v2uint_10_20"), "^",
453                    AstFor("v2uint_20_10")},
454         // Both v2int
455         BinaryData{"v2int", "v2int_30_40", "OpBitwiseXor", "v2int_40_30",
456                    "vec2<i32>", AstFor("v2int_30_40"), "^",
457                    AstFor("v2int_40_30")}));
458 
459 INSTANTIATE_TEST_SUITE_P(
460     SpvParserTest_BitwiseXor_MixedSignedness,
461     SpvBinaryBitGeneralTest,
462     ::testing::Values(
463         // Mixed, uint <- int uint
464         BinaryDataGeneral{"uint", "int_30", "OpBitwiseXor", "uint_10", "u32",
465                           "bitcast<u32>((30 ^ bitcast<i32>(10u)))"},
466         // Mixed, int <- int uint
467         BinaryDataGeneral{"int", "int_30", "OpBitwiseXor", "uint_10", "i32",
468                           "(30 ^ bitcast<i32>(10u))"},
469         // Mixed, uint <- uint int
470         BinaryDataGeneral{"uint", "uint_10", "OpBitwiseXor", "int_30", "u32",
471                           "(10u ^ bitcast<u32>(30))"},
472         // Mixed, int <- uint uint
473         BinaryDataGeneral{"int", "uint_20", "OpBitwiseXor", "uint_10", "i32",
474                           "bitcast<i32>((20u ^ 10u))"},
475         // Mixed, returning v2uint
476         BinaryDataGeneral{
477             "v2uint", "v2int_30_40", "OpBitwiseXor", "v2uint_10_20",
478             "vec2<u32>",
479             R"(bitcast<vec2<u32>>((vec2<i32>(30, 40) ^ bitcast<vec2<i32>>(vec2<u32>(10u, 20u)))))"},
480         // Mixed, returning v2int
481         BinaryDataGeneral{
482             "v2int", "v2uint_10_20", "OpBitwiseXor", "v2int_40_30", "vec2<i32>",
483             R"(bitcast<vec2<i32>>((vec2<u32>(10u, 20u) ^ bitcast<vec2<u32>>(vec2<i32>(40, 30)))))"}));
484 
TEST_F(SpvUnaryBitTest,Not_Int_Int)485 TEST_F(SpvUnaryBitTest, Not_Int_Int) {
486   const auto assembly = SimplePreamble() + R"(
487      %100 = OpFunction %void None %voidfn
488      %entry = OpLabel
489      %1 = OpNot %int %int_30
490      OpReturn
491      OpFunctionEnd
492   )";
493   auto p = parser(test::Assemble(assembly));
494   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
495   auto fe = p->function_emitter(100);
496   EXPECT_TRUE(fe.EmitBody()) << p->error();
497   auto ast_body = fe.ast_body();
498   auto body = test::ToString(p->program(), ast_body);
499   EXPECT_THAT(body, HasSubstr("let x_1 : i32 = ~(30);"));
500 }
501 
TEST_F(SpvUnaryBitTest,Not_Int_Uint)502 TEST_F(SpvUnaryBitTest, Not_Int_Uint) {
503   const auto assembly = SimplePreamble() + R"(
504      %100 = OpFunction %void None %voidfn
505      %entry = OpLabel
506      %1 = OpNot %int %uint_10
507      OpReturn
508      OpFunctionEnd
509   )";
510   auto p = parser(test::Assemble(assembly));
511   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
512   auto fe = p->function_emitter(100);
513   EXPECT_TRUE(fe.EmitBody()) << p->error();
514   auto ast_body = fe.ast_body();
515   auto body = test::ToString(p->program(), ast_body);
516   EXPECT_THAT(body, HasSubstr("let x_1 : i32 = bitcast<i32>(~(10u));"));
517 }
518 
TEST_F(SpvUnaryBitTest,Not_Uint_Int)519 TEST_F(SpvUnaryBitTest, Not_Uint_Int) {
520   const auto assembly = SimplePreamble() + R"(
521      %100 = OpFunction %void None %voidfn
522      %entry = OpLabel
523      %1 = OpNot %uint %int_30
524      OpReturn
525      OpFunctionEnd
526   )";
527   auto p = parser(test::Assemble(assembly));
528   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
529   auto fe = p->function_emitter(100);
530   EXPECT_TRUE(fe.EmitBody()) << p->error();
531   auto ast_body = fe.ast_body();
532   auto body = test::ToString(p->program(), ast_body);
533   EXPECT_THAT(body, HasSubstr("let x_1 : u32 = bitcast<u32>(~(30));"));
534 }
535 
TEST_F(SpvUnaryBitTest,Not_Uint_Uint)536 TEST_F(SpvUnaryBitTest, Not_Uint_Uint) {
537   const auto assembly = SimplePreamble() + R"(
538      %100 = OpFunction %void None %voidfn
539      %entry = OpLabel
540      %1 = OpNot %uint %uint_10
541      OpReturn
542      OpFunctionEnd
543   )";
544   auto p = parser(test::Assemble(assembly));
545   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
546   auto fe = p->function_emitter(100);
547   EXPECT_TRUE(fe.EmitBody()) << p->error();
548   auto ast_body = fe.ast_body();
549   auto body = test::ToString(p->program(), ast_body);
550   EXPECT_THAT(body, HasSubstr("let x_1 : u32 = ~(10u);"));
551 }
552 
TEST_F(SpvUnaryBitTest,Not_SignedVec_SignedVec)553 TEST_F(SpvUnaryBitTest, Not_SignedVec_SignedVec) {
554   const auto assembly = SimplePreamble() + R"(
555      %100 = OpFunction %void None %voidfn
556      %entry = OpLabel
557      %1 = OpNot %v2int %v2int_30_40
558      OpReturn
559      OpFunctionEnd
560   )";
561   auto p = parser(test::Assemble(assembly));
562   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
563   auto fe = p->function_emitter(100);
564   EXPECT_TRUE(fe.EmitBody()) << p->error();
565   auto ast_body = fe.ast_body();
566   auto body = test::ToString(p->program(), ast_body);
567   EXPECT_THAT(body, HasSubstr("let x_1 : vec2<i32> = ~(vec2<i32>(30, 40));"));
568 }
569 
TEST_F(SpvUnaryBitTest,Not_SignedVec_UnsignedVec)570 TEST_F(SpvUnaryBitTest, Not_SignedVec_UnsignedVec) {
571   const auto assembly = SimplePreamble() + R"(
572      %100 = OpFunction %void None %voidfn
573      %entry = OpLabel
574      %1 = OpNot %v2int %v2uint_10_20
575      OpReturn
576      OpFunctionEnd
577   )";
578   auto p = parser(test::Assemble(assembly));
579   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
580   auto fe = p->function_emitter(100);
581   EXPECT_TRUE(fe.EmitBody()) << p->error();
582   auto ast_body = fe.ast_body();
583   auto body = test::ToString(p->program(), ast_body);
584   EXPECT_THAT(
585       body,
586       HasSubstr(
587           "let x_1 : vec2<i32> = bitcast<vec2<i32>>(~(vec2<u32>(10u, 20u)));"));
588 }
589 
TEST_F(SpvUnaryBitTest,Not_UnsignedVec_SignedVec)590 TEST_F(SpvUnaryBitTest, Not_UnsignedVec_SignedVec) {
591   const auto assembly = SimplePreamble() + R"(
592      %100 = OpFunction %void None %voidfn
593      %entry = OpLabel
594      %1 = OpNot %v2uint %v2int_30_40
595      OpReturn
596      OpFunctionEnd
597   )";
598   auto p = parser(test::Assemble(assembly));
599   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
600   auto fe = p->function_emitter(100);
601   EXPECT_TRUE(fe.EmitBody()) << p->error();
602   auto ast_body = fe.ast_body();
603   auto body = test::ToString(p->program(), ast_body);
604   EXPECT_THAT(
605       body,
606       HasSubstr(
607           "let x_1 : vec2<u32> = bitcast<vec2<u32>>(~(vec2<i32>(30, 40)));"));
608 }
TEST_F(SpvUnaryBitTest,Not_UnsignedVec_UnsignedVec)609 TEST_F(SpvUnaryBitTest, Not_UnsignedVec_UnsignedVec) {
610   const auto assembly = SimplePreamble() + R"(
611      %100 = OpFunction %void None %voidfn
612      %entry = OpLabel
613      %1 = OpNot %v2uint %v2uint_10_20
614      OpReturn
615      OpFunctionEnd
616   )";
617   auto p = parser(test::Assemble(assembly));
618   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
619   auto fe = p->function_emitter(100);
620   EXPECT_TRUE(fe.EmitBody()) << p->error();
621   auto ast_body = fe.ast_body();
622   auto body = test::ToString(p->program(), ast_body);
623   EXPECT_THAT(body, HasSubstr("let x_1 : vec2<u32> = ~(vec2<u32>(10u, 20u));"));
624 }
625 
BitTestPreamble()626 std::string BitTestPreamble() {
627   return R"(
628   OpCapability Shader
629   %glsl = OpExtInstImport "GLSL.std.450"
630   OpMemoryModel Logical GLSL450
631   OpEntryPoint GLCompute %100 "main"
632   OpExecutionMode %100 LocalSize 1 1 1
633 
634   OpName %u1 "u1"
635   OpName %i1 "i1"
636   OpName %v2u1 "v2u1"
637   OpName %v2i1 "v2i1"
638 
639 )" + CommonTypes() +
640          R"(
641 
642   %100 = OpFunction %void None %voidfn
643   %entry = OpLabel
644 
645   %u1 = OpCopyObject %uint %uint_10
646   %i1 = OpCopyObject %int %int_30
647   %v2u1 = OpCopyObject %v2uint %v2uint_10_20
648   %v2i1 = OpCopyObject %v2int %v2int_30_40
649 )";
650 }
651 
TEST_F(SpvUnaryBitTest,BitCount_Uint_Uint)652 TEST_F(SpvUnaryBitTest, BitCount_Uint_Uint) {
653   const auto assembly = BitTestPreamble() + R"(
654      %1 = OpBitCount %uint %u1
655      OpReturn
656      OpFunctionEnd
657   )";
658   auto p = parser(test::Assemble(assembly));
659   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
660   auto fe = p->function_emitter(100);
661   EXPECT_TRUE(fe.EmitBody()) << p->error();
662   auto ast_body = fe.ast_body();
663   auto body = test::ToString(p->program(), ast_body);
664   EXPECT_THAT(body, HasSubstr("let x_1 : u32 = countOneBits(u1);")) << body;
665 }
666 
TEST_F(SpvUnaryBitTest,BitCount_Uint_Int)667 TEST_F(SpvUnaryBitTest, BitCount_Uint_Int) {
668   const auto assembly = BitTestPreamble() + R"(
669      %1 = OpBitCount %uint %i1
670      OpReturn
671      OpFunctionEnd
672   )";
673   auto p = parser(test::Assemble(assembly));
674   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
675   auto fe = p->function_emitter(100);
676   EXPECT_TRUE(fe.EmitBody()) << p->error();
677   auto ast_body = fe.ast_body();
678   auto body = test::ToString(p->program(), ast_body);
679   EXPECT_THAT(body,
680               HasSubstr("let x_1 : u32 = bitcast<u32>(countOneBits(i1));"))
681       << body;
682 }
683 
TEST_F(SpvUnaryBitTest,BitCount_Int_Uint)684 TEST_F(SpvUnaryBitTest, BitCount_Int_Uint) {
685   const auto assembly = BitTestPreamble() + R"(
686      %1 = OpBitCount %int %u1
687      OpReturn
688      OpFunctionEnd
689   )";
690   auto p = parser(test::Assemble(assembly));
691   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
692   auto fe = p->function_emitter(100);
693   EXPECT_TRUE(fe.EmitBody()) << p->error();
694   auto ast_body = fe.ast_body();
695   auto body = test::ToString(p->program(), ast_body);
696   EXPECT_THAT(body,
697               HasSubstr("let x_1 : i32 = bitcast<i32>(countOneBits(u1));"))
698       << body;
699 }
700 
TEST_F(SpvUnaryBitTest,BitCount_Int_Int)701 TEST_F(SpvUnaryBitTest, BitCount_Int_Int) {
702   const auto assembly = BitTestPreamble() + R"(
703      %1 = OpBitCount %int %i1
704      OpReturn
705      OpFunctionEnd
706   )";
707   auto p = parser(test::Assemble(assembly));
708   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
709   auto fe = p->function_emitter(100);
710   EXPECT_TRUE(fe.EmitBody()) << p->error();
711   auto ast_body = fe.ast_body();
712   auto body = test::ToString(p->program(), ast_body);
713   EXPECT_THAT(body, HasSubstr("let x_1 : i32 = countOneBits(i1);")) << body;
714 }
715 
TEST_F(SpvUnaryBitTest,BitCount_UintVector_UintVector)716 TEST_F(SpvUnaryBitTest, BitCount_UintVector_UintVector) {
717   const auto assembly = BitTestPreamble() + R"(
718      %1 = OpBitCount %v2uint %v2u1
719      OpReturn
720      OpFunctionEnd
721   )";
722   auto p = parser(test::Assemble(assembly));
723   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
724   auto fe = p->function_emitter(100);
725   EXPECT_TRUE(fe.EmitBody()) << p->error();
726   auto ast_body = fe.ast_body();
727   auto body = test::ToString(p->program(), ast_body);
728   EXPECT_THAT(body, HasSubstr("let x_1 : vec2<u32> = countOneBits(v2u1);"))
729       << body;
730 }
731 
TEST_F(SpvUnaryBitTest,BitCount_UintVector_IntVector)732 TEST_F(SpvUnaryBitTest, BitCount_UintVector_IntVector) {
733   const auto assembly = BitTestPreamble() + R"(
734      %1 = OpBitCount %v2uint %v2i1
735      OpReturn
736      OpFunctionEnd
737   )";
738   auto p = parser(test::Assemble(assembly));
739   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
740   auto fe = p->function_emitter(100);
741   EXPECT_TRUE(fe.EmitBody()) << p->error();
742   auto ast_body = fe.ast_body();
743   auto body = test::ToString(p->program(), ast_body);
744   EXPECT_THAT(
745       body,
746       HasSubstr(
747           "let x_1 : vec2<u32> = bitcast<vec2<u32>>(countOneBits(v2i1));"))
748       << body;
749 }
750 
TEST_F(SpvUnaryBitTest,BitCount_IntVector_UintVector)751 TEST_F(SpvUnaryBitTest, BitCount_IntVector_UintVector) {
752   const auto assembly = BitTestPreamble() + R"(
753      %1 = OpBitCount %v2int %v2u1
754      OpReturn
755      OpFunctionEnd
756   )";
757   auto p = parser(test::Assemble(assembly));
758   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
759   auto fe = p->function_emitter(100);
760   EXPECT_TRUE(fe.EmitBody()) << p->error();
761   auto ast_body = fe.ast_body();
762   auto body = test::ToString(p->program(), ast_body);
763   EXPECT_THAT(
764       body,
765       HasSubstr(
766           "let x_1 : vec2<i32> = bitcast<vec2<i32>>(countOneBits(v2u1));"))
767       << body;
768 }
769 
TEST_F(SpvUnaryBitTest,BitCount_IntVector_IntVector)770 TEST_F(SpvUnaryBitTest, BitCount_IntVector_IntVector) {
771   const auto assembly = BitTestPreamble() + R"(
772      %1 = OpBitCount %v2int %v2i1
773      OpReturn
774      OpFunctionEnd
775   )";
776   auto p = parser(test::Assemble(assembly));
777   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
778   auto fe = p->function_emitter(100);
779   EXPECT_TRUE(fe.EmitBody()) << p->error();
780   auto ast_body = fe.ast_body();
781   auto body = test::ToString(p->program(), ast_body);
782   EXPECT_THAT(body, HasSubstr("let x_1 : vec2<i32> = countOneBits(v2i1);"))
783       << body;
784 }
785 
TEST_F(SpvUnaryBitTest,BitReverse_Uint_Uint)786 TEST_F(SpvUnaryBitTest, BitReverse_Uint_Uint) {
787   const auto assembly = BitTestPreamble() + R"(
788      %1 = OpBitReverse %uint %u1
789      OpReturn
790      OpFunctionEnd
791   )";
792   auto p = parser(test::Assemble(assembly));
793   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
794   auto fe = p->function_emitter(100);
795   EXPECT_TRUE(fe.EmitBody()) << p->error();
796   auto ast_body = fe.ast_body();
797   auto body = test::ToString(p->program(), ast_body);
798   EXPECT_THAT(body, HasSubstr("let x_1 : u32 = reverseBits(u1);")) << body;
799 }
800 
TEST_F(SpvUnaryBitTest,BitReverse_Uint_Int)801 TEST_F(SpvUnaryBitTest, BitReverse_Uint_Int) {
802   const auto assembly = BitTestPreamble() + R"(
803      %1 = OpBitReverse %uint %i1
804      OpReturn
805      OpFunctionEnd
806   )";
807   auto p = parser(test::Assemble(assembly));
808   EXPECT_FALSE(p->Parse());
809   EXPECT_FALSE(p->success());
810   EXPECT_THAT(
811       p->error(),
812       HasSubstr("Expected Base Type to be equal to Result Type: BitReverse"));
813 }
814 
TEST_F(SpvUnaryBitTest,BitReverse_Int_Uint)815 TEST_F(SpvUnaryBitTest, BitReverse_Int_Uint) {
816   const auto assembly = BitTestPreamble() + R"(
817      %1 = OpBitReverse %int %u1
818      OpReturn
819      OpFunctionEnd
820   )";
821   auto p = parser(test::Assemble(assembly));
822   EXPECT_FALSE(p->Parse());
823   EXPECT_FALSE(p->success());
824   EXPECT_THAT(
825       p->error(),
826       HasSubstr("Expected Base Type to be equal to Result Type: BitReverse"));
827 }
828 
TEST_F(SpvUnaryBitTest,BitReverse_Int_Int)829 TEST_F(SpvUnaryBitTest, BitReverse_Int_Int) {
830   const auto assembly = BitTestPreamble() + R"(
831      %1 = OpBitReverse %int %i1
832      OpReturn
833      OpFunctionEnd
834   )";
835   auto p = parser(test::Assemble(assembly));
836   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
837   auto fe = p->function_emitter(100);
838   EXPECT_TRUE(fe.EmitBody()) << p->error();
839   auto ast_body = fe.ast_body();
840   auto body = test::ToString(p->program(), ast_body);
841   EXPECT_THAT(body, HasSubstr("let x_1 : i32 = reverseBits(i1);")) << body;
842 }
843 
TEST_F(SpvUnaryBitTest,BitReverse_UintVector_UintVector)844 TEST_F(SpvUnaryBitTest, BitReverse_UintVector_UintVector) {
845   const auto assembly = BitTestPreamble() + R"(
846      %1 = OpBitReverse %v2uint %v2u1
847      OpReturn
848      OpFunctionEnd
849   )";
850   auto p = parser(test::Assemble(assembly));
851   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
852   auto fe = p->function_emitter(100);
853   EXPECT_TRUE(fe.EmitBody()) << p->error();
854   auto ast_body = fe.ast_body();
855   auto body = test::ToString(p->program(), ast_body);
856   EXPECT_THAT(body, HasSubstr("let x_1 : vec2<u32> = reverseBits(v2u1);"))
857       << body;
858 }
859 
TEST_F(SpvUnaryBitTest,BitReverse_UintVector_IntVector)860 TEST_F(SpvUnaryBitTest, BitReverse_UintVector_IntVector) {
861   const auto assembly = BitTestPreamble() + R"(
862      %1 = OpBitReverse %v2uint %v2i1
863      OpReturn
864      OpFunctionEnd
865   )";
866   auto p = parser(test::Assemble(assembly));
867   EXPECT_FALSE(p->Parse());
868   EXPECT_FALSE(p->success());
869   EXPECT_THAT(
870       p->error(),
871       HasSubstr("Expected Base Type to be equal to Result Type: BitReverse"));
872 }
873 
TEST_F(SpvUnaryBitTest,BitReverse_IntVector_UintVector)874 TEST_F(SpvUnaryBitTest, BitReverse_IntVector_UintVector) {
875   const auto assembly = BitTestPreamble() + R"(
876      %1 = OpBitReverse %v2int %v2u1
877      OpReturn
878      OpFunctionEnd
879   )";
880   auto p = parser(test::Assemble(assembly));
881   EXPECT_FALSE(p->Parse());
882   EXPECT_FALSE(p->success());
883   EXPECT_THAT(
884       p->error(),
885       HasSubstr("Expected Base Type to be equal to Result Type: BitReverse"));
886 }
887 
TEST_F(SpvUnaryBitTest,BitReverse_IntVector_IntVector)888 TEST_F(SpvUnaryBitTest, BitReverse_IntVector_IntVector) {
889   const auto assembly = BitTestPreamble() + R"(
890      %1 = OpBitReverse %v2int %v2i1
891      OpReturn
892      OpFunctionEnd
893   )";
894   auto p = parser(test::Assemble(assembly));
895   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
896   auto fe = p->function_emitter(100);
897   EXPECT_TRUE(fe.EmitBody()) << p->error();
898   auto ast_body = fe.ast_body();
899   auto body = test::ToString(p->program(), ast_body);
900   EXPECT_THAT(body, HasSubstr("let x_1 : vec2<i32> = reverseBits(v2i1);"))
901       << body;
902 }
903 
904 // TODO(dneto): OpBitFieldInsert
905 // TODO(dneto): OpBitFieldSExtract
906 // TODO(dneto): OpBitFieldUExtract
907 
908 }  // namespace
909 }  // namespace spirv
910 }  // namespace reader
911 }  // namespace tint
912