1 // Copyright (c) 2020 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_equation_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(TransformationEquationInstructionTest,SignedNegate)26 TEST(TransformationEquationInstructionTest, SignedNegate) {
27 std::string shader = R"(
28 OpCapability Shader
29 %1 = OpExtInstImport "GLSL.std.450"
30 OpMemoryModel Logical GLSL450
31 OpEntryPoint Fragment %12 "main"
32 OpExecutionMode %12 OriginUpperLeft
33 OpSource ESSL 310
34 %2 = OpTypeVoid
35 %3 = OpTypeFunction %2
36 %6 = OpTypeInt 32 1
37 %7 = OpConstant %6 24
38 %40 = OpTypeBool
39 %41 = OpConstantTrue %40
40 %20 = OpUndef %6
41 %12 = OpFunction %2 None %3
42 %13 = OpLabel
43 %30 = OpCopyObject %6 %7
44 OpReturn
45 OpFunctionEnd
46 )";
47
48 const auto env = SPV_ENV_UNIVERSAL_1_3;
49 const auto consumer = nullptr;
50 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
51 spvtools::ValidatorOptions validator_options;
52 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
53 kConsoleMessageConsumer));
54 TransformationContext transformation_context(
55 MakeUnique<FactManager>(context.get()), validator_options);
56 protobufs::InstructionDescriptor return_instruction =
57 MakeInstructionDescriptor(13, SpvOpReturn, 0);
58
59 // Bad: id already in use.
60 ASSERT_FALSE(TransformationEquationInstruction(7, SpvOpSNegate, {7},
61 return_instruction)
62 .IsApplicable(context.get(), transformation_context));
63
64 // Bad: identified instruction does not exist.
65 ASSERT_FALSE(
66 TransformationEquationInstruction(
67 14, SpvOpSNegate, {7}, MakeInstructionDescriptor(13, SpvOpLoad, 0))
68 .IsApplicable(context.get(), transformation_context));
69
70 // Bad: id 100 does not exist
71 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {100},
72 return_instruction)
73 .IsApplicable(context.get(), transformation_context));
74
75 // Bad: id 20 is an OpUndef
76 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {20},
77 return_instruction)
78 .IsApplicable(context.get(), transformation_context));
79
80 // Bad: id 30 is not available right before its definition
81 ASSERT_FALSE(TransformationEquationInstruction(
82 14, SpvOpSNegate, {30},
83 MakeInstructionDescriptor(30, SpvOpCopyObject, 0))
84 .IsApplicable(context.get(), transformation_context));
85
86 // Bad: too many arguments to OpSNegate.
87 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {7, 7},
88 return_instruction)
89 .IsApplicable(context.get(), transformation_context));
90
91 // Bad: 40 is a type id.
92 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {40},
93 return_instruction)
94 .IsApplicable(context.get(), transformation_context));
95
96 // Bad: wrong type of argument to OpSNegate.
97 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {41},
98 return_instruction)
99 .IsApplicable(context.get(), transformation_context));
100
101 auto transformation1 = TransformationEquationInstruction(
102 14, SpvOpSNegate, {7}, return_instruction);
103 ASSERT_TRUE(
104 transformation1.IsApplicable(context.get(), transformation_context));
105 ApplyAndCheckFreshIds(transformation1, context.get(),
106 &transformation_context);
107 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
108 kConsoleMessageConsumer));
109
110 auto transformation2 = TransformationEquationInstruction(
111 15, SpvOpSNegate, {14}, return_instruction);
112 ASSERT_TRUE(
113 transformation2.IsApplicable(context.get(), transformation_context));
114 ApplyAndCheckFreshIds(transformation2, context.get(),
115 &transformation_context);
116 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
117 kConsoleMessageConsumer));
118
119 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
120 MakeDataDescriptor(15, {}), MakeDataDescriptor(7, {})));
121
122 std::string after_transformation = R"(
123 OpCapability Shader
124 %1 = OpExtInstImport "GLSL.std.450"
125 OpMemoryModel Logical GLSL450
126 OpEntryPoint Fragment %12 "main"
127 OpExecutionMode %12 OriginUpperLeft
128 OpSource ESSL 310
129 %2 = OpTypeVoid
130 %3 = OpTypeFunction %2
131 %6 = OpTypeInt 32 1
132 %7 = OpConstant %6 24
133 %40 = OpTypeBool
134 %41 = OpConstantTrue %40
135 %20 = OpUndef %6
136 %12 = OpFunction %2 None %3
137 %13 = OpLabel
138 %30 = OpCopyObject %6 %7
139 %14 = OpSNegate %6 %7
140 %15 = OpSNegate %6 %14
141 OpReturn
142 OpFunctionEnd
143 )";
144
145 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
146 }
147
TEST(TransformationEquationInstructionTest,LogicalNot)148 TEST(TransformationEquationInstructionTest, LogicalNot) {
149 std::string shader = R"(
150 OpCapability Shader
151 %1 = OpExtInstImport "GLSL.std.450"
152 OpMemoryModel Logical GLSL450
153 OpEntryPoint Fragment %12 "main"
154 OpExecutionMode %12 OriginUpperLeft
155 OpSource ESSL 310
156 %2 = OpTypeVoid
157 %3 = OpTypeFunction %2
158 %6 = OpTypeBool
159 %7 = OpConstantTrue %6
160 %20 = OpTypeInt 32 0
161 %21 = OpConstant %20 5
162 %12 = OpFunction %2 None %3
163 %13 = 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 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
171 spvtools::ValidatorOptions validator_options;
172 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
173 kConsoleMessageConsumer));
174 TransformationContext transformation_context(
175 MakeUnique<FactManager>(context.get()), validator_options);
176 protobufs::InstructionDescriptor return_instruction =
177 MakeInstructionDescriptor(13, SpvOpReturn, 0);
178
179 // Bad: too few arguments to OpLogicalNot.
180 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {},
181 return_instruction)
182 .IsApplicable(context.get(), transformation_context));
183
184 // Bad: 6 is a type id.
185 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {6},
186 return_instruction)
187 .IsApplicable(context.get(), transformation_context));
188
189 // Bad: wrong type of argument to OpLogicalNot.
190 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {21},
191 return_instruction)
192 .IsApplicable(context.get(), transformation_context));
193
194 auto transformation1 = TransformationEquationInstruction(
195 14, SpvOpLogicalNot, {7}, return_instruction);
196 ASSERT_TRUE(
197 transformation1.IsApplicable(context.get(), transformation_context));
198 ApplyAndCheckFreshIds(transformation1, context.get(),
199 &transformation_context);
200 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
201 kConsoleMessageConsumer));
202
203 auto transformation2 = TransformationEquationInstruction(
204 15, SpvOpLogicalNot, {14}, return_instruction);
205 ASSERT_TRUE(
206 transformation2.IsApplicable(context.get(), transformation_context));
207 ApplyAndCheckFreshIds(transformation2, context.get(),
208 &transformation_context);
209 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
210 kConsoleMessageConsumer));
211
212 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
213 MakeDataDescriptor(15, {}), MakeDataDescriptor(7, {})));
214
215 std::string after_transformation = R"(
216 OpCapability Shader
217 %1 = OpExtInstImport "GLSL.std.450"
218 OpMemoryModel Logical GLSL450
219 OpEntryPoint Fragment %12 "main"
220 OpExecutionMode %12 OriginUpperLeft
221 OpSource ESSL 310
222 %2 = OpTypeVoid
223 %3 = OpTypeFunction %2
224 %6 = OpTypeBool
225 %7 = OpConstantTrue %6
226 %20 = OpTypeInt 32 0
227 %21 = OpConstant %20 5
228 %12 = OpFunction %2 None %3
229 %13 = OpLabel
230 %14 = OpLogicalNot %6 %7
231 %15 = OpLogicalNot %6 %14
232 OpReturn
233 OpFunctionEnd
234 )";
235
236 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
237 }
238
TEST(TransformationEquationInstructionTest,AddSubNegate1)239 TEST(TransformationEquationInstructionTest, AddSubNegate1) {
240 std::string shader = R"(
241 OpCapability Shader
242 %1 = OpExtInstImport "GLSL.std.450"
243 OpMemoryModel Logical GLSL450
244 OpEntryPoint Fragment %12 "main"
245 OpExecutionMode %12 OriginUpperLeft
246 OpSource ESSL 310
247 %2 = OpTypeVoid
248 %3 = OpTypeFunction %2
249 %6 = OpTypeInt 32 1
250 %30 = OpTypeVector %6 3
251 %15 = OpConstant %6 24
252 %16 = OpConstant %6 37
253 %31 = OpConstantComposite %30 %15 %16 %15
254 %33 = OpTypeBool
255 %32 = OpConstantTrue %33
256 %12 = OpFunction %2 None %3
257 %13 = OpLabel
258 OpReturn
259 OpFunctionEnd
260 )";
261
262 const auto env = SPV_ENV_UNIVERSAL_1_3;
263 const auto consumer = nullptr;
264 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
265 spvtools::ValidatorOptions validator_options;
266 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
267 kConsoleMessageConsumer));
268 TransformationContext transformation_context(
269 MakeUnique<FactManager>(context.get()), validator_options);
270 protobufs::InstructionDescriptor return_instruction =
271 MakeInstructionDescriptor(13, SpvOpReturn, 0);
272
273 // Bad: too many arguments to OpIAdd.
274 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 16, 16},
275 return_instruction)
276 .IsApplicable(context.get(), transformation_context));
277 // Bad: boolean argument to OpIAdd.
278 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 32},
279 return_instruction)
280 .IsApplicable(context.get(), transformation_context));
281 // Bad: type as argument to OpIAdd.
282 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {33, 16},
283 return_instruction)
284 .IsApplicable(context.get(), transformation_context));
285 // Bad: arguments of mismatched widths
286 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 31},
287 return_instruction)
288 .IsApplicable(context.get(), transformation_context));
289 // Bad: arguments of mismatched widths
290 ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {31, 15},
291 return_instruction)
292 .IsApplicable(context.get(), transformation_context));
293
294 auto transformation1 = TransformationEquationInstruction(
295 14, SpvOpIAdd, {15, 16}, return_instruction);
296 ASSERT_TRUE(
297 transformation1.IsApplicable(context.get(), transformation_context));
298 ApplyAndCheckFreshIds(transformation1, context.get(),
299 &transformation_context);
300 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
301 kConsoleMessageConsumer));
302
303 auto transformation2 = TransformationEquationInstruction(
304 19, SpvOpISub, {14, 16}, return_instruction);
305 ASSERT_TRUE(
306 transformation2.IsApplicable(context.get(), transformation_context));
307 ApplyAndCheckFreshIds(transformation2, context.get(),
308 &transformation_context);
309 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
310 kConsoleMessageConsumer));
311 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
312 MakeDataDescriptor(15, {}), MakeDataDescriptor(19, {})));
313
314 auto transformation3 = TransformationEquationInstruction(
315 20, SpvOpISub, {14, 15}, return_instruction);
316 ASSERT_TRUE(
317 transformation3.IsApplicable(context.get(), transformation_context));
318 ApplyAndCheckFreshIds(transformation3, context.get(),
319 &transformation_context);
320 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
321 kConsoleMessageConsumer));
322 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
323 MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {})));
324
325 auto transformation4 = TransformationEquationInstruction(
326 22, SpvOpISub, {16, 14}, return_instruction);
327 ASSERT_TRUE(
328 transformation4.IsApplicable(context.get(), transformation_context));
329 ApplyAndCheckFreshIds(transformation4, context.get(),
330 &transformation_context);
331 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
332 kConsoleMessageConsumer));
333
334 auto transformation5 = TransformationEquationInstruction(
335 24, SpvOpSNegate, {22}, return_instruction);
336 ASSERT_TRUE(
337 transformation5.IsApplicable(context.get(), transformation_context));
338 ApplyAndCheckFreshIds(transformation5, context.get(),
339 &transformation_context);
340 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
341 kConsoleMessageConsumer));
342 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
343 MakeDataDescriptor(24, {}), MakeDataDescriptor(15, {})));
344
345 std::string after_transformation = R"(
346 OpCapability Shader
347 %1 = OpExtInstImport "GLSL.std.450"
348 OpMemoryModel Logical GLSL450
349 OpEntryPoint Fragment %12 "main"
350 OpExecutionMode %12 OriginUpperLeft
351 OpSource ESSL 310
352 %2 = OpTypeVoid
353 %3 = OpTypeFunction %2
354 %6 = OpTypeInt 32 1
355 %30 = OpTypeVector %6 3
356 %15 = OpConstant %6 24
357 %16 = OpConstant %6 37
358 %31 = OpConstantComposite %30 %15 %16 %15
359 %33 = OpTypeBool
360 %32 = OpConstantTrue %33
361 %12 = OpFunction %2 None %3
362 %13 = OpLabel
363 %14 = OpIAdd %6 %15 %16
364 %19 = OpISub %6 %14 %16 ; ==> synonymous(%19, %15)
365 %20 = OpISub %6 %14 %15 ; ==> synonymous(%20, %16)
366 %22 = OpISub %6 %16 %14
367 %24 = OpSNegate %6 %22 ; ==> synonymous(%24, %15)
368 OpReturn
369 OpFunctionEnd
370 )";
371
372 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
373 }
374
TEST(TransformationEquationInstructionTest,AddSubNegate2)375 TEST(TransformationEquationInstructionTest, AddSubNegate2) {
376 std::string shader = R"(
377 OpCapability Shader
378 %1 = OpExtInstImport "GLSL.std.450"
379 OpMemoryModel Logical GLSL450
380 OpEntryPoint Fragment %12 "main"
381 OpExecutionMode %12 OriginUpperLeft
382 OpSource ESSL 310
383 %2 = OpTypeVoid
384 %3 = OpTypeFunction %2
385 %6 = OpTypeInt 32 1
386 %15 = OpConstant %6 24
387 %16 = OpConstant %6 37
388 %12 = OpFunction %2 None %3
389 %13 = OpLabel
390 OpReturn
391 OpFunctionEnd
392 )";
393
394 const auto env = SPV_ENV_UNIVERSAL_1_3;
395 const auto consumer = nullptr;
396 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
397 spvtools::ValidatorOptions validator_options;
398 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
399 kConsoleMessageConsumer));
400 TransformationContext transformation_context(
401 MakeUnique<FactManager>(context.get()), validator_options);
402 protobufs::InstructionDescriptor return_instruction =
403 MakeInstructionDescriptor(13, SpvOpReturn, 0);
404
405 auto transformation1 = TransformationEquationInstruction(
406 14, SpvOpISub, {15, 16}, return_instruction);
407 ASSERT_TRUE(
408 transformation1.IsApplicable(context.get(), transformation_context));
409 ApplyAndCheckFreshIds(transformation1, context.get(),
410 &transformation_context);
411 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
412 kConsoleMessageConsumer));
413
414 auto transformation2 = TransformationEquationInstruction(
415 17, SpvOpIAdd, {14, 16}, return_instruction);
416 ASSERT_TRUE(
417 transformation2.IsApplicable(context.get(), transformation_context));
418 ApplyAndCheckFreshIds(transformation2, context.get(),
419 &transformation_context);
420 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
421 kConsoleMessageConsumer));
422 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
423 MakeDataDescriptor(17, {}), MakeDataDescriptor(15, {})));
424
425 auto transformation3 = TransformationEquationInstruction(
426 18, SpvOpIAdd, {16, 14}, return_instruction);
427 ASSERT_TRUE(
428 transformation3.IsApplicable(context.get(), transformation_context));
429 ApplyAndCheckFreshIds(transformation3, context.get(),
430 &transformation_context);
431 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
432 kConsoleMessageConsumer));
433 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
434 MakeDataDescriptor(17, {}), MakeDataDescriptor(18, {})));
435 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
436 MakeDataDescriptor(18, {}), MakeDataDescriptor(15, {})));
437
438 auto transformation4 = TransformationEquationInstruction(
439 19, SpvOpISub, {14, 15}, return_instruction);
440 ASSERT_TRUE(
441 transformation4.IsApplicable(context.get(), transformation_context));
442 ApplyAndCheckFreshIds(transformation4, context.get(),
443 &transformation_context);
444 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
445 kConsoleMessageConsumer));
446
447 auto transformation5 = TransformationEquationInstruction(
448 20, SpvOpSNegate, {19}, return_instruction);
449 ASSERT_TRUE(
450 transformation5.IsApplicable(context.get(), transformation_context));
451 ApplyAndCheckFreshIds(transformation5, context.get(),
452 &transformation_context);
453 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
454 kConsoleMessageConsumer));
455 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
456 MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {})));
457
458 auto transformation6 = TransformationEquationInstruction(
459 21, SpvOpISub, {14, 19}, return_instruction);
460 ASSERT_TRUE(
461 transformation6.IsApplicable(context.get(), transformation_context));
462 ApplyAndCheckFreshIds(transformation6, context.get(),
463 &transformation_context);
464 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
465 kConsoleMessageConsumer));
466 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
467 MakeDataDescriptor(21, {}), MakeDataDescriptor(15, {})));
468
469 auto transformation7 = TransformationEquationInstruction(
470 22, SpvOpISub, {14, 18}, return_instruction);
471 ASSERT_TRUE(
472 transformation7.IsApplicable(context.get(), transformation_context));
473 ApplyAndCheckFreshIds(transformation7, context.get(),
474 &transformation_context);
475 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
476 kConsoleMessageConsumer));
477
478 auto transformation8 = TransformationEquationInstruction(
479 23, SpvOpSNegate, {22}, return_instruction);
480 ASSERT_TRUE(
481 transformation8.IsApplicable(context.get(), transformation_context));
482 ApplyAndCheckFreshIds(transformation8, context.get(),
483 &transformation_context);
484 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
485 kConsoleMessageConsumer));
486 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
487 MakeDataDescriptor(23, {}), MakeDataDescriptor(16, {})));
488
489 std::string after_transformation = R"(
490 OpCapability Shader
491 %1 = OpExtInstImport "GLSL.std.450"
492 OpMemoryModel Logical GLSL450
493 OpEntryPoint Fragment %12 "main"
494 OpExecutionMode %12 OriginUpperLeft
495 OpSource ESSL 310
496 %2 = OpTypeVoid
497 %3 = OpTypeFunction %2
498 %6 = OpTypeInt 32 1
499 %15 = OpConstant %6 24
500 %16 = OpConstant %6 37
501 %12 = OpFunction %2 None %3
502 %13 = OpLabel
503 %14 = OpISub %6 %15 %16
504 %17 = OpIAdd %6 %14 %16 ; ==> synonymous(%17, %15)
505 %18 = OpIAdd %6 %16 %14 ; ==> synonymous(%17, %18, %15)
506 %19 = OpISub %6 %14 %15
507 %20 = OpSNegate %6 %19 ; ==> synonymous(%20, %16)
508 %21 = OpISub %6 %14 %19 ; ==> synonymous(%21, %15)
509 %22 = OpISub %6 %14 %18
510 %23 = OpSNegate %6 %22 ; ==> synonymous(%23, %16)
511 OpReturn
512 OpFunctionEnd
513 )";
514
515 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
516 }
517
TEST(TransformationEquationInstructionTest,Bitcast)518 TEST(TransformationEquationInstructionTest, Bitcast) {
519 std::string shader = R"(
520 OpCapability Shader
521 %1 = OpExtInstImport "GLSL.std.450"
522 OpMemoryModel Logical GLSL450
523 OpEntryPoint Fragment %12 "main"
524 OpExecutionMode %12 OriginUpperLeft
525 OpSource ESSL 310
526 %2 = OpTypeVoid
527 %3 = OpTypeFunction %2
528 %6 = OpTypeInt 32 1
529 %7 = OpTypeInt 32 0
530 %8 = OpTypeFloat 32
531 %9 = OpTypeVector %6 2
532 %10 = OpTypeVector %7 2
533 %11 = OpTypeVector %8 2
534 %21 = OpTypeBool
535 %22 = OpTypeVector %21 2
536 %15 = OpConstant %6 24
537 %16 = OpConstant %7 24
538 %17 = OpConstant %8 24
539 %18 = OpConstantComposite %9 %15 %15
540 %19 = OpConstantComposite %10 %16 %16
541 %20 = OpConstantComposite %11 %17 %17
542 %23 = OpConstantTrue %21
543 %24 = OpConstantComposite %22 %23 %23
544 %12 = OpFunction %2 None %3
545 %13 = OpLabel
546 OpReturn
547 OpFunctionEnd
548 )";
549
550 const auto env = SPV_ENV_UNIVERSAL_1_3;
551 const auto consumer = nullptr;
552 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
553 spvtools::ValidatorOptions validator_options;
554 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
555 kConsoleMessageConsumer));
556 TransformationContext transformation_context(
557 MakeUnique<FactManager>(context.get()), validator_options);
558 auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
559
560 // Too many operands.
561 ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpBitcast, {15, 16},
562 insert_before)
563 .IsApplicable(context.get(), transformation_context));
564
565 // Too few operands.
566 ASSERT_FALSE(
567 TransformationEquationInstruction(50, SpvOpBitcast, {}, insert_before)
568 .IsApplicable(context.get(), transformation_context));
569
570 // Operand's id is invalid.
571 ASSERT_FALSE(
572 TransformationEquationInstruction(50, SpvOpBitcast, {50}, insert_before)
573 .IsApplicable(context.get(), transformation_context));
574
575 // Operand's type is invalid
576 ASSERT_FALSE(
577 TransformationEquationInstruction(50, SpvOpBitcast, {13}, insert_before)
578 .IsApplicable(context.get(), transformation_context));
579
580 // Operand must be a scalar or a vector of numerical type.
581 #ifndef NDEBUG
582 ASSERT_DEATH(
583 TransformationEquationInstruction(50, SpvOpBitcast, {23}, insert_before)
584 .IsApplicable(context.get(), transformation_context),
585 "Operand is not a scalar or a vector of numerical type");
586 ASSERT_DEATH(
587 TransformationEquationInstruction(50, SpvOpBitcast, {24}, insert_before)
588 .IsApplicable(context.get(), transformation_context),
589 "Only vectors of numerical components are supported");
590 #else
591 ASSERT_FALSE(
592 TransformationEquationInstruction(50, SpvOpBitcast, {23}, insert_before)
593 .IsApplicable(context.get(), transformation_context));
594 ASSERT_FALSE(
595 TransformationEquationInstruction(50, SpvOpBitcast, {24}, insert_before)
596 .IsApplicable(context.get(), transformation_context));
597 #endif
598
599 for (uint32_t operand_id = 15, fresh_id = 50; operand_id <= 20;
600 ++operand_id, ++fresh_id) {
601 TransformationEquationInstruction transformation(
602 fresh_id, SpvOpBitcast, {operand_id}, insert_before);
603 ASSERT_TRUE(
604 transformation.IsApplicable(context.get(), transformation_context));
605 ApplyAndCheckFreshIds(transformation, context.get(),
606 &transformation_context);
607 }
608
609 std::string expected_shader = R"(
610 OpCapability Shader
611 %1 = OpExtInstImport "GLSL.std.450"
612 OpMemoryModel Logical GLSL450
613 OpEntryPoint Fragment %12 "main"
614 OpExecutionMode %12 OriginUpperLeft
615 OpSource ESSL 310
616 %2 = OpTypeVoid
617 %3 = OpTypeFunction %2
618 %6 = OpTypeInt 32 1
619 %7 = OpTypeInt 32 0
620 %8 = OpTypeFloat 32
621 %9 = OpTypeVector %6 2
622 %10 = OpTypeVector %7 2
623 %11 = OpTypeVector %8 2
624 %21 = OpTypeBool
625 %22 = OpTypeVector %21 2
626 %15 = OpConstant %6 24
627 %16 = OpConstant %7 24
628 %17 = OpConstant %8 24
629 %18 = OpConstantComposite %9 %15 %15
630 %19 = OpConstantComposite %10 %16 %16
631 %20 = OpConstantComposite %11 %17 %17
632 %23 = OpConstantTrue %21
633 %24 = OpConstantComposite %22 %23 %23
634 %12 = OpFunction %2 None %3
635 %13 = OpLabel
636 %50 = OpBitcast %8 %15
637 %51 = OpBitcast %8 %16
638 %52 = OpBitcast %6 %17
639 %53 = OpBitcast %11 %18
640 %54 = OpBitcast %11 %19
641 %55 = OpBitcast %9 %20
642 OpReturn
643 OpFunctionEnd
644 )";
645
646 ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
647 }
648
TEST(TransformationEquationInstructionTest,BitcastResultTypeFloatDoesNotExist)649 TEST(TransformationEquationInstructionTest,
650 BitcastResultTypeFloatDoesNotExist) {
651 std::string shader = R"(
652 OpCapability Shader
653 %1 = OpExtInstImport "GLSL.std.450"
654 OpMemoryModel Logical GLSL450
655 OpEntryPoint Fragment %12 "main"
656 OpExecutionMode %12 OriginUpperLeft
657 OpSource ESSL 310
658 %2 = OpTypeVoid
659 %3 = OpTypeFunction %2
660 %6 = OpTypeInt 32 1
661 %7 = OpTypeInt 32 0
662 %9 = OpTypeVector %6 2
663 %10 = OpTypeVector %7 2
664 %15 = OpConstant %6 24
665 %16 = OpConstant %7 24
666 %18 = OpConstantComposite %9 %15 %15
667 %19 = OpConstantComposite %10 %16 %16
668 %12 = OpFunction %2 None %3
669 %13 = OpLabel
670 OpReturn
671 OpFunctionEnd
672 )";
673
674 const auto env = SPV_ENV_UNIVERSAL_1_3;
675 const auto consumer = nullptr;
676 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
677 spvtools::ValidatorOptions validator_options;
678 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
679 kConsoleMessageConsumer));
680 TransformationContext transformation_context(
681 MakeUnique<FactManager>(context.get()), validator_options);
682 auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
683
684 // Scalar floating-point type does not exist.
685 ASSERT_FALSE(
686 TransformationEquationInstruction(50, SpvOpBitcast, {15}, insert_before)
687 .IsApplicable(context.get(), transformation_context));
688 ASSERT_FALSE(
689 TransformationEquationInstruction(50, SpvOpBitcast, {16}, insert_before)
690 .IsApplicable(context.get(), transformation_context));
691
692 // Vector of floating-point components does not exist.
693 ASSERT_FALSE(
694 TransformationEquationInstruction(50, SpvOpBitcast, {18}, insert_before)
695 .IsApplicable(context.get(), transformation_context));
696 ASSERT_FALSE(
697 TransformationEquationInstruction(50, SpvOpBitcast, {19}, insert_before)
698 .IsApplicable(context.get(), transformation_context));
699 }
700
TEST(TransformationEquationInstructionTest,BitcastResultTypeIntDoesNotExist1)701 TEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist1) {
702 std::string shader = R"(
703 OpCapability Shader
704 %1 = OpExtInstImport "GLSL.std.450"
705 OpMemoryModel Logical GLSL450
706 OpEntryPoint Fragment %12 "main"
707 OpExecutionMode %12 OriginUpperLeft
708 OpSource ESSL 310
709 %2 = OpTypeVoid
710 %3 = OpTypeFunction %2
711 %8 = OpTypeFloat 32
712 %11 = OpTypeVector %8 2
713 %17 = OpConstant %8 24
714 %20 = OpConstantComposite %11 %17 %17
715 %12 = OpFunction %2 None %3
716 %13 = OpLabel
717 OpReturn
718 OpFunctionEnd
719 )";
720
721 const auto env = SPV_ENV_UNIVERSAL_1_3;
722 const auto consumer = nullptr;
723 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
724 spvtools::ValidatorOptions validator_options;
725 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
726 kConsoleMessageConsumer));
727 TransformationContext transformation_context(
728 MakeUnique<FactManager>(context.get()), validator_options);
729 auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
730
731 // Scalar integral type does not exist.
732 ASSERT_FALSE(
733 TransformationEquationInstruction(50, SpvOpBitcast, {17}, insert_before)
734 .IsApplicable(context.get(), transformation_context));
735
736 // Vector of integral components does not exist.
737 ASSERT_FALSE(
738 TransformationEquationInstruction(50, SpvOpBitcast, {20}, insert_before)
739 .IsApplicable(context.get(), transformation_context));
740 }
741
TEST(TransformationEquationInstructionTest,BitcastResultTypeIntDoesNotExist2)742 TEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist2) {
743 std::string shader = R"(
744 OpCapability Shader
745 %1 = OpExtInstImport "GLSL.std.450"
746 OpMemoryModel Logical GLSL450
747 OpEntryPoint Fragment %12 "main"
748 OpExecutionMode %12 OriginUpperLeft
749 OpSource ESSL 310
750 %2 = OpTypeVoid
751 %3 = OpTypeFunction %2
752 %4 = OpTypeInt 32 0
753 %8 = OpTypeFloat 32
754 %9 = OpTypeVector %4 2
755 %11 = OpTypeVector %8 2
756 %17 = OpConstant %8 24
757 %20 = OpConstantComposite %11 %17 %17
758 %12 = OpFunction %2 None %3
759 %13 = OpLabel
760 OpReturn
761 OpFunctionEnd
762 )";
763
764 const auto env = SPV_ENV_UNIVERSAL_1_3;
765 const auto consumer = nullptr;
766 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
767 spvtools::ValidatorOptions validator_options;
768 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
769 kConsoleMessageConsumer));
770 TransformationContext transformation_context(
771 MakeUnique<FactManager>(context.get()), validator_options);
772 auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
773
774 {
775 TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
776 insert_before);
777 ASSERT_TRUE(
778 transformation.IsApplicable(context.get(), transformation_context));
779 ApplyAndCheckFreshIds(transformation, context.get(),
780 &transformation_context);
781 }
782 {
783 TransformationEquationInstruction transformation(51, SpvOpBitcast, {20},
784 insert_before);
785 ASSERT_TRUE(
786 transformation.IsApplicable(context.get(), transformation_context));
787 ApplyAndCheckFreshIds(transformation, context.get(),
788 &transformation_context);
789 }
790
791 std::string expected_shader = R"(
792 OpCapability Shader
793 %1 = OpExtInstImport "GLSL.std.450"
794 OpMemoryModel Logical GLSL450
795 OpEntryPoint Fragment %12 "main"
796 OpExecutionMode %12 OriginUpperLeft
797 OpSource ESSL 310
798 %2 = OpTypeVoid
799 %3 = OpTypeFunction %2
800 %4 = OpTypeInt 32 0
801 %8 = OpTypeFloat 32
802 %9 = OpTypeVector %4 2
803 %11 = OpTypeVector %8 2
804 %17 = OpConstant %8 24
805 %20 = OpConstantComposite %11 %17 %17
806 %12 = OpFunction %2 None %3
807 %13 = OpLabel
808 %50 = OpBitcast %4 %17
809 %51 = OpBitcast %9 %20
810 OpReturn
811 OpFunctionEnd
812 )";
813
814 ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
815 }
816
TEST(TransformationEquationInstructionTest,BitcastResultTypeIntDoesNotExist3)817 TEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist3) {
818 std::string shader = R"(
819 OpCapability Shader
820 %1 = OpExtInstImport "GLSL.std.450"
821 OpMemoryModel Logical GLSL450
822 OpEntryPoint Fragment %12 "main"
823 OpExecutionMode %12 OriginUpperLeft
824 OpSource ESSL 310
825 %2 = OpTypeVoid
826 %3 = OpTypeFunction %2
827 %4 = OpTypeInt 32 1
828 %8 = OpTypeFloat 32
829 %9 = OpTypeVector %4 2
830 %11 = OpTypeVector %8 2
831 %17 = OpConstant %8 24
832 %20 = OpConstantComposite %11 %17 %17
833 %12 = OpFunction %2 None %3
834 %13 = OpLabel
835 OpReturn
836 OpFunctionEnd
837 )";
838
839 const auto env = SPV_ENV_UNIVERSAL_1_3;
840 const auto consumer = nullptr;
841 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
842 spvtools::ValidatorOptions validator_options;
843 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
844 kConsoleMessageConsumer));
845 TransformationContext transformation_context(
846 MakeUnique<FactManager>(context.get()), validator_options);
847 auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
848
849 {
850 TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
851 insert_before);
852 ASSERT_TRUE(
853 transformation.IsApplicable(context.get(), transformation_context));
854 ApplyAndCheckFreshIds(transformation, context.get(),
855 &transformation_context);
856 }
857 {
858 TransformationEquationInstruction transformation(51, SpvOpBitcast, {20},
859 insert_before);
860 ASSERT_TRUE(
861 transformation.IsApplicable(context.get(), transformation_context));
862 ApplyAndCheckFreshIds(transformation, context.get(),
863 &transformation_context);
864 }
865
866 std::string expected_shader = R"(
867 OpCapability Shader
868 %1 = OpExtInstImport "GLSL.std.450"
869 OpMemoryModel Logical GLSL450
870 OpEntryPoint Fragment %12 "main"
871 OpExecutionMode %12 OriginUpperLeft
872 OpSource ESSL 310
873 %2 = OpTypeVoid
874 %3 = OpTypeFunction %2
875 %4 = OpTypeInt 32 1
876 %8 = OpTypeFloat 32
877 %9 = OpTypeVector %4 2
878 %11 = OpTypeVector %8 2
879 %17 = OpConstant %8 24
880 %20 = OpConstantComposite %11 %17 %17
881 %12 = OpFunction %2 None %3
882 %13 = OpLabel
883 %50 = OpBitcast %4 %17
884 %51 = OpBitcast %9 %20
885 OpReturn
886 OpFunctionEnd
887 )";
888
889 ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
890 }
891
TEST(TransformationEquationInstructionTest,BitcastResultTypeIntDoesNotExist4)892 TEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist4) {
893 std::string shader = R"(
894 OpCapability Shader
895 %1 = OpExtInstImport "GLSL.std.450"
896 OpMemoryModel Logical GLSL450
897 OpEntryPoint Fragment %12 "main"
898 OpExecutionMode %12 OriginUpperLeft
899 OpSource ESSL 310
900 %2 = OpTypeVoid
901 %3 = OpTypeFunction %2
902 %4 = OpTypeInt 32 1
903 %8 = OpTypeFloat 32
904 %11 = OpTypeVector %8 2
905 %17 = OpConstant %8 24
906 %20 = OpConstantComposite %11 %17 %17
907 %12 = OpFunction %2 None %3
908 %13 = OpLabel
909 OpReturn
910 OpFunctionEnd
911 )";
912
913 const auto env = SPV_ENV_UNIVERSAL_1_3;
914 const auto consumer = nullptr;
915 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
916 spvtools::ValidatorOptions validator_options;
917 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
918 kConsoleMessageConsumer));
919 TransformationContext transformation_context(
920 MakeUnique<FactManager>(context.get()), validator_options);
921 auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
922
923 {
924 TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
925 insert_before);
926 ASSERT_TRUE(
927 transformation.IsApplicable(context.get(), transformation_context));
928 ApplyAndCheckFreshIds(transformation, context.get(),
929 &transformation_context);
930 }
931
932 ASSERT_FALSE(
933 TransformationEquationInstruction(51, SpvOpBitcast, {20}, insert_before)
934 .IsApplicable(context.get(), transformation_context));
935
936 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
937 kConsoleMessageConsumer));
938
939 std::string expected_shader = R"(
940 OpCapability Shader
941 %1 = OpExtInstImport "GLSL.std.450"
942 OpMemoryModel Logical GLSL450
943 OpEntryPoint Fragment %12 "main"
944 OpExecutionMode %12 OriginUpperLeft
945 OpSource ESSL 310
946 %2 = OpTypeVoid
947 %3 = OpTypeFunction %2
948 %4 = OpTypeInt 32 1
949 %8 = OpTypeFloat 32
950 %11 = OpTypeVector %8 2
951 %17 = OpConstant %8 24
952 %20 = OpConstantComposite %11 %17 %17
953 %12 = OpFunction %2 None %3
954 %13 = OpLabel
955 %50 = OpBitcast %4 %17
956 OpReturn
957 OpFunctionEnd
958 )";
959
960 ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
961 }
962
TEST(TransformationEquationInstructionTest,BitcastResultTypeIntDoesNotExist5)963 TEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist5) {
964 std::string shader = R"(
965 OpCapability Shader
966 %1 = OpExtInstImport "GLSL.std.450"
967 OpMemoryModel Logical GLSL450
968 OpEntryPoint Fragment %12 "main"
969 OpExecutionMode %12 OriginUpperLeft
970 OpSource ESSL 310
971 %2 = OpTypeVoid
972 %3 = OpTypeFunction %2
973 %4 = OpTypeInt 32 0
974 %8 = OpTypeFloat 32
975 %11 = OpTypeVector %8 2
976 %17 = OpConstant %8 24
977 %20 = OpConstantComposite %11 %17 %17
978 %12 = OpFunction %2 None %3
979 %13 = OpLabel
980 OpReturn
981 OpFunctionEnd
982 )";
983
984 const auto env = SPV_ENV_UNIVERSAL_1_3;
985 const auto consumer = nullptr;
986 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
987 spvtools::ValidatorOptions validator_options;
988 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
989 kConsoleMessageConsumer));
990 TransformationContext transformation_context(
991 MakeUnique<FactManager>(context.get()), validator_options);
992 auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
993
994 {
995 TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
996 insert_before);
997 ASSERT_TRUE(
998 transformation.IsApplicable(context.get(), transformation_context));
999 ApplyAndCheckFreshIds(transformation, context.get(),
1000 &transformation_context);
1001 }
1002
1003 ASSERT_FALSE(
1004 TransformationEquationInstruction(51, SpvOpBitcast, {20}, insert_before)
1005 .IsApplicable(context.get(), transformation_context));
1006
1007 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1008 kConsoleMessageConsumer));
1009
1010 std::string expected_shader = R"(
1011 OpCapability Shader
1012 %1 = OpExtInstImport "GLSL.std.450"
1013 OpMemoryModel Logical GLSL450
1014 OpEntryPoint Fragment %12 "main"
1015 OpExecutionMode %12 OriginUpperLeft
1016 OpSource ESSL 310
1017 %2 = OpTypeVoid
1018 %3 = OpTypeFunction %2
1019 %4 = OpTypeInt 32 0
1020 %8 = OpTypeFloat 32
1021 %11 = OpTypeVector %8 2
1022 %17 = OpConstant %8 24
1023 %20 = OpConstantComposite %11 %17 %17
1024 %12 = OpFunction %2 None %3
1025 %13 = OpLabel
1026 %50 = OpBitcast %4 %17
1027 OpReturn
1028 OpFunctionEnd
1029 )";
1030
1031 ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
1032 }
1033
TEST(TransformationEquationInstructionTest,BitcastResultTypeIntDoesNotExist6)1034 TEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist6) {
1035 std::string shader = R"(
1036 OpCapability Shader
1037 %1 = OpExtInstImport "GLSL.std.450"
1038 OpMemoryModel Logical GLSL450
1039 OpEntryPoint Fragment %12 "main"
1040 OpExecutionMode %12 OriginUpperLeft
1041 OpSource ESSL 310
1042 %2 = OpTypeVoid
1043 %3 = OpTypeFunction %2
1044 %4 = OpTypeInt 32 1
1045 %5 = OpTypeInt 32 0
1046 %8 = OpTypeFloat 32
1047 %9 = OpTypeVector %5 2
1048 %11 = OpTypeVector %8 2
1049 %17 = OpConstant %8 24
1050 %20 = OpConstantComposite %11 %17 %17
1051 %12 = OpFunction %2 None %3
1052 %13 = OpLabel
1053 OpReturn
1054 OpFunctionEnd
1055 )";
1056
1057 const auto env = SPV_ENV_UNIVERSAL_1_3;
1058 const auto consumer = nullptr;
1059 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1060 spvtools::ValidatorOptions validator_options;
1061 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1062 kConsoleMessageConsumer));
1063 TransformationContext transformation_context(
1064 MakeUnique<FactManager>(context.get()), validator_options);
1065 auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
1066
1067 {
1068 TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
1069 insert_before);
1070 ASSERT_TRUE(
1071 transformation.IsApplicable(context.get(), transformation_context));
1072 ApplyAndCheckFreshIds(transformation, context.get(),
1073 &transformation_context);
1074 }
1075 {
1076 TransformationEquationInstruction transformation(51, SpvOpBitcast, {20},
1077 insert_before);
1078 ASSERT_TRUE(
1079 transformation.IsApplicable(context.get(), transformation_context));
1080 ApplyAndCheckFreshIds(transformation, context.get(),
1081 &transformation_context);
1082 }
1083
1084 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1085 kConsoleMessageConsumer));
1086
1087 std::string expected_shader = R"(
1088 OpCapability Shader
1089 %1 = OpExtInstImport "GLSL.std.450"
1090 OpMemoryModel Logical GLSL450
1091 OpEntryPoint Fragment %12 "main"
1092 OpExecutionMode %12 OriginUpperLeft
1093 OpSource ESSL 310
1094 %2 = OpTypeVoid
1095 %3 = OpTypeFunction %2
1096 %4 = OpTypeInt 32 1
1097 %5 = OpTypeInt 32 0
1098 %8 = OpTypeFloat 32
1099 %9 = OpTypeVector %5 2
1100 %11 = OpTypeVector %8 2
1101 %17 = OpConstant %8 24
1102 %20 = OpConstantComposite %11 %17 %17
1103 %12 = OpFunction %2 None %3
1104 %13 = OpLabel
1105 %50 = OpBitcast %4 %17
1106 %51 = OpBitcast %9 %20
1107 OpReturn
1108 OpFunctionEnd
1109 )";
1110
1111 ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
1112 }
1113
TEST(TransformationEquationInstructionTest,BitcastResultTypeIntDoesNotExist7)1114 TEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist7) {
1115 std::string shader = R"(
1116 OpCapability Shader
1117 %1 = OpExtInstImport "GLSL.std.450"
1118 OpMemoryModel Logical GLSL450
1119 OpEntryPoint Fragment %12 "main"
1120 OpExecutionMode %12 OriginUpperLeft
1121 OpSource ESSL 310
1122 %2 = OpTypeVoid
1123 %3 = OpTypeFunction %2
1124 %4 = OpTypeInt 32 1
1125 %5 = OpTypeInt 32 0
1126 %8 = OpTypeFloat 32
1127 %9 = OpTypeVector %4 2
1128 %11 = OpTypeVector %8 2
1129 %17 = OpConstant %8 24
1130 %20 = OpConstantComposite %11 %17 %17
1131 %12 = OpFunction %2 None %3
1132 %13 = OpLabel
1133 OpReturn
1134 OpFunctionEnd
1135 )";
1136
1137 const auto env = SPV_ENV_UNIVERSAL_1_3;
1138 const auto consumer = nullptr;
1139 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1140 spvtools::ValidatorOptions validator_options;
1141 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1142 kConsoleMessageConsumer));
1143 TransformationContext transformation_context(
1144 MakeUnique<FactManager>(context.get()), validator_options);
1145 auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
1146
1147 {
1148 TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
1149 insert_before);
1150 ASSERT_TRUE(
1151 transformation.IsApplicable(context.get(), transformation_context));
1152 ApplyAndCheckFreshIds(transformation, context.get(),
1153 &transformation_context);
1154 }
1155 {
1156 TransformationEquationInstruction transformation(51, SpvOpBitcast, {20},
1157 insert_before);
1158 ASSERT_TRUE(
1159 transformation.IsApplicable(context.get(), transformation_context));
1160 ApplyAndCheckFreshIds(transformation, context.get(),
1161 &transformation_context);
1162 }
1163
1164 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1165 kConsoleMessageConsumer));
1166
1167 std::string expected_shader = R"(
1168 OpCapability Shader
1169 %1 = OpExtInstImport "GLSL.std.450"
1170 OpMemoryModel Logical GLSL450
1171 OpEntryPoint Fragment %12 "main"
1172 OpExecutionMode %12 OriginUpperLeft
1173 OpSource ESSL 310
1174 %2 = OpTypeVoid
1175 %3 = OpTypeFunction %2
1176 %4 = OpTypeInt 32 1
1177 %5 = OpTypeInt 32 0
1178 %8 = OpTypeFloat 32
1179 %9 = OpTypeVector %4 2
1180 %11 = OpTypeVector %8 2
1181 %17 = OpConstant %8 24
1182 %20 = OpConstantComposite %11 %17 %17
1183 %12 = OpFunction %2 None %3
1184 %13 = OpLabel
1185 %50 = OpBitcast %4 %17
1186 %51 = OpBitcast %9 %20
1187 OpReturn
1188 OpFunctionEnd
1189 )";
1190
1191 ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
1192 }
1193
TEST(TransformationEquationInstructionTest,Miscellaneous1)1194 TEST(TransformationEquationInstructionTest, Miscellaneous1) {
1195 std::string shader = R"(
1196 OpCapability Shader
1197 %1 = OpExtInstImport "GLSL.std.450"
1198 OpMemoryModel Logical GLSL450
1199 OpEntryPoint Fragment %12 "main"
1200 OpExecutionMode %12 OriginUpperLeft
1201 OpSource ESSL 310
1202 %2 = OpTypeVoid
1203 %3 = OpTypeFunction %2
1204 %6 = OpTypeInt 32 1
1205 %113 = OpConstant %6 24
1206 %12 = OpFunction %2 None %3
1207 %13 = OpLabel
1208 OpReturn
1209 OpFunctionEnd
1210 )";
1211
1212 const auto env = SPV_ENV_UNIVERSAL_1_3;
1213 const auto consumer = nullptr;
1214 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1215 spvtools::ValidatorOptions validator_options;
1216 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1217 kConsoleMessageConsumer));
1218 TransformationContext transformation_context(
1219 MakeUnique<FactManager>(context.get()), validator_options);
1220 protobufs::InstructionDescriptor return_instruction =
1221 MakeInstructionDescriptor(13, SpvOpReturn, 0);
1222
1223 auto transformation1 = TransformationEquationInstruction(
1224 522, SpvOpISub, {113, 113}, return_instruction);
1225 ASSERT_TRUE(
1226 transformation1.IsApplicable(context.get(), transformation_context));
1227 ApplyAndCheckFreshIds(transformation1, context.get(),
1228 &transformation_context);
1229 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1230 kConsoleMessageConsumer));
1231
1232 auto transformation2 = TransformationEquationInstruction(
1233 570, SpvOpIAdd, {522, 113}, return_instruction);
1234 ASSERT_TRUE(
1235 transformation2.IsApplicable(context.get(), transformation_context));
1236 ApplyAndCheckFreshIds(transformation2, context.get(),
1237 &transformation_context);
1238 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1239 kConsoleMessageConsumer));
1240
1241 std::string after_transformation = R"(
1242 OpCapability Shader
1243 %1 = OpExtInstImport "GLSL.std.450"
1244 OpMemoryModel Logical GLSL450
1245 OpEntryPoint Fragment %12 "main"
1246 OpExecutionMode %12 OriginUpperLeft
1247 OpSource ESSL 310
1248 %2 = OpTypeVoid
1249 %3 = OpTypeFunction %2
1250 %6 = OpTypeInt 32 1
1251 %113 = OpConstant %6 24
1252 %12 = OpFunction %2 None %3
1253 %13 = OpLabel
1254 %522 = OpISub %6 %113 %113
1255 %570 = OpIAdd %6 %522 %113
1256 OpReturn
1257 OpFunctionEnd
1258 )";
1259
1260 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
1261 MakeDataDescriptor(570, {}), MakeDataDescriptor(113, {})));
1262
1263 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
1264 }
1265
TEST(TransformationEquationInstructionTest,Miscellaneous2)1266 TEST(TransformationEquationInstructionTest, Miscellaneous2) {
1267 std::string shader = R"(
1268 OpCapability Shader
1269 %1 = OpExtInstImport "GLSL.std.450"
1270 OpMemoryModel Logical GLSL450
1271 OpEntryPoint Fragment %12 "main"
1272 OpExecutionMode %12 OriginUpperLeft
1273 OpSource ESSL 310
1274 %2 = OpTypeVoid
1275 %3 = OpTypeFunction %2
1276 %6 = OpTypeInt 32 1
1277 %113 = OpConstant %6 24
1278 %12 = OpFunction %2 None %3
1279 %13 = OpLabel
1280 OpReturn
1281 OpFunctionEnd
1282 )";
1283
1284 const auto env = SPV_ENV_UNIVERSAL_1_3;
1285 const auto consumer = nullptr;
1286 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1287 spvtools::ValidatorOptions validator_options;
1288 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1289 kConsoleMessageConsumer));
1290 TransformationContext transformation_context(
1291 MakeUnique<FactManager>(context.get()), validator_options);
1292 protobufs::InstructionDescriptor return_instruction =
1293 MakeInstructionDescriptor(13, SpvOpReturn, 0);
1294
1295 auto transformation1 = TransformationEquationInstruction(
1296 522, SpvOpISub, {113, 113}, return_instruction);
1297 ASSERT_TRUE(
1298 transformation1.IsApplicable(context.get(), transformation_context));
1299 ApplyAndCheckFreshIds(transformation1, context.get(),
1300 &transformation_context);
1301 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1302 kConsoleMessageConsumer));
1303
1304 auto transformation2 = TransformationEquationInstruction(
1305 570, SpvOpIAdd, {522, 113}, return_instruction);
1306 ASSERT_TRUE(
1307 transformation2.IsApplicable(context.get(), transformation_context));
1308 ApplyAndCheckFreshIds(transformation2, context.get(),
1309 &transformation_context);
1310 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1311 kConsoleMessageConsumer));
1312
1313 std::string after_transformation = R"(
1314 OpCapability Shader
1315 %1 = OpExtInstImport "GLSL.std.450"
1316 OpMemoryModel Logical GLSL450
1317 OpEntryPoint Fragment %12 "main"
1318 OpExecutionMode %12 OriginUpperLeft
1319 OpSource ESSL 310
1320 %2 = OpTypeVoid
1321 %3 = OpTypeFunction %2
1322 %6 = OpTypeInt 32 1
1323 %113 = OpConstant %6 24
1324 %12 = OpFunction %2 None %3
1325 %13 = OpLabel
1326 %522 = OpISub %6 %113 %113
1327 %570 = OpIAdd %6 %522 %113
1328 OpReturn
1329 OpFunctionEnd
1330 )";
1331
1332 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
1333 MakeDataDescriptor(570, {}), MakeDataDescriptor(113, {})));
1334
1335 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
1336 }
1337
TEST(TransformationEquationInstructionTest,ConversionInstructions)1338 TEST(TransformationEquationInstructionTest, ConversionInstructions) {
1339 std::string shader = R"(
1340 OpCapability Shader
1341 %1 = OpExtInstImport "GLSL.std.450"
1342 OpMemoryModel Logical GLSL450
1343 OpEntryPoint Fragment %12 "main"
1344 OpExecutionMode %12 OriginUpperLeft
1345 OpSource ESSL 310
1346 %2 = OpTypeVoid
1347 %3 = OpTypeFunction %2
1348 %6 = OpTypeInt 32 1
1349 %4 = OpTypeInt 32 0
1350 %5 = OpTypeFloat 32
1351 %7 = OpTypeVector %6 3
1352 %8 = OpTypeVector %4 3
1353 %9 = OpTypeVector %5 3
1354 %10 = OpConstant %6 12
1355 %20 = OpConstant %6 12
1356 %11 = OpConstant %4 12
1357 %21 = OpConstant %4 12
1358 %14 = OpConstant %5 12
1359 %15 = OpConstantComposite %7 %10 %10 %10
1360 %18 = OpConstantComposite %7 %10 %10 %10
1361 %16 = OpConstantComposite %8 %11 %11 %11
1362 %19 = OpConstantComposite %8 %11 %11 %11
1363 %17 = OpConstantComposite %9 %14 %14 %14
1364 %12 = OpFunction %2 None %3
1365 %13 = OpLabel
1366 OpReturn
1367 OpFunctionEnd
1368 )";
1369
1370 const auto env = SPV_ENV_UNIVERSAL_1_3;
1371 const auto consumer = nullptr;
1372 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1373 spvtools::ValidatorOptions validator_options;
1374 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1375 kConsoleMessageConsumer));
1376 TransformationContext transformation_context(
1377 MakeUnique<FactManager>(context.get()), validator_options);
1378 protobufs::InstructionDescriptor return_instruction =
1379 MakeInstructionDescriptor(13, SpvOpReturn, 0);
1380
1381 // Too few instruction operands.
1382 ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {},
1383 return_instruction)
1384 .IsApplicable(context.get(), transformation_context));
1385
1386 // Too many instruction operands.
1387 ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {15, 16},
1388 return_instruction)
1389 .IsApplicable(context.get(), transformation_context));
1390
1391 // Operand has no type id.
1392 ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {7},
1393 return_instruction)
1394 .IsApplicable(context.get(), transformation_context));
1395
1396 // OpConvertSToF and OpConvertUToF require an operand to have scalar or vector
1397 // of integral components type.
1398 ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {17},
1399 return_instruction)
1400 .IsApplicable(context.get(), transformation_context));
1401 ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {14},
1402 return_instruction)
1403 .IsApplicable(context.get(), transformation_context));
1404 ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertUToF, {17},
1405 return_instruction)
1406 .IsApplicable(context.get(), transformation_context));
1407 ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertUToF, {14},
1408 return_instruction)
1409 .IsApplicable(context.get(), transformation_context));
1410
1411 {
1412 TransformationEquationInstruction transformation(50, SpvOpConvertSToF, {15},
1413 return_instruction);
1414 ASSERT_TRUE(
1415 transformation.IsApplicable(context.get(), transformation_context));
1416 ApplyAndCheckFreshIds(transformation, context.get(),
1417 &transformation_context);
1418 }
1419 {
1420 TransformationEquationInstruction transformation(51, SpvOpConvertSToF, {10},
1421 return_instruction);
1422 ASSERT_TRUE(
1423 transformation.IsApplicable(context.get(), transformation_context));
1424 ApplyAndCheckFreshIds(transformation, context.get(),
1425 &transformation_context);
1426 }
1427 {
1428 TransformationEquationInstruction transformation(52, SpvOpConvertUToF, {16},
1429 return_instruction);
1430 ASSERT_TRUE(
1431 transformation.IsApplicable(context.get(), transformation_context));
1432 ApplyAndCheckFreshIds(transformation, context.get(),
1433 &transformation_context);
1434 }
1435 {
1436 TransformationEquationInstruction transformation(53, SpvOpConvertUToF, {11},
1437 return_instruction);
1438 ASSERT_TRUE(
1439 transformation.IsApplicable(context.get(), transformation_context));
1440 ApplyAndCheckFreshIds(transformation, context.get(),
1441 &transformation_context);
1442 }
1443 {
1444 TransformationEquationInstruction transformation(58, SpvOpConvertSToF, {18},
1445 return_instruction);
1446 ASSERT_TRUE(
1447 transformation.IsApplicable(context.get(), transformation_context));
1448 ApplyAndCheckFreshIds(transformation, context.get(),
1449 &transformation_context);
1450 }
1451 {
1452 TransformationEquationInstruction transformation(59, SpvOpConvertUToF, {19},
1453 return_instruction);
1454 ASSERT_TRUE(
1455 transformation.IsApplicable(context.get(), transformation_context));
1456 ApplyAndCheckFreshIds(transformation, context.get(),
1457 &transformation_context);
1458 }
1459 {
1460 TransformationEquationInstruction transformation(60, SpvOpConvertSToF, {20},
1461 return_instruction);
1462 ASSERT_TRUE(
1463 transformation.IsApplicable(context.get(), transformation_context));
1464 ApplyAndCheckFreshIds(transformation, context.get(),
1465 &transformation_context);
1466 }
1467 {
1468 TransformationEquationInstruction transformation(61, SpvOpConvertUToF, {21},
1469 return_instruction);
1470 ASSERT_TRUE(
1471 transformation.IsApplicable(context.get(), transformation_context));
1472 ApplyAndCheckFreshIds(transformation, context.get(),
1473 &transformation_context);
1474 }
1475
1476 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1477 kConsoleMessageConsumer));
1478
1479 std::string after_transformations = R"(
1480 OpCapability Shader
1481 %1 = OpExtInstImport "GLSL.std.450"
1482 OpMemoryModel Logical GLSL450
1483 OpEntryPoint Fragment %12 "main"
1484 OpExecutionMode %12 OriginUpperLeft
1485 OpSource ESSL 310
1486 %2 = OpTypeVoid
1487 %3 = OpTypeFunction %2
1488 %6 = OpTypeInt 32 1
1489 %4 = OpTypeInt 32 0
1490 %5 = OpTypeFloat 32
1491 %7 = OpTypeVector %6 3
1492 %8 = OpTypeVector %4 3
1493 %9 = OpTypeVector %5 3
1494 %10 = OpConstant %6 12
1495 %20 = OpConstant %6 12
1496 %11 = OpConstant %4 12
1497 %21 = OpConstant %4 12
1498 %14 = OpConstant %5 12
1499 %15 = OpConstantComposite %7 %10 %10 %10
1500 %18 = OpConstantComposite %7 %10 %10 %10
1501 %16 = OpConstantComposite %8 %11 %11 %11
1502 %19 = OpConstantComposite %8 %11 %11 %11
1503 %17 = OpConstantComposite %9 %14 %14 %14
1504 %12 = OpFunction %2 None %3
1505 %13 = OpLabel
1506 %50 = OpConvertSToF %9 %15
1507 %51 = OpConvertSToF %5 %10
1508 %52 = OpConvertUToF %9 %16
1509 %53 = OpConvertUToF %5 %11
1510 %58 = OpConvertSToF %9 %18
1511 %59 = OpConvertUToF %9 %19
1512 %60 = OpConvertSToF %5 %20
1513 %61 = OpConvertUToF %5 %21
1514 OpReturn
1515 OpFunctionEnd
1516 )";
1517
1518 ASSERT_TRUE(IsEqual(env, after_transformations, context.get()));
1519 }
1520
TEST(TransformationEquationInstructionTest,FloatResultTypeDoesNotExist)1521 TEST(TransformationEquationInstructionTest, FloatResultTypeDoesNotExist) {
1522 std::string shader = R"(
1523 OpCapability Shader
1524 %1 = OpExtInstImport "GLSL.std.450"
1525 OpMemoryModel Logical GLSL450
1526 OpEntryPoint Fragment %12 "main"
1527 OpExecutionMode %12 OriginUpperLeft
1528 OpSource ESSL 310
1529 %2 = OpTypeVoid
1530 %3 = OpTypeFunction %2
1531 %6 = OpTypeInt 32 0
1532 %7 = OpTypeInt 32 1
1533 %8 = OpTypeVector %6 3
1534 %9 = OpTypeVector %7 3
1535 %10 = OpConstant %6 24
1536 %11 = OpConstant %7 25
1537 %14 = OpConstantComposite %8 %10 %10 %10
1538 %15 = OpConstantComposite %9 %11 %11 %11
1539 %12 = OpFunction %2 None %3
1540 %13 = OpLabel
1541 OpReturn
1542 OpFunctionEnd
1543 )";
1544
1545 const auto env = SPV_ENV_UNIVERSAL_1_3;
1546 const auto consumer = nullptr;
1547 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1548 spvtools::ValidatorOptions validator_options;
1549 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1550 kConsoleMessageConsumer));
1551 TransformationContext transformation_context(
1552 MakeUnique<FactManager>(context.get()), validator_options);
1553 protobufs::InstructionDescriptor return_instruction =
1554 MakeInstructionDescriptor(13, SpvOpReturn, 0);
1555
1556 // Scalar float type doesn't exist.
1557 ASSERT_FALSE(TransformationEquationInstruction(16, SpvOpConvertUToF, {10},
1558 return_instruction)
1559 .IsApplicable(context.get(), transformation_context));
1560 ASSERT_FALSE(TransformationEquationInstruction(16, SpvOpConvertSToF, {11},
1561 return_instruction)
1562 .IsApplicable(context.get(), transformation_context));
1563
1564 // Vector float type doesn't exist.
1565 ASSERT_FALSE(TransformationEquationInstruction(16, SpvOpConvertUToF, {14},
1566 return_instruction)
1567 .IsApplicable(context.get(), transformation_context));
1568 ASSERT_FALSE(TransformationEquationInstruction(16, SpvOpConvertSToF, {15},
1569 return_instruction)
1570 .IsApplicable(context.get(), transformation_context));
1571 }
1572
TEST(TransformationEquationInstructionTest,HandlesIrrelevantIds)1573 TEST(TransformationEquationInstructionTest, HandlesIrrelevantIds) {
1574 std::string shader = R"(
1575 OpCapability Shader
1576 %1 = OpExtInstImport "GLSL.std.450"
1577 OpMemoryModel Logical GLSL450
1578 OpEntryPoint Fragment %12 "main"
1579 OpExecutionMode %12 OriginUpperLeft
1580 OpSource ESSL 310
1581 %2 = OpTypeVoid
1582 %3 = OpTypeFunction %2
1583 %6 = OpTypeInt 32 1
1584 %30 = OpTypeVector %6 3
1585 %15 = OpConstant %6 24
1586 %16 = OpConstant %6 37
1587 %31 = OpConstantComposite %30 %15 %16 %15
1588 %33 = OpTypeBool
1589 %32 = OpConstantTrue %33
1590 %12 = OpFunction %2 None %3
1591 %13 = OpLabel
1592 OpReturn
1593 OpFunctionEnd
1594 )";
1595
1596 const auto env = SPV_ENV_UNIVERSAL_1_3;
1597 const auto consumer = nullptr;
1598 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1599 spvtools::ValidatorOptions validator_options;
1600 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1601 kConsoleMessageConsumer));
1602 TransformationContext transformation_context(
1603 MakeUnique<FactManager>(context.get()), validator_options);
1604 auto return_instruction = MakeInstructionDescriptor(13, SpvOpReturn, 0);
1605
1606 // Applicable.
1607 TransformationEquationInstruction transformation(14, SpvOpIAdd, {15, 16},
1608 return_instruction);
1609 ASSERT_TRUE(
1610 transformation.IsApplicable(context.get(), transformation_context));
1611
1612 // Handles irrelevant ids.
1613 transformation_context.GetFactManager()->AddFactIdIsIrrelevant(16);
1614 ASSERT_FALSE(
1615 transformation.IsApplicable(context.get(), transformation_context));
1616 transformation_context.GetFactManager()->AddFactIdIsIrrelevant(15);
1617 ASSERT_FALSE(
1618 transformation.IsApplicable(context.get(), transformation_context));
1619 }
1620
TEST(TransformationEquationInstructionTest,HandlesDeadBlock)1621 TEST(TransformationEquationInstructionTest, HandlesDeadBlock) {
1622 std::string shader = R"(
1623 OpCapability Shader
1624 %1 = OpExtInstImport "GLSL.std.450"
1625 OpMemoryModel Logical GLSL450
1626 OpEntryPoint Fragment %12 "main"
1627 OpExecutionMode %12 OriginUpperLeft
1628 OpSource ESSL 310
1629 %2 = OpTypeVoid
1630 %3 = OpTypeFunction %2
1631 %6 = OpTypeInt 32 1
1632 %30 = OpTypeVector %6 3
1633 %15 = OpConstant %6 24
1634 %16 = OpConstant %6 37
1635 %31 = OpConstantComposite %30 %15 %16 %15
1636 %33 = OpTypeBool
1637 %32 = OpConstantTrue %33
1638 %12 = OpFunction %2 None %3
1639 %13 = OpLabel
1640 OpSelectionMerge %40 None
1641 OpBranchConditional %32 %40 %41
1642 %41 = OpLabel
1643 OpBranch %40
1644 %40 = OpLabel
1645 OpReturn
1646 OpFunctionEnd
1647 )";
1648
1649 const auto env = SPV_ENV_UNIVERSAL_1_3;
1650 const auto consumer = nullptr;
1651 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
1652 spvtools::ValidatorOptions validator_options;
1653 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
1654 kConsoleMessageConsumer));
1655 TransformationContext transformation_context(
1656 MakeUnique<FactManager>(context.get()), validator_options);
1657
1658 transformation_context.GetFactManager()->AddFactBlockIsDead(41);
1659
1660 TransformationEquationInstruction transformation1(
1661 14, SpvOpIAdd, {15, 16},
1662 MakeInstructionDescriptor(13, SpvOpSelectionMerge, 0));
1663 // No synonym is created since block is dead.
1664 TransformationEquationInstruction transformation2(
1665 100, SpvOpISub, {14, 16}, MakeInstructionDescriptor(41, SpvOpBranch, 0));
1666 ASSERT_TRUE(
1667 transformation1.IsApplicable(context.get(), transformation_context));
1668 ApplyAndCheckFreshIds(transformation1, context.get(),
1669 &transformation_context);
1670 ASSERT_TRUE(
1671 transformation2.IsApplicable(context.get(), transformation_context));
1672 ApplyAndCheckFreshIds(transformation2, context.get(),
1673 &transformation_context);
1674 ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
1675 MakeDataDescriptor(100, {}), MakeDataDescriptor(15, {})));
1676 }
1677
1678 } // namespace
1679 } // namespace fuzz
1680 } // namespace spvtools
1681