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 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 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 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