1// Copyright (c) 2021 Shiyu Liu
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 "gtest/gtest.h"
16#include "source/fuzz/fuzzer_util.h"
17#include "test/fuzz/fuzz_test_util.h"
18
19namespace spvtools {
20namespace fuzz {
21namespace {
22
23TEST(FuzzerUtilMaybeFindBlockTest, BasicTest) {
24  std::string shader = R"(
25               OpCapability Shader
26          %1 = OpExtInstImport "GLSL.std.450"
27               OpMemoryModel Logical GLSL450
28               OpEntryPoint Fragment %4 "main"
29               OpExecutionMode %4 OriginUpperLeft
30               OpSource ESSL 310
31               OpDecorate %8 RelaxedPrecision
32          %2 = OpTypeVoid
33          %3 = OpTypeFunction %2
34          %6 = OpTypeInt 32 1
35          %7 = OpTypePointer Function %6
36          %9 = OpConstant %6 1
37         %10 = OpConstant %6 2
38          %4 = OpFunction %2 None %3
39          %5 = OpLabel
40          %8 = OpVariable %7 Function
41               OpBranch %11
42         %11 = OpLabel
43               OpStore %8 %9
44               OpBranch %12
45         %12 = OpLabel
46               OpStore %8 %10
47               OpReturn
48               OpFunctionEnd
49  )";
50
51  const auto env = SPV_ENV_UNIVERSAL_1_4;
52  const auto consumer = nullptr;
53  const std::unique_ptr<opt::IRContext> context =
54      BuildModule(env, consumer, shader, kFuzzAssembleOption);
55  spvtools::ValidatorOptions validator_options;
56  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
57                                               kConsoleMessageConsumer));
58
59  // Only blocks with id 11 and 12 can be found.
60  // Should return nullptr when id is not a label or id was not found.
61  uint32_t block_id1 = 11;
62  uint32_t block_id2 = 12;
63  uint32_t block_id3 = 13;
64  uint32_t block_id4 = 8;
65
66  opt::IRContext* ir_context = context.get();
67  // Block with id 11 should be found.
68  ASSERT_TRUE(fuzzerutil::MaybeFindBlock(ir_context, block_id1) != nullptr);
69  // Block with id 12 should be found.
70  ASSERT_TRUE(fuzzerutil::MaybeFindBlock(ir_context, block_id2) != nullptr);
71  // Block with id 13 cannot be found.
72  ASSERT_FALSE(fuzzerutil::MaybeFindBlock(ir_context, block_id3) != nullptr);
73  // Block with id 8 exists but don't not of type OpLabel.
74  ASSERT_FALSE(fuzzerutil::MaybeFindBlock(ir_context, block_id4) != nullptr);
75}
76
77TEST(FuzzerutilTest, FuzzerUtilMaybeGetBoolConstantTest) {
78  std::string shader = R"(
79               OpCapability Shader
80          %1 = OpExtInstImport "GLSL.std.450"
81               OpMemoryModel Logical GLSL450
82               OpEntryPoint Fragment %4 "main" %36
83               OpExecutionMode %4 OriginUpperLeft
84               OpSource ESSL 310
85               OpName %4 "main"
86               OpName %8 "b1"
87               OpName %10 "b2"
88               OpName %12 "b3"
89               OpName %13 "b4"
90               OpName %16 "f1"
91               OpName %18 "f2"
92               OpName %20 "cf1"
93               OpName %22 "cf2"
94               OpName %26 "i1"
95               OpName %28 "i2"
96               OpName %30 "ci1"
97               OpName %32 "ci2"
98               OpName %36 "value"
99               OpDecorate %26 RelaxedPrecision
100               OpDecorate %28 RelaxedPrecision
101               OpDecorate %30 RelaxedPrecision
102               OpDecorate %32 RelaxedPrecision
103               OpDecorate %36 Location 0
104          %2 = OpTypeVoid
105          %3 = OpTypeFunction %2
106          %6 = OpTypeBool
107          %7 = OpTypePointer Function %6
108          %9 = OpConstantTrue %6
109         %11 = OpConstantFalse %6
110         %14 = OpTypeFloat 32
111         %15 = OpTypePointer Function %14
112         %17 = OpConstant %14 1.23000002
113         %19 = OpConstant %14 1.11000001
114         %21 = OpConstant %14 2
115         %23 = OpConstant %14 3.29999995
116         %24 = OpTypeInt 32 1
117         %25 = OpTypePointer Function %24
118         %27 = OpConstant %24 1
119         %29 = OpConstant %24 100
120         %31 = OpConstant %24 123
121         %33 = OpConstant %24 1111
122         %35 = OpTypePointer Input %14
123         %36 = OpVariable %35 Input
124          %4 = OpFunction %2 None %3
125          %5 = OpLabel
126          %8 = OpVariable %7 Function
127         %10 = OpVariable %7 Function
128         %12 = OpVariable %7 Function
129         %13 = OpVariable %7 Function
130         %16 = OpVariable %15 Function
131         %18 = OpVariable %15 Function
132         %20 = OpVariable %15 Function
133         %22 = OpVariable %15 Function
134         %26 = OpVariable %25 Function
135         %28 = OpVariable %25 Function
136         %30 = OpVariable %25 Function
137         %32 = OpVariable %25 Function
138               OpStore %8 %9
139               OpStore %10 %11
140               OpStore %12 %9
141               OpStore %13 %11
142               OpStore %16 %17
143               OpStore %18 %19
144               OpStore %20 %21
145               OpStore %22 %23
146               OpStore %26 %27
147               OpStore %28 %29
148               OpStore %30 %31
149               OpStore %32 %33
150               OpReturn
151               OpFunctionEnd
152  )";
153
154  const auto env = SPV_ENV_UNIVERSAL_1_4;
155  const auto consumer = nullptr;
156  const std::unique_ptr<opt::IRContext> context =
157      BuildModule(env, consumer, shader, kFuzzAssembleOption);
158  spvtools::ValidatorOptions validator_options;
159  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
160                                               kConsoleMessageConsumer));
161  TransformationContext transformation_context(
162      MakeUnique<FactManager>(context.get()), validator_options);
163
164  opt::IRContext* ir_context = context.get();
165  // A bool constant with value false exists and the id is 11.
166  ASSERT_EQ(11, fuzzerutil::MaybeGetBoolConstant(
167                    ir_context, transformation_context, false, false));
168  // A bool constant with value true exists and the id is 9.
169  ASSERT_EQ(9, fuzzerutil::MaybeGetBoolConstant(
170                   ir_context, transformation_context, true, false));
171}
172
173TEST(FuzzerutilTest, FuzzerUtilMaybeGetBoolTypeTest) {
174  std::string shader = R"(
175               OpCapability Shader
176          %1 = OpExtInstImport "GLSL.std.450"
177               OpMemoryModel Logical GLSL450
178               OpEntryPoint Fragment %4 "main" %92 %52 %53
179               OpExecutionMode %4 OriginUpperLeft
180               OpSource ESSL 310
181               OpDecorate %92 BuiltIn FragCoord
182          %2 = OpTypeVoid
183          %3 = OpTypeFunction %2
184          %6 = OpTypeInt 32 1
185          %7 = OpTypeFloat 32
186          %8 = OpTypeStruct %6 %7
187          %9 = OpTypePointer Function %8
188         %10 = OpTypeFunction %6 %9
189         %14 = OpConstant %6 0
190         %15 = OpTypePointer Function %6
191         %51 = OpTypePointer Private %6
192         %21 = OpConstant %6 2
193         %23 = OpConstant %6 1
194         %24 = OpConstant %7 1
195         %25 = OpTypePointer Function %7
196         %50 = OpTypePointer Private %7
197         %34 = OpTypeBool
198         %35 = OpConstantFalse %34
199         %52 = OpVariable %50 Private
200         %53 = OpVariable %51 Private
201         %80 = OpConstantComposite %8 %21 %24
202         %90 = OpTypeVector %7 4
203         %91 = OpTypePointer Input %90
204         %92 = OpVariable %91 Input
205         %93 = OpConstantComposite %90 %24 %24 %24 %24
206          %4 = OpFunction %2 None %3
207          %5 = OpLabel
208         %20 = OpVariable %9 Function
209         %27 = OpVariable %9 Function
210         %22 = OpAccessChain %15 %20 %14
211         %44 = OpCopyObject %9 %20
212         %26 = OpAccessChain %25 %20 %23
213         %29 = OpFunctionCall %6 %12 %27
214         %30 = OpAccessChain %15 %20 %14
215         %45 = OpCopyObject %15 %30
216         %81 = OpCopyObject %9 %27
217         %33 = OpAccessChain %15 %20 %14
218               OpSelectionMerge %37 None
219               OpBranchConditional %35 %36 %37
220         %36 = OpLabel
221         %38 = OpAccessChain %15 %20 %14
222         %40 = OpAccessChain %15 %20 %14
223         %43 = OpAccessChain %15 %20 %14
224         %82 = OpCopyObject %9 %27
225               OpBranch %37
226         %37 = OpLabel
227               OpReturn
228               OpFunctionEnd
229         %12 = OpFunction %6 None %10
230         %11 = OpFunctionParameter %9
231         %13 = OpLabel
232         %46 = OpCopyObject %9 %11
233         %16 = OpAccessChain %15 %11 %14
234         %95 = OpCopyObject %8 %80
235               OpReturnValue %21
236        %100 = OpLabel
237               OpUnreachable
238               OpFunctionEnd
239  )";
240
241  const auto env = SPV_ENV_UNIVERSAL_1_4;
242  const auto consumer = nullptr;
243  const std::unique_ptr<opt::IRContext> context =
244      BuildModule(env, consumer, shader, kFuzzAssembleOption);
245  spvtools::ValidatorOptions validator_options;
246  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
247                                               kConsoleMessageConsumer));
248
249  opt::IRContext* ir_context = context.get();
250  // A bool type with result id of 34 exists.
251  ASSERT_TRUE(fuzzerutil::MaybeGetBoolType(ir_context));
252}
253
254TEST(FuzzerutilTest, FuzzerUtilMaybeGetCompositeConstantTest) {
255  std::string shader = R"(
256               OpCapability Shader
257          %1 = OpExtInstImport "GLSL.std.450"
258               OpMemoryModel Logical GLSL450
259               OpEntryPoint Fragment %4 "main" %54
260               OpExecutionMode %4 OriginUpperLeft
261               OpSource ESSL 310
262               OpName %4 "main"
263               OpName %8 "b1"
264               OpName %10 "b2"
265               OpName %12 "b3"
266               OpName %13 "b4"
267               OpName %16 "f1"
268               OpName %18 "f2"
269               OpName %22 "zc"
270               OpName %24 "i1"
271               OpName %28 "i2"
272               OpName %30 "i3"
273               OpName %32 "i4"
274               OpName %37 "f_arr"
275               OpName %47 "i_arr"
276               OpName %54 "value"
277               OpDecorate %22 RelaxedPrecision
278               OpDecorate %24 RelaxedPrecision
279               OpDecorate %28 RelaxedPrecision
280               OpDecorate %30 RelaxedPrecision
281               OpDecorate %32 RelaxedPrecision
282               OpDecorate %47 RelaxedPrecision
283               OpDecorate %54 Location 0
284          %2 = OpTypeVoid
285          %3 = OpTypeFunction %2
286          %6 = OpTypeBool
287          %7 = OpTypePointer Function %6
288          %9 = OpConstantTrue %6
289         %11 = OpConstantFalse %6
290         %14 = OpTypeFloat 32
291         %15 = OpTypePointer Function %14
292         %17 = OpConstant %14 1.23000002
293         %19 = OpConstant %14 1.11000001
294         %20 = OpTypeInt 32 1
295         %21 = OpTypePointer Function %20
296         %23 = OpConstant %20 0
297         %25 = OpConstant %20 1
298         %26 = OpTypeInt 32 0
299         %27 = OpTypePointer Function %26
300         %29 = OpConstant %26 100
301         %31 = OpConstant %20 -1
302         %33 = OpConstant %20 -99
303         %34 = OpConstant %26 5
304         %35 = OpTypeArray %14 %34
305         %36 = OpTypePointer Function %35
306         %38 = OpConstant %14 5.5
307         %39 = OpConstant %14 4.4000001
308         %40 = OpConstant %14 3.29999995
309         %41 = OpConstant %14 2.20000005
310         %42 = OpConstant %14 1.10000002
311         %43 = OpConstantComposite %35 %38 %39 %40 %41 %42
312         %44 = OpConstant %26 3
313         %45 = OpTypeArray %20 %44
314         %46 = OpTypePointer Function %45
315         %48 = OpConstant %20 3
316         %49 = OpConstant %20 7
317         %50 = OpConstant %20 9
318         %51 = OpConstantComposite %45 %48 %49 %50
319         %53 = OpTypePointer Input %14
320         %54 = OpVariable %53 Input
321          %4 = OpFunction %2 None %3
322          %5 = OpLabel
323          %8 = OpVariable %7 Function
324         %10 = OpVariable %7 Function
325         %12 = OpVariable %7 Function
326         %13 = OpVariable %7 Function
327         %16 = OpVariable %15 Function
328         %18 = OpVariable %15 Function
329         %22 = OpVariable %21 Function
330         %24 = OpVariable %21 Function
331         %28 = OpVariable %27 Function
332         %30 = OpVariable %21 Function
333         %32 = OpVariable %21 Function
334         %37 = OpVariable %36 Function
335         %47 = OpVariable %46 Function
336               OpStore %8 %9
337               OpStore %10 %11
338               OpStore %12 %9
339               OpStore %13 %11
340               OpStore %16 %17
341               OpStore %18 %19
342               OpStore %22 %23
343               OpStore %24 %25
344               OpStore %28 %29
345               OpStore %30 %31
346               OpStore %32 %33
347               OpStore %37 %43
348               OpStore %47 %51
349               OpReturn
350               OpFunctionEnd
351  )";
352
353  const auto env = SPV_ENV_UNIVERSAL_1_4;
354  const auto consumer = nullptr;
355  const std::unique_ptr<opt::IRContext> context =
356      BuildModule(env, consumer, shader, kFuzzAssembleOption);
357  spvtools::ValidatorOptions validator_options;
358  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
359                                               kConsoleMessageConsumer));
360  TransformationContext transformation_context(
361      MakeUnique<FactManager>(context.get()), validator_options);
362
363  opt::IRContext* ir_context = context.get();
364
365  //      %43 = OpConstantComposite %35 %38 %39 %40 %41 %42
366  //    %51 = OpConstantComposite %45 %48 %49 %50
367  // This should pass as a float array with 5 elements exist and its id is 43.
368  ASSERT_EQ(43, fuzzerutil::MaybeGetCompositeConstant(
369                    ir_context, transformation_context, {38, 39, 40, 41, 42},
370                    35, false));
371  // This should pass as an int array with 3 elements exist and its id is 51.
372  ASSERT_EQ(51,
373            fuzzerutil::MaybeGetCompositeConstant(
374                ir_context, transformation_context, {48, 49, 50}, 45, false));
375  // An int array with 2 elements does not exist.
376  ASSERT_EQ(0, fuzzerutil::MaybeGetCompositeConstant(
377                   ir_context, transformation_context, {48, 49}, 45, false));
378}
379
380TEST(FuzzerutilTest, FuzzerUtilMaybeGetFloatConstantTest) {
381  std::string shader = R"(
382               OpCapability Shader
383          %1 = OpExtInstImport "GLSL.std.450"
384               OpMemoryModel Logical GLSL450
385               OpEntryPoint Fragment %4 "main" %36
386               OpExecutionMode %4 OriginUpperLeft
387               OpSource ESSL 310
388               OpName %4 "main"
389               OpName %8 "b1"
390               OpName %10 "b2"
391               OpName %12 "b3"
392               OpName %13 "b4"
393               OpName %16 "f1"
394               OpName %18 "f2"
395               OpName %20 "cf1"
396               OpName %22 "cf2"
397               OpName %26 "i1"
398               OpName %28 "i2"
399               OpName %30 "ci1"
400               OpName %32 "ci2"
401               OpName %36 "value"
402               OpDecorate %26 RelaxedPrecision
403               OpDecorate %28 RelaxedPrecision
404               OpDecorate %30 RelaxedPrecision
405               OpDecorate %32 RelaxedPrecision
406               OpDecorate %36 Location 0
407          %2 = OpTypeVoid
408          %3 = OpTypeFunction %2
409          %6 = OpTypeBool
410          %7 = OpTypePointer Function %6
411          %9 = OpConstantTrue %6
412         %11 = OpConstantFalse %6
413         %14 = OpTypeFloat 32
414         %15 = OpTypePointer Function %14
415         %17 = OpConstant %14 1.23000002
416         %19 = OpConstant %14 1.11000001
417         %21 = OpConstant %14 2
418         %23 = OpConstant %14 3.29999995
419         %24 = OpTypeInt 32 1
420         %25 = OpTypePointer Function %24
421         %27 = OpConstant %24 1
422         %29 = OpConstant %24 100
423         %31 = OpConstant %24 123
424         %33 = OpConstant %24 1111
425         %35 = OpTypePointer Input %14
426         %36 = OpVariable %35 Input
427          %4 = OpFunction %2 None %3
428          %5 = OpLabel
429          %8 = OpVariable %7 Function
430         %10 = OpVariable %7 Function
431         %12 = OpVariable %7 Function
432         %13 = OpVariable %7 Function
433         %16 = OpVariable %15 Function
434         %18 = OpVariable %15 Function
435         %20 = OpVariable %15 Function
436         %22 = OpVariable %15 Function
437         %26 = OpVariable %25 Function
438         %28 = OpVariable %25 Function
439         %30 = OpVariable %25 Function
440         %32 = OpVariable %25 Function
441               OpStore %8 %9
442               OpStore %10 %11
443               OpStore %12 %9
444               OpStore %13 %11
445               OpStore %16 %17
446               OpStore %18 %19
447               OpStore %20 %21
448               OpStore %22 %23
449               OpStore %26 %27
450               OpStore %28 %29
451               OpStore %30 %31
452               OpStore %32 %33
453               OpReturn
454               OpFunctionEnd
455  )";
456
457  const auto env = SPV_ENV_UNIVERSAL_1_4;
458  const auto consumer = nullptr;
459  const std::unique_ptr<opt::IRContext> context =
460      BuildModule(env, consumer, shader, kFuzzAssembleOption);
461  spvtools::ValidatorOptions validator_options;
462  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
463                                               kConsoleMessageConsumer));
464  TransformationContext transformation_context(
465      MakeUnique<FactManager>(context.get()), validator_options);
466
467  opt::IRContext* ir_context = context.get();
468
469  uint32_t word1 = fuzzerutil::FloatToWord(2);
470  uint32_t word2 = fuzzerutil::FloatToWord(1.23f);
471
472  // A 32 bit float constant of value 2 exists and its id is 21.
473  ASSERT_EQ(21, fuzzerutil::MaybeGetFloatConstant(
474                    ir_context, transformation_context,
475                    std::vector<uint32_t>{word1}, 32, false));
476  // A 32 bit float constant of value 1.23 exists and its id is 17.
477  ASSERT_EQ(17, fuzzerutil::MaybeGetFloatConstant(
478                    ir_context, transformation_context,
479                    std::vector<uint32_t>{word2}, 32, false));
480}
481
482TEST(FuzzerutilTest, FuzzerUtilMaybeGetFloatTypeTest) {
483  std::string shader = R"(
484               OpCapability Shader
485          %1 = OpExtInstImport "GLSL.std.450"
486               OpMemoryModel Logical GLSL450
487               OpEntryPoint Fragment %4 "main" %92 %52 %53
488               OpExecutionMode %4 OriginUpperLeft
489               OpSource ESSL 310
490               OpDecorate %92 BuiltIn FragCoord
491          %2 = OpTypeVoid
492          %3 = OpTypeFunction %2
493          %6 = OpTypeInt 32 1
494          %7 = OpTypeFloat 32
495          %8 = OpTypeStruct %6 %7
496          %9 = OpTypePointer Function %8
497         %10 = OpTypeFunction %6 %9
498         %14 = OpConstant %6 0
499         %15 = OpTypePointer Function %6
500         %51 = OpTypePointer Private %6
501         %21 = OpConstant %6 2
502         %23 = OpConstant %6 1
503         %24 = OpConstant %7 1
504         %25 = OpTypePointer Function %7
505         %50 = OpTypePointer Private %7
506         %34 = OpTypeBool
507         %35 = OpConstantFalse %34
508         %52 = OpVariable %50 Private
509         %53 = OpVariable %51 Private
510         %80 = OpConstantComposite %8 %21 %24
511         %90 = OpTypeVector %7 4
512         %91 = OpTypePointer Input %90
513         %92 = OpVariable %91 Input
514         %93 = OpConstantComposite %90 %24 %24 %24 %24
515          %4 = OpFunction %2 None %3
516          %5 = OpLabel
517         %20 = OpVariable %9 Function
518         %27 = OpVariable %9 Function
519         %22 = OpAccessChain %15 %20 %14
520         %44 = OpCopyObject %9 %20
521         %26 = OpAccessChain %25 %20 %23
522         %29 = OpFunctionCall %6 %12 %27
523         %30 = OpAccessChain %15 %20 %14
524         %45 = OpCopyObject %15 %30
525         %81 = OpCopyObject %9 %27
526         %33 = OpAccessChain %15 %20 %14
527               OpSelectionMerge %37 None
528               OpBranchConditional %35 %36 %37
529         %36 = OpLabel
530         %38 = OpAccessChain %15 %20 %14
531         %40 = OpAccessChain %15 %20 %14
532         %43 = OpAccessChain %15 %20 %14
533         %82 = OpCopyObject %9 %27
534               OpBranch %37
535         %37 = OpLabel
536               OpReturn
537               OpFunctionEnd
538         %12 = OpFunction %6 None %10
539         %11 = OpFunctionParameter %9
540         %13 = OpLabel
541         %46 = OpCopyObject %9 %11
542         %16 = OpAccessChain %15 %11 %14
543         %95 = OpCopyObject %8 %80
544               OpReturnValue %21
545        %100 = OpLabel
546               OpUnreachable
547               OpFunctionEnd
548  )";
549
550  const auto env = SPV_ENV_UNIVERSAL_1_4;
551  const auto consumer = nullptr;
552  const std::unique_ptr<opt::IRContext> context =
553      BuildModule(env, consumer, shader, kFuzzAssembleOption);
554  spvtools::ValidatorOptions validator_options;
555  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
556                                               kConsoleMessageConsumer));
557
558  opt::IRContext* ir_context = context.get();
559  // A float type with width = 32 and result id of 7 exists.
560  ASSERT_EQ(7, fuzzerutil::MaybeGetFloatType(ir_context, 32));
561
562  // A float int type with width = 32 exists, but the id should be 7.
563  ASSERT_NE(5, fuzzerutil::MaybeGetFloatType(ir_context, 32));
564
565  // A float type with width 30 does not exist.
566  ASSERT_EQ(0, fuzzerutil::MaybeGetFloatType(ir_context, 30));
567}
568
569TEST(FuzzerutilTest, FuzzerUtilMaybeGetIntegerConstantFromValueAndTypeTest) {
570  std::string shader = R"(
571               OpCapability Shader
572          %1 = OpExtInstImport "GLSL.std.450"
573               OpMemoryModel Logical GLSL450
574               OpEntryPoint Fragment %4 "main" %36
575               OpExecutionMode %4 OriginUpperLeft
576               OpSource ESSL 310
577               OpName %4 "main"
578               OpName %8 "b1"
579               OpName %10 "b2"
580               OpName %12 "b3"
581               OpName %13 "b4"
582               OpName %16 "f1"
583               OpName %18 "f2"
584               OpName %22 "zc"
585               OpName %24 "i1"
586               OpName %28 "i2"
587               OpName %30 "i3"
588               OpName %32 "i4"
589               OpName %36 "value"
590               OpDecorate %22 RelaxedPrecision
591               OpDecorate %24 RelaxedPrecision
592               OpDecorate %28 RelaxedPrecision
593               OpDecorate %30 RelaxedPrecision
594               OpDecorate %32 RelaxedPrecision
595               OpDecorate %36 Location 0
596          %2 = OpTypeVoid
597          %3 = OpTypeFunction %2
598          %6 = OpTypeBool
599          %7 = OpTypePointer Function %6
600          %9 = OpConstantTrue %6
601         %11 = OpConstantFalse %6
602         %14 = OpTypeFloat 32
603         %15 = OpTypePointer Function %14
604         %17 = OpConstant %14 1.23000002
605         %19 = OpConstant %14 1.11000001
606         %20 = OpTypeInt 32 1
607         %21 = OpTypePointer Function %20
608         %23 = OpConstant %20 0
609         %25 = OpConstant %20 1
610         %26 = OpTypeInt 32 0
611         %27 = OpTypePointer Function %26
612         %29 = OpConstant %26 100
613         %31 = OpConstant %20 -1
614         %33 = OpConstant %20 -99
615         %35 = OpTypePointer Input %14
616         %36 = OpVariable %35 Input
617          %4 = OpFunction %2 None %3
618          %5 = OpLabel
619          %8 = OpVariable %7 Function
620         %10 = OpVariable %7 Function
621         %12 = OpVariable %7 Function
622         %13 = OpVariable %7 Function
623         %16 = OpVariable %15 Function
624         %18 = OpVariable %15 Function
625         %22 = OpVariable %21 Function
626         %24 = OpVariable %21 Function
627         %28 = OpVariable %27 Function
628         %30 = OpVariable %21 Function
629         %32 = OpVariable %21 Function
630               OpStore %8 %9
631               OpStore %10 %11
632               OpStore %12 %9
633               OpStore %13 %11
634               OpStore %16 %17
635               OpStore %18 %19
636               OpStore %22 %23
637               OpStore %24 %25
638               OpStore %28 %29
639               OpStore %30 %31
640               OpStore %32 %33
641               OpReturn
642               OpFunctionEnd
643  )";
644
645  const auto env = SPV_ENV_UNIVERSAL_1_4;
646  const auto consumer = nullptr;
647  const std::unique_ptr<opt::IRContext> context =
648      BuildModule(env, consumer, shader, kFuzzAssembleOption);
649  spvtools::ValidatorOptions validator_options;
650  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
651                                               kConsoleMessageConsumer));
652
653  opt::IRContext* ir_context = context.get();
654
655  // A 32 bit signed int constant (with int type id 20) with value 1 exists and
656  // the id is 25.
657  ASSERT_EQ(25, fuzzerutil::MaybeGetIntegerConstantFromValueAndType(ir_context,
658                                                                    1, 20));
659  // A 32 bit unsigned int constant (with int type id 0) with value 100 exists
660  // and the id is 29.
661  ASSERT_EQ(29, fuzzerutil::MaybeGetIntegerConstantFromValueAndType(ir_context,
662                                                                    100, 26));
663  // A 32 bit unsigned int constant with value 50 does not exist.
664  ASSERT_EQ(0, fuzzerutil::MaybeGetIntegerConstantFromValueAndType(ir_context,
665                                                                   50, 26));
666}
667
668TEST(FuzzerutilTest, FuzzerUtilMaybeGetIntegerConstantTest) {
669  std::string shader = R"(
670OpCapability Shader
671               OpCapability Shader
672          %1 = OpExtInstImport "GLSL.std.450"
673               OpMemoryModel Logical GLSL450
674               OpEntryPoint Fragment %4 "main" %36
675               OpExecutionMode %4 OriginUpperLeft
676               OpSource ESSL 310
677               OpName %4 "main"
678               OpName %8 "b1"
679               OpName %10 "b2"
680               OpName %12 "b3"
681               OpName %13 "b4"
682               OpName %16 "f1"
683               OpName %18 "f2"
684               OpName %22 "zc"
685               OpName %24 "i1"
686               OpName %28 "i2"
687               OpName %30 "i3"
688               OpName %32 "i4"
689               OpName %36 "value"
690               OpDecorate %22 RelaxedPrecision
691               OpDecorate %24 RelaxedPrecision
692               OpDecorate %28 RelaxedPrecision
693               OpDecorate %30 RelaxedPrecision
694               OpDecorate %32 RelaxedPrecision
695               OpDecorate %36 Location 0
696          %2 = OpTypeVoid
697          %3 = OpTypeFunction %2
698          %6 = OpTypeBool
699          %7 = OpTypePointer Function %6
700          %9 = OpConstantTrue %6
701         %11 = OpConstantFalse %6
702         %14 = OpTypeFloat 32
703         %15 = OpTypePointer Function %14
704         %17 = OpConstant %14 1.23000002
705         %19 = OpConstant %14 1.11000001
706         %20 = OpTypeInt 32 1
707         %21 = OpTypePointer Function %20
708         %23 = OpConstant %20 0
709         %25 = OpConstant %20 1
710         %26 = OpTypeInt 32 0
711         %27 = OpTypePointer Function %26
712         %29 = OpConstant %26 100
713         %31 = OpConstant %20 -1
714         %33 = OpConstant %20 -99
715         %35 = OpTypePointer Input %14
716         %36 = OpVariable %35 Input
717          %4 = OpFunction %2 None %3
718          %5 = OpLabel
719          %8 = OpVariable %7 Function
720         %10 = OpVariable %7 Function
721         %12 = OpVariable %7 Function
722         %13 = OpVariable %7 Function
723         %16 = OpVariable %15 Function
724         %18 = OpVariable %15 Function
725         %22 = OpVariable %21 Function
726         %24 = OpVariable %21 Function
727         %28 = OpVariable %27 Function
728         %30 = OpVariable %21 Function
729         %32 = OpVariable %21 Function
730               OpStore %8 %9
731               OpStore %10 %11
732               OpStore %12 %9
733               OpStore %13 %11
734               OpStore %16 %17
735               OpStore %18 %19
736               OpStore %22 %23
737               OpStore %24 %25
738               OpStore %28 %29
739               OpStore %30 %31
740               OpStore %32 %33
741               OpReturn
742               OpFunctionEnd
743  )";
744
745  const auto env = SPV_ENV_UNIVERSAL_1_4;
746  const auto consumer = nullptr;
747  const std::unique_ptr<opt::IRContext> context =
748      BuildModule(env, consumer, shader, kFuzzAssembleOption);
749  spvtools::ValidatorOptions validator_options;
750  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
751                                               kConsoleMessageConsumer));
752  TransformationContext transformation_context(
753      MakeUnique<FactManager>(context.get()), validator_options);
754
755  opt::IRContext* ir_context = context.get();
756
757  // A 32 bit unsigned int constant with value 1 exists and the id is 25.
758  ASSERT_EQ(25, fuzzerutil::MaybeGetIntegerConstant(
759                    ir_context, transformation_context,
760                    std::vector<uint32_t>{1}, 32, true, false));
761  // A 32 bit unsigned int constant with value 100 exists and the id is 29.
762  ASSERT_EQ(29, fuzzerutil::MaybeGetIntegerConstant(
763                    ir_context, transformation_context,
764                    std::vector<uint32_t>{100}, 32, false, false));
765  // A 32 bit signed int constant with value 99 doesn't not exist and should
766  // return 0.
767  ASSERT_EQ(0, fuzzerutil::MaybeGetIntegerConstant(
768                   ir_context, transformation_context,
769                   std::vector<uint32_t>{99}, 32, true, false));
770}
771
772TEST(FuzzerutilTest, FuzzerUtilMaybeGetIntegerTypeTest) {
773  std::string shader = R"(
774               OpCapability Shader
775          %1 = OpExtInstImport "GLSL.std.450"
776               OpMemoryModel Logical GLSL450
777               OpEntryPoint Fragment %4 "main" %92 %52 %53
778               OpExecutionMode %4 OriginUpperLeft
779               OpSource ESSL 310
780               OpDecorate %92 BuiltIn FragCoord
781          %2 = OpTypeVoid
782          %3 = OpTypeFunction %2
783          %6 = OpTypeInt 32 1
784          %7 = OpTypeFloat 32
785          %8 = OpTypeStruct %6 %7
786          %9 = OpTypePointer Function %8
787         %10 = OpTypeFunction %6 %9
788         %14 = OpConstant %6 0
789         %15 = OpTypePointer Function %6
790         %51 = OpTypePointer Private %6
791         %21 = OpConstant %6 2
792         %23 = OpConstant %6 1
793         %24 = OpConstant %7 1
794         %25 = OpTypePointer Function %7
795         %50 = OpTypePointer Private %7
796         %34 = OpTypeBool
797         %35 = OpConstantFalse %34
798         %52 = OpVariable %50 Private
799         %53 = OpVariable %51 Private
800         %80 = OpConstantComposite %8 %21 %24
801         %90 = OpTypeVector %7 4
802         %91 = OpTypePointer Input %90
803         %92 = OpVariable %91 Input
804         %93 = OpConstantComposite %90 %24 %24 %24 %24
805          %4 = OpFunction %2 None %3
806          %5 = OpLabel
807         %20 = OpVariable %9 Function
808         %27 = OpVariable %9 Function
809         %22 = OpAccessChain %15 %20 %14
810         %44 = OpCopyObject %9 %20
811         %26 = OpAccessChain %25 %20 %23
812         %29 = OpFunctionCall %6 %12 %27
813         %30 = OpAccessChain %15 %20 %14
814         %45 = OpCopyObject %15 %30
815         %81 = OpCopyObject %9 %27
816         %33 = OpAccessChain %15 %20 %14
817               OpSelectionMerge %37 None
818               OpBranchConditional %35 %36 %37
819         %36 = OpLabel
820         %38 = OpAccessChain %15 %20 %14
821         %40 = OpAccessChain %15 %20 %14
822         %43 = OpAccessChain %15 %20 %14
823         %82 = OpCopyObject %9 %27
824               OpBranch %37
825         %37 = OpLabel
826               OpReturn
827               OpFunctionEnd
828         %12 = OpFunction %6 None %10
829         %11 = OpFunctionParameter %9
830         %13 = OpLabel
831         %46 = OpCopyObject %9 %11
832         %16 = OpAccessChain %15 %11 %14
833         %95 = OpCopyObject %8 %80
834               OpReturnValue %21
835        %100 = OpLabel
836               OpUnreachable
837               OpFunctionEnd
838  )";
839
840  const auto env = SPV_ENV_UNIVERSAL_1_4;
841  const auto consumer = nullptr;
842  const std::unique_ptr<opt::IRContext> context =
843      BuildModule(env, consumer, shader, kFuzzAssembleOption);
844  spvtools::ValidatorOptions validator_options;
845  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
846                                               kConsoleMessageConsumer));
847
848  opt::IRContext* ir_context = context.get();
849
850  // A signed int type with width = 32 and result id of 6 exists.
851  ASSERT_EQ(6, fuzzerutil::MaybeGetIntegerType(ir_context, 32, true));
852
853  // A signed int type with width = 32 exists, but the id should be 6.
854  ASSERT_FALSE(fuzzerutil::MaybeGetIntegerType(ir_context, 32, true) == 5);
855
856  // A int type with width = 32 and result id of 6 exists, but it should be a
857  // signed int.
858  ASSERT_EQ(0, fuzzerutil::MaybeGetIntegerType(ir_context, 32, false));
859  // A signed int type with width 30 does not exist.
860  ASSERT_EQ(0, fuzzerutil::MaybeGetIntegerType(ir_context, 30, true));
861  // An unsigned int type with width 22 does not exist.
862  ASSERT_EQ(0, fuzzerutil::MaybeGetIntegerType(ir_context, 22, false));
863}
864
865TEST(FuzzerutilTest, FuzzerUtilMaybeGetPointerTypeTest) {
866  std::string shader = R"(
867               OpCapability Shader
868          %1 = OpExtInstImport "GLSL.std.450"
869               OpMemoryModel Logical GLSL450
870               OpEntryPoint Fragment %4 "main" %92 %52 %53
871               OpExecutionMode %4 OriginUpperLeft
872               OpSource ESSL 310
873               OpDecorate %92 BuiltIn FragCoord
874          %2 = OpTypeVoid
875          %3 = OpTypeFunction %2
876          %6 = OpTypeInt 32 1
877          %7 = OpTypeFloat 32
878          %8 = OpTypeStruct %6 %7
879          %9 = OpTypePointer Function %8
880         %10 = OpTypeFunction %6 %9
881         %14 = OpConstant %6 0
882         %15 = OpTypePointer Function %6
883         %51 = OpTypePointer Private %6
884         %21 = OpConstant %6 2
885         %23 = OpConstant %6 1
886         %24 = OpConstant %7 1
887         %25 = OpTypePointer Function %7
888         %50 = OpTypePointer Private %7
889         %34 = OpTypeBool
890         %35 = OpConstantFalse %34
891         %52 = OpVariable %50 Private
892         %53 = OpVariable %51 Private
893         %80 = OpConstantComposite %8 %21 %24
894         %90 = OpTypeVector %7 4
895         %91 = OpTypePointer Input %90
896         %92 = OpVariable %91 Input
897         %93 = OpConstantComposite %90 %24 %24 %24 %24
898          %4 = OpFunction %2 None %3
899          %5 = OpLabel
900         %20 = OpVariable %9 Function
901         %27 = OpVariable %9 Function
902         %22 = OpAccessChain %15 %20 %14
903         %44 = OpCopyObject %9 %20
904         %26 = OpAccessChain %25 %20 %23
905         %29 = OpFunctionCall %6 %12 %27
906         %30 = OpAccessChain %15 %20 %14
907         %45 = OpCopyObject %15 %30
908         %81 = OpCopyObject %9 %27
909         %33 = OpAccessChain %15 %20 %14
910               OpSelectionMerge %37 None
911               OpBranchConditional %35 %36 %37
912         %36 = OpLabel
913         %38 = OpAccessChain %15 %20 %14
914         %40 = OpAccessChain %15 %20 %14
915         %43 = OpAccessChain %15 %20 %14
916         %82 = OpCopyObject %9 %27
917               OpBranch %37
918         %37 = OpLabel
919               OpReturn
920               OpFunctionEnd
921         %12 = OpFunction %6 None %10
922         %11 = OpFunctionParameter %9
923         %13 = OpLabel
924         %46 = OpCopyObject %9 %11
925         %16 = OpAccessChain %15 %11 %14
926         %95 = OpCopyObject %8 %80
927               OpReturnValue %21
928        %100 = OpLabel
929               OpUnreachable
930               OpFunctionEnd
931  )";
932
933  const auto env = SPV_ENV_UNIVERSAL_1_4;
934  const auto consumer = nullptr;
935  const std::unique_ptr<opt::IRContext> context =
936      BuildModule(env, consumer, shader, kFuzzAssembleOption);
937  spvtools::ValidatorOptions validator_options;
938  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
939                                               kConsoleMessageConsumer));
940
941  opt::IRContext* ir_context = context.get();
942  auto private_storage_class = spv::StorageClass::Private;
943  auto function_storage_class = spv::StorageClass::Function;
944  auto input_storage_class = spv::StorageClass::Input;
945
946  // A valid pointer must have the correct |pointee_type_id| and |storageClass|.
947  // A function type pointer with id = 9 and pointee type id 8 should be found.
948  ASSERT_EQ(9, fuzzerutil::MaybeGetPointerType(ir_context, 8,
949                                               function_storage_class));
950  // A function type pointer with id = 15 and pointee type id 6 should be found.
951  ASSERT_EQ(15, fuzzerutil::MaybeGetPointerType(ir_context, 6,
952                                                function_storage_class));
953  // A function type pointer with id = 25 and pointee type id 7 should be found.
954  ASSERT_EQ(25, fuzzerutil::MaybeGetPointerType(ir_context, 7,
955                                                function_storage_class));
956
957  // A private type pointer with id=51 and pointee type id 6 should be found.
958  ASSERT_EQ(51, fuzzerutil::MaybeGetPointerType(ir_context, 6,
959                                                private_storage_class));
960  // A function pointer with id=50 and pointee type id 7 should be found.
961  ASSERT_EQ(50, fuzzerutil::MaybeGetPointerType(ir_context, 7,
962                                                private_storage_class));
963
964  // A input type pointer with id=91 and pointee type id 90 should be found.
965  ASSERT_EQ(
966      91, fuzzerutil::MaybeGetPointerType(ir_context, 90, input_storage_class));
967
968  // A pointer with id=91 and pointee type 90 exists, but the type should be
969  // input.
970  ASSERT_EQ(0, fuzzerutil::MaybeGetPointerType(ir_context, 90,
971                                               function_storage_class));
972  // A input type pointer with id=91 exists but the pointee id should be 90.
973  ASSERT_EQ(
974      0, fuzzerutil::MaybeGetPointerType(ir_context, 89, input_storage_class));
975  // A input type pointer with pointee id 90 exists but result id of the pointer
976  // should be 91.
977  ASSERT_NE(
978      58, fuzzerutil::MaybeGetPointerType(ir_context, 90, input_storage_class));
979}
980
981TEST(FuzzerutilTest, FuzzerUtilMaybeGetScalarConstantTest) {
982  std::string shader = R"(
983               OpCapability Shader
984          %1 = OpExtInstImport "GLSL.std.450"
985               OpMemoryModel Logical GLSL450
986               OpEntryPoint Fragment %4 "main" %56
987               OpExecutionMode %4 OriginUpperLeft
988               OpSource ESSL 310
989               OpName %4 "main"
990               OpName %8 "b1"
991               OpName %10 "b2"
992               OpName %12 "b3"
993               OpName %13 "b4"
994               OpName %16 "f1"
995               OpName %18 "f2"
996               OpName %22 "zc"
997               OpName %24 "i1"
998               OpName %28 "i2"
999               OpName %30 "i"
1000               OpName %32 "i3"
1001               OpName %34 "i4"
1002               OpName %39 "f_arr"
1003               OpName %49 "i_arr"
1004               OpName %56 "value"
1005               OpDecorate %22 RelaxedPrecision
1006               OpDecorate %24 RelaxedPrecision
1007               OpDecorate %28 RelaxedPrecision
1008               OpDecorate %30 RelaxedPrecision
1009               OpDecorate %32 RelaxedPrecision
1010               OpDecorate %34 RelaxedPrecision
1011               OpDecorate %49 RelaxedPrecision
1012               OpDecorate %56 Location 0
1013          %2 = OpTypeVoid
1014          %3 = OpTypeFunction %2
1015          %6 = OpTypeBool
1016          %7 = OpTypePointer Function %6
1017          %9 = OpConstantTrue %6
1018         %11 = OpConstantFalse %6
1019         %14 = OpTypeFloat 32
1020         %15 = OpTypePointer Function %14
1021         %17 = OpConstant %14 1.23000002
1022         %19 = OpConstant %14 1.11000001
1023         %20 = OpTypeInt 32 1
1024         %21 = OpTypePointer Function %20
1025         %23 = OpConstant %20 0
1026         %25 = OpConstant %20 1
1027         %26 = OpTypeInt 32 0
1028         %27 = OpTypePointer Function %26
1029         %29 = OpConstant %26 100
1030         %31 = OpConstant %26 0
1031         %33 = OpConstant %20 -1
1032         %35 = OpConstant %20 -99
1033         %36 = OpConstant %26 5
1034         %37 = OpTypeArray %14 %36
1035         %38 = OpTypePointer Function %37
1036         %40 = OpConstant %14 5.5
1037         %41 = OpConstant %14 4.4000001
1038         %42 = OpConstant %14 3.29999995
1039         %43 = OpConstant %14 2.20000005
1040         %44 = OpConstant %14 1.10000002
1041         %45 = OpConstantComposite %37 %40 %41 %42 %43 %44
1042         %46 = OpConstant %26 3
1043         %47 = OpTypeArray %20 %46
1044         %48 = OpTypePointer Function %47
1045         %50 = OpConstant %20 3
1046         %51 = OpConstant %20 7
1047         %52 = OpConstant %20 9
1048         %53 = OpConstantComposite %47 %50 %51 %52
1049         %55 = OpTypePointer Input %14
1050         %56 = OpVariable %55 Input
1051          %4 = OpFunction %2 None %3
1052          %5 = OpLabel
1053          %8 = OpVariable %7 Function
1054         %10 = OpVariable %7 Function
1055         %12 = OpVariable %7 Function
1056         %13 = OpVariable %7 Function
1057         %16 = OpVariable %15 Function
1058         %18 = OpVariable %15 Function
1059         %22 = OpVariable %21 Function
1060         %24 = OpVariable %21 Function
1061         %28 = OpVariable %27 Function
1062         %30 = OpVariable %27 Function
1063         %32 = OpVariable %21 Function
1064         %34 = OpVariable %21 Function
1065         %39 = OpVariable %38 Function
1066         %49 = OpVariable %48 Function
1067               OpStore %8 %9
1068               OpStore %10 %11
1069               OpStore %12 %9
1070               OpStore %13 %11
1071               OpStore %16 %17
1072               OpStore %18 %19
1073               OpStore %22 %23
1074               OpStore %24 %25
1075               OpStore %28 %29
1076               OpStore %30 %31
1077               OpStore %32 %33
1078               OpStore %34 %35
1079               OpStore %39 %45
1080               OpStore %49 %53
1081               OpReturn
1082               OpFunctionEnd
1083  )";
1084
1085  const auto env = SPV_ENV_UNIVERSAL_1_4;
1086  const auto consumer = nullptr;
1087  const std::unique_ptr<opt::IRContext> context =
1088      BuildModule(env, consumer, shader, kFuzzAssembleOption);
1089  spvtools::ValidatorOptions validator_options;
1090  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1091                                               kConsoleMessageConsumer));
1092  TransformationContext transformation_context(
1093      MakeUnique<FactManager>(context.get()), validator_options);
1094
1095  opt::IRContext* ir_context = context.get();
1096
1097  std::vector<uint32_t> uint_words1 = fuzzerutil::IntToWords(100, 32, false);
1098  std::vector<uint32_t> uint_words2 = fuzzerutil::IntToWords(0, 32, false);
1099  std::vector<uint32_t> int_words1 = fuzzerutil::IntToWords(-99, 32, true);
1100  std::vector<uint32_t> int_words2 = fuzzerutil::IntToWords(1, 32, true);
1101  uint32_t float_word1 = fuzzerutil::FloatToWord(1.11f);
1102  uint32_t float_word2 = fuzzerutil::FloatToWord(4.4f);
1103
1104  // A unsigned int of value 100 that has a scalar type id of 26 exists and its
1105  // id is 29.
1106  ASSERT_EQ(
1107      29, fuzzerutil::MaybeGetScalarConstant(ir_context, transformation_context,
1108                                             uint_words1, 26, false));
1109  // A unsigned int of value 0 that has a scalar type id of 26 exists and its id
1110  // is 29.
1111  ASSERT_EQ(
1112      31, fuzzerutil::MaybeGetScalarConstant(ir_context, transformation_context,
1113                                             uint_words2, 26, false));
1114  // A signed int of value -99 that has a scalar type id of 20 exists and its id
1115  // is 35.
1116  ASSERT_EQ(35, fuzzerutil::MaybeGetScalarConstant(
1117                    ir_context, transformation_context, int_words1, 20, false));
1118  // A signed int of value 1 that has a scalar type id of 20 exists and its id
1119  // is 25.
1120  ASSERT_EQ(25, fuzzerutil::MaybeGetScalarConstant(
1121                    ir_context, transformation_context, int_words2, 20, false));
1122  // A float of value 1.11 that has a scalar type id of 14 exists and its id
1123  // is 19.
1124  ASSERT_EQ(19, fuzzerutil::MaybeGetScalarConstant(
1125                    ir_context, transformation_context,
1126                    std::vector<uint32_t>{float_word1}, 14, false));
1127  // A signed int of value 1 that has a scalar type id of 20 exists and its id
1128  // is 25.
1129  ASSERT_EQ(41, fuzzerutil::MaybeGetScalarConstant(
1130                    ir_context, transformation_context,
1131                    std::vector<uint32_t>{float_word2}, 14, false));
1132}
1133
1134TEST(FuzzerutilTest, FuzzerUtilMaybeGetStructTypeTest) {
1135  std::string shader = R"(
1136               OpCapability Shader
1137          %1 = OpExtInstImport "GLSL.std.450"
1138               OpMemoryModel Logical GLSL450
1139               OpEntryPoint Fragment %4 "main" %92 %52 %53
1140               OpExecutionMode %4 OriginUpperLeft
1141               OpSource ESSL 310
1142               OpDecorate %92 BuiltIn FragCoord
1143          %2 = OpTypeVoid
1144          %3 = OpTypeFunction %2
1145          %6 = OpTypeInt 32 1
1146          %7 = OpTypeFloat 32
1147          %8 = OpTypeStruct %6 %7
1148          %9 = OpTypePointer Function %8
1149         %10 = OpTypeFunction %6 %9
1150         %14 = OpConstant %6 0
1151         %15 = OpTypePointer Function %6
1152         %51 = OpTypePointer Private %6
1153         %21 = OpConstant %6 2
1154         %23 = OpConstant %6 1
1155         %24 = OpConstant %7 1
1156         %25 = OpTypePointer Function %7
1157         %50 = OpTypePointer Private %7
1158         %34 = OpTypeBool
1159         %35 = OpConstantFalse %34
1160         %52 = OpVariable %50 Private
1161         %53 = OpVariable %51 Private
1162         %80 = OpConstantComposite %8 %21 %24
1163         %90 = OpTypeVector %7 4
1164         %91 = OpTypePointer Input %90
1165         %92 = OpVariable %91 Input
1166         %93 = OpConstantComposite %90 %24 %24 %24 %24
1167          %4 = OpFunction %2 None %3
1168          %5 = OpLabel
1169         %20 = OpVariable %9 Function
1170         %27 = OpVariable %9 Function
1171         %22 = OpAccessChain %15 %20 %14
1172         %44 = OpCopyObject %9 %20
1173         %26 = OpAccessChain %25 %20 %23
1174         %29 = OpFunctionCall %6 %12 %27
1175         %30 = OpAccessChain %15 %20 %14
1176         %45 = OpCopyObject %15 %30
1177         %81 = OpCopyObject %9 %27
1178         %33 = OpAccessChain %15 %20 %14
1179               OpSelectionMerge %37 None
1180               OpBranchConditional %35 %36 %37
1181         %36 = OpLabel
1182         %38 = OpAccessChain %15 %20 %14
1183         %40 = OpAccessChain %15 %20 %14
1184         %43 = OpAccessChain %15 %20 %14
1185         %82 = OpCopyObject %9 %27
1186               OpBranch %37
1187         %37 = OpLabel
1188               OpReturn
1189               OpFunctionEnd
1190         %12 = OpFunction %6 None %10
1191         %11 = OpFunctionParameter %9
1192         %13 = OpLabel
1193         %46 = OpCopyObject %9 %11
1194         %16 = OpAccessChain %15 %11 %14
1195         %95 = OpCopyObject %8 %80
1196               OpReturnValue %21
1197        %100 = OpLabel
1198               OpUnreachable
1199               OpFunctionEnd
1200  )";
1201
1202  const auto env = SPV_ENV_UNIVERSAL_1_4;
1203  const auto consumer = nullptr;
1204  const std::unique_ptr<opt::IRContext> context =
1205      BuildModule(env, consumer, shader, kFuzzAssembleOption);
1206  spvtools::ValidatorOptions validator_options;
1207  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1208                                               kConsoleMessageConsumer));
1209
1210  opt::IRContext* ir_context = context.get();
1211
1212  // 6 and 7 are all valid ids from OpTypeInt and OpTypeFloat
1213  // so the result id of 8 should be found.
1214  ASSERT_EQ(8, fuzzerutil::MaybeGetStructType(ir_context,
1215                                              std::vector<uint32_t>{6, 7}));
1216
1217  // |component_type_id| of 16 does not exist in the module, so such a struct
1218  // type cannot be found.
1219  ASSERT_EQ(0, fuzzerutil::MaybeGetStructType(ir_context,
1220                                              std::vector<uint32_t>(6, 16)));
1221
1222  // |component_type_id| of 10 is of OpTypeFunction type and thus the struct
1223  // cannot be found.
1224  ASSERT_EQ(0, fuzzerutil::MaybeGetStructType(ir_context,
1225                                              std::vector<uint32_t>(6, 10)));
1226}
1227
1228TEST(FuzzerutilTest, FuzzerUtilMaybeGetVectorTypeTest) {
1229  std::string shader = R"(
1230               OpCapability Shader
1231          %1 = OpExtInstImport "GLSL.std.450"
1232               OpMemoryModel Logical GLSL450
1233               OpEntryPoint Fragment %4 "main" %92 %52 %53
1234               OpExecutionMode %4 OriginUpperLeft
1235               OpSource ESSL 310
1236               OpDecorate %92 BuiltIn FragCoord
1237          %2 = OpTypeVoid
1238          %3 = OpTypeFunction %2
1239          %6 = OpTypeInt 32 1
1240          %7 = OpTypeFloat 32
1241          %8 = OpTypeStruct %6 %7
1242          %9 = OpTypePointer Function %8
1243         %10 = OpTypeFunction %6 %9
1244         %14 = OpConstant %6 0
1245         %15 = OpTypePointer Function %6
1246         %51 = OpTypePointer Private %6
1247         %21 = OpConstant %6 2
1248         %23 = OpConstant %6 1
1249         %24 = OpConstant %7 1
1250         %25 = OpTypePointer Function %7
1251         %50 = OpTypePointer Private %7
1252         %34 = OpTypeBool
1253         %35 = OpConstantFalse %34
1254         %52 = OpVariable %50 Private
1255         %53 = OpVariable %51 Private
1256         %80 = OpConstantComposite %8 %21 %24
1257         %90 = OpTypeVector %7 4
1258         %91 = OpTypePointer Input %90
1259         %92 = OpVariable %91 Input
1260         %93 = OpConstantComposite %90 %24 %24 %24 %24
1261          %4 = OpFunction %2 None %3
1262          %5 = OpLabel
1263         %20 = OpVariable %9 Function
1264         %27 = OpVariable %9 Function
1265         %22 = OpAccessChain %15 %20 %14
1266         %44 = OpCopyObject %9 %20
1267         %26 = OpAccessChain %25 %20 %23
1268         %29 = OpFunctionCall %6 %12 %27
1269         %30 = OpAccessChain %15 %20 %14
1270         %45 = OpCopyObject %15 %30
1271         %81 = OpCopyObject %9 %27
1272         %33 = OpAccessChain %15 %20 %14
1273               OpSelectionMerge %37 None
1274               OpBranchConditional %35 %36 %37
1275         %36 = OpLabel
1276         %38 = OpAccessChain %15 %20 %14
1277         %40 = OpAccessChain %15 %20 %14
1278         %43 = OpAccessChain %15 %20 %14
1279         %82 = OpCopyObject %9 %27
1280               OpBranch %37
1281         %37 = OpLabel
1282               OpReturn
1283               OpFunctionEnd
1284         %12 = OpFunction %6 None %10
1285         %11 = OpFunctionParameter %9
1286         %13 = OpLabel
1287         %46 = OpCopyObject %9 %11
1288         %16 = OpAccessChain %15 %11 %14
1289         %95 = OpCopyObject %8 %80
1290               OpReturnValue %21
1291        %100 = OpLabel
1292               OpUnreachable
1293               OpFunctionEnd
1294  )";
1295
1296  const auto env = SPV_ENV_UNIVERSAL_1_4;
1297  const auto consumer = nullptr;
1298  const std::unique_ptr<opt::IRContext> context =
1299      BuildModule(env, consumer, shader, kFuzzAssembleOption);
1300  spvtools::ValidatorOptions validator_options;
1301  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1302                                               kConsoleMessageConsumer));
1303
1304  opt::IRContext* ir_context = context.get();
1305  // The vector type with |element_count| 4 and |component_type_id| 7
1306  // is present and has a result id of 90.
1307  ASSERT_EQ(90, fuzzerutil::MaybeGetVectorType(ir_context, 7, 4));
1308
1309  // The vector type with |element_count| 3 and |component_type_id| 7
1310  // is not present in the module.
1311  ASSERT_EQ(0, fuzzerutil::MaybeGetVectorType(ir_context, 7, 3));
1312
1313#ifndef NDEBUG
1314  // It should abort with |component_type_id| of 100
1315  // |component_type_id| must be a valid result id of an OpTypeInt,
1316  // OpTypeFloat or OpTypeBool instruction in the module.
1317  ASSERT_DEATH(fuzzerutil::MaybeGetVectorType(ir_context, 100, 4),
1318               "\\|component_type_id\\| is invalid");
1319
1320  // It should abort with |element_count| of 5.
1321  // |element_count| must be in the range [2,4].
1322  ASSERT_DEATH(fuzzerutil::MaybeGetVectorType(ir_context, 7, 5),
1323               "Precondition: component count must be in range \\[2, 4\\].");
1324#endif
1325}
1326
1327TEST(FuzzerutilTest, FuzzerUtilMaybeGetVoidTypeTest) {
1328  std::string shader = R"(
1329               OpCapability Shader
1330          %1 = OpExtInstImport "GLSL.std.450"
1331               OpMemoryModel Logical GLSL450
1332               OpEntryPoint Fragment %4 "main" %92 %52 %53
1333               OpExecutionMode %4 OriginUpperLeft
1334               OpSource ESSL 310
1335               OpDecorate %92 BuiltIn FragCoord
1336          %2 = OpTypeVoid
1337          %3 = OpTypeFunction %2
1338          %6 = OpTypeInt 32 1
1339          %7 = OpTypeFloat 32
1340          %8 = OpTypeStruct %6 %7
1341          %9 = OpTypePointer Function %8
1342         %10 = OpTypeFunction %6 %9
1343         %14 = OpConstant %6 0
1344         %15 = OpTypePointer Function %6
1345         %51 = OpTypePointer Private %6
1346         %21 = OpConstant %6 2
1347         %23 = OpConstant %6 1
1348         %24 = OpConstant %7 1
1349         %25 = OpTypePointer Function %7
1350         %50 = OpTypePointer Private %7
1351         %34 = OpTypeBool
1352         %35 = OpConstantFalse %34
1353         %52 = OpVariable %50 Private
1354         %53 = OpVariable %51 Private
1355         %80 = OpConstantComposite %8 %21 %24
1356         %90 = OpTypeVector %7 4
1357         %91 = OpTypePointer Input %90
1358         %92 = OpVariable %91 Input
1359         %93 = OpConstantComposite %90 %24 %24 %24 %24
1360          %4 = OpFunction %2 None %3
1361          %5 = OpLabel
1362         %20 = OpVariable %9 Function
1363         %27 = OpVariable %9 Function
1364         %22 = OpAccessChain %15 %20 %14
1365         %44 = OpCopyObject %9 %20
1366         %26 = OpAccessChain %25 %20 %23
1367         %29 = OpFunctionCall %6 %12 %27
1368         %30 = OpAccessChain %15 %20 %14
1369         %45 = OpCopyObject %15 %30
1370         %81 = OpCopyObject %9 %27
1371         %33 = OpAccessChain %15 %20 %14
1372               OpSelectionMerge %37 None
1373               OpBranchConditional %35 %36 %37
1374         %36 = OpLabel
1375         %38 = OpAccessChain %15 %20 %14
1376         %40 = OpAccessChain %15 %20 %14
1377         %43 = OpAccessChain %15 %20 %14
1378         %82 = OpCopyObject %9 %27
1379               OpBranch %37
1380         %37 = OpLabel
1381               OpReturn
1382               OpFunctionEnd
1383         %12 = OpFunction %6 None %10
1384         %11 = OpFunctionParameter %9
1385         %13 = OpLabel
1386         %46 = OpCopyObject %9 %11
1387         %16 = OpAccessChain %15 %11 %14
1388         %95 = OpCopyObject %8 %80
1389               OpReturnValue %21
1390        %100 = OpLabel
1391               OpUnreachable
1392               OpFunctionEnd
1393  )";
1394
1395  const auto env = SPV_ENV_UNIVERSAL_1_4;
1396  const auto consumer = nullptr;
1397  const std::unique_ptr<opt::IRContext> context =
1398      BuildModule(env, consumer, shader, kFuzzAssembleOption);
1399  spvtools::ValidatorOptions validator_options;
1400  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1401                                               kConsoleMessageConsumer));
1402
1403  opt::IRContext* ir_context = context.get();
1404  // A void type with a result id of 2 can be found.
1405  ASSERT_EQ(2, fuzzerutil::MaybeGetVoidType(ir_context));
1406}
1407
1408TEST(FuzzerutilTest, FuzzerUtilMaybeGetZeroConstantTest) {
1409  std::string shader = R"(
1410               OpCapability Shader
1411          %1 = OpExtInstImport "GLSL.std.450"
1412               OpMemoryModel Logical GLSL450
1413               OpEntryPoint Fragment %4 "main" %56
1414               OpExecutionMode %4 OriginUpperLeft
1415               OpSource ESSL 310
1416               OpName %4 "main"
1417               OpName %8 "b1"
1418               OpName %10 "b2"
1419               OpName %12 "b3"
1420               OpName %13 "b4"
1421               OpName %16 "f1"
1422               OpName %18 "f2"
1423               OpName %22 "zc"
1424               OpName %24 "i1"
1425               OpName %28 "i2"
1426               OpName %30 "i"
1427               OpName %32 "i3"
1428               OpName %34 "i4"
1429               OpName %39 "f_arr"
1430               OpName %49 "i_arr"
1431               OpName %56 "value"
1432               OpDecorate %22 RelaxedPrecision
1433               OpDecorate %24 RelaxedPrecision
1434               OpDecorate %28 RelaxedPrecision
1435               OpDecorate %30 RelaxedPrecision
1436               OpDecorate %32 RelaxedPrecision
1437               OpDecorate %34 RelaxedPrecision
1438               OpDecorate %49 RelaxedPrecision
1439               OpDecorate %56 Location 0
1440          %2 = OpTypeVoid
1441          %3 = OpTypeFunction %2
1442          %6 = OpTypeBool
1443          %7 = OpTypePointer Function %6
1444          %9 = OpConstantTrue %6
1445         %11 = OpConstantFalse %6
1446         %14 = OpTypeFloat 32
1447         %15 = OpTypePointer Function %14
1448         %17 = OpConstant %14 1.23000002
1449         %19 = OpConstant %14 1.11000001
1450         %20 = OpTypeInt 32 1
1451         %21 = OpTypePointer Function %20
1452         %23 = OpConstant %20 0
1453         %25 = OpConstant %20 1
1454         %26 = OpTypeInt 32 0
1455         %27 = OpTypePointer Function %26
1456         %29 = OpConstant %26 100
1457         %31 = OpConstant %26 0
1458         %33 = OpConstant %20 -1
1459         %35 = OpConstant %20 -99
1460         %36 = OpConstant %26 5
1461         %37 = OpTypeArray %14 %36
1462         %38 = OpTypePointer Function %37
1463         %40 = OpConstant %14 5.5
1464         %41 = OpConstant %14 4.4000001
1465         %42 = OpConstant %14 3.29999995
1466         %43 = OpConstant %14 2.20000005
1467         %44 = OpConstant %14 1.10000002
1468         %45 = OpConstantComposite %37 %40 %41 %42 %43 %44
1469         %46 = OpConstant %26 3
1470         %47 = OpTypeArray %20 %46
1471         %48 = OpTypePointer Function %47
1472         %50 = OpConstant %20 3
1473         %51 = OpConstant %20 7
1474         %52 = OpConstant %20 9
1475         %53 = OpConstantComposite %47 %50 %51 %52
1476         %55 = OpTypePointer Input %14
1477         %56 = OpVariable %55 Input
1478          %4 = OpFunction %2 None %3
1479          %5 = OpLabel
1480          %8 = OpVariable %7 Function
1481         %10 = OpVariable %7 Function
1482         %12 = OpVariable %7 Function
1483         %13 = OpVariable %7 Function
1484         %16 = OpVariable %15 Function
1485         %18 = OpVariable %15 Function
1486         %22 = OpVariable %21 Function
1487         %24 = OpVariable %21 Function
1488         %28 = OpVariable %27 Function
1489         %30 = OpVariable %27 Function
1490         %32 = OpVariable %21 Function
1491         %34 = OpVariable %21 Function
1492         %39 = OpVariable %38 Function
1493         %49 = OpVariable %48 Function
1494               OpStore %8 %9
1495               OpStore %10 %11
1496               OpStore %12 %9
1497               OpStore %13 %11
1498               OpStore %16 %17
1499               OpStore %18 %19
1500               OpStore %22 %23
1501               OpStore %24 %25
1502               OpStore %28 %29
1503               OpStore %30 %31
1504               OpStore %32 %33
1505               OpStore %34 %35
1506               OpStore %39 %45
1507               OpStore %49 %53
1508               OpReturn
1509               OpFunctionEnd
1510  )";
1511
1512  const auto env = SPV_ENV_UNIVERSAL_1_4;
1513  const auto consumer = nullptr;
1514  const std::unique_ptr<opt::IRContext> context =
1515      BuildModule(env, consumer, shader, kFuzzAssembleOption);
1516  spvtools::ValidatorOptions validator_options;
1517  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1518                                               kConsoleMessageConsumer));
1519  TransformationContext transformation_context(
1520      MakeUnique<FactManager>(context.get()), validator_options);
1521
1522  opt::IRContext* ir_context = context.get();
1523
1524  // The id of a boolean constant will be returned give boolean type id 6.
1525  uint32_t maybe_bool_id = fuzzerutil::MaybeGetZeroConstant(
1526      ir_context, transformation_context, 6, false);
1527  // The id of a 32 bit float constant will be returned given the float type
1528  // id 14.
1529  uint32_t maybe_float_id = fuzzerutil::MaybeGetZeroConstant(
1530      ir_context, transformation_context, 14, false);
1531  uint32_t maybe_signed_int_id = fuzzerutil::MaybeGetZeroConstant(
1532      ir_context, transformation_context, 20, false);
1533  uint32_t maybe_unsigned_int_id = fuzzerutil::MaybeGetZeroConstant(
1534      ir_context, transformation_context, 26, false);
1535
1536  // Lists of possible ids for float, signed int, unsigned int and array.
1537  std::vector<uint32_t> float_ids{17, 19};
1538  std::vector<uint32_t> signed_int_ids{23, 25, 31, 33};
1539
1540  ASSERT_TRUE(maybe_bool_id == 9 || maybe_bool_id == 11);
1541  ASSERT_TRUE(std::find(signed_int_ids.begin(), signed_int_ids.end(),
1542                        maybe_signed_int_id) != signed_int_ids.end());
1543
1544  // There is a unsigned int typed zero constant and its id is 31.
1545  ASSERT_EQ(31, maybe_unsigned_int_id);
1546
1547  // There is no zero float constant.
1548  ASSERT_TRUE(std::find(float_ids.begin(), float_ids.end(), maybe_float_id) ==
1549              float_ids.end());
1550}
1551
1552TEST(FuzzerutilTest, TypesAreCompatible) {
1553  const std::string shader = R"(
1554               OpCapability Shader
1555          %1 = OpExtInstImport "GLSL.std.450"
1556               OpMemoryModel Logical GLSL450
1557               OpEntryPoint Fragment %4 "main"
1558               OpExecutionMode %4 OriginUpperLeft
1559               OpSource ESSL 320
1560          %2 = OpTypeVoid
1561          %3 = OpTypeFunction %2
1562          %6 = OpTypeInt 32 1
1563          %9 = OpTypeInt 32 0
1564          %8 = OpTypeStruct %6
1565         %10 = OpTypePointer StorageBuffer %8
1566         %11 = OpVariable %10 StorageBuffer
1567         %86 = OpTypeStruct %9
1568         %87 = OpTypePointer Workgroup %86
1569         %88 = OpVariable %87 Workgroup
1570         %89 = OpTypePointer Workgroup %9
1571         %19 = OpConstant %9 0
1572         %18 = OpConstant %9 1
1573         %12 = OpConstant %6 0
1574         %13 = OpTypePointer StorageBuffer %6
1575         %15 = OpConstant %6 2
1576         %16 = OpConstant %6 7
1577         %20 = OpConstant %9 64
1578          %4 = OpFunction %2 None %3
1579          %5 = OpLabel
1580         %14 = OpAccessChain %13 %11 %12
1581         %90 = OpAccessChain %89 %88 %19
1582         %21 = OpAtomicLoad %6 %14 %15 %20
1583         %22 = OpAtomicExchange %6 %14 %15 %20 %16
1584         %23 = OpAtomicCompareExchange %6 %14 %15 %20 %12 %16 %15
1585         %24 = OpAtomicIIncrement %6 %14 %15 %20
1586         %25 = OpAtomicIDecrement %6 %14 %15 %20
1587         %26 = OpAtomicIAdd %6  %14 %15 %20 %16
1588         %27 = OpAtomicISub %6  %14 %15 %20 %16
1589         %28 = OpAtomicSMin %6  %14 %15 %20 %16
1590         %29 = OpAtomicUMin %9 %90 %15 %20 %18
1591         %30 = OpAtomicSMax %6  %14 %15 %20 %15
1592         %31 = OpAtomicUMax %9 %90 %15 %20 %18
1593         %32 = OpAtomicAnd  %6  %14 %15 %20 %16
1594         %33 = OpAtomicOr   %6  %14 %15 %20 %16
1595         %34 = OpAtomicXor  %6  %14 %15 %20 %16
1596               OpAtomicStore %14 %15 %20 %16
1597               OpReturn
1598               OpFunctionEnd
1599  )";
1600
1601  const auto env = SPV_ENV_UNIVERSAL_1_3;
1602  const auto consumer = nullptr;
1603  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1604  spvtools::ValidatorOptions validator_options;
1605  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1606                                               kConsoleMessageConsumer));
1607
1608  const uint32_t int_type = 6;   // The id of OpTypeInt 32 1
1609  const uint32_t uint_type = 9;  // The id of OpTypeInt 32 0
1610
1611  // OpAtomicLoad
1612#ifndef NDEBUG
1613  ASSERT_DEATH(
1614      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicLoad, 0,
1615                                     int_type, uint_type),
1616      "Signedness check should not occur on a pointer operand.");
1617#endif
1618  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1619      context.get(), spv::Op::OpAtomicLoad, 1, int_type, uint_type));
1620  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1621      context.get(), spv::Op::OpAtomicLoad, 2, int_type, uint_type));
1622
1623  // OpAtomicExchange
1624#ifndef NDEBUG
1625  ASSERT_DEATH(
1626      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicExchange,
1627                                     0, int_type, uint_type),
1628      "Signedness check should not occur on a pointer operand.");
1629#endif
1630  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1631      context.get(), spv::Op::OpAtomicExchange, 1, int_type, uint_type));
1632  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1633      context.get(), spv::Op::OpAtomicExchange, 2, int_type, uint_type));
1634  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
1635      context.get(), spv::Op::OpAtomicExchange, 3, int_type, uint_type));
1636
1637  // OpAtomicStore
1638#ifndef NDEBUG
1639  ASSERT_DEATH(
1640      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicStore, 0,
1641                                     int_type, uint_type),
1642      "Signedness check should not occur on a pointer operand.");
1643#endif
1644  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1645      context.get(), spv::Op::OpAtomicStore, 1, int_type, uint_type));
1646  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1647      context.get(), spv::Op::OpAtomicStore, 2, int_type, uint_type));
1648  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
1649      context.get(), spv::Op::OpAtomicStore, 3, int_type, uint_type));
1650
1651  // OpAtomicCompareExchange
1652#ifndef NDEBUG
1653  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(),
1654                                              spv::Op::OpAtomicCompareExchange,
1655                                              0, int_type, uint_type),
1656               "Signedness check should not occur on a pointer operand.");
1657#endif
1658  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1659      context.get(), spv::Op::OpAtomicCompareExchange, 1, int_type, uint_type));
1660  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1661      context.get(), spv::Op::OpAtomicCompareExchange, 2, int_type, uint_type));
1662  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1663      context.get(), spv::Op::OpAtomicCompareExchange, 3, int_type, uint_type));
1664  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
1665      context.get(), spv::Op::OpAtomicCompareExchange, 4, int_type, uint_type));
1666
1667  // OpAtomicIIncrement
1668#ifndef NDEBUG
1669  ASSERT_DEATH(
1670      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicIIncrement,
1671                                     0, int_type, uint_type),
1672      "Signedness check should not occur on a pointer operand.");
1673#endif
1674  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1675      context.get(), spv::Op::OpAtomicIIncrement, 1, int_type, uint_type));
1676  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1677      context.get(), spv::Op::OpAtomicIIncrement, 2, int_type, uint_type));
1678
1679// OpAtomicIDecrement
1680#ifndef NDEBUG
1681  ASSERT_DEATH(
1682      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicStore, 0,
1683                                     int_type, uint_type),
1684      "Signedness check should not occur on a pointer operand.");
1685#endif
1686  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1687      context.get(), spv::Op::OpAtomicStore, 1, int_type, uint_type));
1688  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1689      context.get(), spv::Op::OpAtomicStore, 2, int_type, uint_type));
1690
1691// OpAtomicIAdd
1692#ifndef NDEBUG
1693  ASSERT_DEATH(
1694      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicIAdd, 0,
1695                                     int_type, uint_type),
1696      "Signedness check should not occur on a pointer operand.");
1697#endif
1698  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1699      context.get(), spv::Op::OpAtomicIAdd, 1, int_type, uint_type));
1700  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1701      context.get(), spv::Op::OpAtomicIAdd, 2, int_type, uint_type));
1702  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
1703      context.get(), spv::Op::OpAtomicIAdd, 3, int_type, uint_type));
1704
1705// OpAtomicISub
1706#ifndef NDEBUG
1707  ASSERT_DEATH(
1708      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicISub, 0,
1709                                     int_type, uint_type),
1710      "Signedness check should not occur on a pointer operand.");
1711#endif
1712  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1713      context.get(), spv::Op::OpAtomicISub, 1, int_type, uint_type));
1714  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1715      context.get(), spv::Op::OpAtomicISub, 2, int_type, uint_type));
1716  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
1717      context.get(), spv::Op::OpAtomicISub, 3, int_type, uint_type));
1718
1719// OpAtomicSMin
1720#ifndef NDEBUG
1721  ASSERT_DEATH(
1722      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicSMin, 0,
1723                                     int_type, uint_type),
1724      "Signedness check should not occur on a pointer operand.");
1725#endif
1726  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1727      context.get(), spv::Op::OpAtomicSMin, 1, int_type, uint_type));
1728  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1729      context.get(), spv::Op::OpAtomicSMin, 2, int_type, uint_type));
1730  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
1731      context.get(), spv::Op::OpAtomicSMin, 3, int_type, uint_type));
1732
1733// OpAtomicUMin
1734#ifndef NDEBUG
1735  ASSERT_DEATH(
1736      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicUMin, 0,
1737                                     int_type, uint_type),
1738      "Signedness check should not occur on a pointer operand.");
1739#endif
1740  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1741      context.get(), spv::Op::OpAtomicUMin, 1, int_type, uint_type));
1742  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1743      context.get(), spv::Op::OpAtomicUMin, 2, int_type, uint_type));
1744  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
1745      context.get(), spv::Op::OpAtomicUMin, 3, int_type, uint_type));
1746
1747// OpAtomicSMax
1748#ifndef NDEBUG
1749  ASSERT_DEATH(
1750      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicSMax, 0,
1751                                     int_type, uint_type),
1752      "Signedness check should not occur on a pointer operand.");
1753#endif
1754  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1755      context.get(), spv::Op::OpAtomicSMax, 1, int_type, uint_type));
1756  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1757      context.get(), spv::Op::OpAtomicSMax, 2, int_type, uint_type));
1758  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
1759      context.get(), spv::Op::OpAtomicSMax, 3, int_type, uint_type));
1760
1761// OpAtomicUMax
1762#ifndef NDEBUG
1763  ASSERT_DEATH(
1764      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicUMax, 0,
1765                                     int_type, uint_type),
1766      "Signedness check should not occur on a pointer operand.");
1767#endif
1768  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1769      context.get(), spv::Op::OpAtomicUMax, 1, int_type, uint_type));
1770  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1771      context.get(), spv::Op::OpAtomicUMax, 2, int_type, uint_type));
1772  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
1773      context.get(), spv::Op::OpAtomicUMax, 3, int_type, uint_type));
1774
1775// OpAtomicAnd
1776#ifndef NDEBUG
1777  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(
1778                   context.get(), spv::Op::OpAtomicAnd, 0, int_type, uint_type),
1779               "Signedness check should not occur on a pointer operand.");
1780#endif
1781  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1782      context.get(), spv::Op::OpAtomicAnd, 1, int_type, uint_type));
1783  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1784      context.get(), spv::Op::OpAtomicAnd, 2, int_type, uint_type));
1785  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
1786      context.get(), spv::Op::OpAtomicAnd, 3, int_type, uint_type));
1787
1788// OpAtomicOr
1789#ifndef NDEBUG
1790  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(
1791                   context.get(), spv::Op::OpAtomicOr, 0, int_type, uint_type),
1792               "Signedness check should not occur on a pointer operand.");
1793#endif
1794  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicOr,
1795                                             1, int_type, uint_type));
1796  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicOr,
1797                                             2, int_type, uint_type));
1798  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
1799      context.get(), spv::Op::OpAtomicOr, 3, int_type, uint_type));
1800
1801// OpAtomicXor
1802#ifndef NDEBUG
1803  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(
1804                   context.get(), spv::Op::OpAtomicXor, 0, int_type, uint_type),
1805               "Signedness check should not occur on a pointer operand.");
1806#endif
1807  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1808      context.get(), spv::Op::OpAtomicXor, 1, int_type, uint_type));
1809  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
1810      context.get(), spv::Op::OpAtomicXor, 2, int_type, uint_type));
1811  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
1812      context.get(), spv::Op::OpAtomicXor, 3, int_type, uint_type));
1813}
1814
1815}  // namespace
1816}  // namespace fuzz
1817}  // namespace spvtools
1818