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>
This commit is contained in:
Ben Clayton 2023-02-09 15:35:27 +00:00 committed by Ben Clayton
parent 0ddddb00cb
commit 031e2f5585
11 changed files with 551 additions and 2 deletions

View File

@ -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",

View File

@ -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

View File

@ -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 "<unknown>";
}

View File

@ -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<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 @@ 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<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 @@ class ResolvedIdentifier {
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

View File

@ -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<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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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<Case>;
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<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 @@ 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

View File

@ -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 @@ sem::Expression* Resolver::Identifier(const ast::IdentifierExpression* expr) {
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;

View File

@ -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<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>");

View File

@ -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

View File

@ -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_

View File

@ -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 @@ 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<sem::BuiltinEnumExpressionBase>(expr)) {
preserved_identifiers.Add(expr->identifier);
}
},
[&](const ast::CallExpression* call) {
if (auto* ident = call->target.name) {
Switch(