• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2021 Mostafa Ashraf
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_function_variables.h"
16 
17 #include "gtest/gtest.h"
18 #include "source/fuzz/fuzzer_util.h"
19 #include "source/fuzz/instruction_descriptor.h"
20 #include "test/fuzz/fuzz_test_util.h"
21 
22 namespace spvtools {
23 namespace fuzz {
24 namespace {
25 
TEST(TransformationSwapFunctionVariables,NotApplicable)26 TEST(TransformationSwapFunctionVariables, NotApplicable) {
27   std::string shader = R"(
28                OpCapability Shader
29           %1 = OpExtInstImport "GLSL.std.450"
30                OpMemoryModel Logical GLSL450
31                OpEntryPoint Fragment %4 "main"
32                OpExecutionMode %4 OriginUpperLeft
33                OpSource ESSL 320
34           %2 = OpTypeVoid
35           %3 = OpTypeFunction %2
36           %6 = OpTypeInt 32 1
37           %7 = OpTypePointer Function %6
38           %8 = OpTypeFloat 32
39           %9 = OpTypePointer Function %8
40          %10 = OpTypeVector %8 2
41          %11 = OpTypePointer Function %10
42          %12 = OpTypeVector %8 3
43          %13 = OpTypeMatrix %12 3
44          %14 = OpTypePointer Function %13
45          %15 = OpTypeFunction %2 %7 %9 %11 %14 %7 %7
46           %4 = OpFunction %2 None %3
47           %5 = OpLabel
48          %24 = OpVariable %7 Function
49          %25 = OpVariable %9 Function
50          %26 = OpVariable %11 Function
51          %27 = OpVariable %14 Function
52          %28 = OpVariable %7 Function
53          %29 = OpVariable %7 Function
54          %30 = OpVariable %7 Function
55          %32 = OpVariable %9 Function
56          %34 = OpVariable %11 Function
57          %36 = OpVariable %14 Function
58          %38 = OpVariable %7 Function
59          %40 = OpVariable %7 Function
60          %31 = OpLoad %6 %24
61                OpStore %30 %31
62          %33 = OpLoad %8 %25
63                OpStore %32 %33
64          %35 = OpLoad %10 %26
65                OpStore %34 %35
66          %37 = OpLoad %13 %27
67                OpStore %36 %37
68          %39 = OpLoad %6 %28
69                OpStore %38 %39
70          %41 = OpLoad %6 %29
71                OpStore %40 %41
72          %42 = OpFunctionCall %2 %22 %30 %32 %34 %36 %38 %40
73                OpReturn
74                OpFunctionEnd
75          %22 = OpFunction %2 None %15
76          %16 = OpFunctionParameter %7
77          %17 = OpFunctionParameter %9
78          %18 = OpFunctionParameter %11
79          %19 = OpFunctionParameter %14
80          %20 = OpFunctionParameter %7
81          %21 = OpFunctionParameter %7
82          %23 = OpLabel
83                OpReturn
84                OpFunctionEnd
85 )";
86 
87   const auto env = SPV_ENV_UNIVERSAL_1_5;
88   const auto consumer = nullptr;
89   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
90   spvtools::ValidatorOptions validator_options;
91 
92   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
93                                                kConsoleMessageConsumer));
94   TransformationContext transformation_context(
95       MakeUnique<FactManager>(context.get()), validator_options);
96 
97 #ifndef NDEBUG
98   // Can't swap variable with itself.
99   ASSERT_DEATH(TransformationSwapFunctionVariables(7, 7).IsApplicable(
100                    context.get(), transformation_context),
101                "Two results ids are equal");
102 #endif
103 
104   // Invalid because 200 is not the id of an instruction.
105   ASSERT_FALSE(TransformationSwapFunctionVariables(1, 200).IsApplicable(
106       context.get(), transformation_context));
107   // Invalid because 5 is not the id of an instruction.
108   ASSERT_FALSE(TransformationSwapFunctionVariables(5, 24).IsApplicable(
109       context.get(), transformation_context));
110   // Can't swap two instructions from two different blocks.
111   ASSERT_FALSE(TransformationSwapFunctionVariables(16, 26).IsApplicable(
112       context.get(), transformation_context));
113 }
114 
TEST(TransformationSwapFunctionVariables,IsApplicable)115 TEST(TransformationSwapFunctionVariables, IsApplicable) {
116   std::string shader = R"(
117                OpCapability Shader
118           %1 = OpExtInstImport "GLSL.std.450"
119                OpMemoryModel Logical GLSL450
120                OpEntryPoint Fragment %4 "main"
121                OpExecutionMode %4 OriginUpperLeft
122                OpSource ESSL 320
123           %2 = OpTypeVoid
124           %3 = OpTypeFunction %2
125           %6 = OpTypeInt 32 1
126           %7 = OpTypePointer Function %6
127           %8 = OpTypeFloat 32
128           %9 = OpTypePointer Function %8
129          %10 = OpTypeVector %8 2
130          %11 = OpTypePointer Function %10
131          %12 = OpTypeVector %8 3
132          %13 = OpTypeMatrix %12 3
133          %14 = OpTypePointer Function %13
134          %15 = OpTypeFunction %2 %7 %9 %11 %14 %7 %7
135           %4 = OpFunction %2 None %3
136           %5 = OpLabel
137          %24 = OpVariable %7 Function
138          %25 = OpVariable %9 Function
139          %26 = OpVariable %11 Function
140          %27 = OpVariable %14 Function
141          %28 = OpVariable %7 Function
142          %29 = OpVariable %7 Function
143          %30 = OpVariable %7 Function
144          %32 = OpVariable %9 Function
145          %34 = OpVariable %11 Function
146          %36 = OpVariable %14 Function
147          %38 = OpVariable %7 Function
148          %40 = OpVariable %7 Function
149          %31 = OpLoad %6 %24
150                OpStore %30 %31
151          %33 = OpLoad %8 %25
152                OpStore %32 %33
153          %35 = OpLoad %10 %26
154                OpStore %34 %35
155          %37 = OpLoad %13 %27
156                OpStore %36 %37
157          %39 = OpLoad %6 %28
158                OpStore %38 %39
159          %41 = OpLoad %6 %29
160                OpStore %40 %41
161          %42 = OpFunctionCall %2 %22 %30 %32 %34 %36 %38 %40
162                OpReturn
163                OpFunctionEnd
164          %22 = OpFunction %2 None %15
165          %16 = OpFunctionParameter %7
166          %17 = OpFunctionParameter %9
167          %18 = OpFunctionParameter %11
168          %19 = OpFunctionParameter %14
169          %20 = OpFunctionParameter %7
170          %21 = OpFunctionParameter %7
171          %23 = OpLabel
172                OpReturn
173                OpFunctionEnd
174 )";
175 
176   const auto env = SPV_ENV_UNIVERSAL_1_5;
177   const auto consumer = nullptr;
178   // Get Unique pointer of IRContext.
179   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
180   spvtools::ValidatorOptions validator_options;
181 
182   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
183                                                kConsoleMessageConsumer));
184   TransformationContext transformation_context(
185       MakeUnique<FactManager>(context.get()), validator_options);
186 
187   // Successful transformations
188   {
189     auto first_instruction = context->get_def_use_mgr()->GetDef(24);
190     auto second_instruction = context->get_def_use_mgr()->GetDef(28);
191     // Swap two OpVariable instructions in the same function.
192     TransformationSwapFunctionVariables transformation(24, 28);
193 
194     ASSERT_TRUE(
195         transformation.IsApplicable(context.get(), transformation_context));
196 
197     ApplyAndCheckFreshIds(transformation, context.get(),
198                           &transformation_context);
199 
200     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
201         context.get(), validator_options, kConsoleMessageConsumer));
202 
203     ASSERT_EQ(first_instruction, context->get_def_use_mgr()->GetDef(24));
204     ASSERT_EQ(second_instruction, context->get_def_use_mgr()->GetDef(28));
205   }
206   {
207     auto first_instruction = context->get_def_use_mgr()->GetDef(38);
208     auto second_instruction = context->get_def_use_mgr()->GetDef(40);
209     // Swap two OpVariable instructions in the same function.
210     TransformationSwapFunctionVariables transformation(38, 40);
211 
212     ASSERT_TRUE(
213         transformation.IsApplicable(context.get(), transformation_context));
214 
215     ApplyAndCheckFreshIds(transformation, context.get(),
216                           &transformation_context);
217 
218     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
219         context.get(), validator_options, kConsoleMessageConsumer));
220 
221     ASSERT_EQ(first_instruction, context->get_def_use_mgr()->GetDef(38));
222     ASSERT_EQ(second_instruction, context->get_def_use_mgr()->GetDef(40));
223   }
224   std::string after_transformation = R"(
225                OpCapability Shader
226           %1 = OpExtInstImport "GLSL.std.450"
227                OpMemoryModel Logical GLSL450
228                OpEntryPoint Fragment %4 "main"
229                OpExecutionMode %4 OriginUpperLeft
230                OpSource ESSL 320
231           %2 = OpTypeVoid
232           %3 = OpTypeFunction %2
233           %6 = OpTypeInt 32 1
234           %7 = OpTypePointer Function %6
235           %8 = OpTypeFloat 32
236           %9 = OpTypePointer Function %8
237          %10 = OpTypeVector %8 2
238          %11 = OpTypePointer Function %10
239          %12 = OpTypeVector %8 3
240          %13 = OpTypeMatrix %12 3
241          %14 = OpTypePointer Function %13
242          %15 = OpTypeFunction %2 %7 %9 %11 %14 %7 %7
243           %4 = OpFunction %2 None %3
244           %5 = OpLabel
245          %28 = OpVariable %7 Function
246          %25 = OpVariable %9 Function
247          %26 = OpVariable %11 Function
248          %27 = OpVariable %14 Function
249          %24 = OpVariable %7 Function
250          %29 = OpVariable %7 Function
251          %30 = OpVariable %7 Function
252          %32 = OpVariable %9 Function
253          %34 = OpVariable %11 Function
254          %36 = OpVariable %14 Function
255          %40 = OpVariable %7 Function
256          %38 = OpVariable %7 Function
257          %31 = OpLoad %6 %24
258                OpStore %30 %31
259          %33 = OpLoad %8 %25
260                OpStore %32 %33
261          %35 = OpLoad %10 %26
262                OpStore %34 %35
263          %37 = OpLoad %13 %27
264                OpStore %36 %37
265          %39 = OpLoad %6 %28
266                OpStore %38 %39
267          %41 = OpLoad %6 %29
268                OpStore %40 %41
269          %42 = OpFunctionCall %2 %22 %30 %32 %34 %36 %38 %40
270                OpReturn
271                OpFunctionEnd
272          %22 = OpFunction %2 None %15
273          %16 = OpFunctionParameter %7
274          %17 = OpFunctionParameter %9
275          %18 = OpFunctionParameter %11
276          %19 = OpFunctionParameter %14
277          %20 = OpFunctionParameter %7
278          %21 = OpFunctionParameter %7
279          %23 = OpLabel
280                OpReturn
281                OpFunctionEnd
282 )";
283   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
284 }
285 
286 }  // namespace
287 }  // namespace fuzz
288 }  // namespace spvtools
289