Support the zero initializer syntax.
This Cl updates the system to allow zero initializers. This allows: ``` var a : vec3<f32> = vec3<f32>(); ``` Bug: tint:34 Change-Id: I84d6b431914c4ddf112ed375fae028d912f4a080 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23660 Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
parent
9c88ea5988
commit
5b853eebc6
|
@ -40,7 +40,7 @@ bool TypeConstructorExpression::IsTypeConstructor() const {
|
|||
|
||||
bool TypeConstructorExpression::IsValid() const {
|
||||
if (values_.empty()) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (type_ == nullptr) {
|
||||
return false;
|
||||
|
|
|
@ -66,6 +66,14 @@ TEST_F(TypeConstructorExpressionTest, IsValid) {
|
|||
EXPECT_TRUE(t.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(TypeConstructorExpressionTest, IsValid_EmptyValue) {
|
||||
type::F32Type f32;
|
||||
ExpressionList expr;
|
||||
|
||||
TypeConstructorExpression t(&f32, std::move(expr));
|
||||
EXPECT_TRUE(t.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(TypeConstructorExpressionTest, IsValid_NullType) {
|
||||
ExpressionList expr;
|
||||
expr.push_back(std::make_unique<IdentifierExpression>("expr"));
|
||||
|
@ -94,14 +102,6 @@ TEST_F(TypeConstructorExpressionTest, IsValid_InvalidValue) {
|
|||
EXPECT_FALSE(t.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(TypeConstructorExpressionTest, IsValid_EmptyValue) {
|
||||
type::F32Type f32;
|
||||
ExpressionList expr;
|
||||
|
||||
TypeConstructorExpression t(&f32, std::move(expr));
|
||||
EXPECT_FALSE(t.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(TypeConstructorExpressionTest, ToStr) {
|
||||
type::F32Type f32;
|
||||
type::VectorType vec(&f32, 3);
|
||||
|
|
|
@ -1943,7 +1943,7 @@ ast::StatementList ParserImpl::continuing_stmt() {
|
|||
|
||||
// primary_expression
|
||||
// : (IDENT NAMESPACE)* IDENT
|
||||
// | type_decl PAREN_LEFT argument_expression_list PAREN_RIGHT
|
||||
// | type_decl PAREN_LEFT argument_expression_list* PAREN_RIGHT
|
||||
// | const_literal
|
||||
// | paren_rhs_stmt
|
||||
// | CAST LESS_THAN type_decl GREATER_THAN paren_rhs_stmt
|
||||
|
@ -2043,9 +2043,13 @@ std::unique_ptr<ast::Expression> ParserImpl::primary_expression() {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
auto params = argument_expression_list();
|
||||
if (has_error())
|
||||
return nullptr;
|
||||
t = peek();
|
||||
ast::ExpressionList params;
|
||||
if (!t.IsParenRight() && !t.IsEof()) {
|
||||
params = argument_expression_list();
|
||||
if (has_error())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
t = next();
|
||||
if (!t.IsParenRight()) {
|
||||
|
|
|
@ -98,6 +98,18 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
|
|||
EXPECT_EQ(ident->literal()->AsSint()->value(), 4);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_ZeroConstructor) {
|
||||
auto* p = parser("vec4<i32>()");
|
||||
auto e = p->primary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsConstructor());
|
||||
ASSERT_TRUE(e->AsConstructor()->IsTypeConstructor());
|
||||
auto* ty = e->AsConstructor()->AsTypeConstructor();
|
||||
|
||||
ASSERT_EQ(ty->values().size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidTypeDecl) {
|
||||
auto* p = parser("vec4<if>(2., 3., 4., 5.)");
|
||||
auto e = p->primary_expression();
|
||||
|
|
|
@ -940,6 +940,12 @@ uint32_t Builder::GenerateTypeConstructorExpression(
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Generate the zero initializer if there are no values provided.
|
||||
if (init->values().empty()) {
|
||||
ast::NullLiteral nl(init->type()->UnwrapPtrIfNeeded());
|
||||
return GenerateLiteralIfNeeded(&nl);
|
||||
}
|
||||
|
||||
auto* result_type = init->type()->UnwrapPtrIfNeeded();
|
||||
if (result_type->IsVector()) {
|
||||
result_type = result_type->AsVector()->type();
|
||||
|
|
|
@ -78,6 +78,45 @@ TEST_F(BuilderTest, Assign_Var) {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(BuilderTest, Assign_Var_ZeroConstructor) {
|
||||
ast::type::F32Type f32;
|
||||
ast::type::VectorType vec(&f32, 3);
|
||||
|
||||
ast::Variable v("var", ast::StorageClass::kOutput, &vec);
|
||||
|
||||
auto ident = std::make_unique<ast::IdentifierExpression>("var");
|
||||
ast::ExpressionList vals;
|
||||
auto val =
|
||||
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
||||
|
||||
ast::AssignmentStatement assign(std::move(ident), std::move(val));
|
||||
|
||||
Context ctx;
|
||||
ast::Module mod;
|
||||
TypeDeterminer td(&ctx, &mod);
|
||||
td.RegisterVariableForTesting(&v);
|
||||
|
||||
ASSERT_TRUE(td.DetermineResultType(&assign)) << td.error();
|
||||
|
||||
Builder b(&mod);
|
||||
b.push_function(Function{});
|
||||
EXPECT_TRUE(b.GenerateGlobalVariable(&v)) << b.error();
|
||||
ASSERT_FALSE(b.has_error()) << b.error();
|
||||
|
||||
EXPECT_TRUE(b.GenerateAssignStatement(&assign)) << b.error();
|
||||
EXPECT_FALSE(b.has_error());
|
||||
|
||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
|
||||
%3 = OpTypeVector %4 3
|
||||
%2 = OpTypePointer Output %3
|
||||
%5 = OpConstantNull %3
|
||||
%1 = OpVariable %2 Output %5
|
||||
)");
|
||||
|
||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(OpStore %1 %5
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(BuilderTest, Assign_Var_Complex_ConstructorWithExtract) {
|
||||
ast::type::F32Type f32;
|
||||
ast::type::VectorType vec3(&f32, 3);
|
||||
|
|
|
@ -82,6 +82,30 @@ TEST_F(BuilderTest, Constructor_Type) {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(BuilderTest, Constructor_Type_ZeroInit) {
|
||||
ast::type::F32Type f32;
|
||||
ast::type::VectorType vec(&f32, 2);
|
||||
|
||||
ast::ExpressionList vals;
|
||||
ast::TypeConstructorExpression t(&vec, std::move(vals));
|
||||
|
||||
Context ctx;
|
||||
ast::Module mod;
|
||||
TypeDeterminer td(&ctx, &mod);
|
||||
EXPECT_TRUE(td.DetermineResultType(&t)) << td.error();
|
||||
|
||||
Builder b(&mod);
|
||||
b.push_function(Function{});
|
||||
|
||||
EXPECT_EQ(b.GenerateConstructorExpression(&t, false), 3u);
|
||||
ASSERT_FALSE(b.has_error()) << b.error();
|
||||
|
||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
|
||||
%1 = OpTypeVector %2 2
|
||||
%3 = OpConstantNull %1
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(BuilderTest, Constructor_Type_NonConstructorParam) {
|
||||
ast::type::F32Type f32;
|
||||
ast::type::VectorType vec(&f32, 2);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[[location 0]] var<out> gl_FragColor : vec4<f32>;
|
||||
|
||||
fn main() -> void {
|
||||
var a : vec2<f32> = vec2<f32>();
|
||||
gl_FragColor = vec4<f32>(0.4, 0.4, 0.8, 1.0);
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue