1 // Copyright (c) 2015-2016 The Khronos Group Inc.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 // Assembler tests for instructions in the "Group Instrucions" section of the
18 #include "unit_spirv.h"
23 #include "test_fixture.h"
24 #include "gmock/gmock.h"
28 using spvtest::EnumCase;
29 using spvtest::MakeInstruction;
30 using spvtest::Concatenate;
33 // Test Sampler Addressing Mode enum values
35 using SamplerAddressingModeTest = spvtest::TextToBinaryTestBase<
36 ::testing::TestWithParam<EnumCase<SpvSamplerAddressingMode>>>;
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})));
47 #define CASE(NAME) { SpvSamplerAddressingMode##NAME, #NAME }
48 INSTANTIATE_TEST_CASE_P(
49 TextToBinarySamplerAddressingMode, SamplerAddressingModeTest,
50 ::testing::ValuesIn(std::vector<EnumCase<SpvSamplerAddressingMode>>{
60 TEST_F(SamplerAddressingModeTest, WrongMode) {
61 EXPECT_THAT(CompileFailure("%r = OpConstantSampler %t xxyyzz 0 Nearest"),
62 Eq("Invalid sampler addressing mode 'xxyyzz'."));
65 // Test Sampler Filter Mode enum values
67 using SamplerFilterModeTest = spvtest::TextToBinaryTestBase<
68 ::testing::TestWithParam<EnumCase<SpvSamplerFilterMode>>>;
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()})));
79 #define CASE(NAME) { SpvSamplerFilterMode##NAME, #NAME}
80 INSTANTIATE_TEST_CASE_P(
81 TextToBinarySamplerFilterMode, SamplerFilterModeTest,
82 ::testing::ValuesIn(std::vector<EnumCase<SpvSamplerFilterMode>>{
89 TEST_F(SamplerFilterModeTest, WrongMode) {
90 EXPECT_THAT(CompileFailure("%r = OpConstantSampler %t Clamp 0 xxyyzz"),
91 Eq("Invalid sampler filter mode 'xxyyzz'."));
94 struct ConstantTestCase {
95 std::string constant_type;
96 std::string constant_value;
97 std::vector<uint32_t> expected_instructions;
100 using OpConstantValidTest =
101 spvtest::TextToBinaryTestBase<::testing::TestWithParam<ConstantTestCase>>;
103 TEST_P(OpConstantValidTest, ValidTypes) {
104 const std::string input = "%1 = " + GetParam().constant_type +
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;
115 INSTANTIATE_TEST_CASE_P(
116 TextToBinaryOpConstantValid, OpConstantValidTest,
117 ::testing::ValuesIn(std::vector<ConstantTestCase>{
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)})})},
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})})},
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)})})},
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})})},
236 // A test case for checking OpConstant with invalid literals with a leading minus.
237 struct InvalidLeadingMinusCase {
242 using OpConstantInvalidLeadingMinusTest =
243 spvtest::TextToBinaryTestBase<::testing::TestWithParam<InvalidLeadingMinusCase>>;
245 TEST_P(OpConstantInvalidLeadingMinusTest, InvalidCase) {
246 const std::string input = "%1 = " + GetParam().type +
248 "%2 = OpConstant %1 " +
250 EXPECT_THAT(CompileFailure(input),
251 Eq("Cannot put a negative number in an unsigned literal"));
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"},
270 // A test case for invalid floating point literals.
271 struct InvalidFloatConstantCase {
276 using OpConstantInvalidFloatConstant = spvtest::TextToBinaryTestBase<
277 ::testing::TestWithParam<InvalidFloatConstantCase>>;
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()));
293 INSTANTIATE_TEST_CASE_P(
294 TextToBinaryInvalidFloatConstant, OpConstantInvalidFloatConstant,
295 ::testing::ValuesIn(std::vector<InvalidFloatConstantCase>{
301 {16, "1e30"}, // Overflow is an error for 16-bit floats.
312 {32, "1e40"}, // Overflow is an error for 32-bit floats.
321 {32, "1e400"}, // Overflow is an error for 64-bit floats.
326 using OpConstantInvalidTypeTest =
327 spvtest::TextToBinaryTestBase<::testing::TestWithParam<std::string>>;
329 TEST_P(OpConstantInvalidTypeTest, InvalidTypes) {
330 const std::string input = "%1 = " + GetParam() +
332 "%2 = OpConstant %1 0\n";
334 CompileFailure(input),
335 Eq("Type for Constant must be a scalar floating point or integer type"));
339 INSTANTIATE_TEST_CASE_P(
340 TextToBinaryOpConstantInvalidValidType, OpConstantInvalidTypeTest,
341 ::testing::ValuesIn(std::vector<std::string>{
344 "OpTypeVector %a 32",
345 "OpTypeMatrix %a 32",
346 "OpTypeImage %a 1D 0 0 0 0 Unknown",
348 "OpTypeSampledImage %a",
350 "OpTypeRuntimeArray %a",
352 "OpTypeOpaque \"Foo\"",
353 "OpTypePointer UniformConstant %a",
354 "OpTypeFunction %a %b",
359 "OpTypePipe ReadOnly",
360 "OpTypeForwardPointer %a UniformConstant",
361 // At least one thing that isn't a type at all
367 using OpSpecConstantValidTest =
368 spvtest::TextToBinaryTestBase<::testing::TestWithParam<ConstantTestCase>>;
370 TEST_P(OpSpecConstantValidTest, ValidTypes) {
371 const std::string input = "%1 = " + GetParam().constant_type +
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));
381 INSTANTIATE_TEST_CASE_P(
382 TextToBinaryOpSpecConstantValid, OpSpecConstantValidTest,
383 ::testing::ValuesIn(std::vector<ConstantTestCase>{
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)})})},
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})})},
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)})})},
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)})})},
436 using OpSpecConstantInvalidTypeTest =
437 spvtest::TextToBinaryTestBase<::testing::TestWithParam<std::string>>;
439 TEST_P(OpSpecConstantInvalidTypeTest, InvalidTypes) {
440 const std::string input = "%1 = " + GetParam() +
442 "%2 = OpSpecConstant %1 0\n";
443 EXPECT_THAT(CompileFailure(input),
444 Eq("Type for SpecConstant must be a scalar floating point or "
449 INSTANTIATE_TEST_CASE_P(
450 TextToBinaryOpSpecConstantInvalidValidType, OpSpecConstantInvalidTypeTest,
451 ::testing::ValuesIn(std::vector<std::string>{
454 "OpTypeVector %a 32",
455 "OpTypeMatrix %a 32",
456 "OpTypeImage %a 1D 0 0 0 0 Unknown",
458 "OpTypeSampledImage %a",
460 "OpTypeRuntimeArray %a",
462 "OpTypeOpaque \"Foo\"",
463 "OpTypePointer UniformConstant %a",
464 "OpTypeFunction %a %b",
469 "OpTypePipe ReadOnly",
470 "OpTypeForwardPointer %a UniformConstant",
471 // At least one thing that isn't a type at all
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;
481 INSTANTIATE_TEST_CASE_P(
482 OpConstantRoundTrip, RoundTripTest,
483 ::testing::ValuesIn(std::vector<std::string>{
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",
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",
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",
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",
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",
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",
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",
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",
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
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
591 INSTANTIATE_TEST_CASE_P(
592 OpSpecConstantRoundTrip, RoundTripTest,
593 ::testing::ValuesIn(std::vector<std::string>{
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",
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",
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",
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",
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",
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",
634 // Test OpSpecConstantOp
636 using OpSpecConstantOpTestWithIds =
637 spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvOp>>>;
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;
646 EXPECT_THAT(CompiledInstructions(input.str()),
647 Eq(MakeInstruction(SpvOpSpecConstantOp,
648 {1, 2, uint32_t(GetParam().value())},
649 GetParam().operands())));
651 // Check the disassembler as well.
652 EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
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>>{
673 CASE1(ConvertPtrToU),
674 CASE1(ConvertUToPtr),
675 CASE1(GenericCastToPtr),
676 CASE1(PtrCastToGeneric),
678 CASE1(QuantizeToF16),
690 CASE2(ShiftRightLogical),
691 CASE2(ShiftRightArithmetic),
692 CASE2(ShiftLeftLogical),
703 // Composite operations use literal numbers. So they're in another test.
709 CASE2(LogicalNotEqual),
713 CASE2(INotEqual), // Allowed in 1.0 Rev 7
718 CASE2(ULessThanEqual),
719 CASE2(SLessThanEqual),
720 CASE2(UGreaterThanEqual),
721 CASE2(SGreaterThanEqual),
723 // For AccessChain, there is a base Id, then a sequence of index Ids.
724 // Having no index Ids is a corner case.
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),
747 using OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers =
748 spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvOp>>>;
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;
758 EXPECT_THAT(CompiledInstructions(input.str()),
759 Eq(MakeInstruction(SpvOpSpecConstantOp,
760 {1, 2, uint32_t(GetParam().value()), 3, 4},
761 GetParam().operands())));
763 // Check the disassembler as well.
764 EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
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}},
785 using OpSpecConstantOpTestWithOneIdThenLiteralNumbers =
786 spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvOp>>>;
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;
796 EXPECT_THAT(CompiledInstructions(input.str()),
797 Eq(MakeInstruction(SpvOpSpecConstantOp,
798 {1, 2, uint32_t(GetParam().value()), 3},
799 GetParam().operands())));
801 // Check the disassembler as well.
802 EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
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}},
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
826 } // anonymous namespace