1 // Copyright (c) 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "source/fuzz/fact_manager/fact_manager.h"
16 
17 #include "gtest/gtest.h"
18 #include "source/fuzz/fuzzer_util.h"
19 #include "test/fuzz/fuzz_test_util.h"
20 
21 namespace spvtools {
22 namespace fuzz {
23 namespace {
24 
TEST(IrrelevantValueFactsTest,IdIsIrrelevant)25 TEST(IrrelevantValueFactsTest, IdIsIrrelevant) {
26   std::string shader = R"(
27                OpCapability Shader
28           %1 = OpExtInstImport "GLSL.std.450"
29                OpMemoryModel Logical GLSL450
30                OpEntryPoint Fragment %4 "main"
31                OpExecutionMode %4 OriginUpperLeft
32                OpSource ESSL 320
33           %2 = OpTypeVoid
34           %3 = OpTypeFunction %2
35           %6 = OpTypeInt 32 1
36          %12 = OpConstant %6 0
37          %13 = OpConstant %6 1
38           %4 = OpFunction %2 None %3
39           %5 = OpLabel
40                OpReturn
41                OpFunctionEnd
42   )";
43 
44   const auto env = SPV_ENV_UNIVERSAL_1_3;
45   const auto consumer = nullptr;
46   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
47   spvtools::ValidatorOptions validator_options;
48   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
49                                                kConsoleMessageConsumer));
50 
51   FactManager fact_manager(context.get());
52 
53   ASSERT_FALSE(fact_manager.IdIsIrrelevant(12));
54   ASSERT_FALSE(fact_manager.IdIsIrrelevant(13));
55 
56   fact_manager.AddFactIdIsIrrelevant(12);
57 
58   ASSERT_TRUE(fact_manager.IdIsIrrelevant(12));
59   ASSERT_FALSE(fact_manager.IdIsIrrelevant(13));
60 }
61 
TEST(IrrelevantValueFactsTest,GetIrrelevantIds)62 TEST(IrrelevantValueFactsTest, GetIrrelevantIds) {
63   std::string shader = R"(
64                OpCapability Shader
65           %1 = OpExtInstImport "GLSL.std.450"
66                OpMemoryModel Logical GLSL450
67                OpEntryPoint Fragment %4 "main"
68                OpExecutionMode %4 OriginUpperLeft
69                OpSource ESSL 320
70           %2 = OpTypeVoid
71           %3 = OpTypeFunction %2
72           %6 = OpTypeInt 32 1
73          %12 = OpConstant %6 0
74          %13 = OpConstant %6 1
75          %14 = OpConstant %6 2
76           %4 = OpFunction %2 None %3
77           %5 = OpLabel
78                OpReturn
79                OpFunctionEnd
80   )";
81 
82   const auto env = SPV_ENV_UNIVERSAL_1_3;
83   const auto consumer = nullptr;
84   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
85   spvtools::ValidatorOptions validator_options;
86   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
87                                                kConsoleMessageConsumer));
88 
89   FactManager fact_manager(context.get());
90 
91   ASSERT_EQ(fact_manager.GetIrrelevantIds(), std::unordered_set<uint32_t>({}));
92 
93   fact_manager.AddFactIdIsIrrelevant(12);
94 
95   ASSERT_EQ(fact_manager.GetIrrelevantIds(),
96             std::unordered_set<uint32_t>({12}));
97 
98   fact_manager.AddFactIdIsIrrelevant(13);
99 
100   ASSERT_EQ(fact_manager.GetIrrelevantIds(),
101             std::unordered_set<uint32_t>({12, 13}));
102 }
103 
TEST(IrrelevantValueFactsTest,IdsFromDeadBlocksAreIrrelevant)104 TEST(IrrelevantValueFactsTest, IdsFromDeadBlocksAreIrrelevant) {
105   std::string shader = R"(
106                OpCapability Shader
107           %1 = OpExtInstImport "GLSL.std.450"
108                OpMemoryModel Logical GLSL450
109                OpEntryPoint Fragment %2 "main"
110                OpExecutionMode %2 OriginUpperLeft
111                OpSource ESSL 310
112           %3 = OpTypeVoid
113           %4 = OpTypeFunction %3
114           %5 = OpTypeBool
115           %6 = OpConstantTrue %5
116           %7 = OpTypeInt 32 1
117           %8 = OpTypePointer Function %7
118           %9 = OpConstant %7 1
119           %2 = OpFunction %3 None %4
120          %10 = OpLabel
121          %11 = OpVariable %8 Function
122                OpSelectionMerge %12 None
123                OpBranchConditional %6 %13 %14
124          %13 = OpLabel
125                OpBranch %12
126          %14 = OpLabel
127          %15 = OpCopyObject %8 %11
128          %16 = OpCopyObject %7 %9
129          %17 = OpFunctionCall %3 %18
130                OpBranch %12
131          %12 = OpLabel
132                OpReturn
133                OpFunctionEnd
134          %18 = OpFunction %3 None %4
135          %19 = OpLabel
136          %20 = OpVariable %8 Function
137          %21 = OpCopyObject %7 %9
138                OpReturn
139                OpFunctionEnd
140 )";
141 
142   const auto env = SPV_ENV_UNIVERSAL_1_5;
143   const auto consumer = nullptr;
144   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
145   spvtools::ValidatorOptions validator_options;
146   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
147                                                kConsoleMessageConsumer));
148 
149   FactManager fact_manager(context.get());
150 
151   ASSERT_FALSE(fact_manager.BlockIsDead(14));
152   ASSERT_FALSE(fact_manager.BlockIsDead(19));
153 
154   // Initially no id is irrelevant.
155   ASSERT_FALSE(fact_manager.IdIsIrrelevant(16));
156   ASSERT_FALSE(fact_manager.IdIsIrrelevant(17));
157   ASSERT_EQ(fact_manager.GetIrrelevantIds(), std::unordered_set<uint32_t>({}));
158 
159   fact_manager.AddFactBlockIsDead(14);
160 
161   // %16 and %17 should now be considered irrelevant.
162   ASSERT_TRUE(fact_manager.IdIsIrrelevant(16));
163   ASSERT_TRUE(fact_manager.IdIsIrrelevant(17));
164   ASSERT_EQ(fact_manager.GetIrrelevantIds(),
165             std::unordered_set<uint32_t>({16, 17}));
166 
167   // Similarly for %21.
168   ASSERT_FALSE(fact_manager.IdIsIrrelevant(21));
169 
170   fact_manager.AddFactBlockIsDead(19);
171 
172   ASSERT_TRUE(fact_manager.IdIsIrrelevant(21));
173   ASSERT_EQ(fact_manager.GetIrrelevantIds(),
174             std::unordered_set<uint32_t>({16, 17, 21}));
175 }
176 
177 }  // namespace
178 }  // namespace fuzz
179 }  // namespace spvtools
180