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);
}
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) {
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)));
}
/// 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.
/// @param source the source information
/// @param name the function name
/// @param params the function parameters
/// @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 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>
template <typename NAME, typename BODY = utils::VectorRef<const ast::Statement*>>
const ast::Function* Func(
const Source& source,
NAME&& name,
utils::VectorRef<const ast::Parameter*> params,
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*> return_type_attributes = utils::Empty,
utils::VectorRef<const ast::Attribute*> body_attributes = utils::Empty) {
auto* func = create<ast::Function>(
source, 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);
return func;
}
/// 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
/// @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));
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
const ast::BlockStatement* block = nullptr;
using BODY_T = traits::PtrElTy<BODY>;
if constexpr (traits::IsTypeOrDerived<BODY_T, ast::BlockStatement> ||
std::is_same_v<BODY_T, std::nullptr_t>) {
block = body;
} else {
block = Block(std::forward<BODY>(body));
}
auto* func =
create<ast::Function>(source, Sym(std::forward<NAME>(name)), std::move(params), type,
block, std::move(attributes), std::move(return_type_attributes));
AST().AddFunction(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 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
template <typename... STATEMENTS, typename = DisableIfVectorLike<STATEMENTS...>>
const ast::BlockStatement* Block(const Source& source, STATEMENTS&&... statements) {
@ -2732,42 +2766,6 @@ class ProgramBuilder {
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.
struct ElseStmt {
/// Default constructor - no else statement.

View File

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