• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2020 André Perez Maselco
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_toggle_access_chain_instruction.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(TransformationToggleAccessChainInstructionTest,IsApplicableTest)26 TEST(TransformationToggleAccessChainInstructionTest, IsApplicableTest) {
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 310
34                OpName %4 "main"
35           %2 = OpTypeVoid
36           %3 = OpTypeFunction %2
37           %6 = OpTypeInt 32 1
38           %7 = OpTypeInt 32 0
39           %8 = OpConstant %7 2
40           %9 = OpTypeArray %6 %8
41          %10 = OpTypePointer Function %9
42          %12 = OpConstant %6 1
43          %13 = OpConstant %6 2
44          %14 = OpConstantComposite %9 %12 %13
45          %15 = OpTypePointer Function %6
46          %17 = OpConstant %6 0
47          %29 = OpTypeFloat 32
48          %30 = OpTypeArray %29 %8
49          %31 = OpTypePointer Function %30
50          %33 = OpConstant %29 1
51          %34 = OpConstant %29 2
52          %35 = OpConstantComposite %30 %33 %34
53          %36 = OpTypePointer Function %29
54          %49 = OpTypeVector %29 3
55          %50 = OpTypeArray %49 %8
56          %51 = OpTypePointer Function %50
57          %53 = OpConstant %29 3
58          %54 = OpConstantComposite %49 %33 %34 %53
59          %55 = OpConstant %29 4
60          %56 = OpConstant %29 5
61          %57 = OpConstant %29 6
62          %58 = OpConstantComposite %49 %55 %56 %57
63          %59 = OpConstantComposite %50 %54 %58
64          %61 = OpTypePointer Function %49
65           %4 = OpFunction %2 None %3
66           %5 = OpLabel
67          %11 = OpVariable %10 Function
68          %16 = OpVariable %15 Function
69          %23 = OpVariable %15 Function
70          %32 = OpVariable %31 Function
71          %37 = OpVariable %36 Function
72          %43 = OpVariable %36 Function
73          %52 = OpVariable %51 Function
74          %60 = OpVariable %36 Function
75                OpStore %11 %14
76          %18 = OpAccessChain %15 %11 %17
77          %19 = OpLoad %6 %18
78          %20 = OpInBoundsAccessChain %15 %11 %12
79          %21 = OpLoad %6 %20
80          %22 = OpIAdd %6 %19 %21
81                OpStore %16 %22
82          %24 = OpAccessChain %15 %11 %17
83          %25 = OpLoad %6 %24
84          %26 = OpInBoundsAccessChain %15 %11 %12
85          %27 = OpLoad %6 %26
86          %28 = OpIMul %6 %25 %27
87                OpStore %23 %28
88                OpStore %32 %35
89          %38 = OpAccessChain %36 %32 %17
90          %39 = OpLoad %29 %38
91          %40 = OpAccessChain %36 %32 %12
92          %41 = OpLoad %29 %40
93          %42 = OpFAdd %29 %39 %41
94                OpStore %37 %42
95          %44 = OpAccessChain %36 %32 %17
96          %45 = OpLoad %29 %44
97          %46 = OpAccessChain %36 %32 %12
98          %47 = OpLoad %29 %46
99          %48 = OpFMul %29 %45 %47
100                OpStore %43 %48
101                OpStore %52 %59
102          %62 = OpAccessChain %61 %52 %17
103          %63 = OpLoad %49 %62
104          %64 = OpAccessChain %61 %52 %12
105          %65 = OpLoad %49 %64
106          %66 = OpDot %29 %63 %65
107                OpStore %60 %66
108                OpReturn
109                OpFunctionEnd
110   )";
111 
112   const auto env = SPV_ENV_UNIVERSAL_1_5;
113   const auto consumer = nullptr;
114   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
115   spvtools::ValidatorOptions validator_options;
116   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
117                                                kConsoleMessageConsumer));
118   TransformationContext transformation_context(
119       MakeUnique<FactManager>(context.get()), validator_options);
120   // Tests existing access chain instructions
121   auto instructionDescriptor =
122       MakeInstructionDescriptor(18, SpvOpAccessChain, 0);
123   auto transformation =
124       TransformationToggleAccessChainInstruction(instructionDescriptor);
125   ASSERT_TRUE(
126       transformation.IsApplicable(context.get(), transformation_context));
127 
128   instructionDescriptor =
129       MakeInstructionDescriptor(20, SpvOpInBoundsAccessChain, 0);
130   transformation =
131       TransformationToggleAccessChainInstruction(instructionDescriptor);
132   ASSERT_TRUE(
133       transformation.IsApplicable(context.get(), transformation_context));
134 
135   instructionDescriptor = MakeInstructionDescriptor(24, SpvOpAccessChain, 0);
136   transformation =
137       TransformationToggleAccessChainInstruction(instructionDescriptor);
138   ASSERT_TRUE(
139       transformation.IsApplicable(context.get(), transformation_context));
140 
141   instructionDescriptor =
142       MakeInstructionDescriptor(26, SpvOpInBoundsAccessChain, 0);
143   transformation =
144       TransformationToggleAccessChainInstruction(instructionDescriptor);
145   ASSERT_TRUE(
146       transformation.IsApplicable(context.get(), transformation_context));
147 
148   // Tests existing non-access chain instructions
149   instructionDescriptor = MakeInstructionDescriptor(1, SpvOpExtInstImport, 0);
150   transformation =
151       TransformationToggleAccessChainInstruction(instructionDescriptor);
152   ASSERT_FALSE(
153       transformation.IsApplicable(context.get(), transformation_context));
154 
155   instructionDescriptor = MakeInstructionDescriptor(5, SpvOpLabel, 0);
156   transformation =
157       TransformationToggleAccessChainInstruction(instructionDescriptor);
158   ASSERT_FALSE(
159       transformation.IsApplicable(context.get(), transformation_context));
160 
161   instructionDescriptor =
162       MakeInstructionDescriptor(14, SpvOpConstantComposite, 0);
163   transformation =
164       TransformationToggleAccessChainInstruction(instructionDescriptor);
165   ASSERT_FALSE(
166       transformation.IsApplicable(context.get(), transformation_context));
167 
168   // Tests the base instruction id not existing
169   instructionDescriptor = MakeInstructionDescriptor(67, SpvOpAccessChain, 0);
170   transformation =
171       TransformationToggleAccessChainInstruction(instructionDescriptor);
172   ASSERT_FALSE(
173       transformation.IsApplicable(context.get(), transformation_context));
174 
175   instructionDescriptor = MakeInstructionDescriptor(68, SpvOpAccessChain, 0);
176   transformation =
177       TransformationToggleAccessChainInstruction(instructionDescriptor);
178   ASSERT_FALSE(
179       transformation.IsApplicable(context.get(), transformation_context));
180 
181   instructionDescriptor =
182       MakeInstructionDescriptor(69, SpvOpInBoundsAccessChain, 0);
183   transformation =
184       TransformationToggleAccessChainInstruction(instructionDescriptor);
185   ASSERT_FALSE(
186       transformation.IsApplicable(context.get(), transformation_context));
187 
188   // Tests there being no instruction with the desired opcode after the base
189   // instruction id
190   instructionDescriptor = MakeInstructionDescriptor(65, SpvOpAccessChain, 0);
191   transformation =
192       TransformationToggleAccessChainInstruction(instructionDescriptor);
193   ASSERT_FALSE(
194       transformation.IsApplicable(context.get(), transformation_context));
195 
196   instructionDescriptor =
197       MakeInstructionDescriptor(66, SpvOpInBoundsAccessChain, 0);
198   transformation =
199       TransformationToggleAccessChainInstruction(instructionDescriptor);
200   ASSERT_FALSE(
201       transformation.IsApplicable(context.get(), transformation_context));
202 
203   // Tests there being an instruction with the desired opcode after the base
204   // instruction id, but the skip count associated with the instruction
205   // descriptor being so high.
206   instructionDescriptor = MakeInstructionDescriptor(11, SpvOpAccessChain, 100);
207   transformation =
208       TransformationToggleAccessChainInstruction(instructionDescriptor);
209   ASSERT_FALSE(
210       transformation.IsApplicable(context.get(), transformation_context));
211 
212   instructionDescriptor =
213       MakeInstructionDescriptor(16, SpvOpInBoundsAccessChain, 100);
214   transformation =
215       TransformationToggleAccessChainInstruction(instructionDescriptor);
216   ASSERT_FALSE(
217       transformation.IsApplicable(context.get(), transformation_context));
218 }
219 
TEST(TransformationToggleAccessChainInstructionTest,ApplyTest)220 TEST(TransformationToggleAccessChainInstructionTest, ApplyTest) {
221   std::string shader = R"(
222                OpCapability Shader
223           %1 = OpExtInstImport "GLSL.std.450"
224                OpMemoryModel Logical GLSL450
225                OpEntryPoint Fragment %4 "main"
226                OpExecutionMode %4 OriginUpperLeft
227                OpSource ESSL 310
228                OpName %4 "main"
229           %2 = OpTypeVoid
230           %3 = OpTypeFunction %2
231           %6 = OpTypeInt 32 1
232           %7 = OpTypeInt 32 0
233           %8 = OpConstant %7 2
234           %9 = OpTypeArray %6 %8
235          %10 = OpTypePointer Function %9
236          %12 = OpConstant %6 1
237          %13 = OpConstant %6 2
238          %14 = OpConstantComposite %9 %12 %13
239          %15 = OpTypePointer Function %6
240          %17 = OpConstant %6 0
241          %29 = OpTypeFloat 32
242          %30 = OpTypeArray %29 %8
243          %31 = OpTypePointer Function %30
244          %33 = OpConstant %29 1
245          %34 = OpConstant %29 2
246          %35 = OpConstantComposite %30 %33 %34
247          %36 = OpTypePointer Function %29
248          %49 = OpTypeVector %29 3
249          %50 = OpTypeArray %49 %8
250          %51 = OpTypePointer Function %50
251          %53 = OpConstant %29 3
252          %54 = OpConstantComposite %49 %33 %34 %53
253          %55 = OpConstant %29 4
254          %56 = OpConstant %29 5
255          %57 = OpConstant %29 6
256          %58 = OpConstantComposite %49 %55 %56 %57
257          %59 = OpConstantComposite %50 %54 %58
258          %61 = OpTypePointer Function %49
259           %4 = OpFunction %2 None %3
260           %5 = OpLabel
261          %11 = OpVariable %10 Function
262          %16 = OpVariable %15 Function
263          %23 = OpVariable %15 Function
264          %32 = OpVariable %31 Function
265          %37 = OpVariable %36 Function
266          %43 = OpVariable %36 Function
267          %52 = OpVariable %51 Function
268          %60 = OpVariable %36 Function
269                OpStore %11 %14
270          %18 = OpAccessChain %15 %11 %17
271          %19 = OpLoad %6 %18
272          %20 = OpInBoundsAccessChain %15 %11 %12
273          %21 = OpLoad %6 %20
274          %22 = OpIAdd %6 %19 %21
275                OpStore %16 %22
276          %24 = OpAccessChain %15 %11 %17
277          %25 = OpLoad %6 %24
278          %26 = OpInBoundsAccessChain %15 %11 %12
279          %27 = OpLoad %6 %26
280          %28 = OpIMul %6 %25 %27
281                OpStore %23 %28
282                OpStore %32 %35
283          %38 = OpAccessChain %36 %32 %17
284          %39 = OpLoad %29 %38
285          %40 = OpAccessChain %36 %32 %12
286          %41 = OpLoad %29 %40
287          %42 = OpFAdd %29 %39 %41
288                OpStore %37 %42
289          %44 = OpAccessChain %36 %32 %17
290          %45 = OpLoad %29 %44
291          %46 = OpAccessChain %36 %32 %12
292          %47 = OpLoad %29 %46
293          %48 = OpFMul %29 %45 %47
294                OpStore %43 %48
295                OpStore %52 %59
296          %62 = OpAccessChain %61 %52 %17
297          %63 = OpLoad %49 %62
298          %64 = OpAccessChain %61 %52 %12
299          %65 = OpLoad %49 %64
300          %66 = OpDot %29 %63 %65
301                OpStore %60 %66
302                OpReturn
303                OpFunctionEnd
304   )";
305 
306   const auto env = SPV_ENV_UNIVERSAL_1_5;
307   const auto consumer = nullptr;
308   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
309   spvtools::ValidatorOptions validator_options;
310   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
311                                                kConsoleMessageConsumer));
312   TransformationContext transformation_context(
313       MakeUnique<FactManager>(context.get()), validator_options);
314   auto instructionDescriptor =
315       MakeInstructionDescriptor(18, SpvOpAccessChain, 0);
316   auto transformation =
317       TransformationToggleAccessChainInstruction(instructionDescriptor);
318   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
319 
320   instructionDescriptor =
321       MakeInstructionDescriptor(20, SpvOpInBoundsAccessChain, 0);
322   transformation =
323       TransformationToggleAccessChainInstruction(instructionDescriptor);
324   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
325 
326   instructionDescriptor = MakeInstructionDescriptor(24, SpvOpAccessChain, 0);
327   transformation =
328       TransformationToggleAccessChainInstruction(instructionDescriptor);
329   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
330 
331   instructionDescriptor =
332       MakeInstructionDescriptor(26, SpvOpInBoundsAccessChain, 0);
333   transformation =
334       TransformationToggleAccessChainInstruction(instructionDescriptor);
335   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
336 
337   instructionDescriptor = MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
338   transformation =
339       TransformationToggleAccessChainInstruction(instructionDescriptor);
340   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
341 
342   std::string variantShader = R"(
343                OpCapability Shader
344           %1 = OpExtInstImport "GLSL.std.450"
345                OpMemoryModel Logical GLSL450
346                OpEntryPoint Fragment %4 "main"
347                OpExecutionMode %4 OriginUpperLeft
348                OpSource ESSL 310
349                OpName %4 "main"
350           %2 = OpTypeVoid
351           %3 = OpTypeFunction %2
352           %6 = OpTypeInt 32 1
353           %7 = OpTypeInt 32 0
354           %8 = OpConstant %7 2
355           %9 = OpTypeArray %6 %8
356          %10 = OpTypePointer Function %9
357          %12 = OpConstant %6 1
358          %13 = OpConstant %6 2
359          %14 = OpConstantComposite %9 %12 %13
360          %15 = OpTypePointer Function %6
361          %17 = OpConstant %6 0
362          %29 = OpTypeFloat 32
363          %30 = OpTypeArray %29 %8
364          %31 = OpTypePointer Function %30
365          %33 = OpConstant %29 1
366          %34 = OpConstant %29 2
367          %35 = OpConstantComposite %30 %33 %34
368          %36 = OpTypePointer Function %29
369          %49 = OpTypeVector %29 3
370          %50 = OpTypeArray %49 %8
371          %51 = OpTypePointer Function %50
372          %53 = OpConstant %29 3
373          %54 = OpConstantComposite %49 %33 %34 %53
374          %55 = OpConstant %29 4
375          %56 = OpConstant %29 5
376          %57 = OpConstant %29 6
377          %58 = OpConstantComposite %49 %55 %56 %57
378          %59 = OpConstantComposite %50 %54 %58
379          %61 = OpTypePointer Function %49
380           %4 = OpFunction %2 None %3
381           %5 = OpLabel
382          %11 = OpVariable %10 Function
383          %16 = OpVariable %15 Function
384          %23 = OpVariable %15 Function
385          %32 = OpVariable %31 Function
386          %37 = OpVariable %36 Function
387          %43 = OpVariable %36 Function
388          %52 = OpVariable %51 Function
389          %60 = OpVariable %36 Function
390                OpStore %11 %14
391          %18 = OpInBoundsAccessChain %15 %11 %17
392          %19 = OpLoad %6 %18
393          %20 = OpAccessChain %15 %11 %12
394          %21 = OpLoad %6 %20
395          %22 = OpIAdd %6 %19 %21
396                OpStore %16 %22
397          %24 = OpInBoundsAccessChain %15 %11 %17
398          %25 = OpLoad %6 %24
399          %26 = OpAccessChain %15 %11 %12
400          %27 = OpLoad %6 %26
401          %28 = OpIMul %6 %25 %27
402                OpStore %23 %28
403                OpStore %32 %35
404          %38 = OpInBoundsAccessChain %36 %32 %17
405          %39 = OpLoad %29 %38
406          %40 = OpAccessChain %36 %32 %12
407          %41 = OpLoad %29 %40
408          %42 = OpFAdd %29 %39 %41
409                OpStore %37 %42
410          %44 = OpAccessChain %36 %32 %17
411          %45 = OpLoad %29 %44
412          %46 = OpAccessChain %36 %32 %12
413          %47 = OpLoad %29 %46
414          %48 = OpFMul %29 %45 %47
415                OpStore %43 %48
416                OpStore %52 %59
417          %62 = OpAccessChain %61 %52 %17
418          %63 = OpLoad %49 %62
419          %64 = OpAccessChain %61 %52 %12
420          %65 = OpLoad %49 %64
421          %66 = OpDot %29 %63 %65
422                OpStore %60 %66
423                OpReturn
424                OpFunctionEnd
425   )";
426 
427   ASSERT_TRUE(IsEqual(env, variantShader, context.get()));
428 }
429 
430 }  // namespace
431 }  // namespace fuzz
432 }  // namespace spvtools
433