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