From 5c460bf2fc5887f3a9801c232ea104ba9ae1a039 Mon Sep 17 00:00:00 2001 From: James Price Date: Wed, 10 Mar 2021 23:18:29 +0000 Subject: [PATCH] [wgsl-reader] Add support for entry point parameters This just handles non-struct parameters for now. Structs will be handled in a later patch. Bug: tint:513 Change-Id: Idfb202a599fcd84400b89515f21bfed6fd3795b5 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44081 Commit-Queue: James Price Auto-Submit: James Price Reviewed-by: Ben Clayton --- src/reader/wgsl/parser_impl.cc | 66 +++++++++++-------- src/reader/wgsl/parser_impl.h | 3 + .../wgsl/parser_impl_param_list_test.cc | 41 ++++++++++++ 3 files changed, 84 insertions(+), 26 deletions(-) diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc index 420b528a18..6f8184ad41 100644 --- a/src/reader/wgsl/parser_impl.cc +++ b/src/reader/wgsl/parser_impl.cc @@ -1263,40 +1263,54 @@ Maybe ParserImpl::function_header() { // param_list // : -// | (variable_ident_decl COMMA)* variable_ident_decl +// | (param COMMA)* param Expect ParserImpl::expect_param_list() { - if (!peek().IsIdentifier()) // Empty list + // Check for an empty list. + auto t = peek(); + if (!t.IsIdentifier() && !t.IsAttrLeft()) { return ast::VariableList{}; + } + + ast::VariableList ret; + while (synchronized_) { + auto param = expect_param(); + if (param.errored) + return Failure::kErrored; + ret.push_back(param.value); + + if (!match(Token::Type::kComma)) + break; + } + + return ret; +} + +// param +// : decoration_list* variable_ident_decl +Expect ParserImpl::expect_param() { + auto decos = decoration_list(); + auto var_decos = cast_decorations(decos.value); + if (var_decos.errored) + return Failure::kErrored; auto decl = expect_variable_ident_decl("parameter"); if (decl.errored) return Failure::kErrored; - ast::VariableList ret; - for (;;) { - auto* var = create( - decl->source, // source - builder_.Symbols().Register(decl->name), // symbol - ast::StorageClass::kNone, // storage_class - decl->type, // type - true, // is_const - nullptr, // constructor - ast::VariableDecorationList{}); // decorations - // Formal parameters are treated like a const declaration where the - // initializer value is provided by the call's argument. The key point is - // that it's not updatable after intially set. This is unlike C or GLSL - // which treat formal parameters like local variables that can be updated. - ret.push_back(var); + auto* var = + create(decl->source, // source + builder_.Symbols().Register(decl->name), // symbol + ast::StorageClass::kNone, // storage_class + decl->type, // type + true, // is_const + nullptr, // constructor + std::move(var_decos.value)); // decorations + // Formal parameters are treated like a const declaration where the + // initializer value is provided by the call's argument. The key point is + // that it's not updatable after initially set. This is unlike C or GLSL + // which treat formal parameters like local variables that can be updated. - if (!match(Token::Type::kComma)) - break; - - decl = expect_variable_ident_decl("parameter"); - if (decl.errored) - return Failure::kErrored; - } - - return ret; + return var; } // pipeline_stage diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h index 7ac2169c89..2f3ba07eeb 100644 --- a/src/reader/wgsl/parser_impl.h +++ b/src/reader/wgsl/parser_impl.h @@ -419,6 +419,9 @@ class ParserImpl { /// Parses a `param_list` grammar element, erroring on parse failure. /// @returns the parsed variables Expect expect_param_list(); + /// Parses a `param` grammar element, erroring on parse failure. + /// @returns the parsed variable + Expect expect_param(); /// Parses a `pipeline_stage` grammar element, erroring if the next token does /// not match a stage name. /// @returns the pipeline stage. diff --git a/src/reader/wgsl/parser_impl_param_list_test.cc b/src/reader/wgsl/parser_impl_param_list_test.cc index d4ebd036bf..0bf7686420 100644 --- a/src/reader/wgsl/parser_impl_param_list_test.cc +++ b/src/reader/wgsl/parser_impl_param_list_test.cc @@ -95,6 +95,47 @@ TEST_F(ParserImplTest, ParamList_HangingComma) { EXPECT_EQ(p->error(), "1:9: expected identifier for parameter"); } +TEST_F(ParserImplTest, ParamList_Decorations) { + auto p = parser( + "[[builtin(frag_coord)]] coord : vec4, " + "[[location(1)]] loc1 : f32"); + + auto* f32 = p->builder().create(); + auto* vec4 = p->builder().create(f32, 4); + + auto e = p->expect_param_list(); + ASSERT_FALSE(p->has_error()) << p->error(); + ASSERT_FALSE(e.errored); + ASSERT_EQ(e.value.size(), 2u); + + EXPECT_EQ(e.value[0]->symbol(), p->builder().Symbols().Get("coord")); + EXPECT_EQ(e.value[0]->type(), vec4); + EXPECT_TRUE(e.value[0]->is_const()); + auto decos0 = e.value[0]->decorations(); + ASSERT_EQ(decos0.size(), 1u); + EXPECT_TRUE(decos0[0]->Is()); + EXPECT_EQ(decos0[0]->As()->value(), + ast::Builtin::kFragCoord); + + ASSERT_EQ(e.value[0]->source().range.begin.line, 1u); + ASSERT_EQ(e.value[0]->source().range.begin.column, 25u); + ASSERT_EQ(e.value[0]->source().range.end.line, 1u); + ASSERT_EQ(e.value[0]->source().range.end.column, 30u); + + EXPECT_EQ(e.value[1]->symbol(), p->builder().Symbols().Get("loc1")); + EXPECT_EQ(e.value[1]->type(), f32); + EXPECT_TRUE(e.value[1]->is_const()); + auto decos1 = e.value[1]->decorations(); + ASSERT_EQ(decos1.size(), 1u); + EXPECT_TRUE(decos1[0]->Is()); + EXPECT_EQ(decos1[0]->As()->value(), 1u); + + ASSERT_EQ(e.value[1]->source().range.begin.line, 1u); + ASSERT_EQ(e.value[1]->source().range.begin.column, 60u); + ASSERT_EQ(e.value[1]->source().range.end.line, 1u); + ASSERT_EQ(e.value[1]->source().range.end.column, 64u); +} + } // namespace } // namespace wgsl } // namespace reader