spirv-fuzz: Support dead blocks in TransformationAddSynonym (#3832)

Fixes #3830.
This commit is contained in:
Vasyl Teliman 2020-09-24 16:18:07 +03:00 committed by GitHub
parent 36185f8b09
commit 330c72549a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 2 deletions

View File

@ -36,6 +36,12 @@ void FuzzerPassAddSynonyms::Apply() {
[this](opt::Function* function, opt::BasicBlock* block,
opt::BasicBlock::iterator inst_it,
const protobufs::InstructionDescriptor& instruction_descriptor) {
if (GetTransformationContext()->GetFactManager()->BlockIsDead(
block->id())) {
// Don't create synonyms in dead blocks.
return;
}
// Skip |inst_it| if we can't insert anything above it. OpIAdd is just
// a representative of some instruction that might be produced by the
// transformation.

View File

@ -41,6 +41,12 @@ void FuzzerPassCopyObjects::Apply() {
"The opcode of the instruction we might insert before must be "
"the same as the opcode in the descriptor for the instruction");
if (GetTransformationContext()->GetFactManager()->BlockIsDead(
block->id())) {
// Don't create synonyms in dead blocks.
return;
}
// Check whether it is legitimate to insert a copy before this
// instruction.
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyObject,

View File

@ -68,6 +68,17 @@ bool TransformationAddSynonym::IsApplicable(
return false;
}
const auto* insert_before_inst_block =
ir_context->get_instr_block(insert_before_inst);
assert(insert_before_inst_block &&
"|insert_before_inst| must be in some block");
if (transformation_context.GetFactManager()->BlockIsDead(
insert_before_inst_block->id())) {
// We don't create synonyms in dead blocks.
return false;
}
// Check that we can insert |message._synonymous_instruction| before
// |message_.insert_before| instruction. We use OpIAdd to represent some
// instruction that can produce a synonym.

View File

@ -1334,7 +1334,7 @@ TEST(TransformationAddSynonymTest, PropagateIrrelevantPointeeFact) {
transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
}
TEST(TransformationAddSynonym, DoNotCopyOpSampledImage) {
TEST(TransformationAddSynonymTest, DoNotCopyOpSampledImage) {
// This checks that we do not try to copy the result id of an OpSampledImage
// instruction.
std::string shader = R"(
@ -1392,7 +1392,7 @@ TEST(TransformationAddSynonym, DoNotCopyOpSampledImage) {
.IsApplicable(context.get(), transformation_context));
}
TEST(TransformationAddSynonym, DoNotCopyVoidRunctionResult) {
TEST(TransformationAddSynonymTest, DoNotCopyVoidRunctionResult) {
// This checks that we do not try to copy the result of a void function.
std::string shader = R"(
OpCapability Shader
@ -1431,6 +1431,57 @@ TEST(TransformationAddSynonym, DoNotCopyVoidRunctionResult) {
.IsApplicable(context.get(), transformation_context));
}
TEST(TransformationAddSynonymTest, HandlesDeadBlocks) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 320
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeBool
%7 = OpConstantTrue %6
%11 = OpTypePointer Function %6
%4 = OpFunction %2 None %3
%5 = OpLabel
%12 = OpVariable %11 Function
OpSelectionMerge %10 None
OpBranchConditional %7 %8 %9
%8 = OpLabel
OpBranch %10
%9 = OpLabel
OpBranch %10
%10 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_3;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
FactManager fact_manager(context.get());
spvtools::ValidatorOptions validator_options;
TransformationContext transformation_context(&fact_manager,
validator_options);
fact_manager.AddFactBlockIsDead(9);
auto insert_before = MakeInstructionDescriptor(9, SpvOpBranch, 0);
ASSERT_FALSE(TransformationAddSynonym(
7, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
insert_before)
.IsApplicable(context.get(), transformation_context));
ASSERT_FALSE(TransformationAddSynonym(
12, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
insert_before)
.IsApplicable(context.get(), transformation_context));
}
} // namespace
} // namespace fuzz
} // namespace spvtools