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