From 031e2f5585baa1e865806e1b01fc40977658e211 Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Thu, 9 Feb 2023 15:35:27 +0000 Subject: [PATCH] tint/resolver: Resolve builtin enumerators 'address space', 'access' and 'texel_format' Bug: tint:1810 Change-Id: If471912fcef57f7579d76c8c4edd663d1c0311ef Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/119125 Kokoro: Kokoro Reviewed-by: Dan Sinclair --- src/tint/BUILD.gn | 3 + src/tint/CMakeLists.txt | 2 + src/tint/resolver/dependency_graph.cc | 21 ++ src/tint/resolver/dependency_graph.h | 41 +++- src/tint/resolver/dependency_graph_test.cc | 255 +++++++++++++++++++++ src/tint/resolver/expression_kind_test.cc | 98 +++++++- src/tint/resolver/resolver.cc | 20 ++ src/tint/resolver/sem_helper.cc | 13 ++ src/tint/sem/builtin_enum_expression.cc | 27 +++ src/tint/sem/builtin_enum_expression.h | 67 ++++++ src/tint/transform/renamer.cc | 6 + 11 files changed, 551 insertions(+), 2 deletions(-) create mode 100644 src/tint/sem/builtin_enum_expression.cc create mode 100644 src/tint/sem/builtin_enum_expression.h diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn index f08b4ee825..574b275579 100644 --- a/src/tint/BUILD.gn +++ b/src/tint/BUILD.gn @@ -363,6 +363,7 @@ libtint_source_set("libtint_syntax_tree_src") { "sem/block_statement.h", "sem/break_if_statement.h", "sem/builtin.h", + "sem/builtin_enum_expression.h", "sem/builtin_type.h", "sem/call.h", "sem/call_target.h", @@ -755,6 +756,8 @@ libtint_source_set("libtint_sem_src") { "sem/break_if_statement.h", "sem/builtin.cc", "sem/builtin.h", + "sem/builtin_enum_expression.cc", + "sem/builtin_enum_expression.h", "sem/builtin_type.cc", "sem/builtin_type.h", "sem/call.cc", diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt index 46aa1c41fa..473e0ee590 100644 --- a/src/tint/CMakeLists.txt +++ b/src/tint/CMakeLists.txt @@ -325,6 +325,8 @@ list(APPEND TINT_LIB_SRCS sem/break_if_statement.h sem/builtin.cc sem/builtin.h + sem/builtin_enum_expression.cc + sem/builtin_enum_expression.h sem/call_target.cc sem/call_target.h sem/call.cc diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc index b77c81242e..61bb760ac7 100644 --- a/src/tint/resolver/dependency_graph.cc +++ b/src/tint/resolver/dependency_graph.cc @@ -488,6 +488,18 @@ class DependencyScanner { graph_.resolved_identifiers.Add(from, ResolvedIdentifier(builtin_ty)); return; } + if (auto addr = type::ParseAddressSpace(s); addr != type::AddressSpace::kUndefined) { + graph_.resolved_identifiers.Add(from, ResolvedIdentifier(addr)); + return; + } + if (auto fmt = type::ParseTexelFormat(s); fmt != type::TexelFormat::kUndefined) { + graph_.resolved_identifiers.Add(from, ResolvedIdentifier(fmt)); + return; + } + if (auto access = type::ParseAccess(s); access != type::Access::kUndefined) { + graph_.resolved_identifiers.Add(from, ResolvedIdentifier(access)); + return; + } UnknownSymbol(to, from->source, use); return; @@ -859,6 +871,15 @@ std::string ResolvedIdentifier::String(const SymbolTable& symbols, diag::List& d if (auto builtin_ty = BuiltinType(); builtin_ty != type::Builtin::kUndefined) { return "builtin type '" + utils::ToString(builtin_ty) + "'"; } + if (auto access = Access(); access != type::Access::kUndefined) { + return "access '" + utils::ToString(access) + "'"; + } + if (auto addr = AddressSpace(); addr != type::AddressSpace::kUndefined) { + return "address space '" + utils::ToString(addr) + "'"; + } + if (auto fmt = TexelFormat(); fmt != type::TexelFormat::kUndefined) { + return "texel format '" + utils::ToString(fmt) + "'"; + } TINT_UNREACHABLE(Resolver, diagnostics) << "unhandled ResolvedIdentifier"; return ""; } diff --git a/src/tint/resolver/dependency_graph.h b/src/tint/resolver/dependency_graph.h index dc262891f8..8b2e668a11 100644 --- a/src/tint/resolver/dependency_graph.h +++ b/src/tint/resolver/dependency_graph.h @@ -21,7 +21,9 @@ #include "src/tint/ast/module.h" #include "src/tint/diagnostic/diagnostic.h" #include "src/tint/sem/builtin_type.h" +#include "src/tint/type/access.h" #include "src/tint/type/builtin.h" +#include "src/tint/type/texel_format.h" #include "src/tint/utils/hashmap.h" namespace tint::resolver { @@ -32,7 +34,10 @@ namespace tint::resolver { /// - const ast::Variable* (as const ast::Node*) /// - const ast::Function* (as const ast::Node*) /// - sem::BuiltinType +/// - type::Access +/// - type::AddressSpace /// - type::Builtin +/// - type::TexelFormat class ResolvedIdentifier { public: ResolvedIdentifier() = default; @@ -62,6 +67,24 @@ class ResolvedIdentifier { return sem::BuiltinType::kNone; } + /// @return the access if the ResolvedIdentifier holds type::Access, otherwise + /// type::Access::kUndefined + type::Access Access() const { + if (auto n = std::get_if(&value_)) { + return *n; + } + return type::Access::kUndefined; + } + + /// @return the address space if the ResolvedIdentifier holds type::AddressSpace, otherwise + /// type::AddressSpace::kUndefined + type::AddressSpace AddressSpace() const { + if (auto n = std::get_if(&value_)) { + return *n; + } + return type::AddressSpace::kUndefined; + } + /// @return the builtin type if the ResolvedIdentifier holds type::Builtin, otherwise /// type::Builtin::kUndefined type::Builtin BuiltinType() const { @@ -71,6 +94,15 @@ class ResolvedIdentifier { return type::Builtin::kUndefined; } + /// @return the texel format if the ResolvedIdentifier holds type::TexelFormat, otherwise + /// type::TexelFormat::kUndefined + type::TexelFormat TexelFormat() const { + if (auto n = std::get_if(&value_)) { + return *n; + } + return type::TexelFormat::kUndefined; + } + /// @param value the value to compare the ResolvedIdentifier to /// @return true if the ResolvedIdentifier is equal to @p value template @@ -94,7 +126,14 @@ class ResolvedIdentifier { std::string String(const SymbolTable& symbols, diag::List& diagnostics) const; private: - std::variant value_; + std::variant + value_; }; /// DependencyGraph holds information about module-scope declaration dependency diff --git a/src/tint/resolver/dependency_graph_test.cc b/src/tint/resolver/dependency_graph_test.cc index 57e84f1c96..2953ade020 100644 --- a/src/tint/resolver/dependency_graph_test.cc +++ b/src/tint/resolver/dependency_graph_test.cc @@ -1324,6 +1324,261 @@ INSTANTIATE_TEST_SUITE_P(Functions, } // namespace resolve_to_builtin_type +//////////////////////////////////////////////////////////////////////////////// +// Resolve to type::Access tests +//////////////////////////////////////////////////////////////////////////////// +namespace resolve_to_access { + +using ResolverDependencyGraphResolveToAccess = + ResolverDependencyGraphTestWithParam>; + +TEST_P(ResolverDependencyGraphResolveToAccess, Resolve) { + const auto use = std::get<0>(GetParam()); + const auto name = std::get<1>(GetParam()); + const auto symbol = Symbols().New(name); + + SymbolTestHelper helper(this); + auto* ident = helper.Add(use, symbol); + helper.Build(); + + auto resolved = Build().resolved_identifiers.Get(ident); + ASSERT_TRUE(resolved); + EXPECT_EQ(resolved->Access(), type::ParseAccess(name)) + << resolved->String(Symbols(), Diagnostics()); +} + +TEST_P(ResolverDependencyGraphResolveToAccess, ShadowedByGlobalVar) { + const auto use = std::get<0>(GetParam()); + const auto builtin = std::get<1>(GetParam()); + const auto symbol = Symbols().New(utils::ToString(builtin)); + + SymbolTestHelper helper(this); + auto* decl = helper.Add(SymbolDeclKind::GlobalVar, symbol); + auto* ident = helper.Add(use, symbol); + helper.Build(); + + auto resolved = Build().resolved_identifiers.Get(ident); + ASSERT_TRUE(resolved); + EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics()); +} + +TEST_P(ResolverDependencyGraphResolveToAccess, ShadowedByStruct) { + const auto use = std::get<0>(GetParam()); + const auto builtin = std::get<1>(GetParam()); + const auto symbol = Symbols().New(utils::ToString(builtin)); + + SymbolTestHelper helper(this); + auto* decl = helper.Add(SymbolDeclKind::Struct, symbol); + auto* ident = helper.Add(use, symbol); + helper.Build(); + + auto resolved = Build().resolved_identifiers.Get(ident); + ASSERT_TRUE(resolved); + EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics()); +} + +TEST_P(ResolverDependencyGraphResolveToAccess, ShadowedByFunc) { + const auto use = std::get<0>(GetParam()); + const auto builtin = std::get<1>(GetParam()); + const auto symbol = Symbols().New(utils::ToString(builtin)); + + SymbolTestHelper helper(this); + auto* decl = helper.Add(SymbolDeclKind::Function, symbol); + auto* ident = helper.Add(use, symbol); + helper.Build(); + + auto resolved = Build().resolved_identifiers.Get(ident); + ASSERT_TRUE(resolved); + EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics()); +} + +INSTANTIATE_TEST_SUITE_P(Types, + ResolverDependencyGraphResolveToAccess, + testing::Combine(testing::ValuesIn(kTypeUseKinds), + testing::ValuesIn(type::kAccessStrings))); + +INSTANTIATE_TEST_SUITE_P(Values, + ResolverDependencyGraphResolveToAccess, + testing::Combine(testing::ValuesIn(kValueUseKinds), + testing::ValuesIn(type::kAccessStrings))); + +INSTANTIATE_TEST_SUITE_P(Functions, + ResolverDependencyGraphResolveToAccess, + testing::Combine(testing::ValuesIn(kFuncUseKinds), + testing::ValuesIn(type::kAccessStrings))); + +} // namespace resolve_to_access + +//////////////////////////////////////////////////////////////////////////////// +// Resolve to type::AddressSpace tests +//////////////////////////////////////////////////////////////////////////////// +namespace resolve_to_address_space { + +using ResolverDependencyGraphResolveToAddressSpace = + ResolverDependencyGraphTestWithParam>; + +TEST_P(ResolverDependencyGraphResolveToAddressSpace, Resolve) { + const auto use = std::get<0>(GetParam()); + const auto name = std::get<1>(GetParam()); + const auto symbol = Symbols().New(name); + + SymbolTestHelper helper(this); + auto* ident = helper.Add(use, symbol); + helper.Build(); + + auto resolved = Build().resolved_identifiers.Get(ident); + ASSERT_TRUE(resolved); + EXPECT_EQ(resolved->AddressSpace(), type::ParseAddressSpace(name)) + << resolved->String(Symbols(), Diagnostics()); +} + +TEST_P(ResolverDependencyGraphResolveToAddressSpace, ShadowedByGlobalVar) { + const auto use = std::get<0>(GetParam()); + const auto builtin = std::get<1>(GetParam()); + const auto symbol = Symbols().New(utils::ToString(builtin)); + + SymbolTestHelper helper(this); + auto* decl = helper.Add(SymbolDeclKind::GlobalVar, symbol); + auto* ident = helper.Add(use, symbol); + helper.Build(); + + auto resolved = Build().resolved_identifiers.Get(ident); + ASSERT_TRUE(resolved); + EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics()); +} + +TEST_P(ResolverDependencyGraphResolveToAddressSpace, ShadowedByStruct) { + const auto use = std::get<0>(GetParam()); + const auto builtin = std::get<1>(GetParam()); + const auto symbol = Symbols().New(utils::ToString(builtin)); + + SymbolTestHelper helper(this); + auto* decl = helper.Add(SymbolDeclKind::Struct, symbol); + auto* ident = helper.Add(use, symbol); + helper.Build(); + + auto resolved = Build().resolved_identifiers.Get(ident); + ASSERT_TRUE(resolved); + EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics()); +} + +TEST_P(ResolverDependencyGraphResolveToAddressSpace, ShadowedByFunc) { + const auto use = std::get<0>(GetParam()); + const auto builtin = std::get<1>(GetParam()); + const auto symbol = Symbols().New(utils::ToString(builtin)); + + SymbolTestHelper helper(this); + auto* decl = helper.Add(SymbolDeclKind::Function, symbol); + auto* ident = helper.Add(use, symbol); + helper.Build(); + + auto resolved = Build().resolved_identifiers.Get(ident); + ASSERT_TRUE(resolved); + EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics()); +} + +INSTANTIATE_TEST_SUITE_P(Types, + ResolverDependencyGraphResolveToAddressSpace, + testing::Combine(testing::ValuesIn(kTypeUseKinds), + testing::ValuesIn(type::kAddressSpaceStrings))); + +INSTANTIATE_TEST_SUITE_P(Values, + ResolverDependencyGraphResolveToAddressSpace, + testing::Combine(testing::ValuesIn(kValueUseKinds), + testing::ValuesIn(type::kAddressSpaceStrings))); + +INSTANTIATE_TEST_SUITE_P(Functions, + ResolverDependencyGraphResolveToAddressSpace, + testing::Combine(testing::ValuesIn(kFuncUseKinds), + testing::ValuesIn(type::kAddressSpaceStrings))); + +} // namespace resolve_to_address_space + +//////////////////////////////////////////////////////////////////////////////// +// Resolve to type::TexelFormat tests +//////////////////////////////////////////////////////////////////////////////// +namespace resolve_to_texel_format { + +using ResolverDependencyGraphResolveToTexelFormat = + ResolverDependencyGraphTestWithParam>; + +TEST_P(ResolverDependencyGraphResolveToTexelFormat, Resolve) { + const auto use = std::get<0>(GetParam()); + const auto name = std::get<1>(GetParam()); + const auto symbol = Symbols().New(name); + + SymbolTestHelper helper(this); + auto* ident = helper.Add(use, symbol); + helper.Build(); + + auto resolved = Build().resolved_identifiers.Get(ident); + ASSERT_TRUE(resolved); + EXPECT_EQ(resolved->TexelFormat(), type::ParseTexelFormat(name)) + << resolved->String(Symbols(), Diagnostics()); +} + +TEST_P(ResolverDependencyGraphResolveToTexelFormat, ShadowedByGlobalVar) { + const auto use = std::get<0>(GetParam()); + const auto builtin = std::get<1>(GetParam()); + const auto symbol = Symbols().New(utils::ToString(builtin)); + + SymbolTestHelper helper(this); + auto* decl = helper.Add(SymbolDeclKind::GlobalVar, symbol); + auto* ident = helper.Add(use, symbol); + helper.Build(); + + auto resolved = Build().resolved_identifiers.Get(ident); + ASSERT_TRUE(resolved); + EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics()); +} + +TEST_P(ResolverDependencyGraphResolveToTexelFormat, ShadowedByStruct) { + const auto use = std::get<0>(GetParam()); + const auto builtin = std::get<1>(GetParam()); + const auto symbol = Symbols().New(utils::ToString(builtin)); + + SymbolTestHelper helper(this); + auto* decl = helper.Add(SymbolDeclKind::Struct, symbol); + auto* ident = helper.Add(use, symbol); + helper.Build(); + + auto resolved = Build().resolved_identifiers.Get(ident); + ASSERT_TRUE(resolved); + EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics()); +} + +TEST_P(ResolverDependencyGraphResolveToTexelFormat, ShadowedByFunc) { + const auto use = std::get<0>(GetParam()); + const auto builtin = std::get<1>(GetParam()); + const auto symbol = Symbols().New(utils::ToString(builtin)); + + SymbolTestHelper helper(this); + auto* decl = helper.Add(SymbolDeclKind::Function, symbol); + auto* ident = helper.Add(use, symbol); + helper.Build(); + + auto resolved = Build().resolved_identifiers.Get(ident); + ASSERT_TRUE(resolved); + EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics()); +} + +INSTANTIATE_TEST_SUITE_P(Types, + ResolverDependencyGraphResolveToTexelFormat, + testing::Combine(testing::ValuesIn(kTypeUseKinds), + testing::ValuesIn(type::kTexelFormatStrings))); + +INSTANTIATE_TEST_SUITE_P(Values, + ResolverDependencyGraphResolveToTexelFormat, + testing::Combine(testing::ValuesIn(kValueUseKinds), + testing::ValuesIn(type::kTexelFormatStrings))); + +INSTANTIATE_TEST_SUITE_P(Functions, + ResolverDependencyGraphResolveToTexelFormat, + testing::Combine(testing::ValuesIn(kFuncUseKinds), + testing::ValuesIn(type::kTexelFormatStrings))); + +} // namespace resolve_to_texel_format + //////////////////////////////////////////////////////////////////////////////// // Shadowing tests //////////////////////////////////////////////////////////////////////////////// diff --git a/src/tint/resolver/expression_kind_test.cc b/src/tint/resolver/expression_kind_test.cc index e662570554..3a8568d259 100644 --- a/src/tint/resolver/expression_kind_test.cc +++ b/src/tint/resolver/expression_kind_test.cc @@ -23,16 +23,23 @@ namespace tint::resolver { namespace { enum class Def { + kAccess, + kAddressSpace, kBuiltinFunction, kBuiltinType, kFunction, kStruct, + kTexelFormat, kTypeAlias, kVariable, }; std::ostream& operator<<(std::ostream& out, Def def) { switch (def) { + case Def::kAccess: + return out << "Def::kAccess"; + case Def::kAddressSpace: + return out << "Def::kAddressSpace"; case Def::kBuiltinFunction: return out << "Def::kBuiltinFunction"; case Def::kBuiltinType: @@ -41,6 +48,8 @@ std::ostream& operator<<(std::ostream& out, Def def) { return out << "Def::kFunction"; case Def::kStruct: return out << "Def::kStruct"; + case Def::kTexelFormat: + return out << "Def::kTexelFormat"; case Def::kTypeAlias: return out << "Def::kTypeAlias"; case Def::kVariable: @@ -50,16 +59,23 @@ std::ostream& operator<<(std::ostream& out, Def def) { } enum class Use { + kAccess, + kAddressSpace, kCallExpr, kCallStmt, kFunctionReturnType, kMemberType, + kTexelFormat, kValueExpression, kVariableType, }; std::ostream& operator<<(std::ostream& out, Use use) { switch (use) { + case Use::kAccess: + return out << "Use::kAccess"; + case Use::kAddressSpace: + return out << "Use::kAddressSpace"; case Use::kCallExpr: return out << "Use::kCallExpr"; case Use::kCallStmt: @@ -68,6 +84,8 @@ std::ostream& operator<<(std::ostream& out, Use use) { return out << "Use::kFunctionReturnType"; case Use::kMemberType: return out << "Use::kMemberType"; + case Use::kTexelFormat: + return out << "Use::kTexelFormat"; case Use::kValueExpression: return out << "Use::kValueExpression"; case Use::kVariableType: @@ -96,6 +114,12 @@ using ResolverExpressionKindTest = ResolverTestWithParam; TEST_P(ResolverExpressionKindTest, Test) { Symbol sym; switch (GetParam().def) { + case Def::kAccess: + sym = Sym("read_write"); + break; + case Def::kAddressSpace: + sym = Sym("workgroup"); + break; case Def::kBuiltinFunction: sym = Sym("workgroupBarrier"); break; @@ -110,6 +134,9 @@ TEST_P(ResolverExpressionKindTest, Test) { Structure(kDefSource, "STRUCT", utils::Vector{Member("m", ty.i32())}); sym = Sym("STRUCT"); break; + case Def::kTexelFormat: + sym = Sym("rgba8unorm"); + break; case Def::kTypeAlias: Alias(kDefSource, "ALIAS", ty.i32()); sym = Sym("ALIAS"); @@ -121,6 +148,10 @@ TEST_P(ResolverExpressionKindTest, Test) { } switch (GetParam().use) { + case Use::kAccess: + return; // TODO(crbug.com/tint/1810) + case Use::kAddressSpace: + return; // TODO(crbug.com/tint/1810) case Use::kCallExpr: Func("f", utils::Empty, ty.void_(), Decl(Var("v", Call(Ident(kUseSource, sym))))); break; @@ -133,6 +164,8 @@ TEST_P(ResolverExpressionKindTest, Test) { case Use::kMemberType: Structure("s", utils::Vector{Member("m", ty(kUseSource, sym))}); break; + case Use::kTexelFormat: + return; // TODO(crbug.com/tint/1810) case Use::kValueExpression: GlobalVar("v", type::AddressSpace::kPrivate, Expr(kUseSource, sym)); break; @@ -154,26 +187,64 @@ INSTANTIATE_TEST_SUITE_P( , ResolverExpressionKindTest, testing::ValuesIn(std::vector{ + {Def::kAccess, Use::kAccess, kPass}, + {Def::kAccess, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, + {Def::kAccess, Use::kCallExpr, + R"(5:6 error: cannot use access 'read_write' as call target)"}, + {Def::kAccess, Use::kCallStmt, + R"(5:6 error: cannot use access 'read_write' as call target)"}, + {Def::kAccess, Use::kFunctionReturnType, + R"(5:6 error: cannot use access 'read_write' as type)"}, + {Def::kAccess, Use::kMemberType, R"(5:6 error: cannot use access 'read_write' as type)"}, + {Def::kAccess, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"}, + {Def::kAccess, Use::kValueExpression, + R"(5:6 error: cannot use access 'read_write' as value)"}, + {Def::kAccess, Use::kVariableType, R"(5:6 error: cannot use access 'read_write' as type)"}, + + {Def::kAddressSpace, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, + {Def::kAddressSpace, Use::kAddressSpace, kPass}, + {Def::kAddressSpace, Use::kCallExpr, + R"(5:6 error: cannot use address space 'workgroup' as call target)"}, + {Def::kAddressSpace, Use::kCallStmt, + R"(5:6 error: cannot use address space 'workgroup' as call target)"}, + {Def::kAddressSpace, Use::kFunctionReturnType, + R"(5:6 error: cannot use address space 'workgroup' as type)"}, + {Def::kAddressSpace, Use::kMemberType, + R"(5:6 error: cannot use address space 'workgroup' as type)"}, + {Def::kAddressSpace, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"}, + {Def::kAddressSpace, Use::kValueExpression, + R"(5:6 error: cannot use address space 'workgroup' as value)"}, + {Def::kAddressSpace, Use::kVariableType, + R"(5:6 error: cannot use address space 'workgroup' as type)"}, + + {Def::kBuiltinFunction, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, + {Def::kBuiltinFunction, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, {Def::kBuiltinFunction, Use::kCallStmt, kPass}, {Def::kBuiltinFunction, Use::kFunctionReturnType, R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"}, {Def::kBuiltinFunction, Use::kMemberType, R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"}, + {Def::kBuiltinFunction, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"}, {Def::kBuiltinFunction, Use::kValueExpression, R"(7:8 error: missing '(' for builtin function call)"}, {Def::kBuiltinFunction, Use::kVariableType, R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"}, + {Def::kBuiltinType, Use::kAccess, kPass}, + {Def::kBuiltinType, Use::kAddressSpace, kPass}, {Def::kBuiltinType, Use::kCallExpr, kPass}, {Def::kBuiltinType, Use::kCallStmt, kPass}, {Def::kBuiltinType, Use::kFunctionReturnType, kPass}, {Def::kBuiltinType, Use::kMemberType, kPass}, + {Def::kBuiltinType, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"}, {Def::kBuiltinType, Use::kValueExpression, R"(5:6 error: cannot use type 'vec4' as value 7:8 note: are you missing '()' for type initializer?)"}, {Def::kBuiltinType, Use::kVariableType, kPass}, {Def::kFunction, Use::kCallExpr, kPass}, + {Def::kFunction, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, + {Def::kFunction, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, {Def::kFunction, Use::kCallStmt, kPass}, {Def::kFunction, Use::kFunctionReturnType, R"(5:6 error: cannot use function 'FUNCTION' as type @@ -181,30 +252,54 @@ INSTANTIATE_TEST_SUITE_P( {Def::kFunction, Use::kMemberType, R"(5:6 error: cannot use function 'FUNCTION' as type 1:2 note: 'FUNCTION' declared here)"}, + {Def::kFunction, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"}, {Def::kFunction, Use::kValueExpression, R"(7:8 error: missing '(' for function call)"}, {Def::kFunction, Use::kVariableType, R"(5:6 error: cannot use function 'FUNCTION' as type 1:2 note: 'FUNCTION' declared here)"}, - {Def::kStruct, Use::kCallExpr, kPass}, + {Def::kStruct, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, + {Def::kStruct, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, {Def::kStruct, Use::kCallStmt, kPass}, {Def::kStruct, Use::kFunctionReturnType, kPass}, {Def::kStruct, Use::kMemberType, kPass}, + {Def::kStruct, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"}, {Def::kStruct, Use::kValueExpression, R"(5:6 error: cannot use type 'STRUCT' as value 7:8 note: are you missing '()' for type initializer? 1:2 note: 'STRUCT' declared here)"}, {Def::kStruct, Use::kVariableType, kPass}, + {Def::kTexelFormat, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, + {Def::kTexelFormat, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, + {Def::kTexelFormat, Use::kCallExpr, + R"(5:6 error: cannot use texel format 'rgba8unorm' as call target)"}, + {Def::kTexelFormat, Use::kCallStmt, + R"(5:6 error: cannot use texel format 'rgba8unorm' as call target)"}, + {Def::kTexelFormat, Use::kFunctionReturnType, + R"(5:6 error: cannot use texel format 'rgba8unorm' as type)"}, + {Def::kTexelFormat, Use::kMemberType, + R"(5:6 error: cannot use texel format 'rgba8unorm' as type)"}, + {Def::kTexelFormat, Use::kTexelFormat, kPass}, + {Def::kTexelFormat, Use::kValueExpression, + R"(5:6 error: cannot use texel format 'rgba8unorm' as value)"}, + {Def::kTexelFormat, Use::kVariableType, + R"(5:6 error: cannot use texel format 'rgba8unorm' as type)"}, + + {Def::kTypeAlias, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, + {Def::kTypeAlias, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, {Def::kTypeAlias, Use::kCallExpr, kPass}, {Def::kTypeAlias, Use::kCallStmt, kPass}, {Def::kTypeAlias, Use::kFunctionReturnType, kPass}, {Def::kTypeAlias, Use::kMemberType, kPass}, + {Def::kTypeAlias, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"}, {Def::kTypeAlias, Use::kValueExpression, R"(5:6 error: cannot use type 'i32' as value 7:8 note: are you missing '()' for type initializer?)"}, {Def::kTypeAlias, Use::kVariableType, kPass}, + {Def::kVariable, Use::kAccess, R"(TODO(crbug.com/tint/1810))"}, + {Def::kVariable, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"}, {Def::kVariable, Use::kCallStmt, R"(5:6 error: cannot use const 'VARIABLE' as call target 1:2 note: 'VARIABLE' declared here)"}, @@ -217,6 +312,7 @@ INSTANTIATE_TEST_SUITE_P( {Def::kVariable, Use::kMemberType, R"(5:6 error: cannot use const 'VARIABLE' as type 1:2 note: 'VARIABLE' declared here)"}, + {Def::kVariable, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"}, {Def::kVariable, Use::kValueExpression, kPass}, {Def::kVariable, Use::kVariableType, R"(5:6 error: cannot use const 'VARIABLE' as type diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc index 47338a3307..bb229d3f58 100644 --- a/src/tint/resolver/resolver.cc +++ b/src/tint/resolver/resolver.cc @@ -53,6 +53,7 @@ #include "src/tint/ast/workgroup_attribute.h" #include "src/tint/resolver/uniformity.h" #include "src/tint/sem/break_if_statement.h" +#include "src/tint/sem/builtin_enum_expression.h" #include "src/tint/sem/call.h" #include "src/tint/sem/for_loop_statement.h" #include "src/tint/sem/function.h" @@ -93,6 +94,10 @@ #include "src/tint/utils/transform.h" #include "src/tint/utils/vector.h" +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression); +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression); +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression); + namespace tint::resolver { namespace { @@ -2799,6 +2804,21 @@ sem::Expression* Resolver::Identifier(const ast::IdentifierExpression* expr) { return nullptr; } + if (auto access = resolved->Access(); access != type::Access::kUndefined) { + return builder_->create>(expr, current_statement_, + access); + } + + if (auto addr = resolved->AddressSpace(); addr != type::AddressSpace::kUndefined) { + return builder_->create>( + expr, current_statement_, addr); + } + + if (auto fmt = resolved->TexelFormat(); fmt != type::TexelFormat::kUndefined) { + return builder_->create>( + expr, current_statement_, fmt); + } + TINT_UNREACHABLE(Resolver, diagnostics_) << "unhandled resolved identifier: " << resolved->String(builder_->Symbols(), diagnostics_); return nullptr; diff --git a/src/tint/resolver/sem_helper.cc b/src/tint/resolver/sem_helper.cc index 2c11659058..bb769ab20d 100644 --- a/src/tint/resolver/sem_helper.cc +++ b/src/tint/resolver/sem_helper.cc @@ -14,6 +14,7 @@ #include "src/tint/resolver/sem_helper.h" +#include "src/tint/sem/builtin_enum_expression.h" #include "src/tint/sem/type_expression.h" #include "src/tint/sem/value_expression.h" @@ -50,6 +51,18 @@ void SemHelper::ErrorExpectedValueExpr(const sem::Expression* expr) const { AddNote("'" + name + "' declared here", str->Source()); } }, + [&](const sem::BuiltinEnumExpression* access) { + AddError("cannot use access '" + utils::ToString(access->Value()) + "' as value", + access->Declaration()->source); + }, + [&](const sem::BuiltinEnumExpression* addr) { + AddError("cannot use address space '" + utils::ToString(addr->Value()) + "' as value", + addr->Declaration()->source); + }, + [&](const sem::BuiltinEnumExpression* fmt) { + AddError("cannot use texel format '" + utils::ToString(fmt->Value()) + "' as value", + fmt->Declaration()->source); + }, [&](Default) { TINT_ICE(Resolver, builder_->Diagnostics()) << "unhandled sem::Expression type: " << (expr ? expr->TypeInfo().name : ""); diff --git a/src/tint/sem/builtin_enum_expression.cc b/src/tint/sem/builtin_enum_expression.cc new file mode 100644 index 0000000000..0e44220179 --- /dev/null +++ b/src/tint/sem/builtin_enum_expression.cc @@ -0,0 +1,27 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/tint/sem/builtin_enum_expression.h" + +TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpressionBase); + +namespace tint::sem { + +BuiltinEnumExpressionBase::BuiltinEnumExpressionBase(const ast::Expression* declaration, + const Statement* statement) + : Base(declaration, statement) {} + +BuiltinEnumExpressionBase::~BuiltinEnumExpressionBase() = default; + +} // namespace tint::sem diff --git a/src/tint/sem/builtin_enum_expression.h b/src/tint/sem/builtin_enum_expression.h new file mode 100644 index 0000000000..3a403fb44f --- /dev/null +++ b/src/tint/sem/builtin_enum_expression.h @@ -0,0 +1,67 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_TINT_SEM_BUILTIN_ENUM_EXPRESSION_H_ +#define SRC_TINT_SEM_BUILTIN_ENUM_EXPRESSION_H_ + +#include "src/tint/sem/expression.h" + +// Forward declarations +namespace tint::type { +class Type; +} // namespace tint::type + +namespace tint::sem { + +/// Base class for BuiltinEnumExpression. +/// Useful for Is() queries. +class BuiltinEnumExpressionBase : public Castable { + public: + /// Constructor + /// @param declaration the AST node + /// @param statement the statement that owns this expression + BuiltinEnumExpressionBase(const ast::Expression* declaration, const Statement* statement); + + /// Destructor + ~BuiltinEnumExpressionBase() override; +}; + +/// BuiltinEnumExpression holds the semantic information for expression nodes that resolve to a +/// builtin enumerator value. +template +class BuiltinEnumExpression + : public Castable, BuiltinEnumExpressionBase> { + public: + /// Constructor + /// @param declaration the AST node + /// @param statement the statement that owns this expression + /// @param value the enumerator value + BuiltinEnumExpression(const ast::Expression* declaration, + const Statement* statement, + ENUM value) + : BuiltinEnumExpression::Base(declaration, statement), value_(value) {} + + /// Destructor + ~BuiltinEnumExpression() override = default; + + /// @return the enumerator value + ENUM Value() const { return value_; } + + private: + const ENUM value_; +}; + +} // namespace tint::sem + +#endif // SRC_TINT_SEM_BUILTIN_ENUM_EXPRESSION_H_ diff --git a/src/tint/transform/renamer.cc b/src/tint/transform/renamer.cc index 3d4f450b30..ec8dcee970 100644 --- a/src/tint/transform/renamer.cc +++ b/src/tint/transform/renamer.cc @@ -18,6 +18,7 @@ #include #include "src/tint/program_builder.h" +#include "src/tint/sem/builtin_enum_expression.h" #include "src/tint/sem/call.h" #include "src/tint/sem/member_accessor_expression.h" #include "src/tint/sem/type_conversion.h" @@ -1292,6 +1293,11 @@ Transform::ApplyResult Renamer::Apply(const Program* src, preserved_identifiers.Add(diagnostic->control.rule_name); }, [&](const ast::TypeName* ty) { preserve_if_builtin_type(ty->name); }, + [&](const ast::IdentifierExpression* expr) { + if (src->Sem().Get(expr)) { + preserved_identifiers.Add(expr->identifier); + } + }, [&](const ast::CallExpression* call) { if (auto* ident = call->target.name) { Switch(