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>
This commit is contained in:
Ben Clayton 2021-03-17 22:01:53 +00:00 committed by Commit Bot service account
parent ad97343214
commit 893afdfd2c
2 changed files with 44 additions and 16 deletions

View File

@ -1242,6 +1242,15 @@ void Resolver::CreateSemanticNodes() const {
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 @@ bool Resolver::DefaultAlignAndSize(type::Type* ty,
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 @@ const semantic::Array* Resolver::Array(type::Array* arr) {
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 @@ const semantic::Struct* Resolver::Structure(type::Struct* str) {
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(ast::Variable* decl)
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

View File

@ -114,6 +114,18 @@ class Resolver {
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 @@ class Resolver {
/// 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 @@ class Resolver {
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