[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 <jrprice@google.com>
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
James Price 2021-03-10 23:18:29 +00:00 committed by Commit Bot service account
parent f4c0d54423
commit 5c460bf2fc
3 changed files with 84 additions and 26 deletions

View File

@ -1263,40 +1263,54 @@ Maybe<ParserImpl::FunctionHeader> ParserImpl::function_header() {
// param_list
// :
// | (variable_ident_decl COMMA)* variable_ident_decl
// | (param COMMA)* param
Expect<ast::VariableList> 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<ast::Variable*> ParserImpl::expect_param() {
auto decos = decoration_list();
auto var_decos = cast_decorations<ast::VariableDecoration>(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<ast::Variable>(
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<ast::Variable>(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

View File

@ -419,6 +419,9 @@ class ParserImpl {
/// Parses a `param_list` grammar element, erroring on parse failure.
/// @returns the parsed variables
Expect<ast::VariableList> expect_param_list();
/// Parses a `param` grammar element, erroring on parse failure.
/// @returns the parsed variable
Expect<ast::Variable*> expect_param();
/// Parses a `pipeline_stage` grammar element, erroring if the next token does
/// not match a stage name.
/// @returns the pipeline stage.

View File

@ -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<f32>, "
"[[location(1)]] loc1 : f32");
auto* f32 = p->builder().create<type::F32>();
auto* vec4 = p->builder().create<type::Vector>(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<ast::BuiltinDecoration>());
EXPECT_EQ(decos0[0]->As<ast::BuiltinDecoration>()->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<ast::LocationDecoration>());
EXPECT_EQ(decos1[0]->As<ast::LocationDecoration>()->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