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