Resolver: Defer building of semantic::Struct until end This will allow us to collect up usage information of the structures in a single pass. Bug: tint:320 Bug: tint:643 Change-Id: Iaa700dc1e287f6df2717c422e66ec453b23b22dc Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/45123 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: David Neto <dneto@google.com> Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc index fcb9164..53a69f9 100644 --- a/src/resolver/resolver.cc +++ b/src/resolver/resolver.cc
@@ -1242,6 +1242,15 @@ sem.Add(expr, builder_->create<semantic::Expression>(expr, info.type, info.statement)); } + + // Create semantic nodes for all structs + for (auto it : struct_info_) { + auto* str = it.first; + auto* info = it.second; + builder_->Sem().Add(str, builder_->create<semantic::Struct>( + str, std::move(info->members), info->align, + info->size, info->size_no_padding)); + } } bool Resolver::DefaultAlignAndSize(type::Type* ty, @@ -1288,9 +1297,9 @@ size = vector_align[mat->rows()] * mat->columns(); return true; } else if (auto* s = ty->As<type::Struct>()) { - if (auto* sem = Structure(s)) { - align = sem->Align(); - size = sem->Size(); + if (auto* si = Structure(s)) { + align = si->align; + size = si->size; return true; } return false; @@ -1354,10 +1363,11 @@ return create_semantic(utils::RoundUp(el_align, el_size)); } -const semantic::Struct* Resolver::Structure(type::Struct* str) { - if (auto* sem = builder_->Sem().Get(str)) { - // Semantic info already constructed for this structure type - return sem; +Resolver::StructInfo* Resolver::Structure(type::Struct* str) { + auto info_it = struct_info_.find(str); + if (info_it != struct_info_.end()) { + // StructInfo already resolved for this structure type + return info_it->second; } semantic::StructMemberList sem_members; @@ -1451,10 +1461,13 @@ auto size_no_padding = struct_size; struct_size = utils::RoundUp(struct_align, struct_size); - auto* sem = builder_->create<semantic::Struct>( - str, std::move(sem_members), struct_align, struct_size, size_no_padding); - builder_->Sem().Add(str, sem); - return sem; + auto* info = struct_infos_.Create(); + info->members = std::move(sem_members); + info->align = struct_align; + info->size = struct_size; + info->size_no_padding = size_no_padding; + struct_info_.emplace(str, info); + return info; } template <typename F> @@ -1470,8 +1483,10 @@ Resolver::VariableInfo::~VariableInfo() = default; Resolver::FunctionInfo::FunctionInfo(ast::Function* decl) : declaration(decl) {} - Resolver::FunctionInfo::~FunctionInfo() = default; +Resolver::StructInfo::StructInfo() = default; +Resolver::StructInfo::~StructInfo() = default; + } // namespace resolver } // namespace tint
diff --git a/src/resolver/resolver.h b/src/resolver/resolver.h index 8fd6900..4bbe504 100644 --- a/src/resolver/resolver.h +++ b/src/resolver/resolver.h
@@ -114,6 +114,18 @@ semantic::Statement* statement; }; + /// Structure holding semantic information about a struct. + /// Used to build the semantic::Struct nodes at the end of resolving. + struct StructInfo { + StructInfo(); + ~StructInfo(); + + std::vector<semantic::StructMember*> members; + uint32_t align = 0; + uint32_t size = 0; + uint32_t size_no_padding = 0; + }; + /// Structure holding semantic information about a block (i.e. scope), such as /// parent block and variables declared in the block. /// Used to validate variable scoping rules. @@ -201,10 +213,9 @@ /// returned. const semantic::Array* Array(type::Array*); - /// @returns the semantic information for the structure `str`, building it if - /// it hasn't been constructed already. If an error is raised, nullptr is - /// returned. - const semantic::Struct* Structure(type::Struct* str); + /// @returns the StructInfo for the structure `str`, building it if it hasn't + /// been constructed already. If an error is raised, nullptr is returned. + StructInfo* Structure(type::Struct* str); /// @param align the output default alignment in bytes for the type `ty` /// @param size the output default size in bytes for the type `ty` @@ -239,10 +250,12 @@ std::unordered_map<ast::Variable*, VariableInfo*> variable_to_info_; std::unordered_map<ast::CallExpression*, FunctionCallInfo> function_calls_; std::unordered_map<ast::Expression*, ExpressionInfo> expr_info_; + std::unordered_map<type::Struct*, StructInfo*> struct_info_; FunctionInfo* current_function_ = nullptr; semantic::Statement* current_statement_ = nullptr; BlockAllocator<VariableInfo> variable_infos_; BlockAllocator<FunctionInfo> function_infos_; + BlockAllocator<StructInfo> struct_infos_; }; } // namespace resolver