[wgsl-reader] Add support for constant_id decoration

Bug: tint:155
Change-Id: I207fd87d0708c66ea0fe7de81b156db98eea8e60
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/39560
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
James Price 2021-02-01 14:59:13 +00:00 committed by Commit Bot service account
parent 3d20d49211
commit a6ced4d0b4
3 changed files with 112 additions and 15 deletions

View File

@ -27,6 +27,7 @@
#include "src/ast/builtin_decoration.h" #include "src/ast/builtin_decoration.h"
#include "src/ast/call_expression.h" #include "src/ast/call_expression.h"
#include "src/ast/case_statement.h" #include "src/ast/case_statement.h"
#include "src/ast/constant_id_decoration.h"
#include "src/ast/continue_statement.h" #include "src/ast/continue_statement.h"
#include "src/ast/discard_statement.h" #include "src/ast/discard_statement.h"
#include "src/ast/else_statement.h" #include "src/ast/else_statement.h"
@ -134,6 +135,7 @@ const char kAccessDecoration[] = "access";
const char kBindingDecoration[] = "binding"; const char kBindingDecoration[] = "binding";
const char kBlockDecoration[] = "block"; const char kBlockDecoration[] = "block";
const char kBuiltinDecoration[] = "builtin"; const char kBuiltinDecoration[] = "builtin";
const char kConstantIdDecoration[] = "constant_id";
const char kGroupDecoration[] = "group"; const char kGroupDecoration[] = "group";
const char kLocationDecoration[] = "location"; const char kLocationDecoration[] = "location";
const char kOffsetDecoration[] = "offset"; const char kOffsetDecoration[] = "offset";
@ -149,10 +151,10 @@ bool is_decoration(Token t) {
auto s = t.to_str(); auto s = t.to_str();
return s == kAccessDecoration || s == kBindingDecoration || return s == kAccessDecoration || s == kBindingDecoration ||
s == kBlockDecoration || s == kBuiltinDecoration || s == kBlockDecoration || s == kBuiltinDecoration ||
s == kLocationDecoration || s == kOffsetDecoration || s == kConstantIdDecoration || s == kLocationDecoration ||
s == kSetDecoration || s == kGroupDecoration || s == kOffsetDecoration || s == kSetDecoration ||
s == kStageDecoration || s == kStrideDecoration || s == kGroupDecoration || s == kStageDecoration ||
s == kWorkgroupSizeDecoration; s == kStrideDecoration || s == kWorkgroupSizeDecoration;
} }
/// Enter-exit counters for block token types. /// Enter-exit counters for block token types.
@ -323,7 +325,7 @@ Expect<bool> ParserImpl::expect_global_decl() {
return true; return true;
} }
auto gc = global_constant_decl(); auto gc = global_constant_decl(decos.value);
if (gc.errored) if (gc.errored)
return Failure::kErrored; return Failure::kErrored;
@ -441,8 +443,9 @@ Maybe<ast::Variable*> ParserImpl::global_variable_decl(
} }
// global_constant_decl // global_constant_decl
// : CONST variable_ident_decl EQUAL const_expr // : variable_decoration_list* CONST variable_ident_decl EQUAL const_expr
Maybe<ast::Variable*> ParserImpl::global_constant_decl() { Maybe<ast::Variable*> ParserImpl::global_constant_decl(
ast::DecorationList& decos) {
if (!match(Token::Type::kConst)) if (!match(Token::Type::kConst))
return Failure::kNoMatch; return Failure::kNoMatch;
@ -459,6 +462,10 @@ Maybe<ast::Variable*> ParserImpl::global_constant_decl() {
if (init.errored) if (init.errored)
return Failure::kErrored; return Failure::kErrored;
auto var_decos = cast_decorations<ast::VariableDecoration>(decos);
if (var_decos.errored)
return Failure::kErrored;
return create<ast::Variable>( return create<ast::Variable>(
decl->source, // source decl->source, // source
builder_.Symbols().Register(decl->name), // symbol builder_.Symbols().Register(decl->name), // symbol
@ -466,7 +473,7 @@ Maybe<ast::Variable*> ParserImpl::global_constant_decl() {
decl->type, // type decl->type, // type
true, // is_const true, // is_const
init.value, // constructor init.value, // constructor
ast::VariableDecorationList{}); // decorations std::move(var_decos.value)); // decorations
} }
// variable_decl // variable_decl
@ -2939,6 +2946,17 @@ Maybe<ast::Decoration*> ParserImpl::decoration() {
}); });
} }
if (s == kConstantIdDecoration) {
const char* use = "constant_id decoration";
return expect_paren_block(use, [&]() -> Result {
auto val = expect_positive_sint(use);
if (val.errored)
return Failure::kErrored;
return create<ast::ConstantIdDecoration>(t.source(), val.value);
});
}
return Failure::kNoMatch; return Failure::kNoMatch;
} }

View File

@ -365,9 +365,11 @@ class ParserImpl {
/// @returns the variable parsed or nullptr /// @returns the variable parsed or nullptr
/// @param decos the list of decorations for the variable declaration. /// @param decos the list of decorations for the variable declaration.
Maybe<ast::Variable*> global_variable_decl(ast::DecorationList& decos); Maybe<ast::Variable*> global_variable_decl(ast::DecorationList& decos);
/// Parses a `global_constant_decl` grammar element /// Parses a `global_constant_decl` grammar element with the initial
/// `variable_decoration_list*` provided as `decos`
/// @returns the const object or nullptr /// @returns the const object or nullptr
Maybe<ast::Variable*> global_constant_decl(); /// @param decos the list of decorations for the constant declaration.
Maybe<ast::Variable*> global_constant_decl(ast::DecorationList& decos);
/// Parses a `variable_decl` grammar element /// Parses a `variable_decl` grammar element
/// @returns the parsed variable declaration info /// @returns the parsed variable declaration info
Maybe<VarDeclInfo> variable_decl(); Maybe<VarDeclInfo> variable_decl();

View File

@ -26,7 +26,10 @@ namespace {
TEST_F(ParserImplTest, GlobalConstantDecl) { TEST_F(ParserImplTest, GlobalConstantDecl) {
auto p = parser("const a : f32 = 1."); auto p = parser("const a : f32 = 1.");
auto e = p->global_constant_decl(); auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
EXPECT_FALSE(decos.matched);
auto e = p->global_constant_decl(decos.value);
EXPECT_FALSE(p->has_error()) << p->error(); EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_TRUE(e.matched); EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored); EXPECT_FALSE(e.errored);
@ -44,11 +47,16 @@ TEST_F(ParserImplTest, GlobalConstantDecl) {
ASSERT_NE(e->constructor(), nullptr); ASSERT_NE(e->constructor(), nullptr);
EXPECT_TRUE(e->constructor()->Is<ast::ConstructorExpression>()); EXPECT_TRUE(e->constructor()->Is<ast::ConstructorExpression>());
EXPECT_FALSE(e.value->HasConstantIdDecoration());
} }
TEST_F(ParserImplTest, GlobalConstantDecl_MissingEqual) { TEST_F(ParserImplTest, GlobalConstantDecl_MissingEqual) {
auto p = parser("const a: f32 1."); auto p = parser("const a: f32 1.");
auto e = p->global_constant_decl(); auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
EXPECT_FALSE(decos.matched);
auto e = p->global_constant_decl(decos.value);
EXPECT_TRUE(p->has_error()); EXPECT_TRUE(p->has_error());
EXPECT_TRUE(e.errored); EXPECT_TRUE(e.errored);
EXPECT_FALSE(e.matched); EXPECT_FALSE(e.matched);
@ -58,7 +66,10 @@ TEST_F(ParserImplTest, GlobalConstantDecl_MissingEqual) {
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) { TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
auto p = parser("const a: invalid = 1."); auto p = parser("const a: invalid = 1.");
auto e = p->global_constant_decl(); auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
EXPECT_FALSE(decos.matched);
auto e = p->global_constant_decl(decos.value);
EXPECT_TRUE(p->has_error()); EXPECT_TRUE(p->has_error());
EXPECT_TRUE(e.errored); EXPECT_TRUE(e.errored);
EXPECT_FALSE(e.matched); EXPECT_FALSE(e.matched);
@ -68,7 +79,10 @@ TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) { TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) {
auto p = parser("const a: f32 = if (a) {}"); auto p = parser("const a: f32 = if (a) {}");
auto e = p->global_constant_decl(); auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
EXPECT_FALSE(decos.matched);
auto e = p->global_constant_decl(decos.value);
EXPECT_TRUE(p->has_error()); EXPECT_TRUE(p->has_error());
EXPECT_TRUE(e.errored); EXPECT_TRUE(e.errored);
EXPECT_FALSE(e.matched); EXPECT_FALSE(e.matched);
@ -78,7 +92,10 @@ TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) {
TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) { TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
auto p = parser("const a: f32 ="); auto p = parser("const a: f32 =");
auto e = p->global_constant_decl(); auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
EXPECT_FALSE(decos.matched);
auto e = p->global_constant_decl(decos.value);
EXPECT_TRUE(p->has_error()); EXPECT_TRUE(p->has_error());
EXPECT_TRUE(e.errored); EXPECT_TRUE(e.errored);
EXPECT_FALSE(e.matched); EXPECT_FALSE(e.matched);
@ -86,6 +103,66 @@ TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
EXPECT_EQ(p->error(), "1:15: unable to parse const literal"); EXPECT_EQ(p->error(), "1:15: unable to parse const literal");
} }
TEST_F(ParserImplTest, GlobalConstantDec_ConstantId) {
auto p = parser("[[constant_id(7)]] const a : f32 = 1.");
auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
EXPECT_TRUE(decos.matched);
auto e = p->global_constant_decl(decos.value);
EXPECT_FALSE(p->has_error()) << p->error();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
ASSERT_NE(e.value, nullptr);
EXPECT_TRUE(e->is_const());
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
ASSERT_NE(e->type(), nullptr);
EXPECT_TRUE(e->type()->Is<type::F32>());
EXPECT_EQ(e->source().range.begin.line, 1u);
EXPECT_EQ(e->source().range.begin.column, 26u);
EXPECT_EQ(e->source().range.end.line, 1u);
EXPECT_EQ(e->source().range.end.column, 27u);
ASSERT_NE(e->constructor(), nullptr);
EXPECT_TRUE(e->constructor()->Is<ast::ConstructorExpression>());
EXPECT_TRUE(e.value->HasConstantIdDecoration());
EXPECT_EQ(e.value->constant_id(), 7u);
}
TEST_F(ParserImplTest, GlobalConstantDec_ConstantId_Missing) {
auto p = parser("[[constant_id()]] const a : f32 = 1.");
auto decos = p->decoration_list();
EXPECT_TRUE(decos.errored);
EXPECT_FALSE(decos.matched);
auto e = p->global_constant_decl(decos.value);
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
ASSERT_NE(e.value, nullptr);
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(),
"1:15: expected signed integer literal for constant_id decoration");
}
TEST_F(ParserImplTest, GlobalConstantDec_ConstantId_Invalid) {
auto p = parser("[[constant_id(-7)]] const a : f32 = 1.");
auto decos = p->decoration_list();
EXPECT_TRUE(decos.errored);
EXPECT_FALSE(decos.matched);
auto e = p->global_constant_decl(decos.value);
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
ASSERT_NE(e.value, nullptr);
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:15: constant_id decoration must be positive");
}
} // namespace } // namespace
} // namespace wgsl } // namespace wgsl
} // namespace reader } // namespace reader