ast: Remove Function::set_body()
Bug: tint:390
Change-Id: I525086868c6470ba39fe8c4ede7390e74c9489ff
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/35012
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/ast/function.h b/src/ast/function.h
index ba819ab..894525a 100644
--- a/src/ast/function.h
+++ b/src/ast/function.h
@@ -153,9 +153,6 @@
// function is empty
const Statement* get_last_statement() const;
- /// Sets the body of the function
- /// @param body the function body
- void set_body(BlockStatement* body) { body_ = body; }
/// @returns the function body
const BlockStatement* body() const { return body_; }
/// @returns the function body
diff --git a/src/ast/function_test.cc b/src/ast/function_test.cc
index db0e995..1413792 100644
--- a/src/ast/function_test.cc
+++ b/src/ast/function_test.cc
@@ -185,12 +185,11 @@
params.push_back(
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
- auto* block = create<BlockStatement>();
- block->append(create<DiscardStatement>());
+ auto* body = create<BlockStatement>();
+ body->append(create<DiscardStatement>());
- Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+ Function f(Source{}, "func", params, &void_type, body,
FunctionDecorationList{});
- f.set_body(block);
EXPECT_TRUE(f.IsValid());
}
@@ -253,13 +252,13 @@
params.push_back(
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
- auto* block = create<BlockStatement>();
- block->append(create<DiscardStatement>());
- block->append(nullptr);
+ auto* body = create<BlockStatement>();
+ body->append(create<DiscardStatement>());
+ body->append(nullptr);
- Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+ Function f(Source{}, "func", params, &void_type, body,
FunctionDecorationList{});
- f.set_body(block);
+
EXPECT_FALSE(f.IsValid());
}
@@ -271,13 +270,12 @@
params.push_back(
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
- auto* block = create<BlockStatement>();
- block->append(create<DiscardStatement>());
- block->append(nullptr);
+ auto* body = create<BlockStatement>();
+ body->append(create<DiscardStatement>());
+ body->append(nullptr);
- Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+ Function f(Source{}, "func", params, &void_type, body,
FunctionDecorationList{});
- f.set_body(block);
EXPECT_FALSE(f.IsValid());
}
@@ -285,12 +283,10 @@
type::Void void_type;
type::I32 i32;
- auto* block = create<BlockStatement>();
- block->append(create<DiscardStatement>());
+ auto* body = create<BlockStatement>();
+ body->append(create<DiscardStatement>());
- Function f(Source{}, "func", {}, &void_type, create<BlockStatement>(),
- FunctionDecorationList{});
- f.set_body(block);
+ Function f(Source{}, "func", {}, &void_type, body, FunctionDecorationList{});
std::ostringstream out;
f.to_str(out, 2);
@@ -306,11 +302,11 @@
type::Void void_type;
type::I32 i32;
- auto* block = create<BlockStatement>();
- block->append(create<DiscardStatement>());
+ auto* body = create<BlockStatement>();
+ body->append(create<DiscardStatement>());
Function f(
- Source{}, "func", {}, &void_type, block,
+ Source{}, "func", {}, &void_type, body,
FunctionDecorationList{create<WorkgroupDecoration>(2, 4, 6, Source{})});
std::ostringstream out;
@@ -332,12 +328,11 @@
params.push_back(
create<Variable>(Source{}, "var", StorageClass::kNone, &i32));
- auto* block = create<BlockStatement>();
- block->append(create<DiscardStatement>());
+ auto* body = create<BlockStatement>();
+ body->append(create<DiscardStatement>());
- Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+ Function f(Source{}, "func", params, &void_type, body,
FunctionDecorationList{});
- f.set_body(block);
std::ostringstream out;
f.to_str(out, 2);
@@ -386,9 +381,8 @@
auto* body = create<BlockStatement>();
auto* stmt = create<DiscardStatement>();
body->append(stmt);
- Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+ Function f(Source{}, "func", params, &void_type, body,
FunctionDecorationList{});
- f.set_body(body);
EXPECT_EQ(f.get_last_statement(), stmt);
}
@@ -398,9 +392,8 @@
VariableList params;
auto* body = create<BlockStatement>();
- Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+ Function f(Source{}, "func", params, &void_type, body,
FunctionDecorationList{});
- f.set_body(body);
EXPECT_EQ(f.get_last_statement(), nullptr);
}
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index a2d90f7..d6daa3d 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -702,7 +702,8 @@
return true;
}
- if (!EmitFunctionDeclaration()) {
+ FunctionDeclaration decl;
+ if (!ParseFunctionDeclaration(&decl)) {
return false;
}
@@ -716,8 +717,12 @@
"element but has "
<< statements_stack_.size();
}
+
auto* body = statements_stack_[0].statements_;
- parser_impl_.get_module().functions().back()->set_body(body);
+ ast_module_.AddFunction(create<ast::Function>(
+ decl.source, decl.name, std::move(decl.params), decl.return_type, body,
+ std::move(decl.decorations)));
+
// Maintain the invariant by repopulating the one and only element.
statements_stack_.clear();
PushNewStatementBlock(constructs_[0].get(), 0, nullptr, nullptr, nullptr);
@@ -725,7 +730,7 @@
return success();
}
-bool FunctionEmitter::EmitFunctionDeclaration() {
+bool FunctionEmitter::ParseFunctionDeclaration(FunctionDeclaration* decl) {
if (failed()) {
return false;
}
@@ -774,11 +779,11 @@
if (ep_info_ != nullptr) {
decos.emplace_back(create<ast::StageDecoration>(ep_info_->stage, Source{}));
}
- auto* ast_fn =
- create<ast::Function>(Source{}, name, std::move(ast_params), ret_ty,
- create<ast::BlockStatement>(), std::move(decos));
- ast_module_.AddFunction(ast_fn);
+ decl->name = name;
+ decl->params = std::move(ast_params);
+ decl->return_type = ret_ty;
+ decl->decorations = std::move(decos);
return success();
}
@@ -4114,6 +4119,9 @@
return ast_module_.create<ast::BitcastExpression>(dest_type, texel_prefix);
}
+FunctionEmitter::FunctionDeclaration::FunctionDeclaration() = default;
+FunctionEmitter::FunctionDeclaration::~FunctionDeclaration() = default;
+
} // namespace spirv
} // namespace reader
} // namespace tint
diff --git a/src/reader/spirv/function.h b/src/reader/spirv/function.h
index 3bc36f2..d276a54 100644
--- a/src/reader/spirv/function.h
+++ b/src/reader/spirv/function.h
@@ -328,12 +328,6 @@
/// @returns the parser implementation
ParserImpl* parser() { return &parser_impl_; }
- /// Emits the declaration, which comprises the name, parameters, and
- /// return type. The function AST node is appended to the module
- /// AST node.
- /// @returns true if emission has not yet failed.
- bool EmitFunctionDeclaration();
-
/// Emits the function body, populating the bottom entry of the statements
/// stack.
/// @returns false if emission failed.
@@ -700,6 +694,31 @@
const spvtools::opt::Instruction& image_access);
private:
+ /// FunctionDeclaration contains the parsed information for a function header.
+ struct FunctionDeclaration {
+ /// Constructor
+ FunctionDeclaration();
+ /// Destructor
+ ~FunctionDeclaration();
+
+ /// Parsed header source
+ Source source;
+ /// Function name
+ std::string name;
+ /// Function parameters
+ ast::VariableList params;
+ /// Function return type
+ ast::type::Type* return_type;
+ /// Function decorations
+ ast::FunctionDecorationList decorations;
+ };
+
+ /// Parse the function declaration, which comprises the name, parameters, and
+ /// return type, populating `decl`.
+ /// @param decl the FunctionDeclaration to populate
+ /// @returns true if emission has not yet failed.
+ bool ParseFunctionDeclaration(FunctionDeclaration* decl);
+
/// @returns the store type for the OpVariable instruction, or
/// null on failure.
ast::type::Type* GetVariableStoreType(
diff --git a/src/reader/spirv/function_decl_test.cc b/src/reader/spirv/function_decl_test.cc
index ed1afb6..2223893 100644
--- a/src/reader/spirv/function_decl_test.cc
+++ b/src/reader/spirv/function_decl_test.cc
@@ -49,7 +49,7 @@
)";
}
-TEST_F(SpvParserTest, EmitFunctionDeclaration_VoidFunctionWithoutParams) {
+TEST_F(SpvParserTest, Emit_VoidFunctionWithoutParams) {
auto p = parser(test::Assemble(CommonTypes() + R"(
%100 = OpFunction %void None %voidfn
%entry = OpLabel
@@ -58,15 +58,20 @@
)"));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
- EXPECT_TRUE(fe.EmitFunctionDeclaration());
- EXPECT_THAT(p->module().to_str(), HasSubstr(R"(
+ EXPECT_TRUE(fe.Emit());
+ auto got = p->module().to_str();
+ auto* expect = R"(Module{
Function x_100 -> __void
()
{
- })"));
+ Return{}
+ }
+}
+)";
+ EXPECT_EQ(got, expect);
}
-TEST_F(SpvParserTest, EmitFunctionDeclaration_NonVoidResultType) {
+TEST_F(SpvParserTest, Emit_NonVoidResultType) {
auto p = parser(test::Assemble(CommonTypes() + R"(
%fn_ret_float = OpTypeFunction %float
%100 = OpFunction %float None %fn_ret_float
@@ -76,16 +81,25 @@
)"));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
- EXPECT_TRUE(fe.EmitFunctionDeclaration());
+ EXPECT_TRUE(fe.Emit());
- EXPECT_THAT(p->module().to_str(), HasSubstr(R"(
+ auto got = p->module().to_str();
+ auto* expect = R"(Module{
Function x_100 -> __f32
()
{
- })"));
+ Return{
+ {
+ ScalarConstructor[not set]{0.000000}
+ }
+ }
+ }
+}
+)";
+ EXPECT_EQ(got, expect);
}
-TEST_F(SpvParserTest, EmitFunctionDeclaration_MixedParamTypes) {
+TEST_F(SpvParserTest, Emit_MixedParamTypes) {
auto p = parser(test::Assemble(Names({"a", "b", "c"}) + CommonTypes() + R"(
%fn_mixed_params = OpTypeFunction %float %uint %float %int
@@ -99,9 +113,10 @@
)"));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
- EXPECT_TRUE(fe.EmitFunctionDeclaration());
+ EXPECT_TRUE(fe.Emit());
- EXPECT_THAT(p->module().to_str(), HasSubstr(R"(
+ auto got = p->module().to_str();
+ auto* expect = R"(Module{
Function x_100 -> __void
(
VariableConst{
@@ -121,10 +136,14 @@
}
)
{
- })"));
+ Return{}
+ }
+}
+)";
+ EXPECT_EQ(got, expect);
}
-TEST_F(SpvParserTest, EmitFunctionDeclaration_GenerateParamNames) {
+TEST_F(SpvParserTest, Emit_GenerateParamNames) {
auto p = parser(test::Assemble(CommonTypes() + R"(
%fn_mixed_params = OpTypeFunction %float %uint %float %int
@@ -138,9 +157,10 @@
)"));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
- EXPECT_TRUE(fe.EmitFunctionDeclaration());
+ EXPECT_TRUE(fe.Emit());
- EXPECT_THAT(p->module().to_str(), HasSubstr(R"(
+ auto got = p->module().to_str();
+ auto* expect = R"(Module{
Function x_100 -> __void
(
VariableConst{
@@ -160,7 +180,11 @@
}
)
{
- })"));
+ Return{}
+ }
+}
+)";
+ EXPECT_EQ(got, expect);
}
} // namespace
diff --git a/src/writer/spirv/builder_function_decoration_test.cc b/src/writer/spirv/builder_function_decoration_test.cc
index cb5da8a..b796d34 100644
--- a/src/writer/spirv/builder_function_decoration_test.cc
+++ b/src/writer/spirv/builder_function_decoration_test.cc
@@ -143,12 +143,6 @@
ast::type::F32 f32;
ast::type::Void void_type;
- ast::Function func(
- Source{}, "main", {}, &void_type, create<ast::BlockStatement>(),
- ast::FunctionDecorationList{
- create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
- });
-
auto* body = create<ast::BlockStatement>();
body->append(create<ast::AssignmentStatement>(
create<ast::IdentifierExpression>("my_out"),
@@ -160,7 +154,12 @@
body->append(create<ast::AssignmentStatement>(
create<ast::IdentifierExpression>("my_out"),
create<ast::IdentifierExpression>("my_in")));
- func.set_body(body);
+
+ ast::Function func(
+ Source{}, "main", {}, &void_type, body,
+ ast::FunctionDecorationList{
+ create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+ });
auto* v_in =
create<ast::Variable>(Source{}, "my_in", ast::StorageClass::kInput, &f32);