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 {
|
bool TypeConstructorExpression::IsValid() const {
|
||||||
if (values_.empty()) {
|
if (values_.empty()) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
if (type_ == nullptr) {
|
if (type_ == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue