spirv-fuzz: Fix vector wrapping fuzzer pass (#4392)
The fuzzer pass was passing the type of a scalar where a vector type
was required, and was not checking whether synonyms could be made for
the operands to the scalar instruction.
diff --git a/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp b/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp
index 3f324df..5f1ae18 100644
--- a/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp
+++ b/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp
@@ -48,13 +48,6 @@
return;
}
- // The transformation will not be applicable if the id of the scalar
- // operation is irrelevant.
- if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
- instruction_iterator->result_id())) {
- return;
- }
-
// It must be valid to insert an OpCompositeConstruct instruction
// before |instruction_iterator|.
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
@@ -77,6 +70,25 @@
uint32_t target_id1 = instruction_iterator->GetSingleWordInOperand(0);
uint32_t target_id2 = instruction_iterator->GetSingleWordInOperand(1);
+ // We need to be able to make a synonym of the scalar operation's result
+ // id, as well as the operand ids (for example, they cannot be
+ // irrelevant).
+ if (!fuzzerutil::CanMakeSynonymOf(GetIRContext(),
+ *GetTransformationContext(),
+ &*instruction_iterator)) {
+ return;
+ }
+ if (!fuzzerutil::CanMakeSynonymOf(
+ GetIRContext(), *GetTransformationContext(),
+ GetIRContext()->get_def_use_mgr()->GetDef(target_id1))) {
+ return;
+ }
+ if (!fuzzerutil::CanMakeSynonymOf(
+ GetIRContext(), *GetTransformationContext(),
+ GetIRContext()->get_def_use_mgr()->GetDef(target_id2))) {
+ return;
+ }
+
// Stores the ids of scalar constants.
std::vector<uint32_t> vec1_components;
std::vector<uint32_t> vec2_components;
@@ -95,19 +107,21 @@
}
// Add two OpCompositeConstruct to the module with result id returned.
+ const uint32_t vector_type_id =
+ FindOrCreateVectorType(operand_type_id, vector_size);
// Add the first OpCompositeConstruct that wraps the id of the first
// operand.
uint32_t result_id1 = GetFuzzerContext()->GetFreshId();
ApplyTransformation(TransformationCompositeConstruct(
- operand_type_id, vec1_components, instruction_descriptor,
+ vector_type_id, vec1_components, instruction_descriptor,
result_id1));
// Add the second OpCompositeConstruct that wraps the id of the second
// operand.
uint32_t result_id2 = GetFuzzerContext()->GetFreshId();
ApplyTransformation(TransformationCompositeConstruct(
- operand_type_id, vec2_components, instruction_descriptor,
+ vector_type_id, vec2_components, instruction_descriptor,
result_id2));
// Apply transformation to do vector operation and add synonym between
diff --git a/source/fuzz/fuzzer_util.cpp b/source/fuzz/fuzzer_util.cpp
index 0e718e1..cae87a3 100644
--- a/source/fuzz/fuzzer_util.cpp
+++ b/source/fuzz/fuzzer_util.cpp
@@ -305,7 +305,7 @@
bool CanMakeSynonymOf(opt::IRContext* ir_context,
const TransformationContext& transformation_context,
- opt::Instruction* inst) {
+ const opt::Instruction* inst) {
if (inst->opcode() == SpvOpSampledImage) {
// The SPIR-V data rules say that only very specific instructions may
// may consume the result id of an OpSampledImage, and this excludes the
diff --git a/source/fuzz/fuzzer_util.h b/source/fuzz/fuzzer_util.h
index a394661..40b51d5 100644
--- a/source/fuzz/fuzzer_util.h
+++ b/source/fuzz/fuzzer_util.h
@@ -118,7 +118,7 @@
// does not participate in IdIsIrrelevant fact.
bool CanMakeSynonymOf(opt::IRContext* ir_context,
const TransformationContext& transformation_context,
- opt::Instruction* inst);
+ const opt::Instruction* inst);
// Determines whether the given type is a composite; that is: an array, matrix,
// struct or vector.
diff --git a/source/fuzz/transformation_wrap_vector_synonym.cpp b/source/fuzz/transformation_wrap_vector_synonym.cpp
index 86eb51c..4402589 100644
--- a/source/fuzz/transformation_wrap_vector_synonym.cpp
+++ b/source/fuzz/transformation_wrap_vector_synonym.cpp
@@ -55,9 +55,12 @@
return false;
}
- assert(!transformation_context.GetFactManager()->IdIsIrrelevant(
- instruction->result_id()) &&
- "Result id of the scalar operation must be relevant.");
+ // It must be possible to make a synonym of the result id of the scalar
+ // operation
+ if (!fuzzerutil::CanMakeSynonymOf(ir_context, transformation_context,
+ instruction)) {
+ return false;
+ }
// |vector_operand1| and |vector_operand2| must exist.
auto vec1 = ir_context->get_def_use_mgr()->GetDef(message_.vector_operand1());