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