• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2020 Vasyl Teliman
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_replace_parameter_with_global.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(TransformationReplaceParameterWithGlobalTest,BasicTest)25 TEST(TransformationReplaceParameterWithGlobalTest, 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                OpMemberDecorate %13 0 RelaxedPrecision
34                OpDecorate %16 RelaxedPrecision
35           %2 = OpTypeVoid
36           %3 = OpTypeFunction %2
37           %6 = OpTypeInt 32 1
38           %7 = OpTypePointer Private %6
39           %8 = OpTypeFloat 32
40           %9 = OpTypePointer Private %8
41          %10 = OpTypeVector %8 2
42          %11 = OpTypePointer Private %10
43          %12 = OpTypeBool
44          %71 = OpTypeFunction %2 %6
45          %83 = OpTypeFunction %2 %6 %12
46          %93 = OpTypeFunction %2 %10
47          %94 = OpTypeFunction %2 %8 %10
48          %40 = OpTypePointer Function %12
49          %13 = OpTypeStruct %6 %8
50          %14 = OpTypePointer Private %13
51          %15 = OpTypeFunction %2 %6 %8 %10 %13 %40 %12
52          %22 = OpConstant %6 0
53          %23 = OpConstant %8 0
54          %26 = OpConstantComposite %10 %23 %23
55          %27 = OpConstantTrue %12
56          %28 = OpConstantComposite %13 %22 %23
57           %4 = OpFunction %2 None %3
58           %5 = OpLabel
59          %41 = OpVariable %40 Function %27
60          %33 = OpFunctionCall %2 %20 %22 %23 %26 %28 %41 %27
61                OpReturn
62                OpFunctionEnd
63 
64          ; adjust type of the function in-place
65          %20 = OpFunction %2 None %15
66          %16 = OpFunctionParameter %6
67          %17 = OpFunctionParameter %8
68          %18 = OpFunctionParameter %10
69          %19 = OpFunctionParameter %13
70          %42 = OpFunctionParameter %40
71          %43 = OpFunctionParameter %12
72          %21 = OpLabel
73                OpReturn
74                OpFunctionEnd
75 
76          ; reuse an existing function type
77          %70 = OpFunction %2 None %71
78          %72 = OpFunctionParameter %6
79          %73 = OpLabel
80                OpReturn
81                OpFunctionEnd
82          %74 = OpFunction %2 None %71
83          %75 = OpFunctionParameter %6
84          %76 = OpLabel
85                OpReturn
86                OpFunctionEnd
87 
88          ; create a new function type
89          %77 = OpFunction %2 None %83
90          %78 = OpFunctionParameter %6
91          %84 = OpFunctionParameter %12
92          %79 = OpLabel
93                OpReturn
94                OpFunctionEnd
95          %80 = OpFunction %2 None %83
96          %81 = OpFunctionParameter %6
97          %85 = OpFunctionParameter %12
98          %82 = OpLabel
99                OpReturn
100                OpFunctionEnd
101 
102          ; don't adjust the type of the function if it creates a duplicate
103          %86 = OpFunction %2 None %93
104          %87 = OpFunctionParameter %10
105          %89 = OpLabel
106                OpReturn
107                OpFunctionEnd
108          %90 = OpFunction %2 None %94
109          %91 = OpFunctionParameter %8
110          %95 = OpFunctionParameter %10
111          %92 = OpLabel
112                OpReturn
113                OpFunctionEnd
114   )";
115 
116   const auto env = SPV_ENV_UNIVERSAL_1_3;
117   const auto consumer = nullptr;
118   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
119   spvtools::ValidatorOptions validator_options;
120   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
121                                                kConsoleMessageConsumer));
122   TransformationContext transformation_context(
123       MakeUnique<FactManager>(context.get()), validator_options);
124   // Parameter id is invalid.
125   ASSERT_FALSE(TransformationReplaceParameterWithGlobal(50, 50, 51)
126                    .IsApplicable(context.get(), transformation_context));
127 
128   // Parameter id is not a result id of an OpFunctionParameter instruction.
129   ASSERT_FALSE(TransformationReplaceParameterWithGlobal(50, 21, 51)
130                    .IsApplicable(context.get(), transformation_context));
131 
132   // Parameter has unsupported type.
133   ASSERT_FALSE(TransformationReplaceParameterWithGlobal(50, 42, 51)
134                    .IsApplicable(context.get(), transformation_context));
135 
136   // Initializer for a global variable doesn't exist in the module.
137   ASSERT_FALSE(TransformationReplaceParameterWithGlobal(50, 43, 51)
138                    .IsApplicable(context.get(), transformation_context));
139 
140   // Pointer type for a global variable doesn't exist in the module.
141   ASSERT_FALSE(TransformationReplaceParameterWithGlobal(50, 43, 51)
142                    .IsApplicable(context.get(), transformation_context));
143 
144   // Function type id is not fresh.
145   ASSERT_FALSE(TransformationReplaceParameterWithGlobal(16, 16, 51)
146                    .IsApplicable(context.get(), transformation_context));
147 
148   // Global variable id is not fresh.
149   ASSERT_FALSE(TransformationReplaceParameterWithGlobal(50, 16, 16)
150                    .IsApplicable(context.get(), transformation_context));
151 
152   // Function type fresh id and global variable fresh id are equal.
153   ASSERT_FALSE(TransformationReplaceParameterWithGlobal(50, 16, 50)
154                    .IsApplicable(context.get(), transformation_context));
155 
156   {
157     TransformationReplaceParameterWithGlobal transformation(50, 16, 51);
158     ASSERT_TRUE(
159         transformation.IsApplicable(context.get(), transformation_context));
160     ApplyAndCheckFreshIds(transformation, context.get(),
161                           &transformation_context);
162   }
163   {
164     TransformationReplaceParameterWithGlobal transformation(52, 17, 53);
165     ASSERT_TRUE(
166         transformation.IsApplicable(context.get(), transformation_context));
167     ApplyAndCheckFreshIds(transformation, context.get(),
168                           &transformation_context);
169   }
170   {
171     TransformationReplaceParameterWithGlobal transformation(54, 18, 55);
172     ASSERT_TRUE(
173         transformation.IsApplicable(context.get(), transformation_context));
174     ApplyAndCheckFreshIds(transformation, context.get(),
175                           &transformation_context);
176   }
177   {
178     TransformationReplaceParameterWithGlobal transformation(56, 19, 57);
179     ASSERT_TRUE(
180         transformation.IsApplicable(context.get(), transformation_context));
181     ApplyAndCheckFreshIds(transformation, context.get(),
182                           &transformation_context);
183   }
184   {
185     TransformationReplaceParameterWithGlobal transformation(58, 75, 59);
186     ASSERT_TRUE(
187         transformation.IsApplicable(context.get(), transformation_context));
188     ApplyAndCheckFreshIds(transformation, context.get(),
189                           &transformation_context);
190   }
191   {
192     TransformationReplaceParameterWithGlobal transformation(60, 81, 61);
193     ASSERT_TRUE(
194         transformation.IsApplicable(context.get(), transformation_context));
195     ApplyAndCheckFreshIds(transformation, context.get(),
196                           &transformation_context);
197   }
198   {
199     TransformationReplaceParameterWithGlobal transformation(62, 91, 63);
200     ASSERT_TRUE(
201         transformation.IsApplicable(context.get(), transformation_context));
202     ApplyAndCheckFreshIds(transformation, context.get(),
203                           &transformation_context);
204   }
205 
206   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
207                                                kConsoleMessageConsumer));
208 
209   std::string expected_shader = R"(
210                OpCapability Shader
211           %1 = OpExtInstImport "GLSL.std.450"
212                OpMemoryModel Logical GLSL450
213                OpEntryPoint Fragment %4 "main"
214                OpExecutionMode %4 OriginUpperLeft
215                OpSource ESSL 310
216                OpMemberDecorate %13 0 RelaxedPrecision
217                OpDecorate %16 RelaxedPrecision
218           %2 = OpTypeVoid
219           %3 = OpTypeFunction %2
220           %6 = OpTypeInt 32 1
221           %7 = OpTypePointer Private %6
222           %8 = OpTypeFloat 32
223           %9 = OpTypePointer Private %8
224          %10 = OpTypeVector %8 2
225          %11 = OpTypePointer Private %10
226          %12 = OpTypeBool
227          %71 = OpTypeFunction %2 %6
228          %83 = OpTypeFunction %2 %6 %12
229          %93 = OpTypeFunction %2 %10
230          %40 = OpTypePointer Function %12
231          %13 = OpTypeStruct %6 %8
232          %14 = OpTypePointer Private %13
233          %22 = OpConstant %6 0
234          %23 = OpConstant %8 0
235          %26 = OpConstantComposite %10 %23 %23
236          %27 = OpConstantTrue %12
237          %28 = OpConstantComposite %13 %22 %23
238          %51 = OpVariable %7 Private %22
239          %53 = OpVariable %9 Private %23
240          %55 = OpVariable %11 Private %26
241          %57 = OpVariable %14 Private %28
242          %15 = OpTypeFunction %2 %40 %12
243          %59 = OpVariable %7 Private %22
244          %61 = OpVariable %7 Private %22
245          %60 = OpTypeFunction %2 %12
246          %63 = OpVariable %9 Private %23
247           %4 = OpFunction %2 None %3
248           %5 = OpLabel
249          %41 = OpVariable %40 Function %27
250                OpStore %51 %22
251                OpStore %53 %23
252                OpStore %55 %26
253                OpStore %57 %28
254          %33 = OpFunctionCall %2 %20 %41 %27
255                OpReturn
256                OpFunctionEnd
257          %20 = OpFunction %2 None %15
258          %42 = OpFunctionParameter %40
259          %43 = OpFunctionParameter %12
260          %21 = OpLabel
261          %19 = OpLoad %13 %57
262          %18 = OpLoad %10 %55
263          %17 = OpLoad %8 %53
264          %16 = OpLoad %6 %51
265                OpReturn
266                OpFunctionEnd
267          %70 = OpFunction %2 None %71
268          %72 = OpFunctionParameter %6
269          %73 = OpLabel
270                OpReturn
271                OpFunctionEnd
272          %74 = OpFunction %2 None %3
273          %76 = OpLabel
274          %75 = OpLoad %6 %59
275                OpReturn
276                OpFunctionEnd
277          %77 = OpFunction %2 None %83
278          %78 = OpFunctionParameter %6
279          %84 = OpFunctionParameter %12
280          %79 = OpLabel
281                OpReturn
282                OpFunctionEnd
283          %80 = OpFunction %2 None %60
284          %85 = OpFunctionParameter %12
285          %82 = OpLabel
286          %81 = OpLoad %6 %61
287                OpReturn
288                OpFunctionEnd
289          %86 = OpFunction %2 None %93
290          %87 = OpFunctionParameter %10
291          %89 = OpLabel
292                OpReturn
293                OpFunctionEnd
294          %90 = OpFunction %2 None %93
295          %95 = OpFunctionParameter %10
296          %92 = OpLabel
297          %91 = OpLoad %8 %63
298                OpReturn
299                OpFunctionEnd
300   )";
301 
302   ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
303 }
304 
TEST(TransformationReplaceParameterWithGlobalTest,HandlesIrrelevantParameters)305 TEST(TransformationReplaceParameterWithGlobalTest,
306      HandlesIrrelevantParameters) {
307   std::string shader = R"(
308                OpCapability Shader
309           %1 = OpExtInstImport "GLSL.std.450"
310                OpMemoryModel Logical GLSL450
311                OpEntryPoint Fragment %4 "main"
312                OpExecutionMode %4 OriginUpperLeft
313                OpSource ESSL 310
314           %2 = OpTypeVoid
315           %9 = OpTypeInt 32 1
316           %3 = OpTypeFunction %2
317           %7 = OpTypeFunction %2 %9 %9
318          %12 = OpTypePointer Private %9
319          %13 = OpConstant %9 0
320           %4 = OpFunction %2 None %3
321           %5 = OpLabel
322                OpReturn
323                OpFunctionEnd
324           %6 = OpFunction %2 None %7
325          %10 = OpFunctionParameter %9
326          %11 = OpFunctionParameter %9
327           %8 = OpLabel
328                OpReturn
329                OpFunctionEnd
330   )";
331 
332   const auto env = SPV_ENV_UNIVERSAL_1_3;
333   const auto consumer = nullptr;
334   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
335   spvtools::ValidatorOptions validator_options;
336   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
337                                                kConsoleMessageConsumer));
338   TransformationContext transformation_context(
339       MakeUnique<FactManager>(context.get()), validator_options);
340   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(10);
341 
342   {
343     TransformationReplaceParameterWithGlobal transformation(20, 10, 21);
344     ASSERT_TRUE(
345         transformation.IsApplicable(context.get(), transformation_context));
346     ApplyAndCheckFreshIds(transformation, context.get(),
347                           &transformation_context);
348     ASSERT_TRUE(
349         transformation_context.GetFactManager()->PointeeValueIsIrrelevant(21));
350   }
351   {
352     TransformationReplaceParameterWithGlobal transformation(22, 11, 23);
353     ASSERT_TRUE(
354         transformation.IsApplicable(context.get(), transformation_context));
355     ApplyAndCheckFreshIds(transformation, context.get(),
356                           &transformation_context);
357     ASSERT_FALSE(
358         transformation_context.GetFactManager()->PointeeValueIsIrrelevant(23));
359   }
360 }
361 
362 }  // namespace
363 }  // namespace fuzz
364 }  // namespace spvtools
365