Add type alias unwrapping methods Change-Id: I8dbd3bba48ae95d76f75a5eba3e97ed4e091ed01 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23580 Reviewed-by: dan sinclair <dsinclair@google.com>
diff --git a/src/ast/expression.cc b/src/ast/expression.cc index bbbc7ad..c1c9765 100644 --- a/src/ast/expression.cc +++ b/src/ast/expression.cc
@@ -38,10 +38,7 @@ void Expression::set_result_type(type::Type* type) { // The expression result should never be an alias type - while (type->IsAlias()) { - type = type->AsAlias()->type(); - } - result_type_ = type; + result_type_ = type->UnwrapAliasesIfNeeded(); } bool Expression::IsArrayAccessor() const {
diff --git a/src/ast/type/alias_type_test.cc b/src/ast/type/alias_type_test.cc index 38d05b6..35b85f8 100644 --- a/src/ast/type/alias_type_test.cc +++ b/src/ast/type/alias_type_test.cc
@@ -15,7 +15,9 @@ #include "src/ast/type/alias_type.h" #include "gtest/gtest.h" +#include "src/ast/storage_class.h" #include "src/ast/type/i32_type.h" +#include "src/ast/type/pointer_type.h" #include "src/ast/type/u32_type.h" namespace tint { @@ -54,6 +56,61 @@ EXPECT_EQ(at.type_name(), "__alias_Particle__i32"); } +TEST_F(AliasTypeTest, UnwrapAliasesIfNeeded) { + U32Type u32; + AliasType a{"a_type", &u32}; + EXPECT_EQ(a.name(), "a_type"); + EXPECT_EQ(a.type(), &u32); + EXPECT_EQ(a.UnwrapAliasesIfNeeded(), &u32); + EXPECT_EQ(u32.UnwrapAliasesIfNeeded(), &u32); +} + +TEST_F(AliasTypeTest, UnwrapAliasesIfNeeded_MultiLevel) { + U32Type u32; + AliasType a{"a_type", &u32}; + AliasType aa{"aa_type", &a}; + EXPECT_EQ(aa.name(), "aa_type"); + EXPECT_EQ(aa.type(), &a); + EXPECT_EQ(aa.UnwrapAliasesIfNeeded(), &u32); +} + +TEST_F(AliasTypeTest, UnwrapAliasPtrAlias_TwiceAliasPointerTwiceAlias) { + U32Type u32; + AliasType a{"a_type", &u32}; + AliasType aa{"aa_type", &a}; + PointerType paa{&aa, StorageClass::kUniform}; + AliasType apaa{"paa_type", &paa}; + AliasType aapaa{"aapaa_type", &apaa}; + EXPECT_EQ(aapaa.name(), "aapaa_type"); + EXPECT_EQ(aapaa.type(), &apaa); + EXPECT_EQ(aapaa.UnwrapAliasPtrAlias(), &u32); + EXPECT_EQ(u32.UnwrapAliasPtrAlias(), &u32); +} + +TEST_F(AliasTypeTest, + UnwrapAliasPtrAlias_SecondConsecutivePointerBlocksWUnrapping) { + U32Type u32; + AliasType a{"a_type", &u32}; + AliasType aa{"aa_type", &a}; + PointerType paa{&aa, StorageClass::kUniform}; + PointerType ppaa{&paa, StorageClass::kUniform}; + AliasType appaa{"appaa_type", &ppaa}; + EXPECT_EQ(appaa.UnwrapAliasPtrAlias(), &paa); +} + +TEST_F(AliasTypeTest, + UnwrapAliasPtrAlias_SecondNonConsecutivePointerBlocksWUnrapping) { + U32Type u32; + AliasType a{"a_type", &u32}; + AliasType aa{"aa_type", &a}; + PointerType paa{&aa, StorageClass::kUniform}; + AliasType apaa{"apaa_type", &paa}; + AliasType aapaa{"aapaa_type", &apaa}; + PointerType paapaa{&aapaa, StorageClass::kUniform}; + AliasType apaapaa{"apaapaa_type", &paapaa}; + EXPECT_EQ(apaapaa.UnwrapAliasPtrAlias(), &paa); +} + } // namespace } // namespace type } // namespace ast
diff --git a/src/ast/type/type.cc b/src/ast/type/type.cc index a5b3ece..8475e9a 100644 --- a/src/ast/type/type.cc +++ b/src/ast/type/type.cc
@@ -43,6 +43,18 @@ return this; } +Type* Type::UnwrapAliasesIfNeeded() { + auto* where = this; + while (where->IsAlias()) { + where = where->AsAlias()->type(); + } + return where; +} + +Type* Type::UnwrapAliasPtrAlias() { + return UnwrapAliasesIfNeeded()->UnwrapPtrIfNeeded()->UnwrapAliasesIfNeeded(); +} + bool Type::IsAlias() const { return false; }
diff --git a/src/ast/type/type.h b/src/ast/type/type.h index e368bad..b7086aa 100644 --- a/src/ast/type/type.h +++ b/src/ast/type/type.h
@@ -69,6 +69,21 @@ /// @returns the pointee type if this is a pointer, |this| otherwise Type* UnwrapPtrIfNeeded(); + /// Removes all levels of aliasing, if this is an alias type. Otherwise + /// returns |this|. This is just enough to assist with WGSL translation + /// in that you want see through one level of pointer to get from an + /// identifier-like expression as an l-value to its corresponding r-value, + /// plus see through the aliases on either side. + /// @returns the completely unaliased type. + Type* UnwrapAliasesIfNeeded(); + + /// Returns the type found after: + /// - removing all layers of aliasing if they exist, then + /// - removing the pointer, if it exists, then + /// - removing all further layers of aliasing, if they exist + /// @returns the unwrapped type + Type* UnwrapAliasPtrAlias(); + /// @returns true if this type is a float scalar bool is_float_scalar(); /// @returns true if this type is a float matrix
diff --git a/src/type_determiner.cc b/src/type_determiner.cc index 1a7dd00..d118b19 100644 --- a/src/type_determiner.cc +++ b/src/type_determiner.cc
@@ -586,11 +586,7 @@ } auto* res = expr->structure()->result_type(); - auto* data_type = res->UnwrapPtrIfNeeded(); - - while (data_type->IsAlias()) { - data_type = data_type->AsAlias()->type(); - } + auto* data_type = res->UnwrapPtrIfNeeded()->UnwrapAliasesIfNeeded(); ast::type::Type* ret = nullptr; if (data_type->IsStruct()) {
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc index 586b045..0157837 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc
@@ -642,10 +642,10 @@ bool Builder::GenerateMemberAccessor(ast::MemberAccessorExpression* expr, AccessorInfo* info) { - auto* data_type = expr->structure()->result_type()->UnwrapPtrIfNeeded(); - while (data_type->IsAlias()) { - data_type = data_type->AsAlias()->type(); - } + auto* data_type = expr->structure() + ->result_type() + ->UnwrapPtrIfNeeded() + ->UnwrapAliasesIfNeeded(); // If the data_type is a structure we're accessing a member, if it's a // vector we're accessing a swizzle.