spirv-val: Fix validation of OpPhi instructions (#3919)

Fixes #3918.
This commit is contained in:
Alastair Donaldson 2020-10-19 17:36:21 +01:00 committed by GitHub
parent b1350659b6
commit 6fac705e76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 0 deletions

View File

@ -89,6 +89,8 @@ spv_result_t ValidatePhi(ValidationState_t& _, const Instruction* inst) {
<< block->predecessors()->size() << ").";
}
std::unordered_set<uint32_t> observed_predecessors;
for (size_t i = 3; i < inst->words().size(); ++i) {
auto inc_id = inst->word(i);
if (i % 2 == 1) {
@ -115,6 +117,17 @@ spv_result_t ValidatePhi(ValidationState_t& _, const Instruction* inst) {
<< " is not a predecessor of <id> " << _.getIdName(block->id())
<< ".";
}
// We must not have already seen this predecessor as one of the phi's
// operands.
if (observed_predecessors.count(inc_id) != 0) {
return _.diag(SPV_ERROR_INVALID_ID, inst)
<< "OpPhi references incoming basic block <id> "
<< _.getIdName(inc_id) << " multiple times.";
}
// Note the fact that we have now observed this predecessor.
observed_predecessors.insert(inc_id);
}
}

View File

@ -4565,6 +4565,39 @@ OpFunctionEnd
ASSERT_FALSE(b11->reachable());
}
TEST_F(ValidateCFG, PhiInstructionWithDuplicateIncomingEdges) {
const std::string text = 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
%4 = OpFunction %2 None %3
%5 = OpLabel
OpSelectionMerge %10 None
OpBranchConditional %7 %8 %9
%8 = OpLabel
OpBranch %10
%9 = OpLabel
OpBranch %10
%10 = OpLabel
%11 = OpPhi %6 %7 %8 %7 %8
OpReturn
OpFunctionEnd
)";
CompileSuccessfully(text);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
HasSubstr("OpPhi references incoming basic block <id> "));
EXPECT_THAT(getDiagnosticString(), HasSubstr("multiple times."));
}
} // namespace
} // namespace val
} // namespace spvtools