Home | History | Annotate | Download | only in opt
      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