• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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