• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "gmock/gmock.h"
21 #include "source/opt/instruction.h"
22 #include "source/opt/ir_context.h"
23 #include "spirv-tools/libspirv.h"
24 #include "test/opt/pass_fixture.h"
25 #include "test/opt/pass_utils.h"
26 #include "test/unit_spirv.h"
27 
28 namespace spvtools {
29 namespace opt {
30 namespace {
31 
32 using spvtest::MakeInstruction;
33 using ::testing::Eq;
34 using DescriptorTypeTest = PassTest<::testing::Test>;
35 using OpaqueTypeTest = PassTest<::testing::Test>;
36 using GetBaseTest = PassTest<::testing::Test>;
37 using ValidBasePointerTest = PassTest<::testing::Test>;
38 using VulkanBufferTest = PassTest<::testing::Test>;
39 
TEST(InstructionTest,CreateTrivial)40 TEST(InstructionTest, CreateTrivial) {
41   Instruction empty;
42   EXPECT_EQ(SpvOpNop, empty.opcode());
43   EXPECT_EQ(0u, empty.type_id());
44   EXPECT_EQ(0u, empty.result_id());
45   EXPECT_EQ(0u, empty.NumOperands());
46   EXPECT_EQ(0u, empty.NumOperandWords());
47   EXPECT_EQ(0u, empty.NumInOperandWords());
48   EXPECT_EQ(empty.cend(), empty.cbegin());
49   EXPECT_EQ(empty.end(), empty.begin());
50 }
51 
TEST(InstructionTest,CreateWithOpcodeAndNoOperands)52 TEST(InstructionTest, CreateWithOpcodeAndNoOperands) {
53   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
54   Instruction inst(&context, SpvOpReturn);
55   EXPECT_EQ(SpvOpReturn, inst.opcode());
56   EXPECT_EQ(0u, inst.type_id());
57   EXPECT_EQ(0u, inst.result_id());
58   EXPECT_EQ(0u, inst.NumOperands());
59   EXPECT_EQ(0u, inst.NumOperandWords());
60   EXPECT_EQ(0u, inst.NumInOperandWords());
61   EXPECT_EQ(inst.cend(), inst.cbegin());
62   EXPECT_EQ(inst.end(), inst.begin());
63 }
64 
TEST(InstructionTest,OperandAsCString)65 TEST(InstructionTest, OperandAsCString) {
66   Operand::OperandData abcde{0x64636261, 0x65};
67   Operand operand(SPV_OPERAND_TYPE_LITERAL_STRING, std::move(abcde));
68   EXPECT_STREQ("abcde", operand.AsCString());
69 }
70 
TEST(InstructionTest,OperandAsString)71 TEST(InstructionTest, OperandAsString) {
72   Operand::OperandData abcde{0x64636261, 0x65};
73   Operand operand(SPV_OPERAND_TYPE_LITERAL_STRING, std::move(abcde));
74   EXPECT_EQ("abcde", operand.AsString());
75 }
76 
77 // The words for an OpTypeInt for 32-bit signed integer resulting in Id 44.
78 uint32_t kSampleInstructionWords[] = {(4 << 16) | uint32_t(SpvOpTypeInt), 44,
79                                       32, 1};
80 // The operands that would be parsed from kSampleInstructionWords
81 spv_parsed_operand_t kSampleParsedOperands[] = {
82     {1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0},
83     {2, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 32},
84     {3, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 1},
85 };
86 
87 // A valid parse of kSampleParsedOperands.
88 spv_parsed_instruction_t kSampleParsedInstruction = {kSampleInstructionWords,
89                                                      uint16_t(4),
90                                                      uint16_t(SpvOpTypeInt),
91                                                      SPV_EXT_INST_TYPE_NONE,
92                                                      0,   // type id
93                                                      44,  // result id
94                                                      kSampleParsedOperands,
95                                                      3};
96 
97 // The words for an OpAccessChain instruction.
98 uint32_t kSampleAccessChainInstructionWords[] = {
99     (7 << 16) | uint32_t(SpvOpAccessChain), 100, 101, 102, 103, 104, 105};
100 
101 // The operands that would be parsed from kSampleAccessChainInstructionWords.
102 spv_parsed_operand_t kSampleAccessChainOperands[] = {
103     {1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0},
104     {2, 1, SPV_OPERAND_TYPE_TYPE_ID, SPV_NUMBER_NONE, 0},
105     {3, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
106     {4, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
107     {5, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
108     {6, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
109 };
110 
111 // A valid parse of kSampleAccessChainInstructionWords
112 spv_parsed_instruction_t kSampleAccessChainInstruction = {
113     kSampleAccessChainInstructionWords,
114     uint16_t(7),
115     uint16_t(SpvOpAccessChain),
116     SPV_EXT_INST_TYPE_NONE,
117     100,  // type id
118     101,  // result id
119     kSampleAccessChainOperands,
120     6};
121 
122 // The words for an OpControlBarrier instruction.
123 uint32_t kSampleControlBarrierInstructionWords[] = {
124     (4 << 16) | uint32_t(SpvOpControlBarrier), 100, 101, 102};
125 
126 // The operands that would be parsed from kSampleControlBarrierInstructionWords.
127 spv_parsed_operand_t kSampleControlBarrierOperands[] = {
128     {1, 1, SPV_OPERAND_TYPE_SCOPE_ID, SPV_NUMBER_NONE, 0},  // Execution
129     {2, 1, SPV_OPERAND_TYPE_SCOPE_ID, SPV_NUMBER_NONE, 0},  // Memory
130     {3, 1, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_NUMBER_NONE,
131      0},  // Semantics
132 };
133 
134 // A valid parse of kSampleControlBarrierInstructionWords
135 spv_parsed_instruction_t kSampleControlBarrierInstruction = {
136     kSampleControlBarrierInstructionWords,
137     uint16_t(4),
138     uint16_t(SpvOpControlBarrier),
139     SPV_EXT_INST_TYPE_NONE,
140     0,  // type id
141     0,  // result id
142     kSampleControlBarrierOperands,
143     3};
144 
TEST(InstructionTest,CreateWithOpcodeAndOperands)145 TEST(InstructionTest, CreateWithOpcodeAndOperands) {
146   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
147   Instruction inst(&context, kSampleParsedInstruction);
148   EXPECT_EQ(SpvOpTypeInt, inst.opcode());
149   EXPECT_EQ(0u, inst.type_id());
150   EXPECT_EQ(44u, inst.result_id());
151   EXPECT_EQ(3u, inst.NumOperands());
152   EXPECT_EQ(3u, inst.NumOperandWords());
153   EXPECT_EQ(2u, inst.NumInOperandWords());
154 }
155 
TEST(InstructionTest,GetOperand)156 TEST(InstructionTest, GetOperand) {
157   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
158   Instruction inst(&context, kSampleParsedInstruction);
159   EXPECT_THAT(inst.GetOperand(0).words, Eq(std::vector<uint32_t>{44}));
160   EXPECT_THAT(inst.GetOperand(1).words, Eq(std::vector<uint32_t>{32}));
161   EXPECT_THAT(inst.GetOperand(2).words, Eq(std::vector<uint32_t>{1}));
162 }
163 
TEST(InstructionTest,GetInOperand)164 TEST(InstructionTest, GetInOperand) {
165   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
166   Instruction inst(&context, kSampleParsedInstruction);
167   EXPECT_THAT(inst.GetInOperand(0).words, Eq(std::vector<uint32_t>{32}));
168   EXPECT_THAT(inst.GetInOperand(1).words, Eq(std::vector<uint32_t>{1}));
169 }
170 
TEST(InstructionTest,OperandConstIterators)171 TEST(InstructionTest, OperandConstIterators) {
172   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
173   Instruction inst(&context, kSampleParsedInstruction);
174   // Spot check iteration across operands.
175   auto cbegin = inst.cbegin();
176   auto cend = inst.cend();
177   EXPECT_NE(cend, inst.cbegin());
178 
179   auto citer = inst.cbegin();
180   for (int i = 0; i < 3; ++i, ++citer) {
181     const auto& operand = *citer;
182     EXPECT_THAT(operand.type, Eq(kSampleParsedOperands[i].type));
183     EXPECT_THAT(operand.words,
184                 Eq(std::vector<uint32_t>{kSampleInstructionWords[i + 1]}));
185     EXPECT_NE(cend, citer);
186   }
187   EXPECT_EQ(cend, citer);
188 
189   // Check that cbegin and cend have not changed.
190   EXPECT_EQ(cbegin, inst.cbegin());
191   EXPECT_EQ(cend, inst.cend());
192 
193   // Check arithmetic.
194   const Operand& operand2 = *(inst.cbegin() + 2);
195   EXPECT_EQ(SPV_OPERAND_TYPE_LITERAL_INTEGER, operand2.type);
196 }
197 
TEST(InstructionTest,OperandIterators)198 TEST(InstructionTest, OperandIterators) {
199   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
200   Instruction inst(&context, kSampleParsedInstruction);
201   // Spot check iteration across operands, with mutable iterators.
202   auto begin = inst.begin();
203   auto end = inst.end();
204   EXPECT_NE(end, inst.begin());
205 
206   auto iter = inst.begin();
207   for (int i = 0; i < 3; ++i, ++iter) {
208     const auto& operand = *iter;
209     EXPECT_THAT(operand.type, Eq(kSampleParsedOperands[i].type));
210     EXPECT_THAT(operand.words,
211                 Eq(std::vector<uint32_t>{kSampleInstructionWords[i + 1]}));
212     EXPECT_NE(end, iter);
213   }
214   EXPECT_EQ(end, iter);
215 
216   // Check that begin and end have not changed.
217   EXPECT_EQ(begin, inst.begin());
218   EXPECT_EQ(end, inst.end());
219 
220   // Check arithmetic.
221   Operand& operand2 = *(inst.begin() + 2);
222   EXPECT_EQ(SPV_OPERAND_TYPE_LITERAL_INTEGER, operand2.type);
223 
224   // Check mutation through an iterator.
225   operand2.type = SPV_OPERAND_TYPE_TYPE_ID;
226   EXPECT_EQ(SPV_OPERAND_TYPE_TYPE_ID, (*(inst.cbegin() + 2)).type);
227 }
228 
TEST(InstructionTest,ForInIdStandardIdTypes)229 TEST(InstructionTest, ForInIdStandardIdTypes) {
230   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
231   Instruction inst(&context, kSampleAccessChainInstruction);
232 
233   std::vector<uint32_t> ids;
234   inst.ForEachInId([&ids](const uint32_t* idptr) { ids.push_back(*idptr); });
235   EXPECT_THAT(ids, Eq(std::vector<uint32_t>{102, 103, 104, 105}));
236 
237   ids.clear();
238   inst.ForEachInId([&ids](uint32_t* idptr) { ids.push_back(*idptr); });
239   EXPECT_THAT(ids, Eq(std::vector<uint32_t>{102, 103, 104, 105}));
240 }
241 
TEST(InstructionTest,ForInIdNonstandardIdTypes)242 TEST(InstructionTest, ForInIdNonstandardIdTypes) {
243   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
244   Instruction inst(&context, kSampleControlBarrierInstruction);
245 
246   std::vector<uint32_t> ids;
247   inst.ForEachInId([&ids](const uint32_t* idptr) { ids.push_back(*idptr); });
248   EXPECT_THAT(ids, Eq(std::vector<uint32_t>{100, 101, 102}));
249 
250   ids.clear();
251   inst.ForEachInId([&ids](uint32_t* idptr) { ids.push_back(*idptr); });
252   EXPECT_THAT(ids, Eq(std::vector<uint32_t>{100, 101, 102}));
253 }
254 
TEST(InstructionTest,UniqueIds)255 TEST(InstructionTest, UniqueIds) {
256   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
257   Instruction inst1(&context);
258   Instruction inst2(&context);
259   EXPECT_NE(inst1.unique_id(), inst2.unique_id());
260 }
261 
TEST(InstructionTest,CloneUniqueIdDifferent)262 TEST(InstructionTest, CloneUniqueIdDifferent) {
263   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
264   Instruction inst(&context);
265   std::unique_ptr<Instruction> clone(inst.Clone(&context));
266   EXPECT_EQ(inst.context(), clone->context());
267   EXPECT_NE(inst.unique_id(), clone->unique_id());
268 }
269 
TEST(InstructionTest,CloneDifferentContext)270 TEST(InstructionTest, CloneDifferentContext) {
271   IRContext c1(SPV_ENV_UNIVERSAL_1_2, nullptr);
272   IRContext c2(SPV_ENV_UNIVERSAL_1_2, nullptr);
273   Instruction inst(&c1);
274   std::unique_ptr<Instruction> clone(inst.Clone(&c2));
275   EXPECT_EQ(&c1, inst.context());
276   EXPECT_EQ(&c2, clone->context());
277   EXPECT_NE(&c1, &c2);
278 }
279 
TEST(InstructionTest,CloneDifferentContextDifferentUniqueId)280 TEST(InstructionTest, CloneDifferentContextDifferentUniqueId) {
281   IRContext c1(SPV_ENV_UNIVERSAL_1_2, nullptr);
282   IRContext c2(SPV_ENV_UNIVERSAL_1_2, nullptr);
283   Instruction inst(&c1);
284   Instruction other(&c2);
285   std::unique_ptr<Instruction> clone(inst.Clone(&c2));
286   EXPECT_EQ(&c2, clone->context());
287   EXPECT_NE(other.unique_id(), clone->unique_id());
288 }
289 
TEST(InstructionTest,EqualsEqualsOperator)290 TEST(InstructionTest, EqualsEqualsOperator) {
291   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
292   Instruction i1(&context);
293   Instruction i2(&context);
294   std::unique_ptr<Instruction> clone(i1.Clone(&context));
295   EXPECT_TRUE(i1 == i1);
296   EXPECT_FALSE(i1 == i2);
297   EXPECT_FALSE(i1 == *clone);
298   EXPECT_FALSE(i2 == *clone);
299 }
300 
TEST(InstructionTest,LessThanOperator)301 TEST(InstructionTest, LessThanOperator) {
302   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
303   Instruction i1(&context);
304   Instruction i2(&context);
305   std::unique_ptr<Instruction> clone(i1.Clone(&context));
306   EXPECT_TRUE(i1 < i2);
307   EXPECT_TRUE(i1 < *clone);
308   EXPECT_TRUE(i2 < *clone);
309 }
310 
TEST_F(DescriptorTypeTest,StorageImage)311 TEST_F(DescriptorTypeTest, StorageImage) {
312   const std::string text = R"(
313                OpCapability Shader
314           %1 = OpExtInstImport "GLSL.std.450"
315                OpMemoryModel Logical GLSL450
316                OpEntryPoint Fragment %2 "main"
317                OpExecutionMode %2 OriginUpperLeft
318                OpSource GLSL 430
319                OpName %3 "myStorageImage"
320                OpDecorate %3 DescriptorSet 0
321                OpDecorate %3 Binding 0
322           %4 = OpTypeVoid
323           %5 = OpTypeFunction %4
324           %6 = OpTypeFloat 32
325           %7 = OpTypeImage %6 2D 0 0 0 2 R32f
326           %8 = OpTypePointer UniformConstant %7
327           %3 = OpVariable %8 UniformConstant
328           %2 = OpFunction %4 None %5
329           %9 = OpLabel
330                OpReturn
331                OpFunctionEnd
332 )";
333 
334   std::unique_ptr<IRContext> context =
335       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
336   Instruction* type = context->get_def_use_mgr()->GetDef(8);
337   EXPECT_TRUE(type->IsVulkanStorageImage());
338   EXPECT_FALSE(type->IsVulkanSampledImage());
339   EXPECT_FALSE(type->IsVulkanStorageTexelBuffer());
340   EXPECT_FALSE(type->IsVulkanStorageBuffer());
341   EXPECT_FALSE(type->IsVulkanUniformBuffer());
342 
343   Instruction* variable = context->get_def_use_mgr()->GetDef(3);
344   EXPECT_FALSE(variable->IsReadOnlyVariable());
345 }
346 
TEST_F(DescriptorTypeTest,SampledImage)347 TEST_F(DescriptorTypeTest, SampledImage) {
348   const std::string text = R"(
349                OpCapability Shader
350           %1 = OpExtInstImport "GLSL.std.450"
351                OpMemoryModel Logical GLSL450
352                OpEntryPoint Fragment %2 "main"
353                OpExecutionMode %2 OriginUpperLeft
354                OpSource GLSL 430
355                OpName %3 "myStorageImage"
356                OpDecorate %3 DescriptorSet 0
357                OpDecorate %3 Binding 0
358           %4 = OpTypeVoid
359           %5 = OpTypeFunction %4
360           %6 = OpTypeFloat 32
361           %7 = OpTypeImage %6 2D 0 0 0 1 Unknown
362           %8 = OpTypePointer UniformConstant %7
363           %3 = OpVariable %8 UniformConstant
364           %2 = OpFunction %4 None %5
365           %9 = OpLabel
366                OpReturn
367                OpFunctionEnd
368 )";
369 
370   std::unique_ptr<IRContext> context =
371       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
372   Instruction* type = context->get_def_use_mgr()->GetDef(8);
373   EXPECT_FALSE(type->IsVulkanStorageImage());
374   EXPECT_TRUE(type->IsVulkanSampledImage());
375   EXPECT_FALSE(type->IsVulkanStorageTexelBuffer());
376   EXPECT_FALSE(type->IsVulkanStorageBuffer());
377   EXPECT_FALSE(type->IsVulkanUniformBuffer());
378 
379   Instruction* variable = context->get_def_use_mgr()->GetDef(3);
380   EXPECT_TRUE(variable->IsReadOnlyVariable());
381 }
382 
TEST_F(DescriptorTypeTest,StorageTexelBuffer)383 TEST_F(DescriptorTypeTest, StorageTexelBuffer) {
384   const std::string text = R"(
385                OpCapability Shader
386           %1 = OpExtInstImport "GLSL.std.450"
387                OpMemoryModel Logical GLSL450
388                OpEntryPoint Fragment %2 "main"
389                OpExecutionMode %2 OriginUpperLeft
390                OpSource GLSL 430
391                OpName %3 "myStorageImage"
392                OpDecorate %3 DescriptorSet 0
393                OpDecorate %3 Binding 0
394           %4 = OpTypeVoid
395           %5 = OpTypeFunction %4
396           %6 = OpTypeFloat 32
397           %7 = OpTypeImage %6 Buffer 0 0 0 2 R32f
398           %8 = OpTypePointer UniformConstant %7
399           %3 = OpVariable %8 UniformConstant
400           %2 = OpFunction %4 None %5
401           %9 = OpLabel
402                OpReturn
403                OpFunctionEnd
404 )";
405 
406   std::unique_ptr<IRContext> context =
407       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
408   Instruction* type = context->get_def_use_mgr()->GetDef(8);
409   EXPECT_FALSE(type->IsVulkanStorageImage());
410   EXPECT_FALSE(type->IsVulkanSampledImage());
411   EXPECT_TRUE(type->IsVulkanStorageTexelBuffer());
412   EXPECT_FALSE(type->IsVulkanStorageBuffer());
413   EXPECT_FALSE(type->IsVulkanUniformBuffer());
414 
415   Instruction* variable = context->get_def_use_mgr()->GetDef(3);
416   EXPECT_FALSE(variable->IsReadOnlyVariable());
417 }
418 
TEST_F(DescriptorTypeTest,StorageBuffer)419 TEST_F(DescriptorTypeTest, StorageBuffer) {
420   const std::string text = R"(
421                OpCapability Shader
422           %1 = OpExtInstImport "GLSL.std.450"
423                OpMemoryModel Logical GLSL450
424                OpEntryPoint Fragment %2 "main"
425                OpExecutionMode %2 OriginUpperLeft
426                OpSource GLSL 430
427                OpName %3 "myStorageImage"
428                OpDecorate %3 DescriptorSet 0
429                OpDecorate %3 Binding 0
430                OpDecorate %9 BufferBlock
431           %4 = OpTypeVoid
432           %5 = OpTypeFunction %4
433           %6 = OpTypeFloat 32
434           %7 = OpTypeVector %6 4
435           %8 = OpTypeRuntimeArray %7
436           %9 = OpTypeStruct %8
437          %10 = OpTypePointer Uniform %9
438           %3 = OpVariable %10 Uniform
439           %2 = OpFunction %4 None %5
440          %11 = OpLabel
441                OpReturn
442                OpFunctionEnd
443 )";
444 
445   std::unique_ptr<IRContext> context =
446       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
447   Instruction* type = context->get_def_use_mgr()->GetDef(10);
448   EXPECT_FALSE(type->IsVulkanStorageImage());
449   EXPECT_FALSE(type->IsVulkanSampledImage());
450   EXPECT_FALSE(type->IsVulkanStorageTexelBuffer());
451   EXPECT_TRUE(type->IsVulkanStorageBuffer());
452   EXPECT_FALSE(type->IsVulkanUniformBuffer());
453 
454   Instruction* variable = context->get_def_use_mgr()->GetDef(3);
455   EXPECT_FALSE(variable->IsReadOnlyVariable());
456 }
457 
TEST_F(DescriptorTypeTest,UniformBuffer)458 TEST_F(DescriptorTypeTest, UniformBuffer) {
459   const std::string text = R"(
460                OpCapability Shader
461           %1 = OpExtInstImport "GLSL.std.450"
462                OpMemoryModel Logical GLSL450
463                OpEntryPoint Fragment %2 "main"
464                OpExecutionMode %2 OriginUpperLeft
465                OpSource GLSL 430
466                OpName %3 "myStorageImage"
467                OpDecorate %3 DescriptorSet 0
468                OpDecorate %3 Binding 0
469                OpDecorate %9 Block
470           %4 = OpTypeVoid
471           %5 = OpTypeFunction %4
472           %6 = OpTypeFloat 32
473           %7 = OpTypeVector %6 4
474           %8 = OpTypeRuntimeArray %7
475           %9 = OpTypeStruct %8
476          %10 = OpTypePointer Uniform %9
477           %3 = OpVariable %10 Uniform
478           %2 = OpFunction %4 None %5
479          %11 = OpLabel
480                OpReturn
481                OpFunctionEnd
482 )";
483 
484   std::unique_ptr<IRContext> context =
485       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
486   Instruction* type = context->get_def_use_mgr()->GetDef(10);
487   EXPECT_FALSE(type->IsVulkanStorageImage());
488   EXPECT_FALSE(type->IsVulkanSampledImage());
489   EXPECT_FALSE(type->IsVulkanStorageTexelBuffer());
490   EXPECT_FALSE(type->IsVulkanStorageBuffer());
491   EXPECT_TRUE(type->IsVulkanUniformBuffer());
492 
493   Instruction* variable = context->get_def_use_mgr()->GetDef(3);
494   EXPECT_TRUE(variable->IsReadOnlyVariable());
495 }
496 
TEST_F(DescriptorTypeTest,NonWritableIsReadOnly)497 TEST_F(DescriptorTypeTest, NonWritableIsReadOnly) {
498   const std::string text = R"(
499                OpCapability Shader
500           %1 = OpExtInstImport "GLSL.std.450"
501                OpMemoryModel Logical GLSL450
502                OpEntryPoint Fragment %2 "main"
503                OpExecutionMode %2 OriginUpperLeft
504                OpSource GLSL 430
505                OpName %3 "myStorageImage"
506                OpDecorate %3 DescriptorSet 0
507                OpDecorate %3 Binding 0
508                OpDecorate %9 BufferBlock
509                OpDecorate %3 NonWritable
510           %4 = OpTypeVoid
511           %5 = OpTypeFunction %4
512           %6 = OpTypeFloat 32
513           %7 = OpTypeVector %6 4
514           %8 = OpTypeRuntimeArray %7
515           %9 = OpTypeStruct %8
516          %10 = OpTypePointer Uniform %9
517           %3 = OpVariable %10 Uniform
518           %2 = OpFunction %4 None %5
519          %11 = OpLabel
520                OpReturn
521                OpFunctionEnd
522 )";
523 
524   std::unique_ptr<IRContext> context =
525       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
526   Instruction* variable = context->get_def_use_mgr()->GetDef(3);
527   EXPECT_TRUE(variable->IsReadOnlyVariable());
528 }
529 
TEST_F(OpaqueTypeTest,BaseOpaqueTypesShader)530 TEST_F(OpaqueTypeTest, BaseOpaqueTypesShader) {
531   const std::string text = R"(
532                OpCapability Shader
533           %1 = OpExtInstImport "GLSL.std.450"
534                OpMemoryModel Logical GLSL450
535                OpEntryPoint Fragment %2 "main"
536                OpExecutionMode %2 OriginUpperLeft
537                OpSource GLSL 430
538           %3 = OpTypeVoid
539           %4 = OpTypeFunction %3
540           %5 = OpTypeFloat 32
541           %6 = OpTypeImage %5 2D 1 0 0 1 Unknown
542           %7 = OpTypeSampler
543           %8 = OpTypeSampledImage %6
544           %9 = OpTypeRuntimeArray %5
545           %2 = OpFunction %3 None %4
546          %10 = OpLabel
547                OpReturn
548                OpFunctionEnd
549 )";
550 
551   std::unique_ptr<IRContext> context =
552       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
553   Instruction* image_type = context->get_def_use_mgr()->GetDef(6);
554   EXPECT_TRUE(image_type->IsOpaqueType());
555   Instruction* sampler_type = context->get_def_use_mgr()->GetDef(7);
556   EXPECT_TRUE(sampler_type->IsOpaqueType());
557   Instruction* sampled_image_type = context->get_def_use_mgr()->GetDef(8);
558   EXPECT_TRUE(sampled_image_type->IsOpaqueType());
559   Instruction* runtime_array_type = context->get_def_use_mgr()->GetDef(9);
560   EXPECT_TRUE(runtime_array_type->IsOpaqueType());
561   Instruction* float_type = context->get_def_use_mgr()->GetDef(5);
562   EXPECT_FALSE(float_type->IsOpaqueType());
563   Instruction* void_type = context->get_def_use_mgr()->GetDef(3);
564   EXPECT_FALSE(void_type->IsOpaqueType());
565 }
566 
TEST_F(OpaqueTypeTest,OpaqueStructTypes)567 TEST_F(OpaqueTypeTest, OpaqueStructTypes) {
568   const std::string text = R"(
569                OpCapability Shader
570           %1 = OpExtInstImport "GLSL.std.450"
571                OpMemoryModel Logical GLSL450
572                OpEntryPoint Fragment %2 "main"
573                OpExecutionMode %2 OriginUpperLeft
574                OpSource GLSL 430
575           %3 = OpTypeVoid
576           %4 = OpTypeFunction %3
577           %5 = OpTypeFloat 32
578           %6 = OpTypeRuntimeArray %5
579           %7 = OpTypeStruct %6 %6
580           %8 = OpTypeStruct %5 %6
581           %9 = OpTypeStruct %6 %5
582          %10 = OpTypeStruct %7
583           %2 = OpFunction %3 None %4
584          %11 = OpLabel
585                OpReturn
586                OpFunctionEnd
587 )";
588 
589   std::unique_ptr<IRContext> context =
590       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
591   for (int i = 7; i <= 10; i++) {
592     Instruction* type = context->get_def_use_mgr()->GetDef(i);
593     EXPECT_TRUE(type->IsOpaqueType());
594   }
595 }
596 
TEST_F(GetBaseTest,SampleImage)597 TEST_F(GetBaseTest, SampleImage) {
598   const std::string text = R"(
599                OpCapability Shader
600           %1 = OpExtInstImport "GLSL.std.450"
601                OpMemoryModel Logical GLSL450
602                OpEntryPoint Fragment %2 "main"
603                OpExecutionMode %2 OriginUpperLeft
604                OpSource GLSL 430
605                OpName %3 "myStorageImage"
606                OpDecorate %3 DescriptorSet 0
607                OpDecorate %3 Binding 0
608           %4 = OpTypeVoid
609           %5 = OpTypeFunction %4
610           %6 = OpTypeFloat 32
611           %7 = OpTypeVector %6 2
612           %8 = OpTypeVector %6 4
613           %9 = OpConstant %6 0
614          %10 = OpConstantComposite %7 %9 %9
615          %11 = OpTypeImage %6 2D 0 0 0 1 R32f
616          %12 = OpTypePointer UniformConstant %11
617           %3 = OpVariable %12 UniformConstant
618          %13 = OpTypeSampledImage %11
619          %14 = OpTypeSampler
620          %15 = OpTypePointer UniformConstant %14
621          %16 = OpVariable %15 UniformConstant
622           %2 = OpFunction %4 None %5
623          %17 = OpLabel
624          %18 = OpLoad %11 %3
625          %19 = OpLoad %14 %16
626          %20 = OpSampledImage %13 %18 %19
627          %21 = OpImageSampleImplicitLod %8 %20 %10
628                OpReturn
629                OpFunctionEnd
630 )";
631 
632   std::unique_ptr<IRContext> context =
633       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
634   Instruction* load = context->get_def_use_mgr()->GetDef(21);
635   Instruction* base = context->get_def_use_mgr()->GetDef(20);
636   EXPECT_TRUE(load->GetBaseAddress() == base);
637 }
638 
TEST_F(GetBaseTest,PtrAccessChain)639 TEST_F(GetBaseTest, PtrAccessChain) {
640   const std::string text = R"(
641                OpCapability VariablePointers
642                OpMemoryModel Logical GLSL450
643                OpEntryPoint Fragment %1 "PSMain" %2
644                OpExecutionMode %1 OriginUpperLeft
645        %void = OpTypeVoid
646           %4 = OpTypeFunction %void
647       %float = OpTypeFloat 32
648     %v4float = OpTypeVector %float 4
649         %int = OpTypeInt 32 8388353
650       %int_0 = OpConstant %int 0
651 %_ptr_Function_v4float = OpTypePointer Function %v4float
652           %2 = OpVariable %_ptr_Function_v4float Input
653           %1 = OpFunction %void None %4
654          %10 = OpLabel
655          %11 = OpPtrAccessChain %_ptr_Function_v4float %2 %int_0
656          %12 = OpLoad %v4float %11
657                OpReturn
658                OpFunctionEnd
659 )";
660 
661   std::unique_ptr<IRContext> context =
662       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
663   Instruction* load = context->get_def_use_mgr()->GetDef(12);
664   Instruction* base = context->get_def_use_mgr()->GetDef(2);
665   EXPECT_TRUE(load->GetBaseAddress() == base);
666 }
667 
TEST_F(GetBaseTest,ImageRead)668 TEST_F(GetBaseTest, ImageRead) {
669   const std::string text = R"(
670                OpCapability Shader
671           %1 = OpExtInstImport "GLSL.std.450"
672                OpMemoryModel Logical GLSL450
673                OpEntryPoint Fragment %2 "main"
674                OpExecutionMode %2 OriginUpperLeft
675                OpSource GLSL 430
676                OpName %3 "myStorageImage"
677                OpDecorate %3 DescriptorSet 0
678                OpDecorate %3 Binding 0
679           %4 = OpTypeVoid
680           %5 = OpTypeFunction %4
681           %6 = OpTypeInt 32 0
682           %7 = OpTypeVector %6 2
683           %8 = OpConstant %6 0
684           %9 = OpConstantComposite %7 %8 %8
685          %10 = OpTypeImage %6 2D 0 0 0 2 R32f
686          %11 = OpTypePointer UniformConstant %10
687           %3 = OpVariable %11 UniformConstant
688           %2 = OpFunction %4 None %5
689          %12 = OpLabel
690          %13 = OpLoad %10 %3
691          %14 = OpImageRead %6 %13 %9
692                OpReturn
693                OpFunctionEnd
694 )";
695 
696   std::unique_ptr<IRContext> context =
697       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
698   Instruction* load = context->get_def_use_mgr()->GetDef(14);
699   Instruction* base = context->get_def_use_mgr()->GetDef(13);
700   EXPECT_TRUE(load->GetBaseAddress() == base);
701 }
702 
TEST_F(ValidBasePointerTest,OpSelectBadNoVariablePointersStorageBuffer)703 TEST_F(ValidBasePointerTest, OpSelectBadNoVariablePointersStorageBuffer) {
704   const std::string text = R"(
705 OpCapability Shader
706 OpMemoryModel Logical GLSL450
707 OpEntryPoint Fragment %1 "func"
708 %2 = OpTypeVoid
709 %3 = OpTypeInt 32 0
710 %4 = OpTypePointer StorageBuffer %3
711 %5 = OpVariable %4 StorageBuffer
712 %6 = OpTypeFunction %2
713 %7 = OpTypeBool
714 %8 = OpConstantTrue %7
715 %1 = OpFunction %2 None %6
716 %9 = OpLabel
717 %10 = OpSelect %4 %8 %5 %5
718 OpReturn
719 OpFunctionEnd
720 )";
721 
722   std::unique_ptr<IRContext> context =
723       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
724   EXPECT_NE(context, nullptr);
725   Instruction* select = context->get_def_use_mgr()->GetDef(10);
726   EXPECT_NE(select, nullptr);
727   EXPECT_FALSE(select->IsValidBasePointer());
728 }
729 
TEST_F(ValidBasePointerTest,OpSelectBadNoVariablePointers)730 TEST_F(ValidBasePointerTest, OpSelectBadNoVariablePointers) {
731   const std::string text = R"(
732 OpCapability Shader
733 OpCapability VariablePointersStorageBuffer
734 OpMemoryModel Logical GLSL450
735 OpEntryPoint Fragment %1 "func"
736 %2 = OpTypeVoid
737 %3 = OpTypeInt 32 0
738 %4 = OpTypePointer Workgroup %3
739 %5 = OpVariable %4 Workgroup
740 %6 = OpTypeFunction %2
741 %7 = OpTypeBool
742 %8 = OpConstantTrue %7
743 %1 = OpFunction %2 None %6
744 %9 = OpLabel
745 %10 = OpSelect %4 %8 %5 %5
746 OpReturn
747 OpFunctionEnd
748 )";
749 
750   std::unique_ptr<IRContext> context =
751       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
752   EXPECT_NE(context, nullptr);
753   Instruction* select = context->get_def_use_mgr()->GetDef(10);
754   EXPECT_NE(select, nullptr);
755   EXPECT_FALSE(select->IsValidBasePointer());
756 }
757 
TEST_F(ValidBasePointerTest,OpSelectGoodVariablePointersStorageBuffer)758 TEST_F(ValidBasePointerTest, OpSelectGoodVariablePointersStorageBuffer) {
759   const std::string text = R"(
760 OpCapability Shader
761 OpCapability VariablePointersStorageBuffer
762 OpMemoryModel Logical GLSL450
763 OpEntryPoint Fragment %1 "func"
764 %2 = OpTypeVoid
765 %3 = OpTypeInt 32 0
766 %4 = OpTypePointer StorageBuffer %3
767 %5 = OpVariable %4 StorageBuffer
768 %6 = OpTypeFunction %2
769 %7 = OpTypeBool
770 %8 = OpConstantTrue %7
771 %1 = OpFunction %2 None %6
772 %9 = OpLabel
773 %10 = OpSelect %4 %8 %5 %5
774 OpReturn
775 OpFunctionEnd
776 )";
777 
778   std::unique_ptr<IRContext> context =
779       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
780   EXPECT_NE(context, nullptr);
781   Instruction* select = context->get_def_use_mgr()->GetDef(10);
782   EXPECT_NE(select, nullptr);
783   EXPECT_TRUE(select->IsValidBasePointer());
784 }
785 
TEST_F(ValidBasePointerTest,OpSelectGoodVariablePointers)786 TEST_F(ValidBasePointerTest, OpSelectGoodVariablePointers) {
787   const std::string text = R"(
788 OpCapability Shader
789 OpCapability VariablePointers
790 OpMemoryModel Logical GLSL450
791 OpEntryPoint Fragment %1 "func"
792 %2 = OpTypeVoid
793 %3 = OpTypeInt 32 0
794 %4 = OpTypePointer Workgroup %3
795 %5 = OpVariable %4 Workgroup
796 %6 = OpTypeFunction %2
797 %7 = OpTypeBool
798 %8 = OpConstantTrue %7
799 %1 = OpFunction %2 None %6
800 %9 = OpLabel
801 %10 = OpSelect %4 %8 %5 %5
802 OpReturn
803 OpFunctionEnd
804 )";
805 
806   std::unique_ptr<IRContext> context =
807       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
808   EXPECT_NE(context, nullptr);
809   Instruction* select = context->get_def_use_mgr()->GetDef(10);
810   EXPECT_NE(select, nullptr);
811   EXPECT_TRUE(select->IsValidBasePointer());
812 }
813 
TEST_F(ValidBasePointerTest,OpConstantNullBadNoVariablePointersStorageBuffer)814 TEST_F(ValidBasePointerTest, OpConstantNullBadNoVariablePointersStorageBuffer) {
815   const std::string text = R"(
816 OpCapability Shader
817 OpMemoryModel Logical GLSL450
818 OpEntryPoint Fragment %1 "func"
819 %2 = OpTypeVoid
820 %3 = OpTypeInt 32 0
821 %4 = OpTypePointer StorageBuffer %3
822 %5 = OpConstantNull %4
823 %6 = OpTypeFunction %2
824 %1 = OpFunction %2 None %6
825 %7 = OpLabel
826 OpReturn
827 OpFunctionEnd
828 )";
829 
830   std::unique_ptr<IRContext> context =
831       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
832   EXPECT_NE(context, nullptr);
833   Instruction* null_inst = context->get_def_use_mgr()->GetDef(5);
834   EXPECT_NE(null_inst, nullptr);
835   EXPECT_FALSE(null_inst->IsValidBasePointer());
836 }
837 
TEST_F(ValidBasePointerTest,OpConstantNullBadNoVariablePointers)838 TEST_F(ValidBasePointerTest, OpConstantNullBadNoVariablePointers) {
839   const std::string text = R"(
840 OpCapability Shader
841 OpCapability VariablePointersStorageBuffer
842 OpMemoryModel Logical GLSL450
843 OpEntryPoint Fragment %1 "func"
844 %2 = OpTypeVoid
845 %3 = OpTypeInt 32 0
846 %4 = OpTypePointer Workgroup %3
847 %5 = OpConstantNull %4
848 %6 = OpTypeFunction %2
849 %1 = OpFunction %2 None %6
850 %7 = OpLabel
851 OpReturn
852 OpFunctionEnd
853 )";
854 
855   std::unique_ptr<IRContext> context =
856       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
857   EXPECT_NE(context, nullptr);
858   Instruction* null_inst = context->get_def_use_mgr()->GetDef(5);
859   EXPECT_NE(null_inst, nullptr);
860   EXPECT_FALSE(null_inst->IsValidBasePointer());
861 }
862 
TEST_F(ValidBasePointerTest,OpConstantNullGoodVariablePointersStorageBuffer)863 TEST_F(ValidBasePointerTest, OpConstantNullGoodVariablePointersStorageBuffer) {
864   const std::string text = R"(
865 OpCapability Shader
866 OpCapability VariablePointersStorageBuffer
867 OpMemoryModel Logical GLSL450
868 OpEntryPoint Fragment %1 "func"
869 %2 = OpTypeVoid
870 %3 = OpTypeInt 32 0
871 %4 = OpTypePointer StorageBuffer %3
872 %5 = OpConstantNull %4
873 %6 = OpTypeFunction %2
874 %1 = OpFunction %2 None %6
875 %9 = OpLabel
876 OpReturn
877 OpFunctionEnd
878 )";
879 
880   std::unique_ptr<IRContext> context =
881       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
882   EXPECT_NE(context, nullptr);
883   Instruction* null_inst = context->get_def_use_mgr()->GetDef(5);
884   EXPECT_NE(null_inst, nullptr);
885   EXPECT_TRUE(null_inst->IsValidBasePointer());
886 }
887 
TEST_F(ValidBasePointerTest,OpConstantNullGoodVariablePointers)888 TEST_F(ValidBasePointerTest, OpConstantNullGoodVariablePointers) {
889   const std::string text = R"(
890 OpCapability Shader
891 OpCapability VariablePointers
892 OpMemoryModel Logical GLSL450
893 OpEntryPoint Fragment %1 "func"
894 %2 = OpTypeVoid
895 %3 = OpTypeInt 32 0
896 %4 = OpTypePointer Workgroup %3
897 %5 = OpConstantNull %4
898 %6 = OpTypeFunction %2
899 %1 = OpFunction %2 None %6
900 %7 = OpLabel
901 OpReturn
902 OpFunctionEnd
903 )";
904 
905   std::unique_ptr<IRContext> context =
906       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
907   EXPECT_NE(context, nullptr);
908   Instruction* null_inst = context->get_def_use_mgr()->GetDef(5);
909   EXPECT_NE(null_inst, nullptr);
910   EXPECT_TRUE(null_inst->IsValidBasePointer());
911 }
912 
TEST_F(ValidBasePointerTest,OpPhiBadNoVariablePointersStorageBuffer)913 TEST_F(ValidBasePointerTest, OpPhiBadNoVariablePointersStorageBuffer) {
914   const std::string text = R"(
915 OpCapability Shader
916 OpMemoryModel Logical GLSL450
917 OpEntryPoint Fragment %1 "func"
918 %2 = OpTypeVoid
919 %3 = OpTypeInt 32 0
920 %4 = OpTypePointer StorageBuffer %3
921 %5 = OpVariable %4 StorageBuffer
922 %6 = OpTypeFunction %2
923 %1 = OpFunction %2 None %6
924 %7 = OpLabel
925 OpBranch %8
926 %8 = OpLabel
927 %9 = OpPhi %4 %5 %7
928 OpReturn
929 OpFunctionEnd
930 )";
931 
932   std::unique_ptr<IRContext> context =
933       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
934   EXPECT_NE(context, nullptr);
935   Instruction* phi = context->get_def_use_mgr()->GetDef(9);
936   EXPECT_NE(phi, nullptr);
937   EXPECT_FALSE(phi->IsValidBasePointer());
938 }
939 
TEST_F(ValidBasePointerTest,OpPhiBadNoVariablePointers)940 TEST_F(ValidBasePointerTest, OpPhiBadNoVariablePointers) {
941   const std::string text = R"(
942 OpCapability Shader
943 OpCapability VariablePointersStorageBuffer
944 OpMemoryModel Logical GLSL450
945 OpEntryPoint Fragment %1 "func"
946 %2 = OpTypeVoid
947 %3 = OpTypeInt 32 0
948 %4 = OpTypePointer Workgroup %3
949 %5 = OpVariable %4 Workgroup
950 %6 = OpTypeFunction %2
951 %1 = OpFunction %2 None %6
952 %7 = OpLabel
953 OpBranch %8
954 %8 = OpLabel
955 %9 = OpPhi %4 %5 %7
956 OpReturn
957 OpFunctionEnd
958 )";
959 
960   std::unique_ptr<IRContext> context =
961       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
962   EXPECT_NE(context, nullptr);
963   Instruction* phi = context->get_def_use_mgr()->GetDef(9);
964   EXPECT_NE(phi, nullptr);
965   EXPECT_FALSE(phi->IsValidBasePointer());
966 }
967 
TEST_F(ValidBasePointerTest,OpPhiGoodVariablePointersStorageBuffer)968 TEST_F(ValidBasePointerTest, OpPhiGoodVariablePointersStorageBuffer) {
969   const std::string text = R"(
970 OpCapability Shader
971 OpCapability VariablePointersStorageBuffer
972 OpMemoryModel Logical GLSL450
973 OpEntryPoint Fragment %1 "func"
974 %2 = OpTypeVoid
975 %3 = OpTypeInt 32 0
976 %4 = OpTypePointer StorageBuffer %3
977 %5 = OpVariable %4 StorageBuffer
978 %6 = OpTypeFunction %2
979 %1 = OpFunction %2 None %6
980 %7 = OpLabel
981 OpBranch %8
982 %8 = OpLabel
983 %9 = OpPhi %4 %5 %7
984 OpReturn
985 OpFunctionEnd
986 )";
987 
988   std::unique_ptr<IRContext> context =
989       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
990   EXPECT_NE(context, nullptr);
991   Instruction* phi = context->get_def_use_mgr()->GetDef(9);
992   EXPECT_NE(phi, nullptr);
993   EXPECT_TRUE(phi->IsValidBasePointer());
994 }
995 
TEST_F(ValidBasePointerTest,OpPhiGoodVariablePointers)996 TEST_F(ValidBasePointerTest, OpPhiGoodVariablePointers) {
997   const std::string text = R"(
998 OpCapability Shader
999 OpCapability VariablePointers
1000 OpMemoryModel Logical GLSL450
1001 OpEntryPoint Fragment %1 "func"
1002 %2 = OpTypeVoid
1003 %3 = OpTypeInt 32 0
1004 %4 = OpTypePointer Workgroup %3
1005 %5 = OpVariable %4 Workgroup
1006 %6 = OpTypeFunction %2
1007 %1 = OpFunction %2 None %6
1008 %7 = OpLabel
1009 OpBranch %8
1010 %8 = OpLabel
1011 %9 = OpPhi %4 %5 %7
1012 OpReturn
1013 OpFunctionEnd
1014 )";
1015 
1016   std::unique_ptr<IRContext> context =
1017       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1018   EXPECT_NE(context, nullptr);
1019   Instruction* phi = context->get_def_use_mgr()->GetDef(9);
1020   EXPECT_NE(phi, nullptr);
1021   EXPECT_TRUE(phi->IsValidBasePointer());
1022 }
1023 
TEST_F(ValidBasePointerTest,OpFunctionCallBadNoVariablePointersStorageBuffer)1024 TEST_F(ValidBasePointerTest, OpFunctionCallBadNoVariablePointersStorageBuffer) {
1025   const std::string text = R"(
1026 OpCapability Shader
1027 OpMemoryModel Logical GLSL450
1028 OpEntryPoint Fragment %1 "func"
1029 %2 = OpTypeVoid
1030 %3 = OpTypeInt 32 0
1031 %4 = OpTypePointer StorageBuffer %3
1032 %5 = OpConstantNull %4
1033 %6 = OpTypeFunction %2
1034 %7 = OpTypeFunction %4
1035 %1 = OpFunction %2 None %6
1036 %8 = OpLabel
1037 %9 = OpFunctionCall %4 %10
1038 OpReturn
1039 OpFunctionEnd
1040 %10 = OpFunction %4 None %7
1041 %11 = OpLabel
1042 OpReturnValue %5
1043 OpFunctionEnd
1044 )";
1045 
1046   std::unique_ptr<IRContext> context =
1047       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1048   EXPECT_NE(context, nullptr);
1049   Instruction* null_inst = context->get_def_use_mgr()->GetDef(9);
1050   EXPECT_NE(null_inst, nullptr);
1051   EXPECT_FALSE(null_inst->IsValidBasePointer());
1052 }
1053 
TEST_F(ValidBasePointerTest,OpFunctionCallBadNoVariablePointers)1054 TEST_F(ValidBasePointerTest, OpFunctionCallBadNoVariablePointers) {
1055   const std::string text = R"(
1056 OpCapability Shader
1057 OpCapability VariablePointersStorageBuffer
1058 OpMemoryModel Logical GLSL450
1059 OpEntryPoint Fragment %1 "func"
1060 %2 = OpTypeVoid
1061 %3 = OpTypeInt 32 0
1062 %4 = OpTypePointer Workgroup %3
1063 %5 = OpConstantNull %4
1064 %6 = OpTypeFunction %2
1065 %7 = OpTypeFunction %4
1066 %1 = OpFunction %2 None %6
1067 %8 = OpLabel
1068 %9 = OpFunctionCall %4 %10
1069 OpReturn
1070 OpFunctionEnd
1071 %10 = OpFunction %4 None %7
1072 %11 = OpLabel
1073 OpReturnValue %5
1074 OpFunctionEnd
1075 )";
1076 
1077   std::unique_ptr<IRContext> context =
1078       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1079   EXPECT_NE(context, nullptr);
1080   Instruction* null_inst = context->get_def_use_mgr()->GetDef(9);
1081   EXPECT_NE(null_inst, nullptr);
1082   EXPECT_FALSE(null_inst->IsValidBasePointer());
1083 }
1084 
TEST_F(ValidBasePointerTest,OpFunctionCallGoodVariablePointersStorageBuffer)1085 TEST_F(ValidBasePointerTest, OpFunctionCallGoodVariablePointersStorageBuffer) {
1086   const std::string text = R"(
1087 OpCapability Shader
1088 OpCapability VariablePointersStorageBuffer
1089 OpMemoryModel Logical GLSL450
1090 OpEntryPoint Fragment %1 "func"
1091 %2 = OpTypeVoid
1092 %3 = OpTypeInt 32 0
1093 %4 = OpTypePointer StorageBuffer %3
1094 %5 = OpConstantNull %4
1095 %6 = OpTypeFunction %2
1096 %7 = OpTypeFunction %4
1097 %1 = OpFunction %2 None %6
1098 %8 = OpLabel
1099 %9 = OpFunctionCall %4 %10
1100 OpReturn
1101 OpFunctionEnd
1102 %10 = OpFunction %4 None %7
1103 %11 = OpLabel
1104 OpReturnValue %5
1105 OpFunctionEnd
1106 )";
1107 
1108   std::unique_ptr<IRContext> context =
1109       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1110   EXPECT_NE(context, nullptr);
1111   Instruction* null_inst = context->get_def_use_mgr()->GetDef(9);
1112   EXPECT_NE(null_inst, nullptr);
1113   EXPECT_TRUE(null_inst->IsValidBasePointer());
1114 }
1115 
TEST_F(ValidBasePointerTest,OpFunctionCallGoodVariablePointers)1116 TEST_F(ValidBasePointerTest, OpFunctionCallGoodVariablePointers) {
1117   const std::string text = R"(
1118 OpCapability Shader
1119 OpCapability VariablePointers
1120 OpMemoryModel Logical GLSL450
1121 OpEntryPoint Fragment %1 "func"
1122 %2 = OpTypeVoid
1123 %3 = OpTypeInt 32 0
1124 %4 = OpTypePointer Workgroup %3
1125 %5 = OpConstantNull %4
1126 %6 = OpTypeFunction %2
1127 %7 = OpTypeFunction %4
1128 %1 = OpFunction %2 None %6
1129 %8 = OpLabel
1130 %9 = OpFunctionCall %4 %10
1131 OpReturn
1132 OpFunctionEnd
1133 %10 = OpFunction %4 None %7
1134 %11 = OpLabel
1135 OpReturnValue %5
1136 OpFunctionEnd
1137 )";
1138 
1139   std::unique_ptr<IRContext> context =
1140       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1141   EXPECT_NE(context, nullptr);
1142   Instruction* null_inst = context->get_def_use_mgr()->GetDef(9);
1143   EXPECT_NE(null_inst, nullptr);
1144   EXPECT_TRUE(null_inst->IsValidBasePointer());
1145 }
1146 
TEST_F(VulkanBufferTest,VulkanStorageBuffer)1147 TEST_F(VulkanBufferTest, VulkanStorageBuffer) {
1148   const std::string text = R"(
1149 OpCapability Shader
1150 OpCapability RuntimeDescriptorArray
1151 OpMemoryModel Logical GLSL450
1152 OpEntryPoint GLCompute %1 "main"
1153 OpExecutionMode %1 LocalSize 1 1 1
1154 OpDecorate %2 Block
1155 OpMemberDecorate %2 0 Offset 0
1156 OpDecorate %3 BufferBlock
1157 OpMemberDecorate %3 0 Offset 0
1158 %4 = OpTypeVoid
1159 %5 = OpTypeInt 32 0
1160 %2 = OpTypeStruct %5
1161 %3 = OpTypeStruct %5
1162 
1163 %6 = OpTypePointer StorageBuffer %2
1164 %7 = OpTypePointer Uniform %2
1165 %8 = OpTypePointer Uniform %3
1166 
1167 %9 = OpConstant %5 1
1168 %10 = OpTypeArray %2 %9
1169 %11 = OpTypeArray %3 %9
1170 %12 = OpTypePointer StorageBuffer %10
1171 %13 = OpTypePointer Uniform %10
1172 %14 = OpTypePointer Uniform %11
1173 
1174 %15 = OpTypeRuntimeArray %2
1175 %16 = OpTypeRuntimeArray %3
1176 %17 = OpTypePointer StorageBuffer %15
1177 %18 = OpTypePointer Uniform %15
1178 %19 = OpTypePointer Uniform %16
1179 
1180 %50 = OpTypeFunction %4
1181 %1 = OpFunction %4 None %50
1182 %51 = OpLabel
1183 OpReturn
1184 OpFunctionEnd
1185 )";
1186 
1187   std::unique_ptr<IRContext> context =
1188       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1189   EXPECT_NE(context, nullptr);
1190 
1191   // Standard SSBO and UBO
1192   Instruction* inst = context->get_def_use_mgr()->GetDef(6);
1193   EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
1194   inst = context->get_def_use_mgr()->GetDef(7);
1195   EXPECT_EQ(false, inst->IsVulkanStorageBuffer());
1196   inst = context->get_def_use_mgr()->GetDef(8);
1197   EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
1198 
1199   // Arrayed SSBO and UBO
1200   inst = context->get_def_use_mgr()->GetDef(12);
1201   EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
1202   inst = context->get_def_use_mgr()->GetDef(13);
1203   EXPECT_EQ(false, inst->IsVulkanStorageBuffer());
1204   inst = context->get_def_use_mgr()->GetDef(14);
1205   EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
1206 
1207   // Runtime arrayed SSBO and UBO
1208   inst = context->get_def_use_mgr()->GetDef(17);
1209   EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
1210   inst = context->get_def_use_mgr()->GetDef(18);
1211   EXPECT_EQ(false, inst->IsVulkanStorageBuffer());
1212   inst = context->get_def_use_mgr()->GetDef(19);
1213   EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
1214 }
1215 
TEST_F(VulkanBufferTest,VulkanUniformBuffer)1216 TEST_F(VulkanBufferTest, VulkanUniformBuffer) {
1217   const std::string text = R"(
1218 OpCapability Shader
1219 OpCapability RuntimeDescriptorArray
1220 OpMemoryModel Logical GLSL450
1221 OpEntryPoint GLCompute %1 "main"
1222 OpExecutionMode %1 LocalSize 1 1 1
1223 OpDecorate %2 Block
1224 OpMemberDecorate %2 0 Offset 0
1225 OpDecorate %3 BufferBlock
1226 OpMemberDecorate %3 0 Offset 0
1227 %4 = OpTypeVoid
1228 %5 = OpTypeInt 32 0
1229 %2 = OpTypeStruct %5
1230 %3 = OpTypeStruct %5
1231 
1232 %6 = OpTypePointer StorageBuffer %2
1233 %7 = OpTypePointer Uniform %2
1234 %8 = OpTypePointer Uniform %3
1235 
1236 %9 = OpConstant %5 1
1237 %10 = OpTypeArray %2 %9
1238 %11 = OpTypeArray %3 %9
1239 %12 = OpTypePointer StorageBuffer %10
1240 %13 = OpTypePointer Uniform %10
1241 %14 = OpTypePointer Uniform %11
1242 
1243 %15 = OpTypeRuntimeArray %2
1244 %16 = OpTypeRuntimeArray %3
1245 %17 = OpTypePointer StorageBuffer %15
1246 %18 = OpTypePointer Uniform %15
1247 %19 = OpTypePointer Uniform %16
1248 
1249 %50 = OpTypeFunction %4
1250 %1 = OpFunction %4 None %50
1251 %51 = OpLabel
1252 OpReturn
1253 OpFunctionEnd
1254 )";
1255 
1256   std::unique_ptr<IRContext> context =
1257       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1258   EXPECT_NE(context, nullptr);
1259 
1260   // Standard SSBO and UBO
1261   Instruction* inst = context->get_def_use_mgr()->GetDef(6);
1262   EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
1263   inst = context->get_def_use_mgr()->GetDef(7);
1264   EXPECT_EQ(true, inst->IsVulkanUniformBuffer());
1265   inst = context->get_def_use_mgr()->GetDef(8);
1266   EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
1267 
1268   // Arrayed SSBO and UBO
1269   inst = context->get_def_use_mgr()->GetDef(12);
1270   EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
1271   inst = context->get_def_use_mgr()->GetDef(13);
1272   EXPECT_EQ(true, inst->IsVulkanUniformBuffer());
1273   inst = context->get_def_use_mgr()->GetDef(14);
1274   EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
1275 
1276   // Runtime arrayed SSBO and UBO
1277   inst = context->get_def_use_mgr()->GetDef(17);
1278   EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
1279   inst = context->get_def_use_mgr()->GetDef(18);
1280   EXPECT_EQ(true, inst->IsVulkanUniformBuffer());
1281   inst = context->get_def_use_mgr()->GetDef(19);
1282   EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
1283 }
1284 
TEST_F(VulkanBufferTest,ImageQueries)1285 TEST_F(VulkanBufferTest, ImageQueries) {
1286   const std::string text = R"(
1287 OpCapability Shader
1288 OpCapability ImageBuffer
1289 OpCapability RuntimeDescriptorArray
1290 OpMemoryModel Logical GLSL450
1291 OpEntryPoint GLCompute %1 "main"
1292 OpExecutionMode %1 LocalSize 1 1 1
1293 %2 = OpTypeVoid
1294 %3 = OpTypeFloat 32
1295 
1296 %4 = OpTypeImage %3 Buffer 0 0 0 1 Rgba32f
1297 %5 = OpTypeImage %3 Buffer 0 0 0 2 Rgba32f
1298 %6 = OpTypeImage %3 2D 0 0 0 1 Rgba32f
1299 %7 = OpTypeImage %3 2D 0 0 0 2 Rgba32f
1300 
1301 %8 = OpTypePointer UniformConstant %4
1302 %9 = OpTypePointer UniformConstant %5
1303 %10 = OpTypePointer UniformConstant %6
1304 %11 = OpTypePointer UniformConstant %7
1305 
1306 %12 = OpTypeInt 32 0
1307 %13 = OpConstant %12 1
1308 %14 = OpTypeArray %4 %13
1309 %15 = OpTypeArray %5 %13
1310 %16 = OpTypeArray %6 %13
1311 %17 = OpTypeArray %7 %13
1312 %18 = OpTypePointer UniformConstant %14
1313 %19 = OpTypePointer UniformConstant %15
1314 %20 = OpTypePointer UniformConstant %16
1315 %21 = OpTypePointer UniformConstant %17
1316 
1317 %22 = OpTypeRuntimeArray %4
1318 %23 = OpTypeRuntimeArray %5
1319 %24 = OpTypeRuntimeArray %6
1320 %25 = OpTypeRuntimeArray %7
1321 %26 = OpTypePointer UniformConstant %22
1322 %27 = OpTypePointer UniformConstant %23
1323 %28 = OpTypePointer UniformConstant %24
1324 %29 = OpTypePointer UniformConstant %25
1325 
1326 %50 = OpTypeFunction %4
1327 %1 = OpFunction %4 None %50
1328 %51 = OpLabel
1329 OpReturn
1330 OpFunctionEnd
1331 )";
1332 
1333   std::unique_ptr<IRContext> context =
1334       BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1335   EXPECT_NE(context, nullptr);
1336 
1337   // Bare pointers
1338   Instruction* inst = context->get_def_use_mgr()->GetDef(8);
1339   EXPECT_EQ(false, inst->IsVulkanStorageImage());
1340   EXPECT_EQ(false, inst->IsVulkanSampledImage());
1341   EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1342 
1343   inst = context->get_def_use_mgr()->GetDef(9);
1344   EXPECT_EQ(false, inst->IsVulkanStorageImage());
1345   EXPECT_EQ(false, inst->IsVulkanSampledImage());
1346   EXPECT_EQ(true, inst->IsVulkanStorageTexelBuffer());
1347 
1348   inst = context->get_def_use_mgr()->GetDef(10);
1349   EXPECT_EQ(false, inst->IsVulkanStorageImage());
1350   EXPECT_EQ(true, inst->IsVulkanSampledImage());
1351   EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1352 
1353   inst = context->get_def_use_mgr()->GetDef(11);
1354   EXPECT_EQ(true, inst->IsVulkanStorageImage());
1355   EXPECT_EQ(false, inst->IsVulkanSampledImage());
1356   EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1357 
1358   // Array pointers
1359   inst = context->get_def_use_mgr()->GetDef(18);
1360   EXPECT_EQ(false, inst->IsVulkanStorageImage());
1361   EXPECT_EQ(false, inst->IsVulkanSampledImage());
1362   EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1363 
1364   inst = context->get_def_use_mgr()->GetDef(19);
1365   EXPECT_EQ(false, inst->IsVulkanStorageImage());
1366   EXPECT_EQ(false, inst->IsVulkanSampledImage());
1367   EXPECT_EQ(true, inst->IsVulkanStorageTexelBuffer());
1368 
1369   inst = context->get_def_use_mgr()->GetDef(20);
1370   EXPECT_EQ(false, inst->IsVulkanStorageImage());
1371   EXPECT_EQ(true, inst->IsVulkanSampledImage());
1372   EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1373 
1374   inst = context->get_def_use_mgr()->GetDef(21);
1375   EXPECT_EQ(true, inst->IsVulkanStorageImage());
1376   EXPECT_EQ(false, inst->IsVulkanSampledImage());
1377   EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1378 
1379   // Runtime array pointers
1380   inst = context->get_def_use_mgr()->GetDef(26);
1381   EXPECT_EQ(false, inst->IsVulkanStorageImage());
1382   EXPECT_EQ(false, inst->IsVulkanSampledImage());
1383   EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1384 
1385   inst = context->get_def_use_mgr()->GetDef(27);
1386   EXPECT_EQ(false, inst->IsVulkanStorageImage());
1387   EXPECT_EQ(false, inst->IsVulkanSampledImage());
1388   EXPECT_EQ(true, inst->IsVulkanStorageTexelBuffer());
1389 
1390   inst = context->get_def_use_mgr()->GetDef(28);
1391   EXPECT_EQ(false, inst->IsVulkanStorageImage());
1392   EXPECT_EQ(true, inst->IsVulkanSampledImage());
1393   EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1394 
1395   inst = context->get_def_use_mgr()->GetDef(29);
1396   EXPECT_EQ(true, inst->IsVulkanStorageImage());
1397   EXPECT_EQ(false, inst->IsVulkanSampledImage());
1398   EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1399 }
1400 
1401 }  // namespace
1402 }  // namespace opt
1403 }  // namespace spvtools
1404