• 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   // Tests |words| having 2 words for a 32-bit float type.
119   transformation = TransformationAddConstantScalar(19, 4, {0, 1}, false);
120   ASSERT_FALSE(
121       transformation.IsApplicable(context.get(), transformation_context));
122 }
123 
TEST(TransformationAddConstantScalarTest,Apply)124 TEST(TransformationAddConstantScalarTest, Apply) {
125   std::string reference_shader = R"(
126                OpCapability Shader
127                OpCapability Int64
128                OpCapability Float64
129           %1 = OpExtInstImport "GLSL.std.450"
130                OpMemoryModel Logical GLSL450
131                OpEntryPoint Vertex %17 "main"
132 
133 ; Types
134 
135   ; 32-bit types
136           %2 = OpTypeInt 32 0
137           %3 = OpTypeInt 32 1
138           %4 = OpTypeFloat 32
139 
140   ; 64-bit types
141           %5 = OpTypeInt 64 0
142           %6 = OpTypeInt 64 1
143           %7 = OpTypeFloat 64
144 
145           %8 = OpTypePointer Private %2
146           %9 = OpTypeVoid
147          %10 = OpTypeFunction %9
148 
149 ; Constants
150 
151   ; 32-bit constants
152          %11 = OpConstant %2 1
153          %12 = OpConstant %3 2
154          %13 = OpConstant %4 3
155 
156   ; 64-bit constants
157          %14 = OpConstant %5 1
158          %15 = OpConstant %6 2
159          %16 = OpConstant %7 3
160 
161 ; main function
162          %17 = OpFunction %9 None %10
163          %18 = OpLabel
164                OpReturn
165                OpFunctionEnd
166   )";
167 
168   const auto env = SPV_ENV_UNIVERSAL_1_3;
169   const auto consumer = nullptr;
170   const auto context =
171       BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
172   spvtools::ValidatorOptions validator_options;
173   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
174                                                kConsoleMessageConsumer));
175   TransformationContext transformation_context(
176       MakeUnique<FactManager>(context.get()), validator_options);
177   // Adds 32-bit unsigned integer (1 logical operand with 1 word).
178   auto transformation = TransformationAddConstantScalar(19, 2, {4}, false);
179   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(19));
180   ASSERT_EQ(nullptr, context->get_constant_mgr()->FindDeclaredConstant(19));
181   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
182   ASSERT_EQ(SpvOpConstant, context->get_def_use_mgr()->GetDef(19)->opcode());
183   ASSERT_EQ(4, context->get_constant_mgr()->FindDeclaredConstant(19)->GetU32());
184   auto* constant_instruction = context->get_def_use_mgr()->GetDef(19);
185   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
186   EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
187   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
188                                                kConsoleMessageConsumer));
189 
190   // Adds 32-bit signed integer (1 logical operand with 1 word).
191   transformation = TransformationAddConstantScalar(20, 3, {5}, false);
192   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
193   constant_instruction = context->get_def_use_mgr()->GetDef(20);
194   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
195   EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
196   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
197                                                kConsoleMessageConsumer));
198 
199   // Adds 32-bit float (1 logical operand with 1 word).
200   transformation = TransformationAddConstantScalar(
201       21, 4, {0b01000000110000000000000000000000}, false);
202   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
203   constant_instruction = context->get_def_use_mgr()->GetDef(21);
204   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
205   EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
206   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
207                                                kConsoleMessageConsumer));
208 
209   // Adds 64-bit unsigned integer (1 logical operand with 2 words).
210   transformation = TransformationAddConstantScalar(22, 5, {7, 0}, false);
211   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
212   constant_instruction = context->get_def_use_mgr()->GetDef(22);
213   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
214   EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
215   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
216                                                kConsoleMessageConsumer));
217 
218   // Adds 64-bit signed integer (1 logical operand with 2 words).
219   transformation = TransformationAddConstantScalar(23, 6, {8, 0}, false);
220   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
221   constant_instruction = context->get_def_use_mgr()->GetDef(23);
222   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
223   EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
224   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
225                                                kConsoleMessageConsumer));
226 
227   // Adds 64-bit float (1 logical operand with 2 words).
228   transformation = TransformationAddConstantScalar(
229       24, 7, {0, 0b01000000001000100000000000000000}, false);
230   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
231   constant_instruction = context->get_def_use_mgr()->GetDef(24);
232   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
233   EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
234   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
235                                                kConsoleMessageConsumer));
236 
237   // Adds irrelevant 32-bit unsigned integer (1 logical operand with 1 word).
238   transformation = TransformationAddConstantScalar(25, 2, {10}, true);
239   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
240   constant_instruction = context->get_def_use_mgr()->GetDef(25);
241   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
242   EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
243   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
244                                                kConsoleMessageConsumer));
245 
246   // Adds irrelevant 32-bit signed integer (1 logical operand with 1 word).
247   transformation = TransformationAddConstantScalar(26, 3, {11}, true);
248   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
249   constant_instruction = context->get_def_use_mgr()->GetDef(26);
250   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
251   EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
252   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
253                                                kConsoleMessageConsumer));
254 
255   // Adds irrelevant 32-bit float (1 logical operand with 1 word).
256   transformation = TransformationAddConstantScalar(
257       27, 4, {0b01000001010000000000000000000000}, true);
258   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
259   constant_instruction = context->get_def_use_mgr()->GetDef(27);
260   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
261   EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
262   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
263                                                kConsoleMessageConsumer));
264 
265   // Adds irrelevant 64-bit unsigned integer (1 logical operand with 2 words).
266   transformation = TransformationAddConstantScalar(28, 5, {13, 0}, true);
267   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
268   constant_instruction = context->get_def_use_mgr()->GetDef(28);
269   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
270   EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
271   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
272                                                kConsoleMessageConsumer));
273 
274   // Adds irrelevant 64-bit signed integer (1 logical operand with 2 words).
275   transformation = TransformationAddConstantScalar(29, 6, {14, 0}, true);
276   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
277   constant_instruction = context->get_def_use_mgr()->GetDef(29);
278   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
279   EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
280   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
281                                                kConsoleMessageConsumer));
282 
283   // Adds irrelevant 64-bit float (1 logical operand with 2 words).
284   transformation = TransformationAddConstantScalar(
285       30, 7, {0, 0b01000000001011100000000000000000}, true);
286   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
287   constant_instruction = context->get_def_use_mgr()->GetDef(30);
288   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
289   EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
290   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
291                                                kConsoleMessageConsumer));
292 
293   for (uint32_t result_id = 19; result_id <= 24; ++result_id) {
294     ASSERT_FALSE(
295         transformation_context.GetFactManager()->IdIsIrrelevant(result_id));
296   }
297 
298   for (uint32_t result_id = 25; result_id <= 30; ++result_id) {
299     ASSERT_TRUE(
300         transformation_context.GetFactManager()->IdIsIrrelevant(result_id));
301   }
302 
303   std::string variant_shader = R"(
304                OpCapability Shader
305                OpCapability Int64
306                OpCapability Float64
307           %1 = OpExtInstImport "GLSL.std.450"
308                OpMemoryModel Logical GLSL450
309                OpEntryPoint Vertex %17 "main"
310 
311 ; Types
312 
313   ; 32-bit types
314           %2 = OpTypeInt 32 0
315           %3 = OpTypeInt 32 1
316           %4 = OpTypeFloat 32
317 
318   ; 64-bit types
319           %5 = OpTypeInt 64 0
320           %6 = OpTypeInt 64 1
321           %7 = OpTypeFloat 64
322 
323           %8 = OpTypePointer Private %2
324           %9 = OpTypeVoid
325          %10 = OpTypeFunction %9
326 
327 ; Constants
328 
329   ; 32-bit constants
330          %11 = OpConstant %2 1
331          %12 = OpConstant %3 2
332          %13 = OpConstant %4 3
333 
334   ; 64-bit constants
335          %14 = OpConstant %5 1
336          %15 = OpConstant %6 2
337          %16 = OpConstant %7 3
338 
339   ; added constants
340          %19 = OpConstant %2 4
341          %20 = OpConstant %3 5
342          %21 = OpConstant %4 6
343          %22 = OpConstant %5 7
344          %23 = OpConstant %6 8
345          %24 = OpConstant %7 9
346          %25 = OpConstant %2 10
347          %26 = OpConstant %3 11
348          %27 = OpConstant %4 12
349          %28 = OpConstant %5 13
350          %29 = OpConstant %6 14
351          %30 = OpConstant %7 15
352 
353 ; main function
354          %17 = OpFunction %9 None %10
355          %18 = OpLabel
356                OpReturn
357                OpFunctionEnd
358   )";
359 
360   ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
361 }
362 
363 }  // namespace
364 }  // namespace fuzz
365 }  // namespace spvtools
366