• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019 Google LLC
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_add_constant_scalar.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(TransformationAddConstantScalarTest,IsApplicable)25 TEST(TransformationAddConstantScalarTest, IsApplicable) {
26   std::string reference_shader = R"(
27                OpCapability Shader
28                OpCapability Int64
29                OpCapability Float64
30           %1 = OpExtInstImport "GLSL.std.450"
31                OpMemoryModel Logical GLSL450
32                OpEntryPoint Vertex %17 "main"
33 
34 ; Types
35 
36   ; 32-bit types
37           %2 = OpTypeInt 32 0
38           %3 = OpTypeInt 32 1
39           %4 = OpTypeFloat 32
40 
41   ; 64-bit types
42           %5 = OpTypeInt 64 0
43           %6 = OpTypeInt 64 1
44           %7 = OpTypeFloat 64
45 
46           %8 = OpTypePointer Private %2
47           %9 = OpTypeVoid
48          %10 = OpTypeFunction %9
49 
50 ; Constants
51 
52   ; 32-bit constants
53          %11 = OpConstant %2 1
54          %12 = OpConstant %3 2
55          %13 = OpConstant %4 3
56 
57   ; 64-bit constants
58          %14 = OpConstant %5 1
59          %15 = OpConstant %6 2
60          %16 = OpConstant %7 3
61 
62 ; main function
63          %17 = OpFunction %9 None %10
64          %18 = OpLabel
65                OpReturn
66                OpFunctionEnd
67   )";
68 
69   const auto env = SPV_ENV_UNIVERSAL_1_3;
70   const auto consumer = nullptr;
71   const auto context =
72       BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
73   spvtools::ValidatorOptions validator_options;
74   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
75                                                kConsoleMessageConsumer));
76   TransformationContext transformation_context(
77       MakeUnique<FactManager>(context.get()), validator_options);
78   // Tests |fresh_id| being non-fresh.
79   auto transformation = TransformationAddConstantScalar(18, 2, {0}, false);
80   ASSERT_FALSE(
81       transformation.IsApplicable(context.get(), transformation_context));
82 
83   // Tests undefined |type_id|.
84   transformation = TransformationAddConstantScalar(19, 20, {0}, false);
85   ASSERT_FALSE(
86       transformation.IsApplicable(context.get(), transformation_context));
87 
88   // Tests |type_id| not representing a type instruction.
89   transformation = TransformationAddConstantScalar(19, 11, {0}, false);
90   ASSERT_FALSE(
91       transformation.IsApplicable(context.get(), transformation_context));
92 
93   // Tests |type_id| representing an OpTypePointer instruction.
94   transformation = TransformationAddConstantScalar(19, 8, {0}, false);
95   ASSERT_FALSE(
96       transformation.IsApplicable(context.get(), transformation_context));
97 
98   // Tests |type_id| representing an OpTypeVoid instruction.
99   transformation = TransformationAddConstantScalar(19, 9, {0}, false);
100   ASSERT_FALSE(
101       transformation.IsApplicable(context.get(), transformation_context));
102 
103   // Tests |words| having no words.
104   transformation = TransformationAddConstantScalar(19, 2, {}, false);
105   ASSERT_FALSE(
106       transformation.IsApplicable(context.get(), transformation_context));
107 
108   // Tests |words| having 2 words for a 32-bit type.
109   transformation = TransformationAddConstantScalar(19, 2, {0, 1}, false);
110   ASSERT_FALSE(
111       transformation.IsApplicable(context.get(), transformation_context));
112 
113   // Tests |words| having 3 words for a 64-bit type.
114   transformation = TransformationAddConstantScalar(19, 5, {0, 1, 2}, false);
115   ASSERT_FALSE(
116       transformation.IsApplicable(context.get(), transformation_context));
117 }
118 
TEST(TransformationAddConstantScalarTest,Apply)119 TEST(TransformationAddConstantScalarTest, Apply) {
120   std::string reference_shader = R"(
121                OpCapability Shader
122                OpCapability Int64
123                OpCapability Float64
124           %1 = OpExtInstImport "GLSL.std.450"
125                OpMemoryModel Logical GLSL450
126                OpEntryPoint Vertex %17 "main"
127 
128 ; Types
129 
130   ; 32-bit types
131           %2 = OpTypeInt 32 0
132           %3 = OpTypeInt 32 1
133           %4 = OpTypeFloat 32
134 
135   ; 64-bit types
136           %5 = OpTypeInt 64 0
137           %6 = OpTypeInt 64 1
138           %7 = OpTypeFloat 64
139 
140           %8 = OpTypePointer Private %2
141           %9 = OpTypeVoid
142          %10 = OpTypeFunction %9
143 
144 ; Constants
145 
146   ; 32-bit constants
147          %11 = OpConstant %2 1
148          %12 = OpConstant %3 2
149          %13 = OpConstant %4 3
150 
151   ; 64-bit constants
152          %14 = OpConstant %5 1
153          %15 = OpConstant %6 2
154          %16 = OpConstant %7 3
155 
156 ; main function
157          %17 = OpFunction %9 None %10
158          %18 = OpLabel
159                OpReturn
160                OpFunctionEnd
161   )";
162 
163   const auto env = SPV_ENV_UNIVERSAL_1_3;
164   const auto consumer = nullptr;
165   const auto context =
166       BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
167   spvtools::ValidatorOptions validator_options;
168   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
169                                                kConsoleMessageConsumer));
170   TransformationContext transformation_context(
171       MakeUnique<FactManager>(context.get()), validator_options);
172   // Adds 32-bit unsigned integer (1 logical operand with 1 word).
173   auto transformation = TransformationAddConstantScalar(19, 2, {4}, false);
174   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(19));
175   ASSERT_EQ(nullptr, context->get_constant_mgr()->FindDeclaredConstant(19));
176   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
177   ASSERT_EQ(SpvOpConstant, context->get_def_use_mgr()->GetDef(19)->opcode());
178   ASSERT_EQ(4, context->get_constant_mgr()->FindDeclaredConstant(19)->GetU32());
179   auto* constant_instruction = context->get_def_use_mgr()->GetDef(19);
180   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
181   EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
182   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
183                                                kConsoleMessageConsumer));
184 
185   // Adds 32-bit signed integer (1 logical operand with 1 word).
186   transformation = TransformationAddConstantScalar(20, 3, {5}, false);
187   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
188   constant_instruction = context->get_def_use_mgr()->GetDef(20);
189   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
190   EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
191   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
192                                                kConsoleMessageConsumer));
193 
194   // Adds 32-bit float (1 logical operand with 1 word).
195   transformation = TransformationAddConstantScalar(
196       21, 4, {0b01000000110000000000000000000000}, false);
197   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
198   constant_instruction = context->get_def_use_mgr()->GetDef(21);
199   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
200   EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
201   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
202                                                kConsoleMessageConsumer));
203 
204   // Adds 64-bit unsigned integer (1 logical operand with 2 words).
205   transformation = TransformationAddConstantScalar(22, 5, {7, 0}, false);
206   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
207   constant_instruction = context->get_def_use_mgr()->GetDef(22);
208   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
209   EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
210   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
211                                                kConsoleMessageConsumer));
212 
213   // Adds 64-bit signed integer (1 logical operand with 2 words).
214   transformation = TransformationAddConstantScalar(23, 6, {8, 0}, false);
215   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
216   constant_instruction = context->get_def_use_mgr()->GetDef(23);
217   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
218   EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
219   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
220                                                kConsoleMessageConsumer));
221 
222   // Adds 64-bit float (1 logical operand with 2 words).
223   transformation = TransformationAddConstantScalar(
224       24, 7, {0, 0b01000000001000100000000000000000}, false);
225   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
226   constant_instruction = context->get_def_use_mgr()->GetDef(24);
227   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
228   EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
229   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
230                                                kConsoleMessageConsumer));
231 
232   // Adds irrelevant 32-bit unsigned integer (1 logical operand with 1 word).
233   transformation = TransformationAddConstantScalar(25, 2, {10}, true);
234   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
235   constant_instruction = context->get_def_use_mgr()->GetDef(25);
236   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
237   EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
238   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
239                                                kConsoleMessageConsumer));
240 
241   // Adds irrelevant 32-bit signed integer (1 logical operand with 1 word).
242   transformation = TransformationAddConstantScalar(26, 3, {11}, true);
243   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
244   constant_instruction = context->get_def_use_mgr()->GetDef(26);
245   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
246   EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
247   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
248                                                kConsoleMessageConsumer));
249 
250   // Adds irrelevant 32-bit float (1 logical operand with 1 word).
251   transformation = TransformationAddConstantScalar(
252       27, 4, {0b01000001010000000000000000000000}, true);
253   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
254   constant_instruction = context->get_def_use_mgr()->GetDef(27);
255   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
256   EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
257   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
258                                                kConsoleMessageConsumer));
259 
260   // Adds irrelevant 64-bit unsigned integer (1 logical operand with 2 words).
261   transformation = TransformationAddConstantScalar(28, 5, {13, 0}, true);
262   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
263   constant_instruction = context->get_def_use_mgr()->GetDef(28);
264   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
265   EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
266   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
267                                                kConsoleMessageConsumer));
268 
269   // Adds irrelevant 64-bit signed integer (1 logical operand with 2 words).
270   transformation = TransformationAddConstantScalar(29, 6, {14, 0}, true);
271   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
272   constant_instruction = context->get_def_use_mgr()->GetDef(29);
273   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
274   EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
275   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
276                                                kConsoleMessageConsumer));
277 
278   // Adds irrelevant 64-bit float (1 logical operand with 2 words).
279   transformation = TransformationAddConstantScalar(
280       30, 7, {0, 0b01000000001011100000000000000000}, true);
281   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
282   constant_instruction = context->get_def_use_mgr()->GetDef(30);
283   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
284   EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
285   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
286                                                kConsoleMessageConsumer));
287 
288   for (uint32_t result_id = 19; result_id <= 24; ++result_id) {
289     ASSERT_FALSE(
290         transformation_context.GetFactManager()->IdIsIrrelevant(result_id));
291   }
292 
293   for (uint32_t result_id = 25; result_id <= 30; ++result_id) {
294     ASSERT_TRUE(
295         transformation_context.GetFactManager()->IdIsIrrelevant(result_id));
296   }
297 
298   std::string variant_shader = R"(
299                OpCapability Shader
300                OpCapability Int64
301                OpCapability Float64
302           %1 = OpExtInstImport "GLSL.std.450"
303                OpMemoryModel Logical GLSL450
304                OpEntryPoint Vertex %17 "main"
305 
306 ; Types
307 
308   ; 32-bit types
309           %2 = OpTypeInt 32 0
310           %3 = OpTypeInt 32 1
311           %4 = OpTypeFloat 32
312 
313   ; 64-bit types
314           %5 = OpTypeInt 64 0
315           %6 = OpTypeInt 64 1
316           %7 = OpTypeFloat 64
317 
318           %8 = OpTypePointer Private %2
319           %9 = OpTypeVoid
320          %10 = OpTypeFunction %9
321 
322 ; Constants
323 
324   ; 32-bit constants
325          %11 = OpConstant %2 1
326          %12 = OpConstant %3 2
327          %13 = OpConstant %4 3
328 
329   ; 64-bit constants
330          %14 = OpConstant %5 1
331          %15 = OpConstant %6 2
332          %16 = OpConstant %7 3
333 
334   ; added constants
335          %19 = OpConstant %2 4
336          %20 = OpConstant %3 5
337          %21 = OpConstant %4 6
338          %22 = OpConstant %5 7
339          %23 = OpConstant %6 8
340          %24 = OpConstant %7 9
341          %25 = OpConstant %2 10
342          %26 = OpConstant %3 11
343          %27 = OpConstant %4 12
344          %28 = OpConstant %5 13
345          %29 = OpConstant %6 14
346          %30 = OpConstant %7 15
347 
348 ; main function
349          %17 = OpFunction %9 None %10
350          %18 = OpLabel
351                OpReturn
352                OpFunctionEnd
353   )";
354 
355   ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
356 }
357 
358 }  // namespace
359 }  // namespace fuzz
360 }  // namespace spvtools
361