[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>
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 8fc397b..1e4a834 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -27,6 +27,7 @@
#include "src/ast/builtin_decoration.h"
#include "src/ast/call_expression.h"
#include "src/ast/case_statement.h"
+#include "src/ast/constant_id_decoration.h"
#include "src/ast/continue_statement.h"
#include "src/ast/discard_statement.h"
#include "src/ast/else_statement.h"
@@ -134,6 +135,7 @@
const char kBindingDecoration[] = "binding";
const char kBlockDecoration[] = "block";
const char kBuiltinDecoration[] = "builtin";
+const char kConstantIdDecoration[] = "constant_id";
const char kGroupDecoration[] = "group";
const char kLocationDecoration[] = "location";
const char kOffsetDecoration[] = "offset";
@@ -149,10 +151,10 @@
auto s = t.to_str();
return s == kAccessDecoration || s == kBindingDecoration ||
s == kBlockDecoration || s == kBuiltinDecoration ||
- s == kLocationDecoration || s == kOffsetDecoration ||
- s == kSetDecoration || s == kGroupDecoration ||
- s == kStageDecoration || s == kStrideDecoration ||
- s == kWorkgroupSizeDecoration;
+ s == kConstantIdDecoration || s == kLocationDecoration ||
+ s == kOffsetDecoration || s == kSetDecoration ||
+ s == kGroupDecoration || s == kStageDecoration ||
+ s == kStrideDecoration || s == kWorkgroupSizeDecoration;
}
/// Enter-exit counters for block token types.
@@ -323,7 +325,7 @@
return true;
}
- auto gc = global_constant_decl();
+ auto gc = global_constant_decl(decos.value);
if (gc.errored)
return Failure::kErrored;
@@ -441,8 +443,9 @@
}
// global_constant_decl
-// : CONST variable_ident_decl EQUAL const_expr
-Maybe<ast::Variable*> ParserImpl::global_constant_decl() {
+// : variable_decoration_list* CONST variable_ident_decl EQUAL const_expr
+Maybe<ast::Variable*> ParserImpl::global_constant_decl(
+ ast::DecorationList& decos) {
if (!match(Token::Type::kConst))
return Failure::kNoMatch;
@@ -459,6 +462,10 @@
if (init.errored)
return Failure::kErrored;
+ auto var_decos = cast_decorations<ast::VariableDecoration>(decos);
+ if (var_decos.errored)
+ return Failure::kErrored;
+
return create<ast::Variable>(
decl->source, // source
builder_.Symbols().Register(decl->name), // symbol
@@ -466,7 +473,7 @@
decl->type, // type
true, // is_const
init.value, // constructor
- ast::VariableDecorationList{}); // decorations
+ std::move(var_decos.value)); // decorations
}
// variable_decl
@@ -2939,6 +2946,17 @@
});
}
+ 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;
}
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index 56229b7..4105416 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -365,9 +365,11 @@
/// @returns the variable parsed or nullptr
/// @param decos the list of decorations for the variable declaration.
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
- 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
/// @returns the parsed variable declaration info
Maybe<VarDeclInfo> variable_decl();
diff --git a/src/reader/wgsl/parser_impl_global_constant_decl_test.cc b/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
index ca2b7f4..2025e3b 100644
--- a/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
@@ -26,7 +26,10 @@
TEST_F(ParserImplTest, GlobalConstantDecl) {
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_TRUE(e.matched);
EXPECT_FALSE(e.errored);
@@ -44,11 +47,16 @@
ASSERT_NE(e->constructor(), nullptr);
EXPECT_TRUE(e->constructor()->Is<ast::ConstructorExpression>());
+
+ EXPECT_FALSE(e.value->HasConstantIdDecoration());
}
TEST_F(ParserImplTest, GlobalConstantDecl_MissingEqual) {
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(e.errored);
EXPECT_FALSE(e.matched);
@@ -58,7 +66,10 @@
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
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(e.errored);
EXPECT_FALSE(e.matched);
@@ -68,7 +79,10 @@
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) {
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(e.errored);
EXPECT_FALSE(e.matched);
@@ -78,7 +92,10 @@
TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
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(e.errored);
EXPECT_FALSE(e.matched);
@@ -86,6 +103,66 @@
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 wgsl
} // namespace reader