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