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