From 32a4f957b48934b1f6f179b697c26bbd2ab2292e Mon Sep 17 00:00:00 2001 From: David Neto Date: Mon, 22 Jun 2020 20:30:33 +0000 Subject: [PATCH] Add type alias unwrapping methods Change-Id: I8dbd3bba48ae95d76f75a5eba3e97ed4e091ed01 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23580 Reviewed-by: dan sinclair --- src/ast/expression.cc | 5 +-- src/ast/type/alias_type_test.cc | 57 +++++++++++++++++++++++++++++++++ src/ast/type/type.cc | 12 +++++++ src/ast/type/type.h | 15 +++++++++ src/type_determiner.cc | 6 +--- src/writer/spirv/builder.cc | 8 ++--- 6 files changed, 90 insertions(+), 13 deletions(-) diff --git a/src/ast/expression.cc b/src/ast/expression.cc index bbbc7ad124..c1c97656c9 100644 --- a/src/ast/expression.cc +++ b/src/ast/expression.cc @@ -38,10 +38,7 @@ Expression::~Expression() = default; 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 38d05b6d42..35b85f8e59 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 @@ TEST_F(AliasTypeTest, TypeName) { 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 a5b3ece70b..8475e9a4c8 100644 --- a/src/ast/type/type.cc +++ b/src/ast/type/type.cc @@ -43,6 +43,18 @@ Type* Type::UnwrapPtrIfNeeded() { 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 e368bad371..b7086aa068 100644 --- a/src/ast/type/type.h +++ b/src/ast/type/type.h @@ -69,6 +69,21 @@ class Type { /// @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 1a7dd00afb..d118b199e8 100644 --- a/src/type_determiner.cc +++ b/src/type_determiner.cc @@ -586,11 +586,7 @@ bool TypeDeterminer::DetermineMemberAccessor( } 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 586b0457a6..0157837cc3 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc @@ -642,10 +642,10 @@ bool Builder::GenerateArrayAccessor(ast::ArrayAccessorExpression* expr, 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.