Setup dependent external sources
[platform/upstream/VK-GL-CTS.git] / external / spirv-tools / src / test / text_to_binary.constant_test.cpp
1 // Copyright (c) 2015-2016 The Khronos Group 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 // Assembler tests for instructions in the "Group Instrucions" section of the
16 // SPIR-V spec.
17
18 #include "unit_spirv.h"
19
20 #include <cstdint>
21 #include <limits>
22
23 #include "test_fixture.h"
24 #include "gmock/gmock.h"
25
26 namespace {
27
28 using spvtest::EnumCase;
29 using spvtest::MakeInstruction;
30 using spvtest::Concatenate;
31 using ::testing::Eq;
32
33 // Test Sampler Addressing Mode enum values
34
35 using SamplerAddressingModeTest = spvtest::TextToBinaryTestBase<
36     ::testing::TestWithParam<EnumCase<SpvSamplerAddressingMode>>>;
37
38 TEST_P(SamplerAddressingModeTest, AnySamplerAddressingMode) {
39   const std::string input =
40       "%result = OpConstantSampler %type " + GetParam().name() + " 0 Nearest";
41   EXPECT_THAT(CompiledInstructions(input),
42               Eq(MakeInstruction(SpvOpConstantSampler,
43                                  {1, 2, GetParam().value(), 0, 0})));
44 }
45
46 // clang-format off
47 #define CASE(NAME) { SpvSamplerAddressingMode##NAME, #NAME }
48 INSTANTIATE_TEST_CASE_P(
49     TextToBinarySamplerAddressingMode, SamplerAddressingModeTest,
50     ::testing::ValuesIn(std::vector<EnumCase<SpvSamplerAddressingMode>>{
51         CASE(None),
52         CASE(ClampToEdge),
53         CASE(Clamp),
54         CASE(Repeat),
55         CASE(RepeatMirrored),
56     }),);
57 #undef CASE
58 // clang-format on
59
60 TEST_F(SamplerAddressingModeTest, WrongMode) {
61   EXPECT_THAT(CompileFailure("%r = OpConstantSampler %t xxyyzz 0 Nearest"),
62               Eq("Invalid sampler addressing mode 'xxyyzz'."));
63 }
64
65 // Test Sampler Filter Mode enum values
66
67 using SamplerFilterModeTest = spvtest::TextToBinaryTestBase<
68     ::testing::TestWithParam<EnumCase<SpvSamplerFilterMode>>>;
69
70 TEST_P(SamplerFilterModeTest, AnySamplerFilterMode) {
71   const std::string input =
72       "%result = OpConstantSampler %type Clamp 0 " + GetParam().name();
73   EXPECT_THAT(CompiledInstructions(input),
74               Eq(MakeInstruction(SpvOpConstantSampler,
75                                  {1, 2, 2, 0, GetParam().value()})));
76 }
77
78 // clang-format off
79 #define CASE(NAME) { SpvSamplerFilterMode##NAME, #NAME}
80 INSTANTIATE_TEST_CASE_P(
81     TextToBinarySamplerFilterMode, SamplerFilterModeTest,
82     ::testing::ValuesIn(std::vector<EnumCase<SpvSamplerFilterMode>>{
83         CASE(Nearest),
84         CASE(Linear),
85     }),);
86 #undef CASE
87 // clang-format on
88
89 TEST_F(SamplerFilterModeTest, WrongMode) {
90   EXPECT_THAT(CompileFailure("%r = OpConstantSampler %t Clamp 0 xxyyzz"),
91               Eq("Invalid sampler filter mode 'xxyyzz'."));
92 }
93
94 struct ConstantTestCase {
95   std::string constant_type;
96   std::string constant_value;
97   std::vector<uint32_t> expected_instructions;
98 };
99
100 using OpConstantValidTest =
101     spvtest::TextToBinaryTestBase<::testing::TestWithParam<ConstantTestCase>>;
102
103 TEST_P(OpConstantValidTest, ValidTypes) {
104   const std::string input = "%1 = " + GetParam().constant_type +
105                             "\n"
106                             "%2 = OpConstant %1 " +
107                             GetParam().constant_value + "\n";
108   std::vector<uint32_t> instructions;
109   EXPECT_THAT(CompiledInstructions(input), Eq(GetParam().expected_instructions))
110       << " type: " << GetParam().constant_type
111       << " literal: " << GetParam().constant_value;
112 }
113
114 // clang-format off
115 INSTANTIATE_TEST_CASE_P(
116     TextToBinaryOpConstantValid, OpConstantValidTest,
117     ::testing::ValuesIn(std::vector<ConstantTestCase>{
118       // Check 16 bits
119       {"OpTypeInt 16 0", "0x1234",
120         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
121          MakeInstruction(SpvOpConstant, {1, 2, 0x1234})})},
122       {"OpTypeInt 16 0", "0x8000",
123         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
124          MakeInstruction(SpvOpConstant, {1, 2, 0x8000})})},
125       {"OpTypeInt 16 0", "0",
126         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
127          MakeInstruction(SpvOpConstant, {1, 2, 0})})},
128       {"OpTypeInt 16 0", "65535",
129         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
130          MakeInstruction(SpvOpConstant, {1, 2, 65535})})},
131       {"OpTypeInt 16 0", "0xffff",
132         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
133          MakeInstruction(SpvOpConstant, {1, 2, 65535})})},
134       {"OpTypeInt 16 1", "0x8000", // Test sign extension.
135         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
136          MakeInstruction(SpvOpConstant, {1, 2, 0xffff8000})})},
137       {"OpTypeInt 16 1", "-32",
138         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
139          MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32)})})},
140       {"OpTypeInt 16 1", "0",
141         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
142          MakeInstruction(SpvOpConstant, {1, 2, 0})})},
143       {"OpTypeInt 16 1", "-0",
144         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
145          MakeInstruction(SpvOpConstant, {1, 2, 0})})},
146       {"OpTypeInt 16 1", "-0x0",
147         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
148          MakeInstruction(SpvOpConstant, {1, 2, 0})})},
149       {"OpTypeInt 16 1", "-32768",
150         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
151          MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32768)})})},
152       // Check 32 bits
153       {"OpTypeInt 32 0", "42",
154         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
155          MakeInstruction(SpvOpConstant, {1, 2, 42})})},
156       {"OpTypeInt 32 1", "-32",
157         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
158          MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32)})})},
159       {"OpTypeInt 32 1", "0",
160         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
161          MakeInstruction(SpvOpConstant, {1, 2, 0})})},
162       {"OpTypeInt 32 1", "-0",
163         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
164          MakeInstruction(SpvOpConstant, {1, 2, 0})})},
165       {"OpTypeInt 32 1", "-0x0",
166         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
167          MakeInstruction(SpvOpConstant, {1, 2, 0})})},
168       {"OpTypeInt 32 1", "-0x001",
169         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
170          MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-1)})})},
171       {"OpTypeInt 32 1", "2147483647",
172         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
173          MakeInstruction(SpvOpConstant, {1, 2, 0x7fffffffu})})},
174       {"OpTypeInt 32 1", "-2147483648",
175         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
176          MakeInstruction(SpvOpConstant, {1, 2, 0x80000000u})})},
177       {"OpTypeFloat 32", "1.0",
178         Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
179          MakeInstruction(SpvOpConstant, {1, 2, 0x3f800000})})},
180       {"OpTypeFloat 32", "10.0",
181         Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
182          MakeInstruction(SpvOpConstant, {1, 2, 0x41200000})})},
183       {"OpTypeFloat 32", "-0x1p+128", // -infinity
184         Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
185          MakeInstruction(SpvOpConstant, {1, 2, 0xFF800000})})},
186       {"OpTypeFloat 32", "0x1p+128", // +infinity
187         Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
188          MakeInstruction(SpvOpConstant, {1, 2, 0x7F800000})})},
189       {"OpTypeFloat 32", "-0x1.8p+128", // A -NaN
190         Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
191          MakeInstruction(SpvOpConstant, {1, 2, 0xFFC00000})})},
192       {"OpTypeFloat 32", "-0x1.0002p+128", // A +NaN
193         Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
194          MakeInstruction(SpvOpConstant, {1, 2, 0xFF800100})})},
195       // Check 48 bits
196       {"OpTypeInt 48 0", "0x1234",
197         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}),
198          MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})},
199       {"OpTypeInt 48 0", "0x800000000001",
200         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}),
201          MakeInstruction(SpvOpConstant, {1, 2, 1, 0x00008000})})},
202       {"OpTypeInt 48 1", "0x800000000000", // Test sign extension.
203         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}),
204          MakeInstruction(SpvOpConstant, {1, 2, 0, 0xffff8000})})},
205       {"OpTypeInt 48 1", "-32",
206         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}),
207          MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
208       // Check 64 bits
209       {"OpTypeInt 64 0", "0x1234",
210         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
211          MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})},
212       {"OpTypeInt 64 0", "18446744073709551615",
213         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
214          MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
215       {"OpTypeInt 64 0", "0xffffffffffffffff",
216         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
217          MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
218       {"OpTypeInt 64 1", "0x1234",
219         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
220          MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})},
221       {"OpTypeInt 64 1", "-42",
222         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
223          MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
224       {"OpTypeInt 64 1", "-0x01",
225         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
226          MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
227       {"OpTypeInt 64 1", "9223372036854775807",
228         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
229          MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0x7fffffffu})})},
230       {"OpTypeInt 64 1", "0x7fffffff",
231         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
232          MakeInstruction(SpvOpConstant, {1, 2, 0x7fffffffu, 0})})},
233     }),);
234 // clang-format on
235
236 // A test case for checking OpConstant with invalid literals with a leading minus.
237 struct InvalidLeadingMinusCase {
238   std::string type;
239   std::string literal;
240 };
241
242 using OpConstantInvalidLeadingMinusTest =
243     spvtest::TextToBinaryTestBase<::testing::TestWithParam<InvalidLeadingMinusCase>>;
244
245 TEST_P(OpConstantInvalidLeadingMinusTest, InvalidCase) {
246   const std::string input = "%1 = " + GetParam().type +
247                             "\n"
248                             "%2 = OpConstant %1 " +
249                             GetParam().literal;
250   EXPECT_THAT(CompileFailure(input),
251               Eq("Cannot put a negative number in an unsigned literal"));
252 }
253
254 // clang-format off
255 INSTANTIATE_TEST_CASE_P(
256     TextToBinaryOpConstantInvalidLeadingMinus, OpConstantInvalidLeadingMinusTest,
257     ::testing::ValuesIn(std::vector<InvalidLeadingMinusCase>{
258       {"OpTypeInt 16 0", "-0"},
259       {"OpTypeInt 16 0", "-0x0"},
260       {"OpTypeInt 16 0", "-1"},
261       {"OpTypeInt 32 0", "-0"},
262       {"OpTypeInt 32 0", "-0x0"},
263       {"OpTypeInt 32 0", "-1"},
264       {"OpTypeInt 64 0", "-0"},
265       {"OpTypeInt 64 0", "-0x0"},
266       {"OpTypeInt 64 0", "-1"},
267     }),);
268 // clang-format on
269
270 // A test case for invalid floating point literals.
271 struct InvalidFloatConstantCase {
272   uint32_t width;
273   std::string literal;
274 };
275
276 using OpConstantInvalidFloatConstant = spvtest::TextToBinaryTestBase<
277     ::testing::TestWithParam<InvalidFloatConstantCase>>;
278
279 TEST_P(OpConstantInvalidFloatConstant, Samples) {
280   // Check both kinds of instructions that take literal floats.
281   for (const auto& instruction : {"OpConstant", "OpSpecConstant"}) {
282     std::stringstream input;
283     input << "%1 = OpTypeFloat " << GetParam().width << "\n"
284           << "%2 = " << instruction << " %1 " << GetParam().literal;
285     std::stringstream expected_error;
286     expected_error << "Invalid " << GetParam().width
287                    << "-bit float literal: " << GetParam().literal;
288     EXPECT_THAT(CompileFailure(input.str()), Eq(expected_error.str()));
289   }
290 }
291
292 // clang-format off
293 INSTANTIATE_TEST_CASE_P(
294     TextToBinaryInvalidFloatConstant, OpConstantInvalidFloatConstant,
295     ::testing::ValuesIn(std::vector<InvalidFloatConstantCase>{
296         {16, "abc"},
297         {16, "--1"},
298         {16, "-+1"},
299         {16, "+-1"},
300         {16, "++1"},
301         {16, "1e30"}, // Overflow is an error for 16-bit floats.
302         {16, "-1e30"},
303         {16, "1e40"},
304         {16, "-1e40"},
305         {16, "1e400"},
306         {16, "-1e400"},
307         {32, "abc"},
308         {32, "--1"},
309         {32, "-+1"},
310         {32, "+-1"},
311         {32, "++1"},
312         {32, "1e40"}, // Overflow is an error for 32-bit floats.
313         {32, "-1e40"},
314         {32, "1e400"},
315         {32, "-1e400"},
316         {64, "abc"},
317         {64, "--1"},
318         {64, "-+1"},
319         {64, "+-1"},
320         {64, "++1"},
321         {32, "1e400"}, // Overflow is an error for 64-bit floats.
322         {32, "-1e400"},
323     }),);
324 // clang-format on
325
326 using OpConstantInvalidTypeTest =
327     spvtest::TextToBinaryTestBase<::testing::TestWithParam<std::string>>;
328
329 TEST_P(OpConstantInvalidTypeTest, InvalidTypes) {
330   const std::string input = "%1 = " + GetParam() +
331                             "\n"
332                             "%2 = OpConstant %1 0\n";
333   EXPECT_THAT(
334       CompileFailure(input),
335       Eq("Type for Constant must be a scalar floating point or integer type"));
336 }
337
338 // clang-format off
339 INSTANTIATE_TEST_CASE_P(
340     TextToBinaryOpConstantInvalidValidType, OpConstantInvalidTypeTest,
341     ::testing::ValuesIn(std::vector<std::string>{
342       {"OpTypeVoid",
343        "OpTypeBool",
344        "OpTypeVector %a 32",
345        "OpTypeMatrix %a 32",
346        "OpTypeImage %a 1D 0 0 0 0 Unknown",
347        "OpTypeSampler",
348        "OpTypeSampledImage %a",
349        "OpTypeArray %a %b",
350        "OpTypeRuntimeArray %a",
351        "OpTypeStruct %a",
352        "OpTypeOpaque \"Foo\"",
353        "OpTypePointer UniformConstant %a",
354        "OpTypeFunction %a %b",
355        "OpTypeEvent",
356        "OpTypeDeviceEvent",
357        "OpTypeReserveId",
358        "OpTypeQueue",
359        "OpTypePipe ReadOnly",
360        "OpTypeForwardPointer %a UniformConstant",
361         // At least one thing that isn't a type at all
362        "OpNot %a %b"
363       },
364     }),);
365 // clang-format on
366
367 using OpSpecConstantValidTest =
368     spvtest::TextToBinaryTestBase<::testing::TestWithParam<ConstantTestCase>>;
369
370 TEST_P(OpSpecConstantValidTest, ValidTypes) {
371   const std::string input = "%1 = " + GetParam().constant_type +
372                             "\n"
373                             "%2 = OpSpecConstant %1 " +
374                             GetParam().constant_value + "\n";
375   std::vector<uint32_t> instructions;
376   EXPECT_THAT(CompiledInstructions(input),
377               Eq(GetParam().expected_instructions));
378 }
379
380 // clang-format off
381 INSTANTIATE_TEST_CASE_P(
382     TextToBinaryOpSpecConstantValid, OpSpecConstantValidTest,
383     ::testing::ValuesIn(std::vector<ConstantTestCase>{
384       // Check 16 bits
385       {"OpTypeInt 16 0", "0x1234",
386         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
387          MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234})})},
388       {"OpTypeInt 16 0", "0x8000",
389         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
390          MakeInstruction(SpvOpSpecConstant, {1, 2, 0x8000})})},
391       {"OpTypeInt 16 1", "0x8000", // Test sign extension.
392         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
393          MakeInstruction(SpvOpSpecConstant, {1, 2, 0xffff8000})})},
394       {"OpTypeInt 16 1", "-32",
395         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
396          MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-32)})})},
397       // Check 32 bits
398       {"OpTypeInt 32 0", "42",
399         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
400          MakeInstruction(SpvOpSpecConstant, {1, 2, 42})})},
401       {"OpTypeInt 32 1", "-32",
402         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
403          MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-32)})})},
404       {"OpTypeFloat 32", "1.0",
405         Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
406          MakeInstruction(SpvOpSpecConstant, {1, 2, 0x3f800000})})},
407       {"OpTypeFloat 32", "10.0",
408         Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
409          MakeInstruction(SpvOpSpecConstant, {1, 2, 0x41200000})})},
410       // Check 48 bits
411       {"OpTypeInt 48 0", "0x1234",
412         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}),
413          MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234, 0})})},
414       {"OpTypeInt 48 0", "0x800000000001",
415         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}),
416          MakeInstruction(SpvOpSpecConstant, {1, 2, 1, 0x00008000})})},
417       {"OpTypeInt 48 1", "0x800000000000", // Test sign extension.
418         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}),
419          MakeInstruction(SpvOpSpecConstant, {1, 2, 0, 0xffff8000})})},
420       {"OpTypeInt 48 1", "-32",
421         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}),
422          MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
423       // Check 64 bits
424       {"OpTypeInt 64 0", "0x1234",
425         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
426          MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234, 0})})},
427       {"OpTypeInt 64 1", "0x1234",
428         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
429          MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234, 0})})},
430       {"OpTypeInt 64 1", "-42",
431         Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
432          MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
433     }),);
434 // clang-format on
435
436 using OpSpecConstantInvalidTypeTest =
437     spvtest::TextToBinaryTestBase<::testing::TestWithParam<std::string>>;
438
439 TEST_P(OpSpecConstantInvalidTypeTest, InvalidTypes) {
440   const std::string input = "%1 = " + GetParam() +
441                             "\n"
442                             "%2 = OpSpecConstant %1 0\n";
443   EXPECT_THAT(CompileFailure(input),
444               Eq("Type for SpecConstant must be a scalar floating point or "
445                  "integer type"));
446 }
447
448 // clang-format off
449 INSTANTIATE_TEST_CASE_P(
450     TextToBinaryOpSpecConstantInvalidValidType, OpSpecConstantInvalidTypeTest,
451     ::testing::ValuesIn(std::vector<std::string>{
452       {"OpTypeVoid",
453        "OpTypeBool",
454        "OpTypeVector %a 32",
455        "OpTypeMatrix %a 32",
456        "OpTypeImage %a 1D 0 0 0 0 Unknown",
457        "OpTypeSampler",
458        "OpTypeSampledImage %a",
459        "OpTypeArray %a %b",
460        "OpTypeRuntimeArray %a",
461        "OpTypeStruct %a",
462        "OpTypeOpaque \"Foo\"",
463        "OpTypePointer UniformConstant %a",
464        "OpTypeFunction %a %b",
465        "OpTypeEvent",
466        "OpTypeDeviceEvent",
467        "OpTypeReserveId",
468        "OpTypeQueue",
469        "OpTypePipe ReadOnly",
470        "OpTypeForwardPointer %a UniformConstant",
471         // At least one thing that isn't a type at all
472        "OpNot %a %b"
473       },
474     }),);
475 // clang-format on
476
477 const int64_t kMaxUnsigned48Bit = (int64_t(1) << 48) - 1;
478 const int64_t kMaxSigned48Bit = (int64_t(1) << 47) - 1;
479 const int64_t kMinSigned48Bit = -kMaxSigned48Bit - 1;
480
481 INSTANTIATE_TEST_CASE_P(
482     OpConstantRoundTrip, RoundTripTest,
483     ::testing::ValuesIn(std::vector<std::string>{
484         // 16 bit
485         "%1 = OpTypeInt 16 0\n%2 = OpConstant %1 0\n",
486         "%1 = OpTypeInt 16 0\n%2 = OpConstant %1 65535\n",
487         "%1 = OpTypeInt 16 1\n%2 = OpConstant %1 -32768\n",
488         "%1 = OpTypeInt 16 1\n%2 = OpConstant %1 32767\n",
489         "%1 = OpTypeInt 32 0\n%2 = OpConstant %1 0\n",
490         // 32 bit
491         std::string("%1 = OpTypeInt 32 0\n%2 = OpConstant %1 0\n"),
492         std::string("%1 = OpTypeInt 32 0\n%2 = OpConstant %1 ") +
493             std::to_string(std::numeric_limits<uint32_t>::max()) + "\n",
494         std::string("%1 = OpTypeInt 32 1\n%2 = OpConstant %1 ") +
495             std::to_string(std::numeric_limits<int32_t>::max()) + "\n",
496         std::string("%1 = OpTypeInt 32 1\n%2 = OpConstant %1 ") +
497             std::to_string(std::numeric_limits<int32_t>::min()) + "\n",
498         // 48 bit
499         std::string("%1 = OpTypeInt 48 0\n%2 = OpConstant %1 0\n"),
500         std::string("%1 = OpTypeInt 48 0\n%2 = OpConstant %1 ") +
501             std::to_string(kMaxUnsigned48Bit) + "\n",
502         std::string("%1 = OpTypeInt 48 1\n%2 = OpConstant %1 ") +
503             std::to_string(kMaxSigned48Bit) + "\n",
504         std::string("%1 = OpTypeInt 48 1\n%2 = OpConstant %1 ") +
505             std::to_string(kMinSigned48Bit) + "\n",
506         // 64 bit
507         std::string("%1 = OpTypeInt 64 0\n%2 = OpConstant %1 0\n"),
508         std::string("%1 = OpTypeInt 64 0\n%2 = OpConstant %1 ") +
509             std::to_string(std::numeric_limits<uint64_t>::max()) + "\n",
510         std::string("%1 = OpTypeInt 64 1\n%2 = OpConstant %1 ") +
511             std::to_string(std::numeric_limits<int64_t>::max()) + "\n",
512         std::string("%1 = OpTypeInt 64 1\n%2 = OpConstant %1 ") +
513             std::to_string(std::numeric_limits<int64_t>::min()) + "\n",
514         // 32-bit float
515         "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0\n",
516         "%1 = OpTypeFloat 32\n%2 = OpConstant %1 13.5\n",
517         "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -12.5\n",
518         // 64-bit float
519         "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0\n",
520         "%1 = OpTypeFloat 64\n%2 = OpConstant %1 1.79769e+308\n",
521         "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -1.79769e+308\n",
522     }),);
523
524 INSTANTIATE_TEST_CASE_P(
525     OpConstantHalfRoundTrip, RoundTripTest,
526     ::testing::ValuesIn(std::vector<std::string>{
527         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x0p+0\n",
528         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x0p+0\n",
529         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p+0\n",
530         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.1p+0\n",
531         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.01p-1\n",
532         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.8p+1\n",
533         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ffcp+1\n",
534         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1p+0\n",
535         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.1p+0\n",
536         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.01p-1\n",
537         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.8p+1\n",
538         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.ffcp+1\n",
539
540         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p-16\n", // some denorms
541         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p-24\n",
542         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1p-24\n",
543
544         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p+16\n", // +inf
545         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1p+16\n", // -inf
546         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.01p+16\n", // -inf
547         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.01p+16\n", // nan
548         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.11p+16\n", // nan
549         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ffp+16\n", // nan
550         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ffcp+16\n", // nan
551         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.004p+16\n", // nan
552         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.01p+16\n", // -nan
553         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.11p+16\n", // -nan
554         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.ffp+16\n", // -nan
555         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.ffcp+16\n", // -nan
556         "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.004p+16\n", // -nan
557     }),);
558
559 // clang-format off
560 // (Clang-format really wants to break up these strings across lines.
561 INSTANTIATE_TEST_CASE_P(
562     OpConstantRoundTripNonFinite, RoundTripTest,
563     ::testing::ValuesIn(std::vector<std::string>{
564   "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1p+128\n",         // -inf
565   "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1p+128\n",          // inf
566   "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.8p+128\n",       // -nan
567   "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0002p+128\n",    // -nan
568   "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0018p+128\n",    // -nan
569   "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.01ep+128\n",     // -nan
570   "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.fffffep+128\n",  // -nan
571   "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.8p+128\n",        // +nan
572   "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.0002p+128\n",     // +nan
573   "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.0018p+128\n",     // +nan
574   "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.01ep+128\n",      // +nan
575   "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.fffffep+128\n",   // +nan
576   "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1p+1024\n",                //-inf
577   "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1p+1024\n",                 //+inf
578   "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.8p+1024\n",              // -nan
579   "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0fp+1024\n",             // -nan
580   "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0000000000001p+1024\n",  // -nan
581   "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.00003p+1024\n",          // -nan
582   "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.fffffffffffffp+1024\n",  // -nan
583   "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.8p+1024\n",               // +nan
584   "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.0fp+1024\n",              // +nan
585   "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.0000000000001p+1024\n",   // -nan
586   "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.00003p+1024\n",           // -nan
587   "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.fffffffffffffp+1024\n",   // -nan
588     }),);
589 // clang-format on
590
591 INSTANTIATE_TEST_CASE_P(
592     OpSpecConstantRoundTrip, RoundTripTest,
593     ::testing::ValuesIn(std::vector<std::string>{
594         // 16 bit
595         "%1 = OpTypeInt 16 0\n%2 = OpSpecConstant %1 0\n",
596         "%1 = OpTypeInt 16 0\n%2 = OpSpecConstant %1 65535\n",
597         "%1 = OpTypeInt 16 1\n%2 = OpSpecConstant %1 -32768\n",
598         "%1 = OpTypeInt 16 1\n%2 = OpSpecConstant %1 32767\n",
599         "%1 = OpTypeInt 32 0\n%2 = OpSpecConstant %1 0\n",
600         // 32 bit
601         std::string("%1 = OpTypeInt 32 0\n%2 = OpSpecConstant %1 0\n"),
602         std::string("%1 = OpTypeInt 32 0\n%2 = OpSpecConstant %1 ") +
603             std::to_string(std::numeric_limits<uint32_t>::max()) + "\n",
604         std::string("%1 = OpTypeInt 32 1\n%2 = OpSpecConstant %1 ") +
605             std::to_string(std::numeric_limits<int32_t>::max()) + "\n",
606         std::string("%1 = OpTypeInt 32 1\n%2 = OpSpecConstant %1 ") +
607             std::to_string(std::numeric_limits<int32_t>::min()) + "\n",
608         // 48 bit
609         std::string("%1 = OpTypeInt 48 0\n%2 = OpSpecConstant %1 0\n"),
610         std::string("%1 = OpTypeInt 48 0\n%2 = OpSpecConstant %1 ") +
611             std::to_string(kMaxUnsigned48Bit) + "\n",
612         std::string("%1 = OpTypeInt 48 1\n%2 = OpSpecConstant %1 ") +
613             std::to_string(kMaxSigned48Bit) + "\n",
614         std::string("%1 = OpTypeInt 48 1\n%2 = OpSpecConstant %1 ") +
615             std::to_string(kMinSigned48Bit) + "\n",
616         // 64 bit
617         std::string("%1 = OpTypeInt 64 0\n%2 = OpSpecConstant %1 0\n"),
618         std::string("%1 = OpTypeInt 64 0\n%2 = OpSpecConstant %1 ") +
619             std::to_string(std::numeric_limits<uint64_t>::max()) + "\n",
620         std::string("%1 = OpTypeInt 64 1\n%2 = OpSpecConstant %1 ") +
621             std::to_string(std::numeric_limits<int64_t>::max()) + "\n",
622         std::string("%1 = OpTypeInt 64 1\n%2 = OpSpecConstant %1 ") +
623             std::to_string(std::numeric_limits<int64_t>::min()) + "\n",
624         // 32-bit float
625         "%1 = OpTypeFloat 32\n%2 = OpSpecConstant %1 0\n",
626         "%1 = OpTypeFloat 32\n%2 = OpSpecConstant %1 13.5\n",
627         "%1 = OpTypeFloat 32\n%2 = OpSpecConstant %1 -12.5\n",
628         // 64-bit float
629         "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 0\n",
630         "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 1.79769e+308\n",
631         "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 -1.79769e+308\n",
632     }),);
633
634 // Test OpSpecConstantOp
635
636 using OpSpecConstantOpTestWithIds =
637     spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvOp>>>;
638
639 // The operands to the OpSpecConstantOp opcode are all Ids.
640 TEST_P(OpSpecConstantOpTestWithIds, Assembly) {
641   std::stringstream input;
642   input << "%2 = OpSpecConstantOp %1 " << GetParam().name();
643   for (auto id : GetParam().operands()) input << " %" << id;
644   input << "\n";
645
646   EXPECT_THAT(CompiledInstructions(input.str()),
647               Eq(MakeInstruction(SpvOpSpecConstantOp,
648                                  {1, 2, uint32_t(GetParam().value())},
649                                  GetParam().operands())));
650
651   // Check the disassembler as well.
652   EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
653 }
654
655 // clang-format off
656 #define CASE1(NAME) { SpvOp##NAME, #NAME, {3} }
657 #define CASE2(NAME) { SpvOp##NAME, #NAME, {3, 4} }
658 #define CASE3(NAME) { SpvOp##NAME, #NAME, {3, 4, 5} }
659 #define CASE4(NAME) { SpvOp##NAME, #NAME, {3, 4, 5, 6} }
660 #define CASE5(NAME) { SpvOp##NAME, #NAME, {3, 4, 5, 6, 7} }
661 #define CASE6(NAME) { SpvOp##NAME, #NAME, {3, 4, 5, 6, 7, 8} }
662 INSTANTIATE_TEST_CASE_P(
663     TextToBinaryOpSpecConstantOp, OpSpecConstantOpTestWithIds,
664     ::testing::ValuesIn(std::vector<EnumCase<SpvOp>>{
665         // Conversion
666         CASE1(SConvert),
667         CASE1(FConvert),
668         CASE1(ConvertFToS),
669         CASE1(ConvertSToF),
670         CASE1(ConvertFToU),
671         CASE1(ConvertUToF),
672         CASE1(UConvert),
673         CASE1(ConvertPtrToU),
674         CASE1(ConvertUToPtr),
675         CASE1(GenericCastToPtr),
676         CASE1(PtrCastToGeneric),
677         CASE1(Bitcast),
678         CASE1(QuantizeToF16),
679         // Arithmetic
680         CASE1(SNegate),
681         CASE1(Not),
682         CASE2(IAdd),
683         CASE2(ISub),
684         CASE2(IMul),
685         CASE2(UDiv),
686         CASE2(SDiv),
687         CASE2(UMod),
688         CASE2(SRem),
689         CASE2(SMod),
690         CASE2(ShiftRightLogical),
691         CASE2(ShiftRightArithmetic),
692         CASE2(ShiftLeftLogical),
693         CASE2(BitwiseOr),
694         CASE2(BitwiseAnd),
695         CASE2(BitwiseXor),
696         CASE1(FNegate),
697         CASE2(FAdd),
698         CASE2(FSub),
699         CASE2(FMul),
700         CASE2(FDiv),
701         CASE2(FRem),
702         CASE2(FMod),
703         // Composite operations use literal numbers. So they're in another test.
704         // Logical
705         CASE2(LogicalOr),
706         CASE2(LogicalAnd),
707         CASE1(LogicalNot),
708         CASE2(LogicalEqual),
709         CASE2(LogicalNotEqual),
710         CASE3(Select),
711         // Comparison
712         CASE2(IEqual),
713         CASE2(INotEqual), // Allowed in 1.0 Rev 7
714         CASE2(ULessThan),
715         CASE2(SLessThan),
716         CASE2(UGreaterThan),
717         CASE2(SGreaterThan),
718         CASE2(ULessThanEqual),
719         CASE2(SLessThanEqual),
720         CASE2(UGreaterThanEqual),
721         CASE2(SGreaterThanEqual),
722         // Memory
723         // For AccessChain, there is a base Id, then a sequence of index Ids.
724         // Having no index Ids is a corner case.
725         CASE1(AccessChain),
726         CASE2(AccessChain),
727         CASE6(AccessChain),
728         CASE1(InBoundsAccessChain),
729         CASE2(InBoundsAccessChain),
730         CASE6(InBoundsAccessChain),
731         // PtrAccessChain also has an element Id.
732         CASE2(PtrAccessChain),
733         CASE3(PtrAccessChain),
734         CASE6(PtrAccessChain),
735         CASE2(InBoundsPtrAccessChain),
736         CASE3(InBoundsPtrAccessChain),
737         CASE6(InBoundsPtrAccessChain),
738     }),);
739 #undef CASE1
740 #undef CASE2
741 #undef CASE3
742 #undef CASE4
743 #undef CASE5
744 #undef CASE6
745 // clang-format on
746
747 using OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers =
748     spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvOp>>>;
749
750 // The operands to the OpSpecConstantOp opcode are two Ids followed by a
751 // sequence of literal numbers.
752 TEST_P(OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers, Assembly) {
753   std::stringstream input;
754   input << "%2 = OpSpecConstantOp %1 " << GetParam().name() << " %3 %4";
755   for (auto number : GetParam().operands()) input << " " << number;
756   input << "\n";
757
758   EXPECT_THAT(CompiledInstructions(input.str()),
759               Eq(MakeInstruction(SpvOpSpecConstantOp,
760                                  {1, 2, uint32_t(GetParam().value()), 3, 4},
761                                  GetParam().operands())));
762
763   // Check the disassembler as well.
764   EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
765 }
766
767 #define CASE(NAME) SpvOp##NAME, #NAME
768 INSTANTIATE_TEST_CASE_P(
769     TextToBinaryOpSpecConstantOp,
770     OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers,
771     ::testing::ValuesIn(std::vector<EnumCase<SpvOp>>{
772         // For VectorShuffle, there are two vector operands, and at least
773         // two selector Ids.  OpenCL can have up to 16-element vectors.
774         {CASE(VectorShuffle), {0, 0}},
775         {CASE(VectorShuffle), {4, 3, 2, 1}},
776         {CASE(VectorShuffle), {0, 2, 4, 6, 1, 3, 5, 7}},
777         {CASE(VectorShuffle),
778          {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}},
779         // For CompositeInsert, there is an object to insert, the target
780         // composite, and then literal indices.
781         {CASE(CompositeInsert), {0}},
782         {CASE(CompositeInsert), {4, 3, 99, 1}},
783     }),);
784
785 using OpSpecConstantOpTestWithOneIdThenLiteralNumbers =
786     spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvOp>>>;
787
788 // The operands to the OpSpecConstantOp opcode are one Id followed by a
789 // sequence of literal numbers.
790 TEST_P(OpSpecConstantOpTestWithOneIdThenLiteralNumbers, Assembly) {
791   std::stringstream input;
792   input << "%2 = OpSpecConstantOp %1 " << GetParam().name() << " %3";
793   for (auto number : GetParam().operands()) input << " " << number;
794   input << "\n";
795
796   EXPECT_THAT(CompiledInstructions(input.str()),
797               Eq(MakeInstruction(SpvOpSpecConstantOp,
798                                  {1, 2, uint32_t(GetParam().value()), 3},
799                                  GetParam().operands())));
800
801   // Check the disassembler as well.
802   EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
803 }
804
805 #define CASE(NAME) SpvOp##NAME, #NAME
806 INSTANTIATE_TEST_CASE_P(
807     TextToBinaryOpSpecConstantOp,
808     OpSpecConstantOpTestWithOneIdThenLiteralNumbers,
809     ::testing::ValuesIn(std::vector<EnumCase<SpvOp>>{
810         // For CompositeExtract, the universal limit permits up to 255 literal
811         // indices.  Let's only test a few.
812         {CASE(CompositeExtract), {0}},
813         {CASE(CompositeExtract), {0, 99, 42, 16, 17, 12, 19}},
814     }),);
815
816 // TODO(dneto): OpConstantTrue
817 // TODO(dneto): OpConstantFalse
818 // TODO(dneto): OpConstantComposite
819 // TODO(dneto): OpConstantSampler: other variations Param is 0 or 1
820 // TODO(dneto): OpConstantNull
821 // TODO(dneto): OpSpecConstantTrue
822 // TODO(dneto): OpSpecConstantFalse
823 // TODO(dneto): OpSpecConstantComposite
824 // TODO(dneto): Negative tests for OpSpecConstantOp
825
826 }  // anonymous namespace