• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2021 Shiyu Liu
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_swap_two_functions.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(TransformationSwapTwoFunctionsTest,SimpleTest)25 TEST(TransformationSwapTwoFunctionsTest, SimpleTest) {
26   //   float multiplyBy2(in float value) {
27   //     return value*2.0;
28   //   }
29 
30   //   float multiplyBy4(in float value) {
31   //     return multiplyBy2(value)*2.0;
32   //   }
33 
34   //   float multiplyBy8(in float value) {
35   //     return multiplyBy2(value)*multiplyBy4(value);
36   //   }
37 
38   //   layout(location=0) in float value;
39   //   void main() { //4
40   //     multiplyBy2(3.7); //10
41   //     multiplyBy4(3.9); //13
42   //     multiplyBy8(5.0); //16
43   //   }
44 
45   std::string shader = R"(
46                OpCapability Shader
47           %1 = OpExtInstImport "GLSL.std.450"
48                OpMemoryModel Logical GLSL450
49                OpEntryPoint Fragment %4 "main" %48
50                OpExecutionMode %4 OriginUpperLeft
51                OpSource ESSL 310
52                OpName %4 "main"
53                OpName %10 "multiplyBy2(f1;"
54                OpName %9 "value"
55                OpName %13 "multiplyBy4(f1;"
56                OpName %12 "value"
57                OpName %16 "multiplyBy8(f1;"
58                OpName %15 "value"
59                OpName %23 "param"
60                OpName %29 "param"
61                OpName %32 "param"
62                OpName %39 "param"
63                OpName %42 "param"
64                OpName %45 "param"
65                OpName %48 "value"
66                OpDecorate %48 Location 0
67           %2 = OpTypeVoid
68           %3 = OpTypeFunction %2
69           %6 = OpTypeFloat 32
70           %7 = OpTypePointer Function %6
71           %8 = OpTypeFunction %6 %7
72          %19 = OpConstant %6 2
73          %38 = OpConstant %6 3.70000005
74          %41 = OpConstant %6 3.9000001
75          %44 = OpConstant %6 5
76          %47 = OpTypePointer Input %6
77          %48 = OpVariable %47 Input
78           %4 = OpFunction %2 None %3
79           %5 = OpLabel
80          %39 = OpVariable %7 Function
81          %42 = OpVariable %7 Function
82          %45 = OpVariable %7 Function
83                OpStore %39 %38
84          %40 = OpFunctionCall %6 %10 %39
85                OpStore %42 %41
86          %43 = OpFunctionCall %6 %13 %42
87                OpStore %45 %44
88          %46 = OpFunctionCall %6 %16 %45
89                OpReturn
90                OpFunctionEnd
91          %10 = OpFunction %6 None %8
92           %9 = OpFunctionParameter %7
93          %11 = OpLabel
94          %18 = OpLoad %6 %9
95          %20 = OpFMul %6 %18 %19
96                OpReturnValue %20
97                OpFunctionEnd
98          %13 = OpFunction %6 None %8
99          %12 = OpFunctionParameter %7
100          %14 = OpLabel
101          %23 = OpVariable %7 Function
102          %24 = OpLoad %6 %12
103                OpStore %23 %24
104          %25 = OpFunctionCall %6 %10 %23
105          %26 = OpFMul %6 %25 %19
106                OpReturnValue %26
107                OpFunctionEnd
108          %16 = OpFunction %6 None %8
109          %15 = OpFunctionParameter %7
110          %17 = OpLabel
111          %29 = OpVariable %7 Function
112          %32 = OpVariable %7 Function
113          %30 = OpLoad %6 %15
114                OpStore %29 %30
115          %31 = OpFunctionCall %6 %10 %29
116          %33 = OpLoad %6 %15
117                OpStore %32 %33
118          %34 = OpFunctionCall %6 %13 %32
119          %35 = OpFMul %6 %31 %34
120                OpReturnValue %35
121                OpFunctionEnd
122   )";
123   const auto env = SPV_ENV_UNIVERSAL_1_3;
124   const auto consumer = nullptr;
125   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
126   spvtools::ValidatorOptions validator_options;
127 
128   // Check context validity.
129   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
130                                                kConsoleMessageConsumer));
131 
132   TransformationContext transformation_context(
133       MakeUnique<FactManager>(context.get()), validator_options);
134 
135 #ifndef NDEBUG
136   // Function should not swap with itself.
137   ASSERT_DEATH(TransformationSwapTwoFunctions(4, 4).IsApplicable(
138                    context.get(), transformation_context),
139                "The two function ids cannot be the same.");
140 #endif
141 
142   // Function with id 29 does not exist.
143   ASSERT_FALSE(TransformationSwapTwoFunctions(10, 29).IsApplicable(
144       context.get(), transformation_context));
145 
146   // Function with id 30 does not exist.
147   ASSERT_FALSE(TransformationSwapTwoFunctions(30, 13).IsApplicable(
148       context.get(), transformation_context));
149 
150   // Both functions with id 5 and 6 do not exist.
151   ASSERT_FALSE(TransformationSwapTwoFunctions(5, 6).IsApplicable(
152       context.get(), transformation_context));
153 
154   // Function with result_id 10 and 13 should swap successfully.
155   auto swap_test5 = TransformationSwapTwoFunctions(10, 13);
156   ASSERT_TRUE(swap_test5.IsApplicable(context.get(), transformation_context));
157 
158   // Get the definitions of functions 10 and 13, as recorded by the def-use
159   // manager.
160   auto def_use_manager = context->get_def_use_mgr();
161   auto function_10_inst = def_use_manager->GetDef(10);
162   auto function_13_inst = def_use_manager->GetDef(13);
163 
164   ApplyAndCheckFreshIds(swap_test5, context.get(), &transformation_context);
165 
166   // Check that def-use information for functions 10 and 13 has been preserved
167   // by the transformation.
168   ASSERT_EQ(function_10_inst, def_use_manager->GetDef(10));
169   ASSERT_EQ(function_13_inst, def_use_manager->GetDef(13));
170 
171   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
172                                                kConsoleMessageConsumer));
173 
174   std::string after_transformation = R"(
175                OpCapability Shader
176           %1 = OpExtInstImport "GLSL.std.450"
177                OpMemoryModel Logical GLSL450
178                OpEntryPoint Fragment %4 "main" %48
179                OpExecutionMode %4 OriginUpperLeft
180                OpSource ESSL 310
181                OpName %4 "main"
182                OpName %10 "multiplyBy2(f1;"
183                OpName %9 "value"
184                OpName %13 "multiplyBy4(f1;"
185                OpName %12 "value"
186                OpName %16 "multiplyBy8(f1;"
187                OpName %15 "value"
188                OpName %23 "param"
189                OpName %29 "param"
190                OpName %32 "param"
191                OpName %39 "param"
192                OpName %42 "param"
193                OpName %45 "param"
194                OpName %48 "value"
195                OpDecorate %48 Location 0
196           %2 = OpTypeVoid
197           %3 = OpTypeFunction %2
198           %6 = OpTypeFloat 32
199           %7 = OpTypePointer Function %6
200           %8 = OpTypeFunction %6 %7
201          %19 = OpConstant %6 2
202          %38 = OpConstant %6 3.70000005
203          %41 = OpConstant %6 3.9000001
204          %44 = OpConstant %6 5
205          %47 = OpTypePointer Input %6
206          %48 = OpVariable %47 Input
207           %4 = OpFunction %2 None %3
208           %5 = OpLabel
209          %39 = OpVariable %7 Function
210          %42 = OpVariable %7 Function
211          %45 = OpVariable %7 Function
212                OpStore %39 %38
213          %40 = OpFunctionCall %6 %10 %39
214                OpStore %42 %41
215          %43 = OpFunctionCall %6 %13 %42
216                OpStore %45 %44
217          %46 = OpFunctionCall %6 %16 %45
218                OpReturn
219                OpFunctionEnd
220          %13 = OpFunction %6 None %8
221          %12 = OpFunctionParameter %7
222          %14 = OpLabel
223          %23 = OpVariable %7 Function
224          %24 = OpLoad %6 %12
225                OpStore %23 %24
226          %25 = OpFunctionCall %6 %10 %23
227          %26 = OpFMul %6 %25 %19
228                OpReturnValue %26
229                OpFunctionEnd
230          %10 = OpFunction %6 None %8
231          %9 = OpFunctionParameter %7
232          %11 = OpLabel
233          %18 = OpLoad %6 %9
234          %20 = OpFMul %6 %18 %19
235                OpReturnValue %20
236                OpFunctionEnd
237          %16 = OpFunction %6 None %8
238          %15 = OpFunctionParameter %7
239          %17 = OpLabel
240          %29 = OpVariable %7 Function
241          %32 = OpVariable %7 Function
242          %30 = OpLoad %6 %15
243                OpStore %29 %30
244          %31 = OpFunctionCall %6 %10 %29
245          %33 = OpLoad %6 %15
246                OpStore %32 %33
247          %34 = OpFunctionCall %6 %13 %32
248          %35 = OpFMul %6 %31 %34
249                OpReturnValue %35
250                OpFunctionEnd
251   )";
252   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
253 }
254 
255 }  // namespace
256 }  // namespace fuzz
257 }  // namespace spvtools
258