[spirv-reader] Support return, return-value
Bug: tint:3 Change-Id: Iaaf6ace739ac30e7f9f0bd4ddcef209ab1b71ed8 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/22480 Reviewed-by: dan sinclair <dsinclair@google.com>
This commit is contained in:
parent
d8613596e2
commit
cb48e79fa5
|
@ -32,6 +32,7 @@
|
||||||
#include "src/ast/if_statement.h"
|
#include "src/ast/if_statement.h"
|
||||||
#include "src/ast/loop_statement.h"
|
#include "src/ast/loop_statement.h"
|
||||||
#include "src/ast/member_accessor_expression.h"
|
#include "src/ast/member_accessor_expression.h"
|
||||||
|
#include "src/ast/return_statement.h"
|
||||||
#include "src/ast/scalar_constructor_expression.h"
|
#include "src/ast/scalar_constructor_expression.h"
|
||||||
#include "src/ast/storage_class.h"
|
#include "src/ast/storage_class.h"
|
||||||
#include "src/ast/switch_statement.h"
|
#include "src/ast/switch_statement.h"
|
||||||
|
@ -1753,9 +1754,23 @@ bool FunctionEmitter::EmitContinuingStart(const Construct* construct) {
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FunctionEmitter::EmitNormalTerminator(const BlockInfo&) {
|
bool FunctionEmitter::EmitNormalTerminator(const BlockInfo& block_info) {
|
||||||
// TODO(dneto): emit fallthrough, break, continue, return, kill
|
const auto& terminator = *(block_info.basic_block->terminator());
|
||||||
|
switch (terminator.opcode()) {
|
||||||
|
case SpvOpReturn:
|
||||||
|
AddStatement(std::make_unique<ast::ReturnStatement>());
|
||||||
return true;
|
return true;
|
||||||
|
case SpvOpReturnValue: {
|
||||||
|
auto value = MakeExpression(terminator.GetSingleWordInOperand(0));
|
||||||
|
AddStatement(
|
||||||
|
std::make_unique<ast::ReturnStatement>(std::move(value.expr)));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// TODO(dneto): emit fallthrough, break, continue, kill
|
||||||
|
return success();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info,
|
bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info,
|
||||||
|
|
|
@ -62,6 +62,8 @@ std::string CommonTypes() {
|
||||||
%uint = OpTypeInt 32 0
|
%uint = OpTypeInt 32 0
|
||||||
%selector = OpConstant %uint 42
|
%selector = OpConstant %uint 42
|
||||||
|
|
||||||
|
%uintfn = OpTypeFunction %uint
|
||||||
|
|
||||||
%uint_0 = OpConstant %uint 0
|
%uint_0 = OpConstant %uint 0
|
||||||
%uint_1 = OpConstant %uint 1
|
%uint_1 = OpConstant %uint 1
|
||||||
%uint_2 = OpConstant %uint 2
|
%uint_2 = OpConstant %uint 2
|
||||||
|
@ -6771,6 +6773,7 @@ Else{
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6820,6 +6823,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6869,6 +6873,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6926,6 +6931,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6994,6 +7000,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7052,6 +7059,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7110,6 +7118,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7223,6 +7232,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7264,6 +7274,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7305,6 +7316,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7345,6 +7357,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7385,6 +7398,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7443,6 +7457,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)")) << ToString(fe.ast_body());
|
)")) << ToString(fe.ast_body());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7509,6 +7524,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)")) << ToString(fe.ast_body());
|
)")) << ToString(fe.ast_body());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7595,6 +7611,7 @@ Assignment{
|
||||||
Identifier{var}
|
Identifier{var}
|
||||||
ScalarConstructor{999}
|
ScalarConstructor{999}
|
||||||
}
|
}
|
||||||
|
Return{}
|
||||||
)")) << ToString(fe.ast_body());
|
)")) << ToString(fe.ast_body());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7626,6 +7643,224 @@ TEST_F(SpvParserTest, DISABLED_EmitBody_Loop_BodyConditionallyBreaks) {
|
||||||
// TODO(dneto): Needs "break" support
|
// TODO(dneto): Needs "break" support
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, EmitBody_Return_TopLevel) {
|
||||||
|
auto* p = parser(test::Assemble(CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = 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"(Return{}
|
||||||
|
)")) << ToString(fe.ast_body());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, EmitBody_Return_InsideIf) {
|
||||||
|
auto* p = parser(test::Assemble(CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpSelectionMerge %99 None
|
||||||
|
OpBranchConditional %cond %20 %99
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
|
||||||
|
%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_Return_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
|
||||||
|
OpReturn
|
||||||
|
|
||||||
|
%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_ReturnValue_TopLevel) {
|
||||||
|
auto* p = parser(test::Assemble(CommonTypes() + R"(
|
||||||
|
%200 = OpFunction %uint None %uintfn
|
||||||
|
|
||||||
|
%210 = OpLabel
|
||||||
|
OpReturnValue %uint_2
|
||||||
|
|
||||||
|
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{2}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)")) << ToString(fe.ast_body());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, EmitBody_ReturnValue_InsideIf) {
|
||||||
|
auto* p = parser(test::Assemble(CommonTypes() + R"(
|
||||||
|
%200 = OpFunction %uint None %uintfn
|
||||||
|
|
||||||
|
%210 = OpLabel
|
||||||
|
OpSelectionMerge %299 None
|
||||||
|
OpBranchConditional %cond %220 %299
|
||||||
|
|
||||||
|
%220 = OpLabel
|
||||||
|
OpReturnValue %uint_2
|
||||||
|
|
||||||
|
%299 = OpLabel
|
||||||
|
OpReturnValue %uint_3
|
||||||
|
|
||||||
|
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"(If{
|
||||||
|
(
|
||||||
|
ScalarConstructor{false}
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Return{
|
||||||
|
{
|
||||||
|
ScalarConstructor{2}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Else{
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Return{
|
||||||
|
{
|
||||||
|
ScalarConstructor{3}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)")) << ToString(fe.ast_body());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, EmitBody_ReturnValue_Loop) {
|
||||||
|
auto* p = parser(test::Assemble(CommonTypes() + R"(
|
||||||
|
%200 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%210 = OpLabel
|
||||||
|
OpBranch %220
|
||||||
|
|
||||||
|
%220 = OpLabel
|
||||||
|
OpLoopMerge %299 %280 None
|
||||||
|
OpBranchConditional %cond %230 %230
|
||||||
|
|
||||||
|
%230 = OpLabel
|
||||||
|
OpReturnValue %uint_2
|
||||||
|
|
||||||
|
%280 = OpLabel
|
||||||
|
OpBranch %220
|
||||||
|
|
||||||
|
%299 = OpLabel
|
||||||
|
OpReturnValue %uint_3
|
||||||
|
|
||||||
|
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"(Loop{
|
||||||
|
Return{
|
||||||
|
{
|
||||||
|
ScalarConstructor{2}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Return{
|
||||||
|
{
|
||||||
|
ScalarConstructor{3}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)")) << ToString(fe.ast_body());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace reader
|
} // namespace reader
|
||||||
|
|
|
@ -107,18 +107,24 @@ TEST_F(SpvParserTest, EmitFunctions_CalleePrecedesCaller) {
|
||||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||||
EXPECT_TRUE(p->error().empty());
|
EXPECT_TRUE(p->error().empty());
|
||||||
const auto module_ast = p->module().to_str();
|
const auto module_ast = p->module().to_str();
|
||||||
|
// TODO(dneto): This will need to be updated when function calls are
|
||||||
|
// supported. Otherwise, use more general matching instead of substring
|
||||||
|
// equality.
|
||||||
EXPECT_THAT(module_ast, HasSubstr(R"(
|
EXPECT_THAT(module_ast, HasSubstr(R"(
|
||||||
Function leaf -> __void
|
Function leaf -> __void
|
||||||
()
|
()
|
||||||
{
|
{
|
||||||
|
Return{}
|
||||||
}
|
}
|
||||||
Function branch -> __void
|
Function branch -> __void
|
||||||
()
|
()
|
||||||
{
|
{
|
||||||
|
Return{}
|
||||||
}
|
}
|
||||||
Function root -> __void
|
Function root -> __void
|
||||||
()
|
()
|
||||||
{
|
{
|
||||||
|
Return{}
|
||||||
})"));
|
})"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +144,13 @@ TEST_F(SpvParserTest, EmitFunctions_NonVoidResultType) {
|
||||||
Function ret_float -> __f32
|
Function ret_float -> __f32
|
||||||
()
|
()
|
||||||
{
|
{
|
||||||
})"));
|
Return{
|
||||||
|
{
|
||||||
|
ScalarConstructor{0.000000}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})"))
|
||||||
|
<< module_ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SpvParserTest, EmitFunctions_MixedParamTypes) {
|
TEST_F(SpvParserTest, EmitFunctions_MixedParamTypes) {
|
||||||
|
@ -177,6 +189,7 @@ TEST_F(SpvParserTest, EmitFunctions_MixedParamTypes) {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
Return{}
|
||||||
})"));
|
})"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +228,7 @@ TEST_F(SpvParserTest, EmitFunctions_GenerateParamNames) {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
Return{}
|
||||||
})"));
|
})"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue