[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:
parent
f4c0d54423
commit
5c460bf2fc
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue