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