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