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:
dan sinclair 2020-06-22 20:44:27 +00:00 committed by David Neto
parent 9c88ea5988
commit 5b853eebc6
8 changed files with 99 additions and 13 deletions

View File

@ -40,7 +40,7 @@ bool TypeConstructorExpression::IsTypeConstructor() const {
bool TypeConstructorExpression::IsValid() const { bool TypeConstructorExpression::IsValid() const {
if (values_.empty()) { if (values_.empty()) {
return false; return true;
} }
if (type_ == nullptr) { if (type_ == nullptr) {
return false; return false;

View File

@ -66,6 +66,14 @@ TEST_F(TypeConstructorExpressionTest, IsValid) {
EXPECT_TRUE(t.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) { TEST_F(TypeConstructorExpressionTest, IsValid_NullType) {
ExpressionList expr; ExpressionList expr;
expr.push_back(std::make_unique<IdentifierExpression>("expr")); expr.push_back(std::make_unique<IdentifierExpression>("expr"));
@ -94,14 +102,6 @@ TEST_F(TypeConstructorExpressionTest, IsValid_InvalidValue) {
EXPECT_FALSE(t.IsValid()); 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) { TEST_F(TypeConstructorExpressionTest, ToStr) {
type::F32Type f32; type::F32Type f32;
type::VectorType vec(&f32, 3); type::VectorType vec(&f32, 3);

View File

@ -1943,7 +1943,7 @@ ast::StatementList ParserImpl::continuing_stmt() {
// primary_expression // primary_expression
// : (IDENT NAMESPACE)* IDENT // : (IDENT NAMESPACE)* IDENT
// | type_decl PAREN_LEFT argument_expression_list PAREN_RIGHT // | type_decl PAREN_LEFT argument_expression_list* PAREN_RIGHT
// | const_literal // | const_literal
// | paren_rhs_stmt // | paren_rhs_stmt
// | CAST LESS_THAN type_decl GREATER_THAN 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; return nullptr;
} }
auto params = argument_expression_list(); t = peek();
if (has_error()) ast::ExpressionList params;
return nullptr; if (!t.IsParenRight() && !t.IsEof()) {
params = argument_expression_list();
if (has_error())
return nullptr;
}
t = next(); t = next();
if (!t.IsParenRight()) { if (!t.IsParenRight()) {

View File

@ -98,6 +98,18 @@ TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
EXPECT_EQ(ident->literal()->AsSint()->value(), 4); 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) { TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidTypeDecl) {
auto* p = parser("vec4<if>(2., 3., 4., 5.)"); auto* p = parser("vec4<if>(2., 3., 4., 5.)");
auto e = p->primary_expression(); auto e = p->primary_expression();

View File

@ -940,6 +940,12 @@ uint32_t Builder::GenerateTypeConstructorExpression(
return 0; 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(); auto* result_type = init->type()->UnwrapPtrIfNeeded();
if (result_type->IsVector()) { if (result_type->IsVector()) {
result_type = result_type->AsVector()->type(); result_type = result_type->AsVector()->type();

View File

@ -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) { TEST_F(BuilderTest, Assign_Var_Complex_ConstructorWithExtract) {
ast::type::F32Type f32; ast::type::F32Type f32;
ast::type::VectorType vec3(&f32, 3); ast::type::VectorType vec3(&f32, 3);

View File

@ -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) { TEST_F(BuilderTest, Constructor_Type_NonConstructorParam) {
ast::type::F32Type f32; ast::type::F32Type f32;
ast::type::VectorType vec(&f32, 2); ast::type::VectorType vec(&f32, 2);

View File

@ -15,6 +15,7 @@
[[location 0]] var<out> gl_FragColor : vec4<f32>; [[location 0]] var<out> gl_FragColor : vec4<f32>;
fn main() -> void { fn main() -> void {
var a : vec2<f32> = vec2<f32>();
gl_FragColor = vec4<f32>(0.4, 0.4, 0.8, 1.0); gl_FragColor = vec4<f32>(0.4, 0.4, 0.8, 1.0);
return; return;
} }