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