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