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/transformation_add_constant_composite.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(TransformationAddConstantCompositeTest,BasicTest)25 TEST(TransformationAddConstantCompositeTest, BasicTest) {
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 310
33 %2 = OpTypeVoid
34 %3 = OpTypeFunction %2
35 %6 = OpTypeFloat 32
36 %7 = OpTypeVector %6 2
37 %8 = OpTypeMatrix %7 3
38 %11 = OpConstant %6 0
39 %12 = OpConstant %6 1
40 %14 = OpConstant %6 2
41 %15 = OpConstant %6 3
42 %17 = OpConstant %6 4
43 %18 = OpConstant %6 5
44 %21 = OpTypeInt 32 1
45 %22 = OpTypeInt 32 0
46 %23 = OpConstant %22 3
47 %24 = OpTypeArray %21 %23
48 %25 = OpTypeBool
49 %26 = OpTypeStruct %24 %25
50 %29 = OpConstant %21 1
51 %30 = OpConstant %21 2
52 %31 = OpConstant %21 3
53 %33 = OpConstantFalse %25
54 %35 = OpTypeVector %6 3
55 %38 = OpConstant %6 6
56 %39 = OpConstant %6 7
57 %40 = OpConstant %6 8
58 %4 = OpFunction %2 None %3
59 %5 = OpLabel
60 OpReturn
61 OpFunctionEnd
62 )";
63
64 const auto env = SPV_ENV_UNIVERSAL_1_4;
65 const auto consumer = nullptr;
66 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
67 spvtools::ValidatorOptions validator_options;
68 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
69 kConsoleMessageConsumer));
70 TransformationContext transformation_context(
71 MakeUnique<FactManager>(context.get()), validator_options);
72 // Too few ids
73 ASSERT_FALSE(TransformationAddConstantComposite(103, 8, {100, 101}, false)
74 .IsApplicable(context.get(), transformation_context));
75 // Too many ids
76 ASSERT_FALSE(TransformationAddConstantComposite(101, 7, {14, 15, 14}, false)
77 .IsApplicable(context.get(), transformation_context));
78 // Id already in use
79 ASSERT_FALSE(TransformationAddConstantComposite(40, 7, {11, 12}, false)
80 .IsApplicable(context.get(), transformation_context));
81 // %39 is not a type
82 ASSERT_FALSE(TransformationAddConstantComposite(100, 39, {11, 12}, false)
83 .IsApplicable(context.get(), transformation_context));
84
85 {
86 // %100 = OpConstantComposite %7 %11 %12
87 TransformationAddConstantComposite transformation(100, 7, {11, 12}, false);
88 ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
89 ASSERT_EQ(nullptr, context->get_constant_mgr()->FindDeclaredConstant(100));
90 ASSERT_TRUE(
91 transformation.IsApplicable(context.get(), transformation_context));
92 ApplyAndCheckFreshIds(transformation, context.get(),
93 &transformation_context);
94 ASSERT_EQ(SpvOpConstantComposite,
95 context->get_def_use_mgr()->GetDef(100)->opcode());
96 ASSERT_EQ(0.0F, context->get_constant_mgr()
97 ->FindDeclaredConstant(100)
98 ->AsVectorConstant()
99 ->GetComponents()[0]
100 ->GetFloat());
101 ASSERT_EQ(1.0F, context->get_constant_mgr()
102 ->FindDeclaredConstant(100)
103 ->AsVectorConstant()
104 ->GetComponents()[1]
105 ->GetFloat());
106 }
107
108 TransformationAddConstantComposite transformations[] = {
109 // %101 = OpConstantComposite %7 %14 %15
110 TransformationAddConstantComposite(101, 7, {14, 15}, false),
111
112 // %102 = OpConstantComposite %7 %17 %18
113 TransformationAddConstantComposite(102, 7, {17, 18}, false),
114
115 // %103 = OpConstantComposite %8 %100 %101 %102
116 TransformationAddConstantComposite(103, 8, {100, 101, 102}, false),
117
118 // %104 = OpConstantComposite %24 %29 %30 %31
119 TransformationAddConstantComposite(104, 24, {29, 30, 31}, false),
120
121 // %105 = OpConstantComposite %26 %104 %33
122 TransformationAddConstantComposite(105, 26, {104, 33}, false),
123
124 // %106 = OpConstantComposite %35 %38 %39 %40
125 TransformationAddConstantComposite(106, 35, {38, 39, 40}, false),
126
127 // Same constants but with an irrelevant fact applied.
128
129 // %107 = OpConstantComposite %7 %11 %12
130 TransformationAddConstantComposite(107, 7, {11, 12}, true),
131
132 // %108 = OpConstantComposite %7 %14 %15
133 TransformationAddConstantComposite(108, 7, {14, 15}, true),
134
135 // %109 = OpConstantComposite %7 %17 %18
136 TransformationAddConstantComposite(109, 7, {17, 18}, true),
137
138 // %110 = OpConstantComposite %8 %100 %101 %102
139 TransformationAddConstantComposite(110, 8, {100, 101, 102}, true),
140
141 // %111 = OpConstantComposite %24 %29 %30 %31
142 TransformationAddConstantComposite(111, 24, {29, 30, 31}, true),
143
144 // %112 = OpConstantComposite %26 %104 %33
145 TransformationAddConstantComposite(112, 26, {104, 33}, true),
146
147 // %113 = OpConstantComposite %35 %38 %39 %40
148 TransformationAddConstantComposite(113, 35, {38, 39, 40}, true)};
149
150 for (auto& transformation : transformations) {
151 ASSERT_TRUE(
152 transformation.IsApplicable(context.get(), transformation_context));
153 ApplyAndCheckFreshIds(transformation, context.get(),
154 &transformation_context);
155 }
156 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
157 kConsoleMessageConsumer));
158
159 for (uint32_t id = 100; id <= 106; ++id) {
160 ASSERT_FALSE(transformation_context.GetFactManager()->IdIsIrrelevant(id));
161 }
162
163 for (uint32_t id = 107; id <= 113; ++id) {
164 ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(id));
165 }
166
167 std::string after_transformation = R"(
168 OpCapability Shader
169 %1 = OpExtInstImport "GLSL.std.450"
170 OpMemoryModel Logical GLSL450
171 OpEntryPoint Fragment %4 "main"
172 OpExecutionMode %4 OriginUpperLeft
173 OpSource ESSL 310
174 %2 = OpTypeVoid
175 %3 = OpTypeFunction %2
176 %6 = OpTypeFloat 32
177 %7 = OpTypeVector %6 2
178 %8 = OpTypeMatrix %7 3
179 %11 = OpConstant %6 0
180 %12 = OpConstant %6 1
181 %14 = OpConstant %6 2
182 %15 = OpConstant %6 3
183 %17 = OpConstant %6 4
184 %18 = OpConstant %6 5
185 %21 = OpTypeInt 32 1
186 %22 = OpTypeInt 32 0
187 %23 = OpConstant %22 3
188 %24 = OpTypeArray %21 %23
189 %25 = OpTypeBool
190 %26 = OpTypeStruct %24 %25
191 %29 = OpConstant %21 1
192 %30 = OpConstant %21 2
193 %31 = OpConstant %21 3
194 %33 = OpConstantFalse %25
195 %35 = OpTypeVector %6 3
196 %38 = OpConstant %6 6
197 %39 = OpConstant %6 7
198 %40 = OpConstant %6 8
199 %100 = OpConstantComposite %7 %11 %12
200 %101 = OpConstantComposite %7 %14 %15
201 %102 = OpConstantComposite %7 %17 %18
202 %103 = OpConstantComposite %8 %100 %101 %102
203 %104 = OpConstantComposite %24 %29 %30 %31
204 %105 = OpConstantComposite %26 %104 %33
205 %106 = OpConstantComposite %35 %38 %39 %40
206 %107 = OpConstantComposite %7 %11 %12
207 %108 = OpConstantComposite %7 %14 %15
208 %109 = OpConstantComposite %7 %17 %18
209 %110 = OpConstantComposite %8 %100 %101 %102
210 %111 = OpConstantComposite %24 %29 %30 %31
211 %112 = OpConstantComposite %26 %104 %33
212 %113 = OpConstantComposite %35 %38 %39 %40
213 %4 = OpFunction %2 None %3
214 %5 = OpLabel
215 OpReturn
216 OpFunctionEnd
217 )";
218 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
219 }
220
TEST(TransformationAddConstantCompositeTest,DisallowBufferBlockDecoration)221 TEST(TransformationAddConstantCompositeTest, DisallowBufferBlockDecoration) {
222 std::string shader = R"(
223 OpCapability Shader
224 %1 = OpExtInstImport "GLSL.std.450"
225 OpMemoryModel Logical GLSL450
226 OpEntryPoint GLCompute %4 "main"
227 OpExecutionMode %4 LocalSize 1 1 1
228 OpSource ESSL 320
229 OpName %4 "main"
230 OpName %7 "buf"
231 OpMemberName %7 0 "a"
232 OpMemberName %7 1 "b"
233 OpName %9 ""
234 OpMemberDecorate %7 0 Offset 0
235 OpMemberDecorate %7 1 Offset 4
236 OpDecorate %7 BufferBlock
237 OpDecorate %9 DescriptorSet 0
238 OpDecorate %9 Binding 0
239 %2 = OpTypeVoid
240 %3 = OpTypeFunction %2
241 %6 = OpTypeInt 32 1
242 %10 = OpConstant %6 42
243 %7 = OpTypeStruct %6 %6
244 %8 = OpTypePointer Uniform %7
245 %9 = OpVariable %8 Uniform
246 %4 = OpFunction %2 None %3
247 %5 = OpLabel
248 OpReturn
249 OpFunctionEnd
250 )";
251
252 const auto env = SPV_ENV_UNIVERSAL_1_0;
253 const auto consumer = nullptr;
254 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
255 spvtools::ValidatorOptions validator_options;
256 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
257 kConsoleMessageConsumer));
258 TransformationContext transformation_context(
259 MakeUnique<FactManager>(context.get()), validator_options);
260 ASSERT_FALSE(TransformationAddConstantComposite(100, 7, {10, 10}, false)
261 .IsApplicable(context.get(), transformation_context));
262 }
263
TEST(TransformationAddConstantCompositeTest,DisallowBlockDecoration)264 TEST(TransformationAddConstantCompositeTest, DisallowBlockDecoration) {
265 std::string shader = R"(
266 OpCapability Shader
267 %1 = OpExtInstImport "GLSL.std.450"
268 OpMemoryModel Logical GLSL450
269 OpEntryPoint GLCompute %4 "main" %9
270 OpExecutionMode %4 LocalSize 1 1 1
271 OpSource ESSL 320
272 OpName %4 "main"
273 OpName %7 "buf"
274 OpMemberName %7 0 "a"
275 OpMemberName %7 1 "b"
276 OpName %9 ""
277 OpMemberDecorate %7 0 Offset 0
278 OpMemberDecorate %7 1 Offset 4
279 OpDecorate %7 Block
280 OpDecorate %9 DescriptorSet 0
281 OpDecorate %9 Binding 0
282 %2 = OpTypeVoid
283 %3 = OpTypeFunction %2
284 %6 = OpTypeInt 32 1
285 %10 = OpConstant %6 42
286 %7 = OpTypeStruct %6 %6
287 %8 = OpTypePointer StorageBuffer %7
288 %9 = OpVariable %8 StorageBuffer
289 %4 = OpFunction %2 None %3
290 %5 = OpLabel
291 OpReturn
292 OpFunctionEnd
293 )";
294
295 const auto env = SPV_ENV_UNIVERSAL_1_5;
296 const auto consumer = nullptr;
297 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
298 spvtools::ValidatorOptions validator_options;
299 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
300 kConsoleMessageConsumer));
301 TransformationContext transformation_context(
302 MakeUnique<FactManager>(context.get()), validator_options);
303 ASSERT_FALSE(TransformationAddConstantComposite(100, 7, {10, 10}, false)
304 .IsApplicable(context.get(), transformation_context));
305 }
306
307 } // namespace
308 } // namespace fuzz
309 } // namespace spvtools
310