[spirv-reader] Support unreachable, as a return

Bug: tint:3
Change-Id: Ia1384f84f7851a9e155c1536a624213ef51ee0a1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/22521
Reviewed-by: dan sinclair <dsinclair@google.com>
This commit is contained in:
David Neto 2020-06-02 19:56:07 +00:00
parent 91332dc475
commit 1649dfadd7
2 changed files with 130 additions and 1 deletions

View File

@ -1772,10 +1772,24 @@ bool FunctionEmitter::EmitNormalTerminator(const BlockInfo& block_info) {
// TODO(dneto): https://github.com/gpuweb/gpuweb/issues/676
AddStatement(std::make_unique<ast::KillStatement>());
return true;
case SpvOpUnreachable:
// Translate as if it's a return. This avoids the problem where WGSL
// requires a return statement at the end of the function body.
{
const auto* result_type = type_mgr_->GetType(function_.type_id());
if (result_type->AsVoid() != nullptr) {
AddStatement(std::make_unique<ast::ReturnStatement>());
} else {
auto* ast_type = parser_impl_.ConvertType(function_.type_id());
AddStatement(std::make_unique<ast::ReturnStatement>(
parser_impl_.MakeNullValue(ast_type)));
}
}
return true;
default:
break;
}
// TODO(dneto): emit fallthrough, break, continue, kill
// TODO(dneto): emit fallthrough, break, continue
return success();
}

View File

@ -7947,6 +7947,121 @@ Kill{}
)")) << ToString(fe.ast_body());
}
TEST_F(SpvParserTest, EmitBody_Unreachable_TopLevel) {
auto* p = parser(test::Assemble(CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpUnreachable
OpFunctionEnd
)"));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
EXPECT_TRUE(fe.EmitBody()) << p->error();
EXPECT_THAT(ToString(fe.ast_body()), Eq(R"(Return{}
)")) << ToString(fe.ast_body());
}
TEST_F(SpvParserTest, EmitBody_Unreachable_InsideIf) {
auto* p = parser(test::Assemble(CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpSelectionMerge %99 None
OpBranchConditional %cond %20 %99
%20 = OpLabel
OpUnreachable
%99 = OpLabel
OpReturn
OpFunctionEnd
)"));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
EXPECT_TRUE(fe.EmitBody()) << p->error();
EXPECT_THAT(ToString(fe.ast_body()), Eq(R"(If{
(
ScalarConstructor{false}
)
{
Return{}
}
}
Else{
{
}
}
Return{}
)")) << ToString(fe.ast_body());
}
TEST_F(SpvParserTest, EmitBody_Unreachable_InsideLoop) {
auto* p = parser(test::Assemble(CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%10 = OpLabel
OpBranch %20
%20 = OpLabel
OpLoopMerge %99 %80 None
OpBranchConditional %cond %30 %30
%30 = OpLabel
OpUnreachable
%80 = OpLabel
OpBranch %20
%99 = OpLabel
OpReturn
OpFunctionEnd
)"));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(100));
EXPECT_TRUE(fe.EmitBody()) << p->error();
EXPECT_THAT(ToString(fe.ast_body()), Eq(R"(Loop{
Return{}
}
Return{}
)")) << ToString(fe.ast_body());
}
TEST_F(SpvParserTest, EmitBody_Unreachable_InNonVoidFunction) {
auto* p = parser(test::Assemble(CommonTypes() + R"(
%200 = OpFunction %uint None %uintfn
%210 = OpLabel
OpUnreachable
OpFunctionEnd
%100 = OpFunction %void None %voidfn
%10 = OpLabel
%11 = OpFunctionCall %uint %200
OpReturn
OpFunctionEnd
)"));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
FunctionEmitter fe(p, *spirv_function(200));
EXPECT_TRUE(fe.EmitBody()) << p->error();
EXPECT_THAT(ToString(fe.ast_body()), Eq(R"(Return{
{
ScalarConstructor{0}
}
}
)")) << ToString(fe.ast_body());
}
} // namespace
} // namespace spirv
} // namespace reader