[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:
parent
3d20d49211
commit
a6ced4d0b4
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue