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 <noreply+kokoro@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index f08b4ee..574b275 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -363,6 +363,7 @@
"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 @@
"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 46aa1c4..473e0ee 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -325,6 +325,8 @@
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 b77c812..61bb760 100644
--- a/src/tint/resolver/dependency_graph.cc
+++ b/src/tint/resolver/dependency_graph.cc
@@ -488,6 +488,18 @@
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 @@
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 "<unknown>";
}
diff --git a/src/tint/resolver/dependency_graph.h b/src/tint/resolver/dependency_graph.h
index dc26289..8b2e668 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 @@
/// - 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 @@
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<type::Access>(&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<type::AddressSpace>(&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 @@
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<type::TexelFormat>(&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 <typename T>
@@ -94,7 +126,14 @@
std::string String(const SymbolTable& symbols, diag::List& diagnostics) const;
private:
- std::variant<std::monostate, const ast::Node*, sem::BuiltinType, type::Builtin> value_;
+ std::variant<std::monostate,
+ const ast::Node*,
+ sem::BuiltinType,
+ type::Access,
+ type::AddressSpace,
+ type::Builtin,
+ type::TexelFormat>
+ 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 57e84f1..2953ade 100644
--- a/src/tint/resolver/dependency_graph_test.cc
+++ b/src/tint/resolver/dependency_graph_test.cc
@@ -1325,6 +1325,261 @@
} // namespace resolve_to_builtin_type
////////////////////////////////////////////////////////////////////////////////
+// Resolve to type::Access tests
+////////////////////////////////////////////////////////////////////////////////
+namespace resolve_to_access {
+
+using ResolverDependencyGraphResolveToAccess =
+ ResolverDependencyGraphTestWithParam<std::tuple<SymbolUseKind, const char*>>;
+
+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<std::tuple<SymbolUseKind, const char*>>;
+
+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<std::tuple<SymbolUseKind, const char*>>;
+
+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
////////////////////////////////////////////////////////////////////////////////
namespace shadowing {
diff --git a/src/tint/resolver/expression_kind_test.cc b/src/tint/resolver/expression_kind_test.cc
index e662570..3a8568d 100644
--- a/src/tint/resolver/expression_kind_test.cc
+++ b/src/tint/resolver/expression_kind_test.cc
@@ -23,16 +23,23 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
,
ResolverExpressionKindTest,
testing::ValuesIn(std::vector<Case>{
+ {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<f32>' 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 @@
{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 @@
{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 47338a3..bb229d3 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::type::Access>);
+TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::type::AddressSpace>);
+TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::type::TexelFormat>);
+
namespace tint::resolver {
namespace {
@@ -2799,6 +2804,21 @@
return nullptr;
}
+ if (auto access = resolved->Access(); access != type::Access::kUndefined) {
+ return builder_->create<sem::BuiltinEnumExpression<type::Access>>(expr, current_statement_,
+ access);
+ }
+
+ if (auto addr = resolved->AddressSpace(); addr != type::AddressSpace::kUndefined) {
+ return builder_->create<sem::BuiltinEnumExpression<type::AddressSpace>>(
+ expr, current_statement_, addr);
+ }
+
+ if (auto fmt = resolved->TexelFormat(); fmt != type::TexelFormat::kUndefined) {
+ return builder_->create<sem::BuiltinEnumExpression<type::TexelFormat>>(
+ 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 2c11659..bb769ab 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 @@
AddNote("'" + name + "' declared here", str->Source());
}
},
+ [&](const sem::BuiltinEnumExpression<type::Access>* access) {
+ AddError("cannot use access '" + utils::ToString(access->Value()) + "' as value",
+ access->Declaration()->source);
+ },
+ [&](const sem::BuiltinEnumExpression<type::AddressSpace>* addr) {
+ AddError("cannot use address space '" + utils::ToString(addr->Value()) + "' as value",
+ addr->Declaration()->source);
+ },
+ [&](const sem::BuiltinEnumExpression<type::TexelFormat>* 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 : "<null>");
diff --git a/src/tint/sem/builtin_enum_expression.cc b/src/tint/sem/builtin_enum_expression.cc
new file mode 100644
index 0000000..0e44220
--- /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 0000000..3a403fb
--- /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<BuiltinEnumExpressionBase, Expression> {
+ 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 <typename ENUM>
+class BuiltinEnumExpression
+ : public Castable<BuiltinEnumExpression<ENUM>, 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<ENUM>::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 3d4f450..ec8dcee 100644
--- a/src/tint/transform/renamer.cc
+++ b/src/tint/transform/renamer.cc
@@ -18,6 +18,7 @@
#include <utility>
#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 @@
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<sem::BuiltinEnumExpressionBase>(expr)) {
+ preserved_identifiers.Add(expr->identifier);
+ }
+ },
[&](const ast::CallExpression* call) {
if (auto* ident = call->target.name) {
Switch(