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:
parent
0ddddb00cb
commit
031e2f5585
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>";
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>");
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue