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.
This commit is contained in:
Alastair Donaldson 2021-07-22 23:43:45 +01:00 committed by GitHub
parent 2419f3be86
commit cc3fe2b67b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 14 deletions

View File

@ -48,13 +48,6 @@ void FuzzerPassWrapVectorSynonym::Apply() {
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 @@ void FuzzerPassWrapVectorSynonym::Apply() {
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 @@ void FuzzerPassWrapVectorSynonym::Apply() {
}
// 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

View File

@ -305,7 +305,7 @@ bool CanInsertOpcodeBeforeInstruction(
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

View File

@ -118,7 +118,7 @@ bool CanInsertOpcodeBeforeInstruction(
// 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.

View File

@ -55,9 +55,12 @@ bool TransformationWrapVectorSynonym::IsApplicable(
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());