1 // Copyright (c) 2016 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <vector>
16
17 #include "gmock/gmock.h"
18 #include "test/opt/pass_fixture.h"
19
20 namespace spvtools {
21 namespace opt {
22 namespace {
23
24 using testing::Eq;
25 using SpecIdToValueStrMap =
26 SetSpecConstantDefaultValuePass::SpecIdToValueStrMap;
27 using SpecIdToValueBitPatternMap =
28 SetSpecConstantDefaultValuePass::SpecIdToValueBitPatternMap;
29
30 struct DefaultValuesStringParsingTestCase {
31 const char* default_values_str;
32 bool expect_success;
33 SpecIdToValueStrMap expected_map;
34 };
35
36 using DefaultValuesStringParsingTest =
37 ::testing::TestWithParam<DefaultValuesStringParsingTestCase>;
38
TEST_P(DefaultValuesStringParsingTest,TestCase)39 TEST_P(DefaultValuesStringParsingTest, TestCase) {
40 const auto& tc = GetParam();
41 auto actual_map = SetSpecConstantDefaultValuePass::ParseDefaultValuesString(
42 tc.default_values_str);
43 if (tc.expect_success) {
44 EXPECT_NE(nullptr, actual_map);
45 if (actual_map) {
46 EXPECT_THAT(*actual_map, Eq(tc.expected_map));
47 }
48 } else {
49 EXPECT_EQ(nullptr, actual_map);
50 }
51 }
52
53 INSTANTIATE_TEST_SUITE_P(
54 ValidString, DefaultValuesStringParsingTest,
55 ::testing::ValuesIn(std::vector<DefaultValuesStringParsingTestCase>{
56 // 0. empty map
57 {"", true, SpecIdToValueStrMap{}},
58 // 1. one pair
59 {"100:1024", true, SpecIdToValueStrMap{{100, "1024"}}},
60 // 2. two pairs
61 {"100:1024 200:2048", true,
62 SpecIdToValueStrMap{{100, "1024"}, {200, "2048"}}},
63 // 3. spaces between entries
64 {"100:1024 \n \r \t \v \f 200:2048", true,
65 SpecIdToValueStrMap{{100, "1024"}, {200, "2048"}}},
66 // 4. \t, \n, \r and spaces before spec id
67 {" \n \r\t \t \v \f 100:1024", true,
68 SpecIdToValueStrMap{{100, "1024"}}},
69 // 5. \t, \n, \r and spaces after value string
70 {"100:1024 \n \r\t \t \v \f ", true,
71 SpecIdToValueStrMap{{100, "1024"}}},
72 // 6. maximum spec id
73 {"4294967295:0", true, SpecIdToValueStrMap{{4294967295, "0"}}},
74 // 7. minimum spec id
75 {"0:100", true, SpecIdToValueStrMap{{0, "100"}}},
76 // 8. random content without spaces are allowed
77 {"200:random_stuff", true, SpecIdToValueStrMap{{200, "random_stuff"}}},
78 // 9. support hex format spec id (just because we use the
79 // ParseNumber() utility)
80 {"0x100:1024", true, SpecIdToValueStrMap{{256, "1024"}}},
81 // 10. multiple entries
82 {"101:1 102:2 103:3 104:4 200:201 9999:1000 0x100:333", true,
83 SpecIdToValueStrMap{{101, "1"},
84 {102, "2"},
85 {103, "3"},
86 {104, "4"},
87 {200, "201"},
88 {9999, "1000"},
89 {256, "333"}}},
90 // 11. default value in hex float format
91 {"100:0x0.3p10", true, SpecIdToValueStrMap{{100, "0x0.3p10"}}},
92 // 12. default value in decimal float format
93 {"100:1.5e-13", true, SpecIdToValueStrMap{{100, "1.5e-13"}}},
94 }));
95
96 INSTANTIATE_TEST_SUITE_P(
97 InvalidString, DefaultValuesStringParsingTest,
98 ::testing::ValuesIn(std::vector<DefaultValuesStringParsingTestCase>{
99 // 0. missing default value
100 {"100:", false, SpecIdToValueStrMap{}},
101 // 1. spec id is not an integer
102 {"100.0:200", false, SpecIdToValueStrMap{}},
103 // 2. spec id is not a number
104 {"something_not_a_number:1", false, SpecIdToValueStrMap{}},
105 // 3. only spec id number
106 {"100", false, SpecIdToValueStrMap{}},
107 // 4. same spec id defined multiple times
108 {"100:20 100:21", false, SpecIdToValueStrMap{}},
109 // 5. Multiple definition of an identical spec id in different forms
110 // is not allowed
111 {"0x100:100 256:200", false, SpecIdToValueStrMap{}},
112 // 6. empty spec id
113 {":3", false, SpecIdToValueStrMap{}},
114 // 7. only colon
115 {":", false, SpecIdToValueStrMap{}},
116 // 8. spec id overflow
117 {"4294967296:200", false, SpecIdToValueStrMap{}},
118 // 9. spec id less than 0
119 {"-1:200", false, SpecIdToValueStrMap{}},
120 // 10. nullptr
121 {nullptr, false, SpecIdToValueStrMap{}},
122 // 11. only a number is invalid
123 {"1234", false, SpecIdToValueStrMap{}},
124 // 12. invalid entry separator
125 {"12:34;23:14", false, SpecIdToValueStrMap{}},
126 // 13. invalid spec id and default value separator
127 {"12@34", false, SpecIdToValueStrMap{}},
128 // 14. spaces before colon
129 {"100 :1024", false, SpecIdToValueStrMap{}},
130 // 15. spaces after colon
131 {"100: 1024", false, SpecIdToValueStrMap{}},
132 // 16. spec id represented in hex float format is invalid
133 {"0x3p10:200", false, SpecIdToValueStrMap{}},
134 }));
135
136 struct SetSpecConstantDefaultValueInStringFormTestCase {
137 const char* code;
138 SpecIdToValueStrMap default_values;
139 const char* expected;
140 };
141
142 using SetSpecConstantDefaultValueInStringFormParamTest = PassTest<
143 ::testing::TestWithParam<SetSpecConstantDefaultValueInStringFormTestCase>>;
144
TEST_P(SetSpecConstantDefaultValueInStringFormParamTest,TestCase)145 TEST_P(SetSpecConstantDefaultValueInStringFormParamTest, TestCase) {
146 const auto& tc = GetParam();
147 SinglePassRunAndCheck<SetSpecConstantDefaultValuePass>(
148 tc.code, tc.expected, /* skip_nop = */ false, tc.default_values);
149 }
150
151 INSTANTIATE_TEST_SUITE_P(
152 ValidCases, SetSpecConstantDefaultValueInStringFormParamTest,
153 ::testing::ValuesIn(std::vector<
154 SetSpecConstantDefaultValueInStringFormTestCase>{
155 // 0. Empty.
156 {"", SpecIdToValueStrMap{}, ""},
157 // 1. Empty with non-empty values to set.
158 {"", SpecIdToValueStrMap{{1, "100"}, {2, "200"}}, ""},
159 // 2. Bool type.
160 {
161 // code
162 "OpDecorate %1 SpecId 100\n"
163 "OpDecorate %2 SpecId 101\n"
164 "%bool = OpTypeBool\n"
165 "%1 = OpSpecConstantTrue %bool\n"
166 "%2 = OpSpecConstantFalse %bool\n",
167 // default values
168 SpecIdToValueStrMap{{100, "false"}, {101, "true"}},
169 // expected
170 "OpDecorate %1 SpecId 100\n"
171 "OpDecorate %2 SpecId 101\n"
172 "%bool = OpTypeBool\n"
173 "%1 = OpSpecConstantFalse %bool\n"
174 "%2 = OpSpecConstantTrue %bool\n",
175 },
176 // 3. 32-bit int type.
177 {
178 // code
179 "OpDecorate %1 SpecId 100\n"
180 "OpDecorate %2 SpecId 101\n"
181 "OpDecorate %3 SpecId 102\n"
182 "%int = OpTypeInt 32 1\n"
183 "%1 = OpSpecConstant %int 10\n"
184 "%2 = OpSpecConstant %int 11\n"
185 "%3 = OpSpecConstant %int 11\n",
186 // default values
187 SpecIdToValueStrMap{
188 {100, "2147483647"}, {101, "0xffffffff"}, {102, "-42"}},
189 // expected
190 "OpDecorate %1 SpecId 100\n"
191 "OpDecorate %2 SpecId 101\n"
192 "OpDecorate %3 SpecId 102\n"
193 "%int = OpTypeInt 32 1\n"
194 "%1 = OpSpecConstant %int 2147483647\n"
195 "%2 = OpSpecConstant %int -1\n"
196 "%3 = OpSpecConstant %int -42\n",
197 },
198 // 4. 64-bit uint type.
199 {
200 // code
201 "OpDecorate %1 SpecId 100\n"
202 "OpDecorate %2 SpecId 101\n"
203 "%ulong = OpTypeInt 64 0\n"
204 "%1 = OpSpecConstant %ulong 10\n"
205 "%2 = OpSpecConstant %ulong 11\n",
206 // default values
207 SpecIdToValueStrMap{{100, "18446744073709551614"}, {101, "0x100"}},
208 // expected
209 "OpDecorate %1 SpecId 100\n"
210 "OpDecorate %2 SpecId 101\n"
211 "%ulong = OpTypeInt 64 0\n"
212 "%1 = OpSpecConstant %ulong 18446744073709551614\n"
213 "%2 = OpSpecConstant %ulong 256\n",
214 },
215 // 5. 32-bit float type.
216 {
217 // code
218 "OpDecorate %1 SpecId 101\n"
219 "OpDecorate %2 SpecId 102\n"
220 "%float = OpTypeFloat 32\n"
221 "%1 = OpSpecConstant %float 200\n"
222 "%2 = OpSpecConstant %float 201\n",
223 // default values
224 SpecIdToValueStrMap{{101, "-0x1.fffffep+128"}, {102, "2.5"}},
225 // expected
226 "OpDecorate %1 SpecId 101\n"
227 "OpDecorate %2 SpecId 102\n"
228 "%float = OpTypeFloat 32\n"
229 "%1 = OpSpecConstant %float -0x1.fffffep+128\n"
230 "%2 = OpSpecConstant %float 2.5\n",
231 },
232 // 6. 64-bit float type.
233 {
234 // code
235 "OpDecorate %1 SpecId 201\n"
236 "OpDecorate %2 SpecId 202\n"
237 "%double = OpTypeFloat 64\n"
238 "%1 = OpSpecConstant %double 3.14159265358979\n"
239 "%2 = OpSpecConstant %double 0.14285\n",
240 // default values
241 SpecIdToValueStrMap{{201, "0x1.fffffffffffffp+1024"},
242 {202, "-32.5"}},
243 // expected
244 "OpDecorate %1 SpecId 201\n"
245 "OpDecorate %2 SpecId 202\n"
246 "%double = OpTypeFloat 64\n"
247 "%1 = OpSpecConstant %double 0x1.fffffffffffffp+1024\n"
248 "%2 = OpSpecConstant %double -32.5\n",
249 },
250 // 7. SpecId not found, expect no modification.
251 {
252 // code
253 "OpDecorate %1 SpecId 201\n"
254 "%double = OpTypeFloat 64\n"
255 "%1 = OpSpecConstant %double 3.14159265358979\n",
256 // default values
257 SpecIdToValueStrMap{{8888, "0.0"}},
258 // expected
259 "OpDecorate %1 SpecId 201\n"
260 "%double = OpTypeFloat 64\n"
261 "%1 = OpSpecConstant %double 3.14159265358979\n",
262 },
263 // 8. Multiple types of spec constants.
264 {
265 // code
266 "OpDecorate %1 SpecId 201\n"
267 "OpDecorate %2 SpecId 202\n"
268 "OpDecorate %3 SpecId 203\n"
269 "%bool = OpTypeBool\n"
270 "%int = OpTypeInt 32 1\n"
271 "%double = OpTypeFloat 64\n"
272 "%1 = OpSpecConstant %double 3.14159265358979\n"
273 "%2 = OpSpecConstant %int 1024\n"
274 "%3 = OpSpecConstantTrue %bool\n",
275 // default values
276 SpecIdToValueStrMap{
277 {201, "0x1.fffffffffffffp+1024"},
278 {202, "2048"},
279 {203, "false"},
280 },
281 // expected
282 "OpDecorate %1 SpecId 201\n"
283 "OpDecorate %2 SpecId 202\n"
284 "OpDecorate %3 SpecId 203\n"
285 "%bool = OpTypeBool\n"
286 "%int = OpTypeInt 32 1\n"
287 "%double = OpTypeFloat 64\n"
288 "%1 = OpSpecConstant %double 0x1.fffffffffffffp+1024\n"
289 "%2 = OpSpecConstant %int 2048\n"
290 "%3 = OpSpecConstantFalse %bool\n",
291 },
292 // 9. Ignore other decorations.
293 {
294 // code
295 "OpDecorate %1 ArrayStride 4\n"
296 "%int = OpTypeInt 32 1\n"
297 "%1 = OpSpecConstant %int 100\n",
298 // default values
299 SpecIdToValueStrMap{{4, "0x7fffffff"}},
300 // expected
301 "OpDecorate %1 ArrayStride 4\n"
302 "%int = OpTypeInt 32 1\n"
303 "%1 = OpSpecConstant %int 100\n",
304 },
305 // 10. Distinguish from other decorations.
306 {
307 // code
308 "OpDecorate %1 SpecId 100\n"
309 "OpDecorate %1 ArrayStride 4\n"
310 "%int = OpTypeInt 32 1\n"
311 "%1 = OpSpecConstant %int 100\n",
312 // default values
313 SpecIdToValueStrMap{{4, "0x7fffffff"}, {100, "0xffffffff"}},
314 // expected
315 "OpDecorate %1 SpecId 100\n"
316 "OpDecorate %1 ArrayStride 4\n"
317 "%int = OpTypeInt 32 1\n"
318 "%1 = OpSpecConstant %int -1\n",
319 },
320 // 11. Decorate through decoration group.
321 {
322 // code
323 "OpDecorate %1 SpecId 100\n"
324 "%1 = OpDecorationGroup\n"
325 "OpGroupDecorate %1 %2\n"
326 "%int = OpTypeInt 32 1\n"
327 "%2 = OpSpecConstant %int 100\n",
328 // default values
329 SpecIdToValueStrMap{{100, "0x7fffffff"}},
330 // expected
331 "OpDecorate %1 SpecId 100\n"
332 "%1 = OpDecorationGroup\n"
333 "OpGroupDecorate %1 %2\n"
334 "%int = OpTypeInt 32 1\n"
335 "%2 = OpSpecConstant %int 2147483647\n",
336 },
337 // 12. Ignore other decorations in decoration group.
338 {
339 // code
340 "OpDecorate %1 ArrayStride 4\n"
341 "%1 = OpDecorationGroup\n"
342 "OpGroupDecorate %1 %2\n"
343 "%int = OpTypeInt 32 1\n"
344 "%2 = OpSpecConstant %int 100\n",
345 // default values
346 SpecIdToValueStrMap{{4, "0x7fffffff"}},
347 // expected
348 "OpDecorate %1 ArrayStride 4\n"
349 "%1 = OpDecorationGroup\n"
350 "OpGroupDecorate %1 %2\n"
351 "%int = OpTypeInt 32 1\n"
352 "%2 = OpSpecConstant %int 100\n",
353 },
354 // 13. Distinguish from other decorations in decoration group.
355 {
356 // code
357 "OpDecorate %1 SpecId 100\n"
358 "OpDecorate %1 ArrayStride 4\n"
359 "%1 = OpDecorationGroup\n"
360 "OpGroupDecorate %1 %2\n"
361 "%int = OpTypeInt 32 1\n"
362 "%2 = OpSpecConstant %int 100\n",
363 // default values
364 SpecIdToValueStrMap{{100, "0x7fffffff"}, {4, "0x00000001"}},
365 // expected
366 "OpDecorate %1 SpecId 100\n"
367 "OpDecorate %1 ArrayStride 4\n"
368 "%1 = OpDecorationGroup\n"
369 "OpGroupDecorate %1 %2\n"
370 "%int = OpTypeInt 32 1\n"
371 "%2 = OpSpecConstant %int 2147483647\n",
372 },
373 // 14. Unchanged bool default value
374 {
375 // code
376 "OpDecorate %1 SpecId 100\n"
377 "OpDecorate %2 SpecId 101\n"
378 "%bool = OpTypeBool\n"
379 "%1 = OpSpecConstantTrue %bool\n"
380 "%2 = OpSpecConstantFalse %bool\n",
381 // default values
382 SpecIdToValueStrMap{{100, "true"}, {101, "false"}},
383 // expected
384 "OpDecorate %1 SpecId 100\n"
385 "OpDecorate %2 SpecId 101\n"
386 "%bool = OpTypeBool\n"
387 "%1 = OpSpecConstantTrue %bool\n"
388 "%2 = OpSpecConstantFalse %bool\n",
389 },
390 // 15. Unchanged int default values
391 {
392 // code
393 "OpDecorate %1 SpecId 100\n"
394 "OpDecorate %2 SpecId 101\n"
395 "%int = OpTypeInt 32 1\n"
396 "%ulong = OpTypeInt 64 0\n"
397 "%1 = OpSpecConstant %int 10\n"
398 "%2 = OpSpecConstant %ulong 11\n",
399 // default values
400 SpecIdToValueStrMap{{100, "10"}, {101, "11"}},
401 // expected
402 "OpDecorate %1 SpecId 100\n"
403 "OpDecorate %2 SpecId 101\n"
404 "%int = OpTypeInt 32 1\n"
405 "%ulong = OpTypeInt 64 0\n"
406 "%1 = OpSpecConstant %int 10\n"
407 "%2 = OpSpecConstant %ulong 11\n",
408 },
409 // 16. Unchanged float default values
410 {
411 // code
412 "OpDecorate %1 SpecId 201\n"
413 "OpDecorate %2 SpecId 202\n"
414 "%float = OpTypeFloat 32\n"
415 "%double = OpTypeFloat 64\n"
416 "%1 = OpSpecConstant %float 3.1415\n"
417 "%2 = OpSpecConstant %double 0.14285\n",
418 // default values
419 SpecIdToValueStrMap{{201, "3.1415"}, {202, "0.14285"}},
420 // expected
421 "OpDecorate %1 SpecId 201\n"
422 "OpDecorate %2 SpecId 202\n"
423 "%float = OpTypeFloat 32\n"
424 "%double = OpTypeFloat 64\n"
425 "%1 = OpSpecConstant %float 3.1415\n"
426 "%2 = OpSpecConstant %double 0.14285\n",
427 },
428 // 17. OpGroupDecorate may have multiple target ids defined by the same
429 // eligible spec constant
430 {
431 // code
432 "OpDecorate %1 SpecId 100\n"
433 "%1 = OpDecorationGroup\n"
434 "OpGroupDecorate %1 %2 %2 %2\n"
435 "%int = OpTypeInt 32 1\n"
436 "%2 = OpSpecConstant %int 100\n",
437 // default values
438 SpecIdToValueStrMap{{100, "0xffffffff"}},
439 // expected
440 "OpDecorate %1 SpecId 100\n"
441 "%1 = OpDecorationGroup\n"
442 "OpGroupDecorate %1 %2 %2 %2\n"
443 "%int = OpTypeInt 32 1\n"
444 "%2 = OpSpecConstant %int -1\n",
445 },
446 }));
447
448 INSTANTIATE_TEST_SUITE_P(
449 InvalidCases, SetSpecConstantDefaultValueInStringFormParamTest,
450 ::testing::ValuesIn(std::vector<
451 SetSpecConstantDefaultValueInStringFormTestCase>{
452 // 0. Do not crash when decoration group is not used.
453 {
454 // code
455 "OpDecorate %1 SpecId 100\n"
456 "%1 = OpDecorationGroup\n"
457 "%int = OpTypeInt 32 1\n"
458 "%3 = OpSpecConstant %int 100\n",
459 // default values
460 SpecIdToValueStrMap{{100, "0x7fffffff"}},
461 // expected
462 "OpDecorate %1 SpecId 100\n"
463 "%1 = OpDecorationGroup\n"
464 "%int = OpTypeInt 32 1\n"
465 "%3 = OpSpecConstant %int 100\n",
466 },
467 // 1. Do not crash when target does not exist.
468 {
469 // code
470 "OpDecorate %1 SpecId 100\n"
471 "%1 = OpDecorationGroup\n"
472 "%int = OpTypeInt 32 1\n",
473 // default values
474 SpecIdToValueStrMap{{100, "0x7fffffff"}},
475 // expected
476 "OpDecorate %1 SpecId 100\n"
477 "%1 = OpDecorationGroup\n"
478 "%int = OpTypeInt 32 1\n",
479 },
480 // 2. Do nothing when SpecId decoration is not attached to a
481 // non-spec-constant instruction.
482 {
483 // code
484 "OpDecorate %1 SpecId 100\n"
485 "%1 = OpDecorationGroup\n"
486 "%int = OpTypeInt 32 1\n"
487 "%int_101 = OpConstant %int 101\n",
488 // default values
489 SpecIdToValueStrMap{{100, "0x7fffffff"}},
490 // expected
491 "OpDecorate %1 SpecId 100\n"
492 "%1 = OpDecorationGroup\n"
493 "%int = OpTypeInt 32 1\n"
494 "%int_101 = OpConstant %int 101\n",
495 },
496 // 3. Do nothing when SpecId decoration is not attached to a
497 // OpSpecConstant{|True|False} instruction.
498 {
499 // code
500 "OpDecorate %1 SpecId 100\n"
501 "%int = OpTypeInt 32 1\n"
502 "%3 = OpSpecConstant %int 101\n"
503 "%1 = OpSpecConstantOp %int IAdd %3 %3\n",
504 // default values
505 SpecIdToValueStrMap{{100, "0x7fffffff"}},
506 // expected
507 "OpDecorate %1 SpecId 100\n"
508 "%int = OpTypeInt 32 1\n"
509 "%3 = OpSpecConstant %int 101\n"
510 "%1 = OpSpecConstantOp %int IAdd %3 %3\n",
511 },
512 // 4. Do not crash and do nothing when SpecId decoration is applied to
513 // multiple spec constants.
514 {
515 // code
516 "OpDecorate %1 SpecId 100\n"
517 "%1 = OpDecorationGroup\n"
518 "OpGroupDecorate %1 %2 %3 %4\n"
519 "%int = OpTypeInt 32 1\n"
520 "%2 = OpSpecConstant %int 100\n"
521 "%3 = OpSpecConstant %int 200\n"
522 "%4 = OpSpecConstant %int 300\n",
523 // default values
524 SpecIdToValueStrMap{{100, "0xffffffff"}},
525 // expected
526 "OpDecorate %1 SpecId 100\n"
527 "%1 = OpDecorationGroup\n"
528 "OpGroupDecorate %1 %2 %3 %4\n"
529 "%int = OpTypeInt 32 1\n"
530 "%2 = OpSpecConstant %int 100\n"
531 "%3 = OpSpecConstant %int 200\n"
532 "%4 = OpSpecConstant %int 300\n",
533 },
534 // 5. Do not crash and do nothing when SpecId decoration is attached to
535 // non-spec-constants (invalid case).
536 {
537 // code
538 "OpDecorate %1 SpecId 100\n"
539 "%1 = OpDecorationGroup\n"
540 "%2 = OpDecorationGroup\n"
541 "OpGroupDecorate %1 %2\n"
542 "%int = OpTypeInt 32 1\n"
543 "%int_100 = OpConstant %int 100\n",
544 // default values
545 SpecIdToValueStrMap{{100, "0xffffffff"}},
546 // expected
547 "OpDecorate %1 SpecId 100\n"
548 "%1 = OpDecorationGroup\n"
549 "%2 = OpDecorationGroup\n"
550 "OpGroupDecorate %1 %2\n"
551 "%int = OpTypeInt 32 1\n"
552 "%int_100 = OpConstant %int 100\n",
553 },
554 // 6. Boolean type spec constant cannot be set with numeric values in
555 // string form. i.e. only 'true' and 'false' are acceptable for setting
556 // boolean type spec constants. Nothing should be done if numeric values
557 // in string form are provided.
558 {
559 // code
560 "OpDecorate %1 SpecId 100\n"
561 "OpDecorate %2 SpecId 101\n"
562 "OpDecorate %3 SpecId 102\n"
563 "OpDecorate %4 SpecId 103\n"
564 "OpDecorate %5 SpecId 104\n"
565 "OpDecorate %6 SpecId 105\n"
566 "%bool = OpTypeBool\n"
567 "%1 = OpSpecConstantTrue %bool\n"
568 "%2 = OpSpecConstantFalse %bool\n"
569 "%3 = OpSpecConstantTrue %bool\n"
570 "%4 = OpSpecConstantTrue %bool\n"
571 "%5 = OpSpecConstantTrue %bool\n"
572 "%6 = OpSpecConstantFalse %bool\n",
573 // default values
574 SpecIdToValueStrMap{{100, "0"},
575 {101, "1"},
576 {102, "0x0"},
577 {103, "0.0"},
578 {104, "-0.0"},
579 {105, "0x12345678"}},
580 // expected
581 "OpDecorate %1 SpecId 100\n"
582 "OpDecorate %2 SpecId 101\n"
583 "OpDecorate %3 SpecId 102\n"
584 "OpDecorate %4 SpecId 103\n"
585 "OpDecorate %5 SpecId 104\n"
586 "OpDecorate %6 SpecId 105\n"
587 "%bool = OpTypeBool\n"
588 "%1 = OpSpecConstantTrue %bool\n"
589 "%2 = OpSpecConstantFalse %bool\n"
590 "%3 = OpSpecConstantTrue %bool\n"
591 "%4 = OpSpecConstantTrue %bool\n"
592 "%5 = OpSpecConstantTrue %bool\n"
593 "%6 = OpSpecConstantFalse %bool\n",
594 },
595 }));
596
597 struct SetSpecConstantDefaultValueInBitPatternFormTestCase {
598 const char* code;
599 SpecIdToValueBitPatternMap default_values;
600 const char* expected;
601 };
602
603 using SetSpecConstantDefaultValueInBitPatternFormParamTest =
604 PassTest<::testing::TestWithParam<
605 SetSpecConstantDefaultValueInBitPatternFormTestCase>>;
606
TEST_P(SetSpecConstantDefaultValueInBitPatternFormParamTest,TestCase)607 TEST_P(SetSpecConstantDefaultValueInBitPatternFormParamTest, TestCase) {
608 const auto& tc = GetParam();
609 SinglePassRunAndCheck<SetSpecConstantDefaultValuePass>(
610 tc.code, tc.expected, /* skip_nop = */ false, tc.default_values);
611 }
612
613 INSTANTIATE_TEST_SUITE_P(
614 ValidCases, SetSpecConstantDefaultValueInBitPatternFormParamTest,
615 ::testing::ValuesIn(std::vector<
616 SetSpecConstantDefaultValueInBitPatternFormTestCase>{
617 // 0. Empty.
618 {"", SpecIdToValueBitPatternMap{}, ""},
619 // 1. Empty with non-empty values to set.
620 {"", SpecIdToValueBitPatternMap{{1, {100}}, {2, {200}}}, ""},
621 // 2. Baisc bool type.
622 {
623 // code
624 "OpDecorate %1 SpecId 100\n"
625 "OpDecorate %2 SpecId 101\n"
626 "%bool = OpTypeBool\n"
627 "%1 = OpSpecConstantTrue %bool\n"
628 "%2 = OpSpecConstantFalse %bool\n",
629 // default values
630 SpecIdToValueBitPatternMap{{100, {0x0}}, {101, {0x1}}},
631 // expected
632 "OpDecorate %1 SpecId 100\n"
633 "OpDecorate %2 SpecId 101\n"
634 "%bool = OpTypeBool\n"
635 "%1 = OpSpecConstantFalse %bool\n"
636 "%2 = OpSpecConstantTrue %bool\n",
637 },
638 // 3. 32-bit int type.
639 {
640 // code
641 "OpDecorate %1 SpecId 100\n"
642 "OpDecorate %2 SpecId 101\n"
643 "OpDecorate %3 SpecId 102\n"
644 "%int = OpTypeInt 32 1\n"
645 "%1 = OpSpecConstant %int 10\n"
646 "%2 = OpSpecConstant %int 11\n"
647 "%3 = OpSpecConstant %int 11\n",
648 // default values
649 SpecIdToValueBitPatternMap{
650 {100, {2147483647}}, {101, {0xffffffff}}, {102, {0xffffffd6}}},
651 // expected
652 "OpDecorate %1 SpecId 100\n"
653 "OpDecorate %2 SpecId 101\n"
654 "OpDecorate %3 SpecId 102\n"
655 "%int = OpTypeInt 32 1\n"
656 "%1 = OpSpecConstant %int 2147483647\n"
657 "%2 = OpSpecConstant %int -1\n"
658 "%3 = OpSpecConstant %int -42\n",
659 },
660 // 4. 64-bit uint type.
661 {
662 // code
663 "OpDecorate %1 SpecId 100\n"
664 "OpDecorate %2 SpecId 101\n"
665 "%ulong = OpTypeInt 64 0\n"
666 "%1 = OpSpecConstant %ulong 10\n"
667 "%2 = OpSpecConstant %ulong 11\n",
668 // default values
669 SpecIdToValueBitPatternMap{{100, {0xFFFFFFFE, 0xFFFFFFFF}},
670 {101, {0x100, 0x0}}},
671 // expected
672 "OpDecorate %1 SpecId 100\n"
673 "OpDecorate %2 SpecId 101\n"
674 "%ulong = OpTypeInt 64 0\n"
675 "%1 = OpSpecConstant %ulong 18446744073709551614\n"
676 "%2 = OpSpecConstant %ulong 256\n",
677 },
678 // 5. 32-bit float type.
679 {
680 // code
681 "OpDecorate %1 SpecId 101\n"
682 "OpDecorate %2 SpecId 102\n"
683 "%float = OpTypeFloat 32\n"
684 "%1 = OpSpecConstant %float 200\n"
685 "%2 = OpSpecConstant %float 201\n",
686 // default values
687 SpecIdToValueBitPatternMap{{101, {0xffffffff}},
688 {102, {0x40200000}}},
689 // expected
690 "OpDecorate %1 SpecId 101\n"
691 "OpDecorate %2 SpecId 102\n"
692 "%float = OpTypeFloat 32\n"
693 "%1 = OpSpecConstant %float -0x1.fffffep+128\n"
694 "%2 = OpSpecConstant %float 2.5\n",
695 },
696 // 6. 64-bit float type.
697 {
698 // code
699 "OpDecorate %1 SpecId 201\n"
700 "OpDecorate %2 SpecId 202\n"
701 "%double = OpTypeFloat 64\n"
702 "%1 = OpSpecConstant %double 3.14159265358979\n"
703 "%2 = OpSpecConstant %double 0.14285\n",
704 // default values
705 SpecIdToValueBitPatternMap{{201, {0xffffffff, 0x7fffffff}},
706 {202, {0x00000000, 0xc0404000}}},
707 // expected
708 "OpDecorate %1 SpecId 201\n"
709 "OpDecorate %2 SpecId 202\n"
710 "%double = OpTypeFloat 64\n"
711 "%1 = OpSpecConstant %double 0x1.fffffffffffffp+1024\n"
712 "%2 = OpSpecConstant %double -32.5\n",
713 },
714 // 7. SpecId not found, expect no modification.
715 {
716 // code
717 "OpDecorate %1 SpecId 201\n"
718 "%double = OpTypeFloat 64\n"
719 "%1 = OpSpecConstant %double 3.14159265358979\n",
720 // default values
721 SpecIdToValueBitPatternMap{{8888, {0x0}}},
722 // expected
723 "OpDecorate %1 SpecId 201\n"
724 "%double = OpTypeFloat 64\n"
725 "%1 = OpSpecConstant %double 3.14159265358979\n",
726 },
727 // 8. Multiple types of spec constants.
728 {
729 // code
730 "OpDecorate %1 SpecId 201\n"
731 "OpDecorate %2 SpecId 202\n"
732 "OpDecorate %3 SpecId 203\n"
733 "%bool = OpTypeBool\n"
734 "%int = OpTypeInt 32 1\n"
735 "%double = OpTypeFloat 64\n"
736 "%1 = OpSpecConstant %double 3.14159265358979\n"
737 "%2 = OpSpecConstant %int 1024\n"
738 "%3 = OpSpecConstantTrue %bool\n",
739 // default values
740 SpecIdToValueBitPatternMap{
741 {201, {0xffffffff, 0x7fffffff}},
742 {202, {0x00000800}},
743 {203, {0x0}},
744 },
745 // expected
746 "OpDecorate %1 SpecId 201\n"
747 "OpDecorate %2 SpecId 202\n"
748 "OpDecorate %3 SpecId 203\n"
749 "%bool = OpTypeBool\n"
750 "%int = OpTypeInt 32 1\n"
751 "%double = OpTypeFloat 64\n"
752 "%1 = OpSpecConstant %double 0x1.fffffffffffffp+1024\n"
753 "%2 = OpSpecConstant %int 2048\n"
754 "%3 = OpSpecConstantFalse %bool\n",
755 },
756 // 9. Ignore other decorations.
757 {
758 // code
759 "OpDecorate %1 ArrayStride 4\n"
760 "%int = OpTypeInt 32 1\n"
761 "%1 = OpSpecConstant %int 100\n",
762 // default values
763 SpecIdToValueBitPatternMap{{4, {0x7fffffff}}},
764 // expected
765 "OpDecorate %1 ArrayStride 4\n"
766 "%int = OpTypeInt 32 1\n"
767 "%1 = OpSpecConstant %int 100\n",
768 },
769 // 10. Distinguish from other decorations.
770 {
771 // code
772 "OpDecorate %1 SpecId 100\n"
773 "OpDecorate %1 ArrayStride 4\n"
774 "%int = OpTypeInt 32 1\n"
775 "%1 = OpSpecConstant %int 100\n",
776 // default values
777 SpecIdToValueBitPatternMap{{4, {0x7fffffff}}, {100, {0xffffffff}}},
778 // expected
779 "OpDecorate %1 SpecId 100\n"
780 "OpDecorate %1 ArrayStride 4\n"
781 "%int = OpTypeInt 32 1\n"
782 "%1 = OpSpecConstant %int -1\n",
783 },
784 // 11. Decorate through decoration group.
785 {
786 // code
787 "OpDecorate %1 SpecId 100\n"
788 "%1 = OpDecorationGroup\n"
789 "OpGroupDecorate %1 %2\n"
790 "%int = OpTypeInt 32 1\n"
791 "%2 = OpSpecConstant %int 100\n",
792 // default values
793 SpecIdToValueBitPatternMap{{100, {0x7fffffff}}},
794 // expected
795 "OpDecorate %1 SpecId 100\n"
796 "%1 = OpDecorationGroup\n"
797 "OpGroupDecorate %1 %2\n"
798 "%int = OpTypeInt 32 1\n"
799 "%2 = OpSpecConstant %int 2147483647\n",
800 },
801 // 12. Ignore other decorations in decoration group.
802 {
803 // code
804 "OpDecorate %1 ArrayStride 4\n"
805 "%1 = OpDecorationGroup\n"
806 "OpGroupDecorate %1 %2\n"
807 "%int = OpTypeInt 32 1\n"
808 "%2 = OpSpecConstant %int 100\n",
809 // default values
810 SpecIdToValueBitPatternMap{{4, {0x7fffffff}}},
811 // expected
812 "OpDecorate %1 ArrayStride 4\n"
813 "%1 = OpDecorationGroup\n"
814 "OpGroupDecorate %1 %2\n"
815 "%int = OpTypeInt 32 1\n"
816 "%2 = OpSpecConstant %int 100\n",
817 },
818 // 13. Distinguish from other decorations in decoration group.
819 {
820 // code
821 "OpDecorate %1 SpecId 100\n"
822 "OpDecorate %1 ArrayStride 4\n"
823 "%1 = OpDecorationGroup\n"
824 "OpGroupDecorate %1 %2\n"
825 "%int = OpTypeInt 32 1\n"
826 "%2 = OpSpecConstant %int 100\n",
827 // default values
828 SpecIdToValueBitPatternMap{{100, {0x7fffffff}}, {4, {0x00000001}}},
829 // expected
830 "OpDecorate %1 SpecId 100\n"
831 "OpDecorate %1 ArrayStride 4\n"
832 "%1 = OpDecorationGroup\n"
833 "OpGroupDecorate %1 %2\n"
834 "%int = OpTypeInt 32 1\n"
835 "%2 = OpSpecConstant %int 2147483647\n",
836 },
837 // 14. Unchanged bool default value
838 {
839 // code
840 "OpDecorate %1 SpecId 100\n"
841 "OpDecorate %2 SpecId 101\n"
842 "%bool = OpTypeBool\n"
843 "%1 = OpSpecConstantTrue %bool\n"
844 "%2 = OpSpecConstantFalse %bool\n",
845 // default values
846 SpecIdToValueBitPatternMap{{100, {0x1}}, {101, {0x0}}},
847 // expected
848 "OpDecorate %1 SpecId 100\n"
849 "OpDecorate %2 SpecId 101\n"
850 "%bool = OpTypeBool\n"
851 "%1 = OpSpecConstantTrue %bool\n"
852 "%2 = OpSpecConstantFalse %bool\n",
853 },
854 // 15. Unchanged int default values
855 {
856 // code
857 "OpDecorate %1 SpecId 100\n"
858 "OpDecorate %2 SpecId 101\n"
859 "%int = OpTypeInt 32 1\n"
860 "%ulong = OpTypeInt 64 0\n"
861 "%1 = OpSpecConstant %int 10\n"
862 "%2 = OpSpecConstant %ulong 11\n",
863 // default values
864 SpecIdToValueBitPatternMap{{100, {10}}, {101, {11, 0}}},
865 // expected
866 "OpDecorate %1 SpecId 100\n"
867 "OpDecorate %2 SpecId 101\n"
868 "%int = OpTypeInt 32 1\n"
869 "%ulong = OpTypeInt 64 0\n"
870 "%1 = OpSpecConstant %int 10\n"
871 "%2 = OpSpecConstant %ulong 11\n",
872 },
873 // 16. Unchanged float default values
874 {
875 // code
876 "OpDecorate %1 SpecId 201\n"
877 "OpDecorate %2 SpecId 202\n"
878 "%float = OpTypeFloat 32\n"
879 "%double = OpTypeFloat 64\n"
880 "%1 = OpSpecConstant %float 3.25\n"
881 "%2 = OpSpecConstant %double 1.25\n",
882 // default values
883 SpecIdToValueBitPatternMap{{201, {0x40500000}},
884 {202, {0x00000000, 0x3ff40000}}},
885 // expected
886 "OpDecorate %1 SpecId 201\n"
887 "OpDecorate %2 SpecId 202\n"
888 "%float = OpTypeFloat 32\n"
889 "%double = OpTypeFloat 64\n"
890 "%1 = OpSpecConstant %float 3.25\n"
891 "%2 = OpSpecConstant %double 1.25\n",
892 },
893 // 17. OpGroupDecorate may have multiple target ids defined by the same
894 // eligible spec constant
895 {
896 // code
897 "OpDecorate %1 SpecId 100\n"
898 "%1 = OpDecorationGroup\n"
899 "OpGroupDecorate %1 %2 %2 %2\n"
900 "%int = OpTypeInt 32 1\n"
901 "%2 = OpSpecConstant %int 100\n",
902 // default values
903 SpecIdToValueBitPatternMap{{100, {0xffffffff}}},
904 // expected
905 "OpDecorate %1 SpecId 100\n"
906 "%1 = OpDecorationGroup\n"
907 "OpGroupDecorate %1 %2 %2 %2\n"
908 "%int = OpTypeInt 32 1\n"
909 "%2 = OpSpecConstant %int -1\n",
910 },
911 // 18. For Boolean type spec constants,if any word in the bit pattern
912 // is not zero, it can be considered as a 'true', otherwise, it can be
913 // considered as a 'false'.
914 {
915 // code
916 "OpDecorate %1 SpecId 100\n"
917 "OpDecorate %2 SpecId 101\n"
918 "OpDecorate %3 SpecId 102\n"
919 "%bool = OpTypeBool\n"
920 "%1 = OpSpecConstantTrue %bool\n"
921 "%2 = OpSpecConstantFalse %bool\n"
922 "%3 = OpSpecConstantFalse %bool\n",
923 // default values
924 SpecIdToValueBitPatternMap{
925 {100, {0x0, 0x0, 0x0, 0x0}},
926 {101, {0x10101010}},
927 {102, {0x0, 0x0, 0x0, 0x2}},
928 },
929 // expected
930 "OpDecorate %1 SpecId 100\n"
931 "OpDecorate %2 SpecId 101\n"
932 "OpDecorate %3 SpecId 102\n"
933 "%bool = OpTypeBool\n"
934 "%1 = OpSpecConstantFalse %bool\n"
935 "%2 = OpSpecConstantTrue %bool\n"
936 "%3 = OpSpecConstantTrue %bool\n",
937 },
938 }));
939
940 INSTANTIATE_TEST_SUITE_P(
941 InvalidCases, SetSpecConstantDefaultValueInBitPatternFormParamTest,
942 ::testing::ValuesIn(std::vector<
943 SetSpecConstantDefaultValueInBitPatternFormTestCase>{
944 // 0. Do not crash when decoration group is not used.
945 {
946 // code
947 "OpDecorate %1 SpecId 100\n"
948 "%1 = OpDecorationGroup\n"
949 "%int = OpTypeInt 32 1\n"
950 "%3 = OpSpecConstant %int 100\n",
951 // default values
952 SpecIdToValueBitPatternMap{{100, {0x7fffffff}}},
953 // expected
954 "OpDecorate %1 SpecId 100\n"
955 "%1 = OpDecorationGroup\n"
956 "%int = OpTypeInt 32 1\n"
957 "%3 = OpSpecConstant %int 100\n",
958 },
959 // 1. Do not crash when target does not exist.
960 {
961 // code
962 "OpDecorate %1 SpecId 100\n"
963 "%1 = OpDecorationGroup\n"
964 "%int = OpTypeInt 32 1\n",
965 // default values
966 SpecIdToValueBitPatternMap{{100, {0x7fffffff}}},
967 // expected
968 "OpDecorate %1 SpecId 100\n"
969 "%1 = OpDecorationGroup\n"
970 "%int = OpTypeInt 32 1\n",
971 },
972 // 2. Do nothing when SpecId decoration is not attached to a
973 // non-spec-constant instruction.
974 {
975 // code
976 "OpDecorate %1 SpecId 100\n"
977 "%1 = OpDecorationGroup\n"
978 "%int = OpTypeInt 32 1\n"
979 "%int_101 = OpConstant %int 101\n",
980 // default values
981 SpecIdToValueBitPatternMap{{100, {0x7fffffff}}},
982 // expected
983 "OpDecorate %1 SpecId 100\n"
984 "%1 = OpDecorationGroup\n"
985 "%int = OpTypeInt 32 1\n"
986 "%int_101 = OpConstant %int 101\n",
987 },
988 // 3. Do nothing when SpecId decoration is not attached to a
989 // OpSpecConstant{|True|False} instruction.
990 {
991 // code
992 "OpDecorate %1 SpecId 100\n"
993 "%int = OpTypeInt 32 1\n"
994 "%3 = OpSpecConstant %int 101\n"
995 "%1 = OpSpecConstantOp %int IAdd %3 %3\n",
996 // default values
997 SpecIdToValueBitPatternMap{{100, {0x7fffffff}}},
998 // expected
999 "OpDecorate %1 SpecId 100\n"
1000 "%int = OpTypeInt 32 1\n"
1001 "%3 = OpSpecConstant %int 101\n"
1002 "%1 = OpSpecConstantOp %int IAdd %3 %3\n",
1003 },
1004 // 4. Do not crash and do nothing when SpecId decoration is applied to
1005 // multiple spec constants.
1006 {
1007 // code
1008 "OpDecorate %1 SpecId 100\n"
1009 "%1 = OpDecorationGroup\n"
1010 "OpGroupDecorate %1 %2 %3 %4\n"
1011 "%int = OpTypeInt 32 1\n"
1012 "%2 = OpSpecConstant %int 100\n"
1013 "%3 = OpSpecConstant %int 200\n"
1014 "%4 = OpSpecConstant %int 300\n",
1015 // default values
1016 SpecIdToValueBitPatternMap{{100, {0xffffffff}}},
1017 // expected
1018 "OpDecorate %1 SpecId 100\n"
1019 "%1 = OpDecorationGroup\n"
1020 "OpGroupDecorate %1 %2 %3 %4\n"
1021 "%int = OpTypeInt 32 1\n"
1022 "%2 = OpSpecConstant %int 100\n"
1023 "%3 = OpSpecConstant %int 200\n"
1024 "%4 = OpSpecConstant %int 300\n",
1025 },
1026 // 5. Do not crash and do nothing when SpecId decoration is attached to
1027 // non-spec-constants (invalid case).
1028 {
1029 // code
1030 "OpDecorate %1 SpecId 100\n"
1031 "%1 = OpDecorationGroup\n"
1032 "%2 = OpDecorationGroup\n"
1033 "OpGroupDecorate %1 %2\n"
1034 "%int = OpTypeInt 32 1\n"
1035 "%int_100 = OpConstant %int 100\n",
1036 // default values
1037 SpecIdToValueBitPatternMap{{100, {0xffffffff}}},
1038 // expected
1039 "OpDecorate %1 SpecId 100\n"
1040 "%1 = OpDecorationGroup\n"
1041 "%2 = OpDecorationGroup\n"
1042 "OpGroupDecorate %1 %2\n"
1043 "%int = OpTypeInt 32 1\n"
1044 "%int_100 = OpConstant %int 100\n",
1045 },
1046 // 6. Incompatible input bit pattern with the type. Nothing should be
1047 // done in such a case.
1048 {
1049 // code
1050 "OpDecorate %1 SpecId 100\n"
1051 "OpDecorate %2 SpecId 101\n"
1052 "OpDecorate %3 SpecId 102\n"
1053 "%int = OpTypeInt 32 1\n"
1054 "%ulong = OpTypeInt 64 0\n"
1055 "%double = OpTypeFloat 64\n"
1056 "%1 = OpSpecConstant %int 100\n"
1057 "%2 = OpSpecConstant %ulong 200\n"
1058 "%3 = OpSpecConstant %double 3.141592653\n",
1059 // default values
1060 SpecIdToValueBitPatternMap{
1061 {100, {10, 0}}, {101, {11}}, {102, {0xffffffff}}},
1062 // expected
1063 "OpDecorate %1 SpecId 100\n"
1064 "OpDecorate %2 SpecId 101\n"
1065 "OpDecorate %3 SpecId 102\n"
1066 "%int = OpTypeInt 32 1\n"
1067 "%ulong = OpTypeInt 64 0\n"
1068 "%double = OpTypeFloat 64\n"
1069 "%1 = OpSpecConstant %int 100\n"
1070 "%2 = OpSpecConstant %ulong 200\n"
1071 "%3 = OpSpecConstant %double 3.141592653\n",
1072 },
1073 }));
1074
1075 } // namespace
1076 } // namespace opt
1077 } // namespace spvtools
1078