reader/wgsl: Parse atomic<T> types

Bug: tint:892
Change-Id: Ib6338ee78fccfca339f53c9074671f89bae1537f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/54645
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton 2021-06-17 15:48:39 +00:00 committed by Ben Clayton
parent 8c7f0da8c8
commit 989c3a1811
8 changed files with 101 additions and 2 deletions

View File

@ -474,6 +474,8 @@ Token Lexer::try_punctuation() {
Token Lexer::check_keyword(const Source& source, const std::string& str) { Token Lexer::check_keyword(const Source& source, const std::string& str) {
if (str == "array") if (str == "array")
return {Token::Type::kArray, source, "array"}; return {Token::Type::kArray, source, "array"};
if (str == "atomic")
return {Token::Type::kAtomic, source, "atomic"};
if (str == "bitcast") if (str == "bitcast")
return {Token::Type::kBitcast, source, "bitcast"}; return {Token::Type::kBitcast, source, "bitcast"};
if (str == "bool") if (str == "bool")

View File

@ -1063,8 +1063,13 @@ Maybe<ast::Type*> ParserImpl::type_decl(ast::DecorationList& decos) {
return expect_type_decl_vector(t); return expect_type_decl_vector(t);
} }
if (match(Token::Type::kPtr)) if (match(Token::Type::kPtr)) {
return expect_type_decl_pointer(t); return expect_type_decl_pointer(t);
}
if (match(Token::Type::kAtomic)) {
return expect_type_decl_atomic(t);
}
if (match(Token::Type::kArray, &source)) { if (match(Token::Type::kArray, &source)) {
return expect_type_decl_array(t, std::move(decos)); return expect_type_decl_array(t, std::move(decos));
@ -1136,6 +1141,17 @@ Expect<ast::Type*> ParserImpl::expect_type_decl_pointer(Token t) {
storage_class, access); storage_class, access);
} }
Expect<ast::Type*> ParserImpl::expect_type_decl_atomic(Token t) {
const char* use = "atomic declaration";
auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); });
if (subtype.errored) {
return Failure::kErrored;
}
return builder_.ty.atomic(make_source_range_from(t.source()), subtype.value);
}
Expect<ast::Type*> ParserImpl::expect_type_decl_vector(Token t) { Expect<ast::Type*> ParserImpl::expect_type_decl_vector(Token t) {
uint32_t count = 2; uint32_t count = 2;
if (t.IsVec3()) if (t.IsVec3())

View File

@ -843,6 +843,7 @@ class ParserImpl {
bool expect_decorations_consumed(const ast::DecorationList& list); bool expect_decorations_consumed(const ast::DecorationList& list);
Expect<ast::Type*> expect_type_decl_pointer(Token t); Expect<ast::Type*> expect_type_decl_pointer(Token t);
Expect<ast::Type*> expect_type_decl_atomic(Token t);
Expect<ast::Type*> expect_type_decl_vector(Token t); Expect<ast::Type*> expect_type_decl_vector(Token t);
Expect<ast::Type*> expect_type_decl_array(Token t, ast::DecorationList decos); Expect<ast::Type*> expect_type_decl_array(Token t, ast::DecorationList decos);
Expect<ast::Type*> expect_type_decl_matrix(Token t); Expect<ast::Type*> expect_type_decl_matrix(Token t);

View File

@ -1023,6 +1023,20 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingType) {
" ^\n"); " ^\n");
} }
TEST_F(ParserImplErrorTest, GlobalDeclVarAtomicMissingLessThan) {
EXPECT("var i : atomic;",
"test.wgsl:1:15 error: expected '<' for atomic declaration\n"
"var i : atomic;\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, GlobalDeclVarAtomicMissingGreaterThan) {
EXPECT("var i : atomic<u32 x;",
"test.wgsl:1:20 error: expected '>' for atomic declaration\n"
"var i : atomic<u32 x;\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, GlobalDeclVarStorageDeclInvalidClass) { TEST_F(ParserImplErrorTest, GlobalDeclVarStorageDeclInvalidClass) {
EXPECT("var<fish> i : i32", EXPECT("var<fish> i : i32",
"test.wgsl:1:5 error: invalid storage class for variable declaration\n" "test.wgsl:1:5 error: invalid storage class for variable declaration\n"

View File

@ -378,6 +378,68 @@ TEST_F(ParserImplTest, TypeDecl_Ptr_BadAccess) {
ASSERT_EQ(p->error(), "1:20: invalid value for access control"); ASSERT_EQ(p->error(), "1:20: invalid value for access control");
} }
TEST_F(ParserImplTest, TypeDecl_Atomic) {
auto p = parser("atomic<f32>");
auto t = p->type_decl();
EXPECT_TRUE(t.matched);
EXPECT_FALSE(t.errored);
ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(t.value->Is<ast::Atomic>());
auto* atomic = t.value->As<ast::Atomic>();
ASSERT_TRUE(atomic->type()->Is<ast::F32>());
EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 12u}}));
}
TEST_F(ParserImplTest, TypeDecl_Atomic_ToVec) {
auto p = parser("atomic<vec2<f32>>");
auto t = p->type_decl();
EXPECT_TRUE(t.matched);
EXPECT_FALSE(t.errored);
ASSERT_NE(t.value, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(t.value->Is<ast::Atomic>());
auto* atomic = t.value->As<ast::Atomic>();
ASSERT_TRUE(atomic->type()->Is<ast::Vector>());
auto* vec = atomic->type()->As<ast::Vector>();
ASSERT_EQ(vec->size(), 2u);
ASSERT_TRUE(vec->type()->Is<ast::F32>());
EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 18u}}));
}
TEST_F(ParserImplTest, TypeDecl_Atomic_MissingLessThan) {
auto p = parser("atomic f32>");
auto t = p->type_decl();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:8: expected '<' for atomic declaration");
}
TEST_F(ParserImplTest, TypeDecl_Atomic_MissingGreaterThan) {
auto p = parser("atomic<f32");
auto t = p->type_decl();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:11: expected '>' for atomic declaration");
}
TEST_F(ParserImplTest, TypeDecl_Atomic_MissingType) {
auto p = parser("atomic<>");
auto t = p->type_decl();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:8: invalid type for atomic declaration");
}
TEST_F(ParserImplTest, TypeDecl_Array) { TEST_F(ParserImplTest, TypeDecl_Array) {
auto p = parser("array<f32, 5>"); auto p = parser("array<f32, 5>");
auto t = p->type_decl(); auto t = p->type_decl();

View File

@ -109,6 +109,8 @@ std::string Token::TypeToName(Type type) {
case Token::Type::kArray: case Token::Type::kArray:
return "array"; return "array";
case Token::Type::kAtomic:
return "atomic";
case Token::Type::kBitcast: case Token::Type::kBitcast:
return "bitcast"; return "bitcast";
case Token::Type::kBool: case Token::Type::kBool:

View File

@ -117,6 +117,8 @@ class Token {
/// A 'array' /// A 'array'
kArray, kArray,
/// A 'atomic'
kAtomic,
/// A 'bitcast' /// A 'bitcast'
kBitcast, kBitcast,
/// A 'bool' /// A 'bool'

View File

@ -943,7 +943,7 @@ INSTANTIATE_TEST_SUITE_P(RenamerTestMsl,
// "array", // Also used in WGSL // "array", // Also used in WGSL
"array_ref", "array_ref",
"as_type", "as_type",
"atomic", // "atomic", // Also used in WGSL
"atomic_bool", "atomic_bool",
"atomic_int", "atomic_int",
"atomic_uint", "atomic_uint",