• 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_params_with_struct.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(TransformationReplaceParamsWithStructTest,BasicTest)25 TEST(TransformationReplaceParamsWithStructTest, 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           %6 = OpTypeInt 32 1
37           %3 = OpTypeFunction %2
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          %51 = OpTypeFunction %2 %12
45          %64 = OpTypeStruct %6
46          %63 = OpTypeFunction %2 %64
47          %65 = OpTypeFunction %2 %6
48          %75 = OpTypeStruct %8
49          %76 = OpTypeFunction %2 %75
50          %77 = OpTypeFunction %2 %8
51          %40 = OpTypePointer Function %12
52          %13 = OpTypeStruct %6 %8
53          %45 = OpTypeStruct %6 %10 %13
54          %46 = OpTypeStruct %12
55          %47 = OpTypeStruct %8 %45 %46
56          %14 = OpTypePointer Private %13
57          %15 = OpTypeFunction %2 %6 %8 %10 %13 %40 %12
58          %22 = OpConstant %6 0
59          %23 = OpConstant %8 0
60          %26 = OpConstantComposite %10 %23 %23
61          %27 = OpConstantTrue %12
62          %28 = OpConstantComposite %13 %22 %23
63           %4 = OpFunction %2 None %3
64           %5 = OpLabel
65          %41 = OpVariable %40 Function %27
66          %33 = OpFunctionCall %2 %20 %22 %23 %26 %28 %41 %27
67                OpReturn
68                OpFunctionEnd
69 
70          ; adjust type of the function in-place
71          %20 = OpFunction %2 None %15
72          %16 = OpFunctionParameter %6
73          %17 = OpFunctionParameter %8
74          %18 = OpFunctionParameter %10
75          %19 = OpFunctionParameter %13
76          %42 = OpFunctionParameter %40
77          %43 = OpFunctionParameter %12
78          %21 = OpLabel
79                OpReturn
80                OpFunctionEnd
81 
82          ; create a new function type
83          %50 = OpFunction %2 None %51
84          %52 = OpFunctionParameter %12
85          %53 = OpLabel
86                OpReturn
87                OpFunctionEnd
88          %54 = OpFunction %2 None %51
89          %55 = OpFunctionParameter %12
90          %56 = OpLabel
91                OpReturn
92                OpFunctionEnd
93 
94          ; reuse an existing function type
95          %57 = OpFunction %2 None %63
96          %58 = OpFunctionParameter %64
97          %59 = OpLabel
98                OpReturn
99                OpFunctionEnd
100          %60 = OpFunction %2 None %65
101          %61 = OpFunctionParameter %6
102          %62 = OpLabel
103                OpReturn
104                OpFunctionEnd
105          %66 = OpFunction %2 None %65
106          %67 = OpFunctionParameter %6
107          %68 = OpLabel
108                OpReturn
109                OpFunctionEnd
110 
111          ; don't adjust the type of the function if it creates a duplicate
112          %69 = OpFunction %2 None %76
113          %70 = OpFunctionParameter %75
114          %71 = OpLabel
115                OpReturn
116                OpFunctionEnd
117          %72 = OpFunction %2 None %77
118          %73 = OpFunctionParameter %8
119          %74 = OpLabel
120                OpReturn
121                OpFunctionEnd
122   )";
123 
124   const auto env = SPV_ENV_UNIVERSAL_1_3;
125   const auto consumer = nullptr;
126   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
127   spvtools::ValidatorOptions validator_options;
128   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
129                                                kConsoleMessageConsumer));
130   TransformationContext transformation_context(
131       MakeUnique<FactManager>(context.get()), validator_options);
132   // |parameter_id| is empty.
133   ASSERT_FALSE(
134       TransformationReplaceParamsWithStruct({}, 90, 91, {{33, 92}, {90, 93}})
135           .IsApplicable(context.get(), transformation_context));
136 
137   // |parameter_id| has duplicates.
138   ASSERT_FALSE(TransformationReplaceParamsWithStruct({16, 16, 17}, 90, 91,
139                                                      {{33, 92}, {90, 93}})
140                    .IsApplicable(context.get(), transformation_context));
141 
142   // |parameter_id| has invalid values.
143   ASSERT_FALSE(TransformationReplaceParamsWithStruct({21, 16, 17}, 90, 91,
144                                                      {{33, 92}, {90, 93}})
145                    .IsApplicable(context.get(), transformation_context));
146   ASSERT_FALSE(TransformationReplaceParamsWithStruct({16, 90, 17}, 90, 91,
147                                                      {{33, 92}, {90, 93}})
148                    .IsApplicable(context.get(), transformation_context));
149 
150   // Parameter's belong to different functions.
151   ASSERT_FALSE(TransformationReplaceParamsWithStruct({16, 17, 52}, 90, 91,
152                                                      {{33, 92}, {90, 93}})
153                    .IsApplicable(context.get(), transformation_context));
154 
155   // Parameter has unsupported type.
156   ASSERT_FALSE(TransformationReplaceParamsWithStruct({16, 17, 42, 43}, 90, 91,
157                                                      {{33, 92}, {90, 93}})
158                    .IsApplicable(context.get(), transformation_context));
159 
160   // OpTypeStruct does not exist in the module.
161   ASSERT_FALSE(TransformationReplaceParamsWithStruct({16, 43}, 90, 91,
162                                                      {{33, 92}, {90, 93}})
163                    .IsApplicable(context.get(), transformation_context));
164 
165   // |caller_id_to_fresh_composite_id| misses values.
166   ASSERT_FALSE(
167       TransformationReplaceParamsWithStruct({16, 17}, 90, 91, {{90, 93}})
168           .IsApplicable(context.get(), transformation_context));
169 
170   // All fresh ids must be unique.
171   ASSERT_FALSE(TransformationReplaceParamsWithStruct({16, 17}, 90, 90,
172                                                      {{33, 92}, {90, 93}})
173                    .IsApplicable(context.get(), transformation_context));
174   ASSERT_FALSE(TransformationReplaceParamsWithStruct({16, 17}, 90, 91,
175                                                      {{33, 90}, {90, 93}})
176                    .IsApplicable(context.get(), transformation_context));
177   ASSERT_FALSE(TransformationReplaceParamsWithStruct({16, 17}, 90, 91,
178                                                      {{33, 92}, {90, 92}})
179                    .IsApplicable(context.get(), transformation_context));
180 
181   // All 'fresh' ids must be fresh.
182   ASSERT_FALSE(TransformationReplaceParamsWithStruct({16, 17}, 90, 91,
183                                                      {{33, 33}, {90, 93}})
184                    .IsApplicable(context.get(), transformation_context));
185   ASSERT_FALSE(TransformationReplaceParamsWithStruct({16, 17}, 33, 91,
186                                                      {{33, 92}, {90, 93}})
187                    .IsApplicable(context.get(), transformation_context));
188   ASSERT_FALSE(TransformationReplaceParamsWithStruct({16, 17}, 90, 33,
189                                                      {{33, 92}, {90, 93}})
190                    .IsApplicable(context.get(), transformation_context));
191 
192   {
193     TransformationReplaceParamsWithStruct transformation({16, 18, 19}, 90, 91,
194                                                          {{33, 92}, {90, 93}});
195     ASSERT_TRUE(
196         transformation.IsApplicable(context.get(), transformation_context));
197     ApplyAndCheckFreshIds(transformation, context.get(),
198                           &transformation_context);
199   }
200   {
201     TransformationReplaceParamsWithStruct transformation({43}, 93, 94,
202                                                          {{33, 95}});
203     ASSERT_TRUE(
204         transformation.IsApplicable(context.get(), transformation_context));
205     ApplyAndCheckFreshIds(transformation, context.get(),
206                           &transformation_context);
207   }
208   {
209     TransformationReplaceParamsWithStruct transformation({17, 91, 94}, 96, 97,
210                                                          {{33, 98}});
211     ASSERT_TRUE(
212         transformation.IsApplicable(context.get(), transformation_context));
213     ApplyAndCheckFreshIds(transformation, context.get(),
214                           &transformation_context);
215   }
216   {
217     TransformationReplaceParamsWithStruct transformation({55}, 99, 100, {{}});
218     ASSERT_TRUE(
219         transformation.IsApplicable(context.get(), transformation_context));
220     ApplyAndCheckFreshIds(transformation, context.get(),
221                           &transformation_context);
222   }
223   {
224     TransformationReplaceParamsWithStruct transformation({61}, 101, 102, {{}});
225     ASSERT_TRUE(
226         transformation.IsApplicable(context.get(), transformation_context));
227     ApplyAndCheckFreshIds(transformation, context.get(),
228                           &transformation_context);
229   }
230   {
231     TransformationReplaceParamsWithStruct transformation({73}, 103, 104, {{}});
232     ASSERT_TRUE(
233         transformation.IsApplicable(context.get(), transformation_context));
234     ApplyAndCheckFreshIds(transformation, context.get(),
235                           &transformation_context);
236   }
237 
238   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
239                                                kConsoleMessageConsumer));
240 
241   std::string expected_shader = R"(
242                OpCapability Shader
243           %1 = OpExtInstImport "GLSL.std.450"
244                OpMemoryModel Logical GLSL450
245                OpEntryPoint Fragment %4 "main"
246                OpExecutionMode %4 OriginUpperLeft
247                OpSource ESSL 310
248                OpMemberDecorate %13 0 RelaxedPrecision
249                OpDecorate %16 RelaxedPrecision
250           %2 = OpTypeVoid
251           %6 = OpTypeInt 32 1
252           %3 = OpTypeFunction %2
253           %7 = OpTypePointer Private %6
254           %8 = OpTypeFloat 32
255           %9 = OpTypePointer Private %8
256          %10 = OpTypeVector %8 2
257          %11 = OpTypePointer Private %10
258          %12 = OpTypeBool
259          %51 = OpTypeFunction %2 %12
260          %64 = OpTypeStruct %6
261          %63 = OpTypeFunction %2 %64
262          %65 = OpTypeFunction %2 %6
263          %75 = OpTypeStruct %8
264          %76 = OpTypeFunction %2 %75
265          %40 = OpTypePointer Function %12
266          %13 = OpTypeStruct %6 %8
267          %45 = OpTypeStruct %6 %10 %13
268          %46 = OpTypeStruct %12
269          %47 = OpTypeStruct %8 %45 %46
270          %14 = OpTypePointer Private %13
271          %22 = OpConstant %6 0
272          %23 = OpConstant %8 0
273          %26 = OpConstantComposite %10 %23 %23
274          %27 = OpConstantTrue %12
275          %28 = OpConstantComposite %13 %22 %23
276          %15 = OpTypeFunction %2 %40 %47
277          %99 = OpTypeFunction %2 %46
278           %4 = OpFunction %2 None %3
279           %5 = OpLabel
280          %41 = OpVariable %40 Function %27
281          %92 = OpCompositeConstruct %45 %22 %26 %28
282          %95 = OpCompositeConstruct %46 %27
283          %98 = OpCompositeConstruct %47 %23 %92 %95
284          %33 = OpFunctionCall %2 %20 %41 %98
285                OpReturn
286                OpFunctionEnd
287          %20 = OpFunction %2 None %15
288          %42 = OpFunctionParameter %40
289          %97 = OpFunctionParameter %47
290          %21 = OpLabel
291          %94 = OpCompositeExtract %46 %97 2
292          %91 = OpCompositeExtract %45 %97 1
293          %17 = OpCompositeExtract %8 %97 0
294          %43 = OpCompositeExtract %12 %94 0
295          %19 = OpCompositeExtract %13 %91 2
296          %18 = OpCompositeExtract %10 %91 1
297          %16 = OpCompositeExtract %6 %91 0
298                OpReturn
299                OpFunctionEnd
300          %50 = OpFunction %2 None %51
301          %52 = OpFunctionParameter %12
302          %53 = OpLabel
303                OpReturn
304                OpFunctionEnd
305          %54 = OpFunction %2 None %99
306         %100 = OpFunctionParameter %46
307          %56 = OpLabel
308          %55 = OpCompositeExtract %12 %100 0
309                OpReturn
310                OpFunctionEnd
311          %57 = OpFunction %2 None %63
312          %58 = OpFunctionParameter %64
313          %59 = OpLabel
314                OpReturn
315                OpFunctionEnd
316          %60 = OpFunction %2 None %63
317         %102 = OpFunctionParameter %64
318          %62 = OpLabel
319          %61 = OpCompositeExtract %6 %102 0
320                OpReturn
321                OpFunctionEnd
322          %66 = OpFunction %2 None %65
323          %67 = OpFunctionParameter %6
324          %68 = OpLabel
325                OpReturn
326                OpFunctionEnd
327          %69 = OpFunction %2 None %76
328          %70 = OpFunctionParameter %75
329          %71 = OpLabel
330                OpReturn
331                OpFunctionEnd
332          %72 = OpFunction %2 None %76
333         %104 = OpFunctionParameter %75
334          %74 = OpLabel
335          %73 = OpCompositeExtract %8 %104 0
336                OpReturn
337                OpFunctionEnd
338   )";
339 
340   ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
341 }
342 
TEST(TransformationReplaceParamsWithStructTest,ParametersRemainValid)343 TEST(TransformationReplaceParamsWithStructTest, ParametersRemainValid) {
344   std::string shader = R"(
345                OpCapability Shader
346           %1 = OpExtInstImport "GLSL.std.450"
347                OpMemoryModel Logical GLSL450
348                OpEntryPoint Fragment %4 "main"
349                OpExecutionMode %4 OriginUpperLeft
350                OpSource ESSL 310
351           %2 = OpTypeVoid
352           %6 = OpTypeInt 32 1
353           %3 = OpTypeFunction %2
354           %8 = OpTypeFloat 32
355          %10 = OpTypeVector %8 2
356          %12 = OpTypeBool
357          %40 = OpTypePointer Function %12
358          %13 = OpTypeStruct %6 %8
359          %45 = OpTypeStruct %6 %8 %13
360          %47 = OpTypeStruct %45 %12 %10
361          %15 = OpTypeFunction %2 %6 %8 %10 %13 %40 %12
362           %4 = OpFunction %2 None %3
363           %5 = OpLabel
364                OpReturn
365                OpFunctionEnd
366          %20 = OpFunction %2 None %15
367          %16 = OpFunctionParameter %6
368          %17 = OpFunctionParameter %8
369          %18 = OpFunctionParameter %10
370          %19 = OpFunctionParameter %13
371          %42 = OpFunctionParameter %40
372          %43 = OpFunctionParameter %12
373          %21 = OpLabel
374                OpReturn
375                OpFunctionEnd
376   )";
377 
378   const auto env = SPV_ENV_UNIVERSAL_1_3;
379   const auto consumer = nullptr;
380   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
381   spvtools::ValidatorOptions validator_options;
382   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
383                                                kConsoleMessageConsumer));
384   TransformationContext transformation_context(
385       MakeUnique<FactManager>(context.get()), validator_options);
386   {
387     // Try to replace parameters in "increasing" order of their declaration.
388     TransformationReplaceParamsWithStruct transformation({16, 17, 19}, 70, 71,
389                                                          {{}});
390     ASSERT_TRUE(
391         transformation.IsApplicable(context.get(), transformation_context));
392     ApplyAndCheckFreshIds(transformation, context.get(),
393                           &transformation_context);
394     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
395         context.get(), validator_options, kConsoleMessageConsumer));
396   }
397 
398   std::string after_transformation = R"(
399                OpCapability Shader
400           %1 = OpExtInstImport "GLSL.std.450"
401                OpMemoryModel Logical GLSL450
402                OpEntryPoint Fragment %4 "main"
403                OpExecutionMode %4 OriginUpperLeft
404                OpSource ESSL 310
405           %2 = OpTypeVoid
406           %6 = OpTypeInt 32 1
407           %3 = OpTypeFunction %2
408           %8 = OpTypeFloat 32
409          %10 = OpTypeVector %8 2
410          %12 = OpTypeBool
411          %40 = OpTypePointer Function %12
412          %13 = OpTypeStruct %6 %8
413          %45 = OpTypeStruct %6 %8 %13
414          %47 = OpTypeStruct %45 %12 %10
415          %15 = OpTypeFunction %2 %10 %40 %12 %45
416           %4 = OpFunction %2 None %3
417           %5 = OpLabel
418                OpReturn
419                OpFunctionEnd
420          %20 = OpFunction %2 None %15
421          %18 = OpFunctionParameter %10
422          %42 = OpFunctionParameter %40
423          %43 = OpFunctionParameter %12
424          %71 = OpFunctionParameter %45
425          %21 = OpLabel
426          %19 = OpCompositeExtract %13 %71 2
427          %17 = OpCompositeExtract %8 %71 1
428          %16 = OpCompositeExtract %6 %71 0
429                OpReturn
430                OpFunctionEnd
431   )";
432 
433   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
434 
435   {
436     // Try to replace parameters in "decreasing" order of their declaration.
437     TransformationReplaceParamsWithStruct transformation({71, 43, 18}, 72, 73,
438                                                          {{}});
439     ASSERT_TRUE(
440         transformation.IsApplicable(context.get(), transformation_context));
441     ApplyAndCheckFreshIds(transformation, context.get(),
442                           &transformation_context);
443     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
444         context.get(), validator_options, kConsoleMessageConsumer));
445   }
446 
447   after_transformation = R"(
448                OpCapability Shader
449           %1 = OpExtInstImport "GLSL.std.450"
450                OpMemoryModel Logical GLSL450
451                OpEntryPoint Fragment %4 "main"
452                OpExecutionMode %4 OriginUpperLeft
453                OpSource ESSL 310
454           %2 = OpTypeVoid
455           %6 = OpTypeInt 32 1
456           %3 = OpTypeFunction %2
457           %8 = OpTypeFloat 32
458          %10 = OpTypeVector %8 2
459          %12 = OpTypeBool
460          %40 = OpTypePointer Function %12
461          %13 = OpTypeStruct %6 %8
462          %45 = OpTypeStruct %6 %8 %13
463          %47 = OpTypeStruct %45 %12 %10
464          %15 = OpTypeFunction %2 %40 %47
465           %4 = OpFunction %2 None %3
466           %5 = OpLabel
467                OpReturn
468                OpFunctionEnd
469          %20 = OpFunction %2 None %15
470          %42 = OpFunctionParameter %40
471          %73 = OpFunctionParameter %47
472          %21 = OpLabel
473          %18 = OpCompositeExtract %10 %73 2
474          %43 = OpCompositeExtract %12 %73 1
475          %71 = OpCompositeExtract %45 %73 0
476          %19 = OpCompositeExtract %13 %71 2
477          %17 = OpCompositeExtract %8 %71 1
478          %16 = OpCompositeExtract %6 %71 0
479                OpReturn
480                OpFunctionEnd
481   )";
482 
483   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
484 }
485 
TEST(TransformationReplaceParamsWithStructTest,IsomorphicStructs)486 TEST(TransformationReplaceParamsWithStructTest, IsomorphicStructs) {
487   std::string shader = R"(
488                OpCapability Shader
489           %1 = OpExtInstImport "GLSL.std.450"
490                OpMemoryModel Logical GLSL450
491                OpEntryPoint Fragment %16 "main"
492                OpExecutionMode %16 OriginUpperLeft
493                OpSource ESSL 310
494           %2 = OpTypeVoid
495           %6 = OpTypeInt 32 1
496           %7 = OpTypeStruct %6
497           %8 = OpTypeStruct %6
498           %9 = OpTypeStruct %8
499          %10 = OpTypeFunction %2 %7
500          %15 = OpTypeFunction %2
501          %16 = OpFunction %2 None %15
502          %17 = OpLabel
503                OpReturn
504                OpFunctionEnd
505          %11 = OpFunction %2 None %10
506          %12 = OpFunctionParameter %7
507          %13 = OpLabel
508                OpReturn
509                OpFunctionEnd
510   )";
511 
512   const auto env = SPV_ENV_UNIVERSAL_1_3;
513   const auto consumer = nullptr;
514   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
515   spvtools::ValidatorOptions validator_options;
516   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
517                                                kConsoleMessageConsumer));
518   TransformationContext transformation_context(
519       MakeUnique<FactManager>(context.get()), validator_options);
520 
521   ASSERT_FALSE(TransformationReplaceParamsWithStruct({12}, 100, 101, {{}})
522                    .IsApplicable(context.get(), transformation_context));
523 }
524 
525 }  // namespace
526 }  // namespace fuzz
527 }  // namespace spvtools
528