tint: Remove body_attributes param from ProgramBuilder::Func()

This belongs on Block(), not Func().

Also make Func() smarter about the `body` argument, allowing the caller
to pass an ast::BlockStatement*, ast::Statement* or nullptr.

Change-Id: I8ac6c1598b37f2a94615b452c5eb37671b4305fa
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/118982
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2023-02-07 21:28:09 +00:00
parent 1906857a50
commit 17aa653fa9
3 changed files with 115 additions and 79 deletions

View File

@ -48,6 +48,47 @@ TEST_F(FunctionTest, Creation_NoReturnType) {
EXPECT_EQ(f->params[0], var); EXPECT_EQ(f->params[0], var);
} }
TEST_F(FunctionTest, Creation_SingleParam) {
utils::Vector params{Param("var", ty.i32())};
auto* var = params[0];
auto* f = Func("func", params, ty.void_(), utils::Empty);
EXPECT_EQ(f->symbol, Symbols().Get("func"));
ASSERT_EQ(f->params.Length(), 1u);
EXPECT_EQ(f->return_type, nullptr);
EXPECT_EQ(f->params[0], var);
ASSERT_NE(f->body, nullptr);
ASSERT_EQ(f->body->statements.Length(), 0u);
}
TEST_F(FunctionTest, Creation_Body_Vector) {
auto* f = Func("func", utils::Empty, ty.void_(), utils::Vector{Discard(), Return()});
ASSERT_NE(f->body, nullptr);
ASSERT_EQ(f->body->statements.Length(), 2u);
EXPECT_TRUE(f->body->statements[0]->Is<ast::DiscardStatement>());
EXPECT_TRUE(f->body->statements[1]->Is<ast::ReturnStatement>());
}
TEST_F(FunctionTest, Creation_Body_Block) {
auto* f = Func("func", utils::Empty, ty.void_(), Block(Discard(), Return()));
ASSERT_NE(f->body, nullptr);
ASSERT_EQ(f->body->statements.Length(), 2u);
EXPECT_TRUE(f->body->statements[0]->Is<ast::DiscardStatement>());
EXPECT_TRUE(f->body->statements[1]->Is<ast::ReturnStatement>());
}
TEST_F(FunctionTest, Creation_Body_Stmt) {
auto* f = Func("func", utils::Empty, ty.void_(), Return());
ASSERT_NE(f->body, nullptr);
ASSERT_EQ(f->body->statements.Length(), 1u);
EXPECT_TRUE(f->body->statements[0]->Is<ast::ReturnStatement>());
}
TEST_F(FunctionTest, Creation_Body_Nullptr) {
auto* f = Func("func", utils::Empty, ty.void_(), nullptr);
EXPECT_EQ(f->body, nullptr);
}
TEST_F(FunctionTest, Creation_WithSource) { TEST_F(FunctionTest, Creation_WithSource) {
utils::Vector params{Param("var", ty.i32())}; utils::Vector params{Param("var", ty.i32())};

View File

@ -2491,58 +2491,60 @@ class ProgramBuilder {
return create<ast::BindingAttribute>(source, Expr(std::forward<EXPR>(value))); return create<ast::BindingAttribute>(source, Expr(std::forward<EXPR>(value)));
} }
/// Creates an ast::Function and registers it with the ast::Module.
/// @param name the function name
/// @param params the function parameters
/// @param type the function return type
/// @param body the function body. Can be an ast::BlockStatement*, as ast::Statement* which will
/// be automatically placed into a block, or nullptr for a stub function.
/// @param attributes the optional function attributes
/// @param return_type_attributes the optional function return type attributes
/// attributes
/// @returns the function pointer
template <typename NAME, typename BODY = utils::VectorRef<const ast::Statement*>>
const ast::Function* Func(
NAME&& name,
utils::VectorRef<const ast::Parameter*> params,
const ast::Type* type,
BODY&& body,
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
return Func(source_, std::forward<NAME>(name), std::move(params), type,
std::forward<BODY>(body), std::move(attributes),
std::move(return_type_attributes));
}
/// Creates an ast::Function and registers it with the ast::Module. /// Creates an ast::Function and registers it with the ast::Module.
/// @param source the source information /// @param source the source information
/// @param name the function name /// @param name the function name
/// @param params the function parameters /// @param params the function parameters
/// @param type the function return type /// @param type the function return type
/// @param body the function body /// @param body the function body. Can be an ast::BlockStatement*, as ast::Statement* which will
/// be automatically placed into a block, or nullptr for a stub function.
/// @param attributes the optional function attributes /// @param attributes the optional function attributes
/// @param return_type_attributes the optional function return type attributes /// @param return_type_attributes the optional function return type attributes
/// @param body_attributes the optional function body attributes
/// attributes /// attributes
/// @returns the function pointer /// @returns the function pointer
template <typename NAME> template <typename NAME, typename BODY = utils::VectorRef<const ast::Statement*>>
const ast::Function* Func( const ast::Function* Func(
const Source& source, const Source& source,
NAME&& name, NAME&& name,
utils::VectorRef<const ast::Parameter*> params, utils::VectorRef<const ast::Parameter*> params,
const ast::Type* type, const ast::Type* type,
utils::VectorRef<const ast::Statement*> body, BODY&& body,
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty, utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty, utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
utils::VectorRef<const ast::Attribute*> body_attributes = utils::Empty) { const ast::BlockStatement* block = nullptr;
auto* func = create<ast::Function>( using BODY_T = traits::PtrElTy<BODY>;
source, Sym(std::forward<NAME>(name)), std::move(params), type, if constexpr (traits::IsTypeOrDerived<BODY_T, ast::BlockStatement> ||
create<ast::BlockStatement>(std::move(body), std::move(body_attributes)), std::is_same_v<BODY_T, std::nullptr_t>) {
std::move(attributes), std::move(return_type_attributes)); block = body;
AST().AddFunction(func); } else {
return func; block = Block(std::forward<BODY>(body));
} }
auto* func =
/// Creates an ast::Function and registers it with the ast::Module. create<ast::Function>(source, Sym(std::forward<NAME>(name)), std::move(params), type,
/// @param name the function name block, std::move(attributes), std::move(return_type_attributes));
/// @param params the function parameters
/// @param type the function return type
/// @param body the function body
/// @param attributes the optional function attributes
/// @param return_type_attributes the optional function return type attributes
/// @param body_attributes the optional function body attributes
/// attributes
/// @returns the function pointer
template <typename NAME>
const ast::Function* Func(
NAME&& name,
utils::VectorRef<const ast::Parameter*> params,
const ast::Type* type,
utils::VectorRef<const ast::Statement*> body,
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty,
utils::VectorRef<const ast::Attribute*> body_attributes = utils::Empty) {
auto* func = create<ast::Function>(
Sym(std::forward<NAME>(name)), std::move(params), type,
create<ast::BlockStatement>(std::move(body), std::move(body_attributes)),
std::move(attributes), std::move(return_type_attributes));
AST().AddFunction(func); AST().AddFunction(func);
return func; return func;
} }
@ -2718,9 +2720,41 @@ class ProgramBuilder {
}); });
} }
/// Creates a ast::BlockStatement with input statements /// Creates a ast::BlockStatement with input statements and attributes
/// @param statements the statements of the block
/// @param attributes the optional attributes of the block
/// @returns the block statement pointer
const ast::BlockStatement* Block(
utils::VectorRef<const ast::Statement*> statements,
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
return Block(source_, std::move(statements), std::move(attributes));
}
/// Creates a ast::BlockStatement with input statements and attributes
/// @param source the source information for the block /// @param source the source information for the block
/// @param statements statements of block /// @param statements the statements of the block
/// @param attributes the optional attributes of the block
/// @returns the block statement pointer
const ast::BlockStatement* Block(
const Source& source,
utils::VectorRef<const ast::Statement*> statements,
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
return create<ast::BlockStatement>(source, std::move(statements), std::move(attributes));
}
/// Creates a ast::BlockStatement with a parameter list of input statements
/// @param statements the optional statements of the block
/// @returns the block statement pointer
template <typename... STATEMENTS,
typename = DisableIfSource<STATEMENTS...>,
typename = DisableIfVectorLike<STATEMENTS...>>
const ast::BlockStatement* Block(STATEMENTS&&... statements) {
return Block(source_, std::forward<STATEMENTS>(statements)...);
}
/// Creates a ast::BlockStatement with a parameter list of input statements
/// @param source the source information for the block
/// @param statements the optional statements of the block
/// @returns the block statement pointer /// @returns the block statement pointer
template <typename... STATEMENTS, typename = DisableIfVectorLike<STATEMENTS...>> template <typename... STATEMENTS, typename = DisableIfVectorLike<STATEMENTS...>>
const ast::BlockStatement* Block(const Source& source, STATEMENTS&&... statements) { const ast::BlockStatement* Block(const Source& source, STATEMENTS&&... statements) {
@ -2732,42 +2766,6 @@ class ProgramBuilder {
utils::Empty); utils::Empty);
} }
/// Creates a ast::BlockStatement with input statements
/// @param statements statements of block
/// @returns the block statement pointer
template <typename... STATEMENTS,
typename = DisableIfSource<STATEMENTS...>,
typename = DisableIfVectorLike<STATEMENTS...>>
const ast::BlockStatement* Block(STATEMENTS&&... statements) {
return create<ast::BlockStatement>(
utils::Vector<const ast::Statement*, sizeof...(statements)>{
std::forward<STATEMENTS>(statements)...,
},
utils::Empty);
}
/// Creates a ast::BlockStatement with input statements and attributes
/// @param source the source information for the block
/// @param statements statements of block
/// @param attributes the attributes
/// @returns the block statement pointer
const ast::BlockStatement* Block(
const Source& source,
utils::VectorRef<const ast::Statement*> statements,
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
return create<ast::BlockStatement>(source, std::move(statements), std::move(attributes));
}
/// Creates a ast::BlockStatement with input statements and attributes
/// @param statements statements of block
/// @param attributes the attributes
/// @returns the block statement pointer
const ast::BlockStatement* Block(
utils::VectorRef<const ast::Statement*> statements,
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
return create<ast::BlockStatement>(std::move(statements), std::move(attributes));
}
/// A wrapper type for the Else statement used to create If statements. /// A wrapper type for the Else statement used to create If statements.
struct ElseStmt { struct ElseStmt {
/// Default constructor - no else statement. /// Default constructor - no else statement.

View File

@ -1050,10 +1050,7 @@ TEST_P(BlockStatementTest, CompoundStatement) {
} }
TEST_P(BlockStatementTest, FunctionBody) { TEST_P(BlockStatementTest, FunctionBody) {
Func("foo", utils::Empty, ty.void_(), Func("foo", utils::Empty, ty.void_(),
utils::Vector{ Block(utils::Vector{Return()}, createAttributes({}, *this, GetParam().kind)));
Block(utils::Vector{Return()}),
},
utils::Empty, utils::Empty, createAttributes({}, *this, GetParam().kind));
Check(); Check();
} }
TEST_P(BlockStatementTest, IfStatementBody) { TEST_P(BlockStatementTest, IfStatementBody) {