Add semantic::MemberAccessorExpression, use it. Pull the mutable 'is_swizzled' semantic field from ast::MemberAccessorExpression and into a new semantic::MemberAccessorExpression node. Have the TypeDeterminer create these semantic::MemberAccessorExpression nodes. Bug: tint:390 Change-Id: I8fc6e36dabb417190528536a94d027af54059222 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/40142 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: David Neto <dneto@google.com>
diff --git a/BUILD.gn b/BUILD.gn index 7a14689..5e3dbff 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -386,6 +386,7 @@ "src/semantic/sem_expression.cc", "src/semantic/sem_function.cc", "src/semantic/sem_info.cc", + "src/semantic/sem_member_accessor_expression.cc", "src/semantic/sem_node.cc", "src/semantic/sem_variable.cc", "src/semantic/type_mappings.h",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d9a15f7..3b417f0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt
@@ -198,6 +198,7 @@ semantic/node.h semantic/sem_call.cc semantic/sem_expression.cc + semantic/sem_member_accessor_expression.cc semantic/sem_function.cc semantic/sem_info.cc semantic/sem_node.cc
diff --git a/src/ast/member_accessor_expression.h b/src/ast/member_accessor_expression.h index 5657e09..3e6fd9b 100644 --- a/src/ast/member_accessor_expression.h +++ b/src/ast/member_accessor_expression.h
@@ -45,12 +45,6 @@ /// @returns the member expression IdentifierExpression* member() const { return member_; } - /// Sets the identifier as a swizzle - void SetIsSwizzle() { is_swizzle_ = true; } - - /// @returns true if this is a swizzle identifier - bool IsSwizzle() const { return is_swizzle_; } - /// Clones this node and all transitive child nodes using the `CloneContext` /// `ctx`. /// @note Semantic information such as resolved expression type and intrinsic @@ -75,8 +69,6 @@ Expression* const struct_; IdentifierExpression* const member_; - - bool is_swizzle_ = false; // Semantic info }; } // namespace ast
diff --git a/src/semantic/member_accessor_expression.h b/src/semantic/member_accessor_expression.h new file mode 100644 index 0000000..7b21f97 --- /dev/null +++ b/src/semantic/member_accessor_expression.h
@@ -0,0 +1,43 @@ +// Copyright 2021 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_SEMANTIC_MEMBER_ACCESSOR_EXPRESSION_H_ +#define SRC_SEMANTIC_MEMBER_ACCESSOR_EXPRESSION_H_ + +#include "src/semantic/expression.h" + +namespace tint { +namespace semantic { + +/// MemberAccessorExpression holds the semantic information for a +/// ast::MemberAccessorExpression node. +class MemberAccessorExpression + : public Castable<MemberAccessorExpression, Expression> { + public: + /// Constructor + /// @param type the resolved type of the expression + /// @param is_swizzle true if this member access is for a vector swizzle + MemberAccessorExpression(type::Type* type, bool is_swizzle); + + /// @return true if this member access is for a vector swizzle + bool IsSwizzle() const { return is_swizzle_; } + + private: + bool const is_swizzle_; +}; + +} // namespace semantic +} // namespace tint + +#endif // SRC_SEMANTIC_MEMBER_ACCESSOR_EXPRESSION_H_
diff --git a/src/semantic/sem_member_accessor_expression.cc b/src/semantic/sem_member_accessor_expression.cc new file mode 100644 index 0000000..1145a23 --- /dev/null +++ b/src/semantic/sem_member_accessor_expression.cc
@@ -0,0 +1,27 @@ +// Copyright 2021 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/semantic/member_accessor_expression.h" + +TINT_INSTANTIATE_CLASS_ID(tint::semantic::MemberAccessorExpression); + +namespace tint { +namespace semantic { + +MemberAccessorExpression::MemberAccessorExpression(type::Type* type, + bool is_swizzle) + : Base(type), is_swizzle_(is_swizzle) {} + +} // namespace semantic +} // namespace tint
diff --git a/src/semantic/type_mappings.h b/src/semantic/type_mappings.h index 95c7fff..36ad538 100644 --- a/src/semantic/type_mappings.h +++ b/src/semantic/type_mappings.h
@@ -25,6 +25,7 @@ class CallExpression; class Expression; class Function; +class MemberAccessorExpression; class Variable; } // namespace ast @@ -34,6 +35,7 @@ class Call; class Expression; class Function; +class MemberAccessorExpression; class Variable; /// TypeMappings is a struct that holds dummy `operator()` methods that's used @@ -47,6 +49,8 @@ semantic::Function* operator()(ast::Function*); semantic::Variable* operator()(ast::Variable*); semantic::Call* operator()(ast::CallExpression*); + semantic::MemberAccessorExpression* operator()( + ast::MemberAccessorExpression*); //! @endcond };
diff --git a/src/type_determiner.cc b/src/type_determiner.cc index bcc55fc..d876ebb 100644 --- a/src/type_determiner.cc +++ b/src/type_determiner.cc
@@ -46,6 +46,7 @@ #include "src/semantic/expression.h" #include "src/semantic/function.h" #include "src/semantic/intrinsic.h" +#include "src/semantic/member_accessor_expression.h" #include "src/semantic/variable.h" #include "src/type/array_type.h" #include "src/type/bool_type.h" @@ -1006,6 +1007,8 @@ auto* data_type = res->UnwrapPtrIfNeeded()->UnwrapIfNeeded(); type::Type* ret = nullptr; + bool is_swizzle = false; + if (auto* ty = data_type->As<type::Struct>()) { auto* strct = ty->impl(); auto symbol = expr->member()->symbol(); @@ -1029,7 +1032,7 @@ ret = builder_->create<type::Pointer>(ret, ptr->storage_class()); } } else if (auto* vec = data_type->As<type::Vector>()) { - expr->SetIsSwizzle(); + is_swizzle = true; auto size = builder_->Symbols().NameFor(expr->member()->symbol()).size(); if (size == 1) { @@ -1054,7 +1057,9 @@ return false; } - SetType(expr, ret); + builder_->Sem().Add( + expr, + builder_->create<semantic::MemberAccessorExpression>(ret, is_swizzle)); return true; }
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc index f78a12e..d9b35cc 100644 --- a/src/writer/hlsl/generator_impl.cc +++ b/src/writer/hlsl/generator_impl.cc
@@ -48,6 +48,7 @@ #include "src/semantic/call.h" #include "src/semantic/expression.h" #include "src/semantic/function.h" +#include "src/semantic/member_accessor_expression.h" #include "src/semantic/variable.h" #include "src/type/access_control_type.h" #include "src/type/alias_type.h" @@ -2104,7 +2105,7 @@ out << "."; // Swizzles output the name directly - if (expr->IsSwizzle()) { + if (builder_.Sem().Get(expr)->IsSwizzle()) { out << builder_.Symbols().NameFor(expr->member()->symbol()); } else if (!EmitExpression(pre, out, expr->member())) { return false;
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc index b1ff19e..5d70e46 100644 --- a/src/writer/msl/generator_impl.cc +++ b/src/writer/msl/generator_impl.cc
@@ -53,6 +53,7 @@ #include "src/semantic/call.h" #include "src/semantic/expression.h" #include "src/semantic/function.h" +#include "src/semantic/member_accessor_expression.h" #include "src/semantic/variable.h" #include "src/type/access_control_type.h" #include "src/type/alias_type.h" @@ -1738,7 +1739,7 @@ out_ << "."; // Swizzles get written out directly - if (expr->IsSwizzle()) { + if (program_->Sem().Get(expr)->IsSwizzle()) { out_ << program_->Symbols().NameFor(expr->member()->symbol()); } else if (!EmitExpression(expr->member())) { return false;