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 <memory> 16 #include <string> 17 #include <utility> 18 #include <vector> 19 20 #include "effcee/effcee.h" 21 #include "gmock/gmock.h" 22 #include "gtest/gtest.h" 23 #include "source/opt/build_module.h" 24 #include "source/opt/instruction.h" 25 #include "source/opt/type_manager.h" 26 #include "spirv-tools/libspirv.hpp" 27 28 namespace spvtools { 29 namespace opt { 30 namespace analysis { 31 namespace { 32 33 bool Validate(const std::vector<uint32_t>& bin) { 34 spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; 35 spv_context spvContext = spvContextCreate(target_env); 36 spv_diagnostic diagnostic = nullptr; 37 spv_const_binary_t binary = {bin.data(), bin.size()}; 38 spv_result_t error = spvValidate(spvContext, &binary, &diagnostic); 39 if (error != 0) spvDiagnosticPrint(diagnostic); 40 spvDiagnosticDestroy(diagnostic); 41 spvContextDestroy(spvContext); 42 return error == 0; 43 } 44 45 void Match(const std::string& original, IRContext* context, 46 bool do_validation = true) { 47 std::vector<uint32_t> bin; 48 context->module()->ToBinary(&bin, true); 49 if (do_validation) { 50 EXPECT_TRUE(Validate(bin)); 51 } 52 std::string assembly; 53 SpirvTools tools(SPV_ENV_UNIVERSAL_1_2); 54 EXPECT_TRUE( 55 tools.Disassemble(bin, &assembly, SpirvTools::kDefaultDisassembleOption)) 56 << "Disassembling failed for shader:\n" 57 << assembly << std::endl; 58 auto match_result = effcee::Match(assembly, original); 59 EXPECT_EQ(effcee::Result::Status::Ok, match_result.status()) 60 << match_result.message() << "\nChecking result:\n" 61 << assembly; 62 } 63 64 std::vector<std::unique_ptr<Type>> GenerateAllTypes() { 65 // Types in this test case are only equal to themselves, nothing else. 66 std::vector<std::unique_ptr<Type>> types; 67 68 // Void, Bool 69 types.emplace_back(new Void()); 70 auto* voidt = types.back().get(); 71 types.emplace_back(new Bool()); 72 auto* boolt = types.back().get(); 73 74 // Integer 75 types.emplace_back(new Integer(32, true)); 76 auto* s32 = types.back().get(); 77 types.emplace_back(new Integer(32, false)); 78 types.emplace_back(new Integer(64, true)); 79 types.emplace_back(new Integer(64, false)); 80 auto* u64 = types.back().get(); 81 82 // Float 83 types.emplace_back(new Float(32)); 84 auto* f32 = types.back().get(); 85 types.emplace_back(new Float(64)); 86 87 // Vector 88 types.emplace_back(new Vector(s32, 2)); 89 types.emplace_back(new Vector(s32, 3)); 90 auto* v3s32 = types.back().get(); 91 types.emplace_back(new Vector(u64, 4)); 92 types.emplace_back(new Vector(f32, 3)); 93 auto* v3f32 = types.back().get(); 94 95 // Matrix 96 types.emplace_back(new Matrix(v3s32, 3)); 97 types.emplace_back(new Matrix(v3s32, 4)); 98 types.emplace_back(new Matrix(v3f32, 4)); 99 100 // Images 101 types.emplace_back(new Image(s32, SpvDim2D, 0, 0, 0, 0, SpvImageFormatRg8, 102 SpvAccessQualifierReadOnly)); 103 auto* image1 = types.back().get(); 104 types.emplace_back(new Image(s32, SpvDim2D, 0, 1, 0, 0, SpvImageFormatRg8, 105 SpvAccessQualifierReadOnly)); 106 types.emplace_back(new Image(s32, SpvDim3D, 0, 1, 0, 0, SpvImageFormatRg8, 107 SpvAccessQualifierReadOnly)); 108 types.emplace_back(new Image(voidt, SpvDim3D, 0, 1, 0, 1, SpvImageFormatRg8, 109 SpvAccessQualifierReadWrite)); 110 auto* image2 = types.back().get(); 111 112 // Sampler 113 types.emplace_back(new Sampler()); 114 115 // Sampled Image 116 types.emplace_back(new SampledImage(image1)); 117 types.emplace_back(new SampledImage(image2)); 118 119 // Array 120 types.emplace_back(new Array(f32, 100)); 121 types.emplace_back(new Array(f32, 42)); 122 auto* a42f32 = types.back().get(); 123 types.emplace_back(new Array(u64, 24)); 124 125 // RuntimeArray 126 types.emplace_back(new RuntimeArray(v3f32)); 127 types.emplace_back(new RuntimeArray(v3s32)); 128 auto* rav3s32 = types.back().get(); 129 130 // Struct 131 types.emplace_back(new Struct(std::vector<const Type*>{s32})); 132 types.emplace_back(new Struct(std::vector<const Type*>{s32, f32})); 133 auto* sts32f32 = types.back().get(); 134 types.emplace_back( 135 new Struct(std::vector<const Type*>{u64, a42f32, rav3s32})); 136 137 // Opaque 138 types.emplace_back(new Opaque("")); 139 types.emplace_back(new Opaque("hello")); 140 types.emplace_back(new Opaque("world")); 141 142 // Pointer 143 types.emplace_back(new Pointer(f32, SpvStorageClassInput)); 144 types.emplace_back(new Pointer(sts32f32, SpvStorageClassFunction)); 145 types.emplace_back(new Pointer(a42f32, SpvStorageClassFunction)); 146 147 // Function 148 types.emplace_back(new Function(voidt, {})); 149 types.emplace_back(new Function(voidt, {boolt})); 150 types.emplace_back(new Function(voidt, {boolt, s32})); 151 types.emplace_back(new Function(s32, {boolt, s32})); 152 153 // Event, Device Event, Reserve Id, Queue, 154 types.emplace_back(new Event()); 155 types.emplace_back(new DeviceEvent()); 156 types.emplace_back(new ReserveId()); 157 types.emplace_back(new Queue()); 158 159 // Pipe, Forward Pointer, PipeStorage, NamedBarrier, AccelerationStructureNV 160 types.emplace_back(new Pipe(SpvAccessQualifierReadWrite)); 161 types.emplace_back(new Pipe(SpvAccessQualifierReadOnly)); 162 types.emplace_back(new ForwardPointer(1, SpvStorageClassInput)); 163 types.emplace_back(new ForwardPointer(2, SpvStorageClassInput)); 164 types.emplace_back(new ForwardPointer(2, SpvStorageClassUniform)); 165 types.emplace_back(new PipeStorage()); 166 types.emplace_back(new NamedBarrier()); 167 types.emplace_back(new AccelerationStructureNV()); 168 169 return types; 170 } 171 172 TEST(TypeManager, TypeStrings) { 173 const std::string text = R"( 174 OpTypeForwardPointer !20 !2 ; id for %p is 20, Uniform is 2 175 %void = OpTypeVoid 176 %bool = OpTypeBool 177 %u32 = OpTypeInt 32 0 178 %id4 = OpConstant %u32 4 179 %s32 = OpTypeInt 32 1 180 %f64 = OpTypeFloat 64 181 %v3u32 = OpTypeVector %u32 3 182 %m3x3 = OpTypeMatrix %v3u32 3 183 %img1 = OpTypeImage %s32 Cube 0 1 1 0 R32f ReadWrite 184 %img2 = OpTypeImage %s32 Cube 0 1 1 0 R32f 185 %sampler = OpTypeSampler 186 %si1 = OpTypeSampledImage %img1 187 %si2 = OpTypeSampledImage %img2 188 %a5u32 = OpTypeArray %u32 %id4 189 %af64 = OpTypeRuntimeArray %f64 190 %st1 = OpTypeStruct %u32 191 %st2 = OpTypeStruct %f64 %s32 %v3u32 192 %opaque1 = OpTypeOpaque "" 193 %opaque2 = OpTypeOpaque "opaque" 194 %p = OpTypePointer Uniform %st1 195 %f = OpTypeFunction %void %u32 %u32 196 %event = OpTypeEvent 197 %de = OpTypeDeviceEvent 198 %ri = OpTypeReserveId 199 %queue = OpTypeQueue 200 %pipe = OpTypePipe ReadOnly 201 %ps = OpTypePipeStorage 202 %nb = OpTypeNamedBarrier 203 )"; 204 205 std::vector<std::pair<uint32_t, std::string>> type_id_strs = { 206 {1, "void"}, 207 {2, "bool"}, 208 {3, "uint32"}, 209 // Id 4 is used by the constant. 210 {5, "sint32"}, 211 {6, "float64"}, 212 {7, "<uint32, 3>"}, 213 {8, "<<uint32, 3>, 3>"}, 214 {9, "image(sint32, 3, 0, 1, 1, 0, 3, 2)"}, 215 {10, "image(sint32, 3, 0, 1, 1, 0, 3, 0)"}, 216 {11, "sampler"}, 217 {12, "sampled_image(image(sint32, 3, 0, 1, 1, 0, 3, 2))"}, 218 {13, "sampled_image(image(sint32, 3, 0, 1, 1, 0, 3, 0))"}, 219 {14, "[uint32, id(4)]"}, 220 {15, "[float64]"}, 221 {16, "{uint32}"}, 222 {17, "{float64, sint32, <uint32, 3>}"}, 223 {18, "opaque('')"}, 224 {19, "opaque('opaque')"}, 225 {20, "{uint32}*"}, 226 {21, "(uint32, uint32) -> void"}, 227 {22, "event"}, 228 {23, "device_event"}, 229 {24, "reserve_id"}, 230 {25, "queue"}, 231 {26, "pipe(0)"}, 232 {27, "pipe_storage"}, 233 {28, "named_barrier"}, 234 }; 235 236 std::unique_ptr<IRContext> context = 237 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); 238 TypeManager manager(nullptr, context.get()); 239 240 EXPECT_EQ(type_id_strs.size(), manager.NumTypes()); 241 242 for (const auto& p : type_id_strs) { 243 EXPECT_EQ(p.second, manager.GetType(p.first)->str()); 244 EXPECT_EQ(p.first, manager.GetId(manager.GetType(p.first))); 245 } 246 } 247 248 TEST(TypeManager, StructWithFwdPtr) { 249 const std::string text = R"( 250 OpCapability Addresses 251 OpCapability Kernel 252 %1 = OpExtInstImport "OpenCL.std" 253 OpMemoryModel Physical64 OpenCL 254 OpEntryPoint Kernel %7 "test" 255 OpSource OpenCL_C 102000 256 OpDecorate %11 FuncParamAttr NoCapture 257 %11 = OpDecorationGroup 258 OpGroupDecorate %11 %8 %9 259 OpTypeForwardPointer %100 CrossWorkgroup 260 %void = OpTypeVoid 261 %150 = OpTypeStruct %100 262 %100 = OpTypePointer CrossWorkgroup %150 263 %6 = OpTypeFunction %void %100 %100 264 %7 = OpFunction %void Pure %6 265 %8 = OpFunctionParameter %100 266 %9 = OpFunctionParameter %100 267 %10 = OpLabel 268 OpReturn 269 OpFunctionEnd 270 )"; 271 272 std::unique_ptr<IRContext> context = 273 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 274 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 275 TypeManager manager(nullptr, context.get()); 276 277 Type* p100 = manager.GetType(100); 278 Type* s150 = manager.GetType(150); 279 280 EXPECT_TRUE(p100->AsPointer()); 281 EXPECT_EQ(p100->AsPointer()->pointee_type(), s150); 282 283 EXPECT_TRUE(s150->AsStruct()); 284 EXPECT_EQ(s150->AsStruct()->element_types()[0], p100); 285 } 286 287 TEST(TypeManager, CircularFwdPtr) { 288 const std::string text = R"( 289 OpCapability Addresses 290 OpCapability Kernel 291 %1 = OpExtInstImport "OpenCL.std" 292 OpMemoryModel Physical64 OpenCL 293 OpEntryPoint Kernel %7 "test" 294 OpSource OpenCL_C 102000 295 OpDecorate %11 FuncParamAttr NoCapture 296 %11 = OpDecorationGroup 297 OpGroupDecorate %11 %8 %9 298 OpTypeForwardPointer %100 CrossWorkgroup 299 OpTypeForwardPointer %200 CrossWorkgroup 300 %void = OpTypeVoid 301 %int = OpTypeInt 32 0 302 %float = OpTypeFloat 32 303 %150 = OpTypeStruct %200 %int 304 %250 = OpTypeStruct %100 %float 305 %100 = OpTypePointer CrossWorkgroup %150 306 %200 = OpTypePointer CrossWorkgroup %250 307 %6 = OpTypeFunction %void %100 %200 308 %7 = OpFunction %void Pure %6 309 %8 = OpFunctionParameter %100 310 %9 = OpFunctionParameter %200 311 %10 = OpLabel 312 OpReturn 313 OpFunctionEnd 314 )"; 315 316 std::unique_ptr<IRContext> context = 317 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 318 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 319 TypeManager manager(nullptr, context.get()); 320 321 Type* p100 = manager.GetType(100); 322 Type* s150 = manager.GetType(150); 323 Type* p200 = manager.GetType(200); 324 Type* s250 = manager.GetType(250); 325 326 EXPECT_TRUE(p100->AsPointer()); 327 EXPECT_EQ(p100->AsPointer()->pointee_type(), s150); 328 329 EXPECT_TRUE(p200->AsPointer()); 330 EXPECT_EQ(p200->AsPointer()->pointee_type(), s250); 331 332 EXPECT_TRUE(s150->AsStruct()); 333 EXPECT_EQ(s150->AsStruct()->element_types()[0], p200); 334 335 EXPECT_TRUE(s250->AsStruct()); 336 EXPECT_EQ(s250->AsStruct()->element_types()[0], p100); 337 } 338 339 TEST(TypeManager, IsomorphicStructWithFwdPtr) { 340 const std::string text = R"( 341 OpCapability Addresses 342 OpCapability Kernel 343 %1 = OpExtInstImport "OpenCL.std" 344 OpMemoryModel Physical64 OpenCL 345 OpEntryPoint Kernel %7 "test" 346 OpSource OpenCL_C 102000 347 OpDecorate %11 FuncParamAttr NoCapture 348 %11 = OpDecorationGroup 349 OpGroupDecorate %11 %8 %9 350 OpTypeForwardPointer %100 CrossWorkgroup 351 OpTypeForwardPointer %200 CrossWorkgroup 352 %void = OpTypeVoid 353 %_struct_1 = OpTypeStruct %100 354 %_struct_2 = OpTypeStruct %200 355 %100 = OpTypePointer CrossWorkgroup %_struct_1 356 %200 = OpTypePointer CrossWorkgroup %_struct_2 357 %6 = OpTypeFunction %void %100 %200 358 %7 = OpFunction %void Pure %6 359 %8 = OpFunctionParameter %100 360 %9 = OpFunctionParameter %200 361 %10 = OpLabel 362 OpReturn 363 OpFunctionEnd 364 )"; 365 366 std::unique_ptr<IRContext> context = 367 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 368 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 369 TypeManager manager(nullptr, context.get()); 370 371 EXPECT_EQ(manager.GetType(100), manager.GetType(200)); 372 } 373 374 TEST(TypeManager, IsomorphicCircularFwdPtr) { 375 const std::string text = R"( 376 OpCapability Addresses 377 OpCapability Kernel 378 %1 = OpExtInstImport "OpenCL.std" 379 OpMemoryModel Physical64 OpenCL 380 OpEntryPoint Kernel %7 "test" 381 OpSource OpenCL_C 102000 382 OpDecorate %11 FuncParamAttr NoCapture 383 %11 = OpDecorationGroup 384 OpGroupDecorate %11 %8 %9 385 OpTypeForwardPointer %100 CrossWorkgroup 386 OpTypeForwardPointer %200 CrossWorkgroup 387 OpTypeForwardPointer %300 CrossWorkgroup 388 OpTypeForwardPointer %400 CrossWorkgroup 389 %void = OpTypeVoid 390 %int = OpTypeInt 32 0 391 %float = OpTypeFloat 32 392 %150 = OpTypeStruct %200 %int 393 %250 = OpTypeStruct %100 %float 394 %350 = OpTypeStruct %400 %int 395 %450 = OpTypeStruct %300 %float 396 %100 = OpTypePointer CrossWorkgroup %150 397 %200 = OpTypePointer CrossWorkgroup %250 398 %300 = OpTypePointer CrossWorkgroup %350 399 %400 = OpTypePointer CrossWorkgroup %450 400 %6 = OpTypeFunction %void %100 %200 401 %7 = OpFunction %void Pure %6 402 %8 = OpFunctionParameter %100 403 %9 = OpFunctionParameter %200 404 %10 = OpLabel 405 OpReturn 406 OpFunctionEnd 407 )"; 408 409 std::unique_ptr<IRContext> context = 410 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 411 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 412 TypeManager manager(nullptr, context.get()); 413 414 Type* p100 = manager.GetType(100); 415 Type* p300 = manager.GetType(300); 416 EXPECT_EQ(p100, p300); 417 Type* p200 = manager.GetType(200); 418 Type* p400 = manager.GetType(400); 419 EXPECT_EQ(p200, p400); 420 421 Type* p150 = manager.GetType(150); 422 Type* p350 = manager.GetType(350); 423 EXPECT_EQ(p150, p350); 424 Type* p250 = manager.GetType(250); 425 Type* p450 = manager.GetType(450); 426 EXPECT_EQ(p250, p450); 427 } 428 429 TEST(TypeManager, PartialIsomorphicFwdPtr) { 430 const std::string text = R"( 431 OpCapability Addresses 432 OpCapability Kernel 433 %1 = OpExtInstImport "OpenCL.std" 434 OpMemoryModel Physical64 OpenCL 435 OpEntryPoint Kernel %7 "test" 436 OpSource OpenCL_C 102000 437 OpDecorate %11 FuncParamAttr NoCapture 438 %11 = OpDecorationGroup 439 OpGroupDecorate %11 %8 %9 440 OpTypeForwardPointer %100 CrossWorkgroup 441 OpTypeForwardPointer %200 CrossWorkgroup 442 %void = OpTypeVoid 443 %int = OpTypeInt 32 0 444 %float = OpTypeFloat 32 445 %150 = OpTypeStruct %200 %int 446 %250 = OpTypeStruct %200 %int 447 %100 = OpTypePointer CrossWorkgroup %150 448 %200 = OpTypePointer CrossWorkgroup %250 449 %6 = OpTypeFunction %void %100 %200 450 %7 = OpFunction %void Pure %6 451 %8 = OpFunctionParameter %100 452 %9 = OpFunctionParameter %200 453 %10 = OpLabel 454 OpReturn 455 OpFunctionEnd 456 )"; 457 458 std::unique_ptr<IRContext> context = 459 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 460 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 461 TypeManager manager(nullptr, context.get()); 462 463 Type* p100 = manager.GetType(100); 464 Type* p200 = manager.GetType(200); 465 EXPECT_EQ(p100->AsPointer()->pointee_type(), 466 p200->AsPointer()->pointee_type()); 467 } 468 469 TEST(TypeManager, DecorationOnStruct) { 470 const std::string text = R"( 471 OpDecorate %struct1 Block 472 OpDecorate %struct2 Block 473 OpDecorate %struct3 Block 474 OpDecorate %struct4 Block 475 476 %u32 = OpTypeInt 32 0 ; id: 5 477 %f32 = OpTypeFloat 32 ; id: 6 478 %struct1 = OpTypeStruct %u32 %f32 ; base 479 %struct2 = OpTypeStruct %f32 %u32 ; different member order 480 %struct3 = OpTypeStruct %f32 ; different member list 481 %struct4 = OpTypeStruct %u32 %f32 ; the same 482 %struct7 = OpTypeStruct %f32 ; no decoration 483 )"; 484 std::unique_ptr<IRContext> context = 485 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); 486 TypeManager manager(nullptr, context.get()); 487 488 ASSERT_EQ(7u, manager.NumTypes()); 489 // Make sure we get ids correct. 490 ASSERT_EQ("uint32", manager.GetType(5)->str()); 491 ASSERT_EQ("float32", manager.GetType(6)->str()); 492 493 // Try all combinations of pairs. Expect to be the same type only when the 494 // same id or (1, 4). 495 for (const auto id1 : {1, 2, 3, 4, 7}) { 496 for (const auto id2 : {1, 2, 3, 4, 7}) { 497 if (id1 == id2 || (id1 == 1 && id2 == 4) || (id1 == 4 && id2 == 1)) { 498 EXPECT_TRUE(manager.GetType(id1)->IsSame(manager.GetType(id2))) 499 << "%struct" << id1 << " is expected to be the same as %struct" 500 << id2; 501 } else { 502 EXPECT_FALSE(manager.GetType(id1)->IsSame(manager.GetType(id2))) 503 << "%struct" << id1 << " is expected to be different with %struct" 504 << id2; 505 } 506 } 507 } 508 } 509 510 TEST(TypeManager, DecorationOnMember) { 511 const std::string text = R"( 512 OpMemberDecorate %struct1 0 Offset 0 513 OpMemberDecorate %struct2 0 Offset 0 514 OpMemberDecorate %struct3 0 Offset 0 515 OpMemberDecorate %struct4 0 Offset 0 516 OpMemberDecorate %struct5 1 Offset 0 517 OpMemberDecorate %struct6 0 Offset 4 518 519 OpDecorate %struct7 Block 520 OpMemberDecorate %struct7 0 Offset 0 521 522 %u32 = OpTypeInt 32 0 ; id: 8 523 %f32 = OpTypeFloat 32 ; id: 9 524 %struct1 = OpTypeStruct %u32 %f32 ; base 525 %struct2 = OpTypeStruct %f32 %u32 ; different member order 526 %struct3 = OpTypeStruct %f32 ; different member list 527 %struct4 = OpTypeStruct %u32 %f32 ; the same 528 %struct5 = OpTypeStruct %u32 %f32 ; member decorate different field 529 %struct6 = OpTypeStruct %u32 %f32 ; different member decoration parameter 530 %struct7 = OpTypeStruct %u32 %f32 ; extra decoration on the struct 531 %struct10 = OpTypeStruct %u32 %f32 ; no member decoration 532 )"; 533 std::unique_ptr<IRContext> context = 534 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); 535 TypeManager manager(nullptr, context.get()); 536 537 ASSERT_EQ(10u, manager.NumTypes()); 538 // Make sure we get ids correct. 539 ASSERT_EQ("uint32", manager.GetType(8)->str()); 540 ASSERT_EQ("float32", manager.GetType(9)->str()); 541 542 // Try all combinations of pairs. Expect to be the same type only when the 543 // same id or (1, 4). 544 for (const auto id1 : {1, 2, 3, 4, 5, 6, 7, 10}) { 545 for (const auto id2 : {1, 2, 3, 4, 5, 6, 7, 10}) { 546 if (id1 == id2 || (id1 == 1 && id2 == 4) || (id1 == 4 && id2 == 1)) { 547 EXPECT_TRUE(manager.GetType(id1)->IsSame(manager.GetType(id2))) 548 << "%struct" << id1 << " is expected to be the same as %struct" 549 << id2; 550 } else { 551 EXPECT_FALSE(manager.GetType(id1)->IsSame(manager.GetType(id2))) 552 << "%struct" << id1 << " is expected to be different with %struct" 553 << id2; 554 } 555 } 556 } 557 } 558 559 TEST(TypeManager, DecorationEmpty) { 560 const std::string text = R"( 561 OpDecorate %struct1 Block 562 OpMemberDecorate %struct2 0 Offset 0 563 564 %u32 = OpTypeInt 32 0 ; id: 3 565 %f32 = OpTypeFloat 32 ; id: 4 566 %struct1 = OpTypeStruct %u32 %f32 567 %struct2 = OpTypeStruct %f32 %u32 568 %struct5 = OpTypeStruct %f32 569 )"; 570 std::unique_ptr<IRContext> context = 571 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); 572 TypeManager manager(nullptr, context.get()); 573 574 ASSERT_EQ(5u, manager.NumTypes()); 575 // Make sure we get ids correct. 576 ASSERT_EQ("uint32", manager.GetType(3)->str()); 577 ASSERT_EQ("float32", manager.GetType(4)->str()); 578 579 // %struct1 with decoration on itself 580 EXPECT_FALSE(manager.GetType(1)->decoration_empty()); 581 // %struct2 with decoration on its member 582 EXPECT_FALSE(manager.GetType(2)->decoration_empty()); 583 EXPECT_TRUE(manager.GetType(3)->decoration_empty()); 584 EXPECT_TRUE(manager.GetType(4)->decoration_empty()); 585 // %struct5 has no decorations 586 EXPECT_TRUE(manager.GetType(5)->decoration_empty()); 587 } 588 589 TEST(TypeManager, BeginEndForEmptyModule) { 590 const std::string text = ""; 591 std::unique_ptr<IRContext> context = 592 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); 593 TypeManager manager(nullptr, context.get()); 594 ASSERT_EQ(0u, manager.NumTypes()); 595 596 EXPECT_EQ(manager.begin(), manager.end()); 597 } 598 599 TEST(TypeManager, BeginEnd) { 600 const std::string text = R"( 601 %void1 = OpTypeVoid 602 %void2 = OpTypeVoid 603 %bool = OpTypeBool 604 %u32 = OpTypeInt 32 0 605 %f64 = OpTypeFloat 64 606 )"; 607 std::unique_ptr<IRContext> context = 608 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text); 609 TypeManager manager(nullptr, context.get()); 610 ASSERT_EQ(5u, manager.NumTypes()); 611 612 EXPECT_NE(manager.begin(), manager.end()); 613 for (const auto& t : manager) { 614 switch (t.first) { 615 case 1: 616 case 2: 617 EXPECT_EQ("void", t.second->str()); 618 break; 619 case 3: 620 EXPECT_EQ("bool", t.second->str()); 621 break; 622 case 4: 623 EXPECT_EQ("uint32", t.second->str()); 624 break; 625 case 5: 626 EXPECT_EQ("float64", t.second->str()); 627 break; 628 default: 629 EXPECT_TRUE(false && "unreachable"); 630 break; 631 } 632 } 633 } 634 635 TEST(TypeManager, LookupType) { 636 const std::string text = R"( 637 %void = OpTypeVoid 638 %uint = OpTypeInt 32 0 639 %int = OpTypeInt 32 1 640 %vec2 = OpTypeVector %int 2 641 )"; 642 643 std::unique_ptr<IRContext> context = 644 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 645 EXPECT_NE(context, nullptr); 646 TypeManager manager(nullptr, context.get()); 647 648 Void voidTy; 649 EXPECT_EQ(manager.GetId(&voidTy), 1u); 650 651 Integer uintTy(32, false); 652 EXPECT_EQ(manager.GetId(&uintTy), 2u); 653 654 Integer intTy(32, true); 655 EXPECT_EQ(manager.GetId(&intTy), 3u); 656 657 Integer intTy2(32, true); 658 Vector vecTy(&intTy2, 2u); 659 EXPECT_EQ(manager.GetId(&vecTy), 4u); 660 } 661 662 TEST(TypeManager, RemoveId) { 663 const std::string text = R"( 664 OpCapability Shader 665 OpCapability Linkage 666 OpMemoryModel Logical GLSL450 667 %1 = OpTypeInt 32 0 668 %2 = OpTypeInt 32 1 669 )"; 670 671 std::unique_ptr<IRContext> context = 672 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 673 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 674 EXPECT_NE(context, nullptr); 675 676 context->get_type_mgr()->RemoveId(1u); 677 ASSERT_EQ(context->get_type_mgr()->GetType(1u), nullptr); 678 ASSERT_NE(context->get_type_mgr()->GetType(2u), nullptr); 679 680 context->get_type_mgr()->RemoveId(2u); 681 ASSERT_EQ(context->get_type_mgr()->GetType(1u), nullptr); 682 ASSERT_EQ(context->get_type_mgr()->GetType(2u), nullptr); 683 } 684 685 TEST(TypeManager, RemoveIdNonDuplicateAmbiguousType) { 686 const std::string text = R"( 687 OpCapability Shader 688 OpCapability Linkage 689 OpMemoryModel Logical GLSL450 690 %1 = OpTypeInt 32 0 691 %2 = OpTypeStruct %1 692 )"; 693 694 std::unique_ptr<IRContext> context = 695 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 696 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 697 EXPECT_NE(context, nullptr); 698 699 Integer u32(32, false); 700 Struct st({&u32}); 701 ASSERT_EQ(context->get_type_mgr()->GetId(&st), 2u); 702 context->get_type_mgr()->RemoveId(2u); 703 ASSERT_EQ(context->get_type_mgr()->GetType(2u), nullptr); 704 ASSERT_EQ(context->get_type_mgr()->GetId(&st), 0u); 705 } 706 707 TEST(TypeManager, RemoveIdDuplicateAmbiguousType) { 708 const std::string text = R"( 709 OpCapability Shader 710 OpCapability Linkage 711 OpMemoryModel Logical GLSL450 712 %1 = OpTypeInt 32 0 713 %2 = OpTypeStruct %1 714 %3 = OpTypeStruct %1 715 )"; 716 717 std::unique_ptr<IRContext> context = 718 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 719 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 720 EXPECT_NE(context, nullptr); 721 722 Integer u32(32, false); 723 Struct st({&u32}); 724 uint32_t id = context->get_type_mgr()->GetId(&st); 725 ASSERT_NE(id, 0u); 726 uint32_t toRemove = id == 2u ? 2u : 3u; 727 uint32_t toStay = id == 2u ? 3u : 2u; 728 context->get_type_mgr()->RemoveId(toRemove); 729 ASSERT_EQ(context->get_type_mgr()->GetType(toRemove), nullptr); 730 ASSERT_EQ(context->get_type_mgr()->GetId(&st), toStay); 731 } 732 733 TEST(TypeManager, RemoveIdDoesntUnmapOtherTypes) { 734 const std::string text = R"( 735 OpCapability Shader 736 OpMemoryModel Logical GLSL450 737 %1 = OpTypeInt 32 0 738 %2 = OpTypeStruct %1 739 %3 = OpTypeStruct %1 740 )"; 741 742 std::unique_ptr<IRContext> context = 743 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 744 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 745 EXPECT_NE(context, nullptr); 746 747 Integer u32(32, false); 748 Struct st({&u32}); 749 750 EXPECT_EQ(1u, context->get_type_mgr()->GetId(&u32)); 751 uint32_t id = context->get_type_mgr()->GetId(&st); 752 ASSERT_NE(id, 0u); 753 uint32_t toRemove = id == 2u ? 3u : 2u; 754 uint32_t toStay = id == 2u ? 2u : 3u; 755 context->get_type_mgr()->RemoveId(toRemove); 756 ASSERT_EQ(context->get_type_mgr()->GetType(toRemove), nullptr); 757 ASSERT_EQ(context->get_type_mgr()->GetId(&st), toStay); 758 } 759 760 TEST(TypeManager, GetTypeAndPointerType) { 761 const std::string text = R"( 762 OpCapability Shader 763 OpCapability Linkage 764 OpMemoryModel Logical GLSL450 765 %1 = OpTypeInt 32 0 766 %2 = OpTypeStruct %1 767 )"; 768 769 std::unique_ptr<IRContext> context = 770 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 771 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 772 EXPECT_NE(context, nullptr); 773 774 Integer u32(32, false); 775 Pointer u32Ptr(&u32, SpvStorageClassFunction); 776 Struct st({&u32}); 777 Pointer stPtr(&st, SpvStorageClassInput); 778 779 auto pair = context->get_type_mgr()->GetTypeAndPointerType( 780 3u, SpvStorageClassFunction); 781 ASSERT_EQ(nullptr, pair.first); 782 ASSERT_EQ(nullptr, pair.second); 783 784 pair = context->get_type_mgr()->GetTypeAndPointerType( 785 1u, SpvStorageClassFunction); 786 ASSERT_TRUE(pair.first->IsSame(&u32)); 787 ASSERT_TRUE(pair.second->IsSame(&u32Ptr)); 788 789 pair = 790 context->get_type_mgr()->GetTypeAndPointerType(2u, SpvStorageClassInput); 791 ASSERT_TRUE(pair.first->IsSame(&st)); 792 ASSERT_TRUE(pair.second->IsSame(&stPtr)); 793 } 794 795 TEST(TypeManager, DuplicateType) { 796 const std::string text = R"( 797 OpCapability Shader 798 OpMemoryModel Logical GLSL450 799 %1 = OpTypeInt 32 0 800 %2 = OpTypeInt 32 0 801 )"; 802 803 std::unique_ptr<IRContext> context = 804 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 805 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 806 EXPECT_NE(context, nullptr); 807 808 const Type* type1 = context->get_type_mgr()->GetType(1u); 809 const Type* type2 = context->get_type_mgr()->GetType(2u); 810 EXPECT_NE(type1, nullptr); 811 EXPECT_NE(type2, nullptr); 812 EXPECT_EQ(*type1, *type2); 813 } 814 815 TEST(TypeManager, MultipleStructs) { 816 const std::string text = R"( 817 OpCapability Shader 818 OpMemoryModel Logical GLSL450 819 OpDecorate %3 Constant 820 %1 = OpTypeInt 32 0 821 %2 = OpTypeStruct %1 822 %3 = OpTypeStruct %1 823 )"; 824 825 std::unique_ptr<IRContext> context = 826 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 827 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 828 EXPECT_NE(context, nullptr); 829 830 const Type* type1 = context->get_type_mgr()->GetType(2u); 831 const Type* type2 = context->get_type_mgr()->GetType(3u); 832 EXPECT_NE(type1, nullptr); 833 EXPECT_NE(type2, nullptr); 834 EXPECT_FALSE(type1->IsSame(type2)); 835 } 836 837 TEST(TypeManager, RemovingIdAvoidsUseAfterFree) { 838 const std::string text = R"( 839 OpCapability Shader 840 OpMemoryModel Logical GLSL450 841 %1 = OpTypeInt 32 0 842 %2 = OpTypeStruct %1 843 )"; 844 845 std::unique_ptr<IRContext> context = 846 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 847 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 848 EXPECT_NE(context, nullptr); 849 850 Integer u32(32, false); 851 Struct st({&u32}); 852 const Type* type = context->get_type_mgr()->GetType(2u); 853 EXPECT_NE(type, nullptr); 854 context->get_type_mgr()->RemoveId(1u); 855 EXPECT_TRUE(type->IsSame(&st)); 856 } 857 858 TEST(TypeManager, RegisterAndRemoveId) { 859 const std::string text = R"( 860 OpCapability Shader 861 OpMemoryModel Logical GLSL450 862 %1 = OpTypeInt 32 0 863 )"; 864 865 std::unique_ptr<IRContext> context = 866 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 867 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 868 EXPECT_NE(context, nullptr); 869 870 uint32_t id = 2u; 871 { 872 // Ensure that u32 goes out of scope. 873 Integer u32(32, false); 874 Struct st({&u32}); 875 context->get_type_mgr()->RegisterType(id, st); 876 } 877 878 context->get_type_mgr()->RemoveId(id); 879 EXPECT_EQ(nullptr, context->get_type_mgr()->GetType(id)); 880 } 881 882 TEST(TypeManager, RegisterAndRemoveIdAllTypes) { 883 const std::string text = R"( 884 OpCapability Shader 885 OpMemoryModel Logical GLSL450 886 )"; 887 888 std::unique_ptr<IRContext> context = 889 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 890 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 891 EXPECT_NE(context, nullptr); 892 893 std::vector<std::unique_ptr<Type>> types = GenerateAllTypes(); 894 uint32_t id = 1u; 895 for (auto& t : types) { 896 context->get_type_mgr()->RegisterType(id, *t); 897 EXPECT_EQ(*t, *context->get_type_mgr()->GetType(id)); 898 } 899 types.clear(); 900 901 for (; id > 0; --id) { 902 context->get_type_mgr()->RemoveId(id); 903 EXPECT_EQ(nullptr, context->get_type_mgr()->GetType(id)); 904 } 905 } 906 907 TEST(TypeManager, RegisterAndRemoveIdWithDecorations) { 908 const std::string text = R"( 909 OpCapability Shader 910 OpMemoryModel Logical GLSL450 911 %1 = OpTypeInt 32 0 912 )"; 913 914 std::unique_ptr<IRContext> context = 915 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 916 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 917 EXPECT_NE(context, nullptr); 918 919 uint32_t id = 2u; 920 { 921 Integer u32(32, false); 922 Struct st({&u32, &u32}); 923 st.AddDecoration({10}); 924 st.AddDecoration({11}); 925 st.AddMemberDecoration(0, {{35, 4}}); 926 st.AddMemberDecoration(1, {{35, 4}}); 927 st.AddMemberDecoration(1, {{36, 5}}); 928 context->get_type_mgr()->RegisterType(id, st); 929 EXPECT_EQ(st, *context->get_type_mgr()->GetType(id)); 930 } 931 932 context->get_type_mgr()->RemoveId(id); 933 EXPECT_EQ(nullptr, context->get_type_mgr()->GetType(id)); 934 } 935 936 TEST(TypeManager, GetTypeInstructionInt) { 937 const std::string text = R"( 938 ; CHECK: OpTypeInt 32 0 939 ; CHECK: OpTypeInt 16 1 940 OpCapability Shader 941 OpCapability Int16 942 OpCapability Linkage 943 OpMemoryModel Logical GLSL450 944 )"; 945 946 std::unique_ptr<IRContext> context = 947 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 948 EXPECT_NE(context, nullptr); 949 950 Integer uint_32(32, false); 951 context->get_type_mgr()->GetTypeInstruction(&uint_32); 952 953 Integer int_16(16, true); 954 context->get_type_mgr()->GetTypeInstruction(&int_16); 955 956 Match(text, context.get()); 957 } 958 959 TEST(TypeManager, GetTypeInstructionDuplicateInts) { 960 const std::string text = R"( 961 ; CHECK: OpTypeInt 32 0 962 ; CHECK-NOT: OpType 963 OpCapability Shader 964 OpCapability Linkage 965 OpMemoryModel Logical GLSL450 966 )"; 967 968 std::unique_ptr<IRContext> context = 969 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text); 970 EXPECT_NE(context, nullptr); 971 972 Integer uint_32(32, false); 973 uint32_t id = context->get_type_mgr()->GetTypeInstruction(&uint_32); 974 975 Integer other(32, false); 976 EXPECT_EQ(context->get_type_mgr()->GetTypeInstruction(&other), id); 977 978 Match(text, context.get()); 979 } 980 981 TEST(TypeManager, GetTypeInstructionAllTypes) { 982 const std::string text = R"( 983 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 984 ; CHECK: [[input_ptr:%\w+]] = OpTypePointer Input [[uint]] 985 ; CHECK: [[uniform_ptr:%\w+]] = OpTypePointer Uniform [[uint]] 986 ; CHECK: [[uint24:%\w+]] = OpConstant [[uint]] 24 987 ; CHECK: [[uint42:%\w+]] = OpConstant [[uint]] 42 988 ; CHECK: [[uint100:%\w+]] = OpConstant [[uint]] 100 989 ; CHECK: [[void:%\w+]] = OpTypeVoid 990 ; CHECK: [[bool:%\w+]] = OpTypeBool 991 ; CHECK: [[s32:%\w+]] = OpTypeInt 32 1 992 ; CHECK: OpTypeInt 64 1 993 ; CHECK: [[u64:%\w+]] = OpTypeInt 64 0 994 ; CHECK: [[f32:%\w+]] = OpTypeFloat 32 995 ; CHECK: OpTypeFloat 64 996 ; CHECK: OpTypeVector [[s32]] 2 997 ; CHECK: [[v3s32:%\w+]] = OpTypeVector [[s32]] 3 998 ; CHECK: OpTypeVector [[u64]] 4 999 ; CHECK: [[v3f32:%\w+]] = OpTypeVector [[f32]] 3 1000 ; CHECK: OpTypeMatrix [[v3s32]] 3 1001 ; CHECK: OpTypeMatrix [[v3s32]] 4 1002 ; CHECK: OpTypeMatrix [[v3f32]] 4 1003 ; CHECK: [[image1:%\w+]] = OpTypeImage [[s32]] 2D 0 0 0 0 Rg8 ReadOnly 1004 ; CHECK: OpTypeImage [[s32]] 2D 0 1 0 0 Rg8 ReadOnly 1005 ; CHECK: OpTypeImage [[s32]] 3D 0 1 0 0 Rg8 ReadOnly 1006 ; CHECK: [[image2:%\w+]] = OpTypeImage [[void]] 3D 0 1 0 1 Rg8 ReadWrite 1007 ; CHECK: OpTypeSampler 1008 ; CHECK: OpTypeSampledImage [[image1]] 1009 ; CHECK: OpTypeSampledImage [[image2]] 1010 ; CHECK: OpTypeArray [[f32]] [[uint100]] 1011 ; CHECK: [[a42f32:%\w+]] = OpTypeArray [[f32]] [[uint42]] 1012 ; CHECK: OpTypeArray [[u64]] [[uint24]] 1013 ; CHECK: OpTypeRuntimeArray [[v3f32]] 1014 ; CHECK: [[rav3s32:%\w+]] = OpTypeRuntimeArray [[v3s32]] 1015 ; CHECK: OpTypeStruct [[s32]] 1016 ; CHECK: [[sts32f32:%\w+]] = OpTypeStruct [[s32]] [[f32]] 1017 ; CHECK: OpTypeStruct [[u64]] [[a42f32]] [[rav3s32]] 1018 ; CHECK: OpTypeOpaque "" 1019 ; CHECK: OpTypeOpaque "hello" 1020 ; CHECK: OpTypeOpaque "world" 1021 ; CHECK: OpTypePointer Input [[f32]] 1022 ; CHECK: OpTypePointer Function [[sts32f32]] 1023 ; CHECK: OpTypePointer Function [[a42f32]] 1024 ; CHECK: OpTypeFunction [[void]] 1025 ; CHECK: OpTypeFunction [[void]] [[bool]] 1026 ; CHECK: OpTypeFunction [[void]] [[bool]] [[s32]] 1027 ; CHECK: OpTypeFunction [[s32]] [[bool]] [[s32]] 1028 ; CHECK: OpTypeEvent 1029 ; CHECK: OpTypeDeviceEvent 1030 ; CHECK: OpTypeReserveId 1031 ; CHECK: OpTypeQueue 1032 ; CHECK: OpTypePipe ReadWrite 1033 ; CHECK: OpTypePipe ReadOnly 1034 ; CHECK: OpTypeForwardPointer [[input_ptr]] Input 1035 ; CHECK: OpTypeForwardPointer [[uniform_ptr]] Input 1036 ; CHECK: OpTypeForwardPointer [[uniform_ptr]] Uniform 1037 ; CHECK: OpTypePipeStorage 1038 ; CHECK: OpTypeNamedBarrier 1039 ; CHECK: OpTypeAccelerationStructureNV 1040 OpCapability Shader 1041 OpCapability Int64 1042 OpCapability Linkage 1043 OpMemoryModel Logical GLSL450 1044 %uint = OpTypeInt 32 0 1045 %1 = OpTypePointer Input %uint 1046 %2 = OpTypePointer Uniform %uint 1047 %24 = OpConstant %uint 24 1048 %42 = OpConstant %uint 42 1049 %100 = OpConstant %uint 100 1050 )"; 1051 1052 std::unique_ptr<IRContext> context = 1053 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 1054 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1055 EXPECT_NE(context, nullptr); 1056 1057 std::vector<std::unique_ptr<Type>> types = GenerateAllTypes(); 1058 for (auto& t : types) { 1059 context->get_type_mgr()->GetTypeInstruction(t.get()); 1060 } 1061 1062 Match(text, context.get(), false); 1063 } 1064 1065 TEST(TypeManager, GetTypeInstructionWithDecorations) { 1066 const std::string text = R"( 1067 ; CHECK: OpDecorate [[struct:%\w+]] CPacked 1068 ; CHECK: OpMemberDecorate [[struct]] 1 Offset 4 1069 ; CHECK: [[uint:%\w+]] = OpTypeInt 32 0 1070 ; CHECK: [[struct]] = OpTypeStruct [[uint]] [[uint]] 1071 OpCapability Shader 1072 OpCapability Kernel 1073 OpCapability Linkage 1074 OpMemoryModel Logical GLSL450 1075 %uint = OpTypeInt 32 0 1076 )"; 1077 1078 std::unique_ptr<IRContext> context = 1079 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 1080 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1081 EXPECT_NE(context, nullptr); 1082 1083 Integer u32(32, false); 1084 Struct st({&u32, &u32}); 1085 st.AddDecoration({10}); 1086 st.AddMemberDecoration(1, {{35, 4}}); 1087 (void)context->get_def_use_mgr(); 1088 context->get_type_mgr()->GetTypeInstruction(&st); 1089 1090 Match(text, context.get()); 1091 } 1092 1093 TEST(TypeManager, GetPointerToAmbiguousType1) { 1094 const std::string text = R"( 1095 ; CHECK: [[struct1:%\w+]] = OpTypeStruct 1096 ; CHECK: [[struct2:%\w+]] = OpTypeStruct 1097 ; CHECK: OpTypePointer Function [[struct2]] 1098 ; CHECK: OpTypePointer Function [[struct1]] 1099 OpCapability Shader 1100 OpCapability Kernel 1101 OpCapability Linkage 1102 OpMemoryModel Logical GLSL450 1103 %uint = OpTypeInt 32 0 1104 %1 = OpTypeStruct %uint 1105 %2 = OpTypeStruct %uint 1106 %3 = OpTypePointer Function %2 1107 )"; 1108 1109 std::unique_ptr<IRContext> context = 1110 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 1111 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1112 EXPECT_NE(context, nullptr); 1113 1114 context->get_type_mgr()->FindPointerToType(1, SpvStorageClassFunction); 1115 Match(text, context.get()); 1116 } 1117 1118 TEST(TypeManager, GetPointerToAmbiguousType2) { 1119 const std::string text = R"( 1120 ; CHECK: [[struct1:%\w+]] = OpTypeStruct 1121 ; CHECK: [[struct2:%\w+]] = OpTypeStruct 1122 ; CHECK: OpTypePointer Function [[struct1]] 1123 ; CHECK: OpTypePointer Function [[struct2]] 1124 OpCapability Shader 1125 OpCapability Kernel 1126 OpCapability Linkage 1127 OpMemoryModel Logical GLSL450 1128 %uint = OpTypeInt 32 0 1129 %1 = OpTypeStruct %uint 1130 %2 = OpTypeStruct %uint 1131 %3 = OpTypePointer Function %1 1132 )"; 1133 1134 std::unique_ptr<IRContext> context = 1135 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text, 1136 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 1137 EXPECT_NE(context, nullptr); 1138 1139 context->get_type_mgr()->FindPointerToType(2, SpvStorageClassFunction); 1140 Match(text, context.get()); 1141 } 1142 1143 } // namespace 1144 } // namespace analysis 1145 } // namespace opt 1146 } // namespace spvtools 1147